changeset 24094:9b69cec6d01b

Merge with jdk8u121-b13
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Mon, 06 Feb 2017 17:18:57 +0100
parents 9a740aa0d87b (diff) 90f94521c351 (current diff)
children 464eb43e7814
files .hgtags src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp src/cpu/sparc/vm/compiledIC_sparc.cpp src/cpu/sparc/vm/sparc.ad src/cpu/x86/vm/c1_CodeStubs_x86.cpp src/cpu/x86/vm/compiledIC_x86.cpp src/cpu/x86/vm/macroAssembler_x86.cpp src/cpu/x86/vm/x86.ad src/cpu/x86/vm/x86_32.ad src/cpu/x86/vm/x86_64.ad src/cpu/zero/vm/cppInterpreter_zero.cpp src/os/linux/vm/os_linux.cpp src/share/vm/c1/c1_LIRAssembler.cpp src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/classLoaderData.cpp src/share/vm/classfile/classLoaderData.inline.hpp src/share/vm/classfile/verifier.cpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/code/compiledIC.hpp src/share/vm/interpreter/bytecodeInterpreter.cpp src/share/vm/oops/method.cpp src/share/vm/oops/method.hpp src/share/vm/opto/compile.cpp src/share/vm/opto/connode.cpp src/share/vm/opto/output.cpp src/share/vm/opto/stringopts.cpp src/share/vm/opto/subnode.cpp src/share/vm/prims/jniCheck.cpp src/share/vm/prims/jvm.cpp src/share/vm/utilities/taskqueue.hpp test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java
diffstat 900 files changed, 57453 insertions(+), 8710 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Dec 05 13:09:39 2016 -0800
+++ b/.hgignore	Mon Feb 06 17:18:57 2017 +0100
@@ -1,9 +1,93 @@
+^mxbuild/
 ^build/
+^build-nograal/
+^build-nojvmci/
 ^dist/
+^java/
+^jdk1.(7|8).0
+^java64/
+^work/
+\.checkstyle$
+\.classpath
+\.factorypath
+\.externalToolBuilders
+\.project
+\.settings/
+\.metadata/
+~$
+.gdb_history
+\.csv$
+\.iml$
+\.swp$
+\.swn$
+\.swo$
+\.class$
+\.log$
+\.bak$
+\.aux$
+\.pdf$
+\.dot$
+\.pyc$
+\.hprof$
+\.hprof\.txt$
+^doc/.*/dot_temp_
+^doc/doxygen/.*$
+\.orig$
+output\.txt$
+output\.cfg$
+\.cfg
 /nbproject/private/
+^graal/hotspot/java$
+^scratch/
+^test-output/
+scratch/
+savedDeps/
+src_gen/
+currentAnnotationProcessors/
+bin/
+^local/
 ^src/share/tools/hsdis/build/
 ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/
 ^src/share/tools/IdealGraphVisualizer/build/
 ^src/share/tools/IdealGraphVisualizer/dist/
+^visualizer/[a-zA-Z0-9]*/build/
+^visualizer/build/
+^visualizer/dist/
+^visualizer/nbplatform/
+^src/share/tools/IdealGraphVisualizer/nbplatform/
 ^.hgtip
 .DS_Store
+javadoc/
+.idea/
+^cscope.out
+^tags
+
+syntax: glob
+lib
+ecj.jar
+jmh
+env
+nbproject
+dist
+build.xml
+eclipse-launches
+*.bgv
+core.*
+*.jar
+*.jar.*
+*.zip
+*.zip.*
+eclipse-build.xml
+rebuild-launch.out
+coverage
+jacoco.exec
+workingsets.xml
+.buildbot/
+jvmci.options
+agent/build/*
+agent/make/filelist
+agent/make/sa17.tar.gz
+export.json
+.recommenders
+syntax: regexp
+test\.[0-9]+\.er
--- a/.hgtags	Mon Dec 05 13:09:39 2016 -0800
+++ b/.hgtags	Mon Feb 06 17:18:57 2017 +0100
@@ -944,3 +944,47 @@
 f26f6895c9dfb32dfb4c228d69b371d8ab118536 jdk8u121-b10
 11f91811e4d7e5ddfaf938dcf386ec8fe5bf7b7c jdk8u121-b11
 b132b08b28bf23a26329928cf6b4ffda5857f4d3 jdk8u121-b12
+b124e22eb772806c13d942cc110de38da0108147 graal-0.1
+483d05bf77a7c2a762aca1e06c4191bc06647176 graal-0.2
+9535eccd2a115f6c6f0b15efb508b11ff74cc0d3 graal-0.3
+7d4f630172a16e983212d46c0f1ad6cdb826dfce graal-0.4
+ae5b662550836e851c39e4fbb5c80517fc62488f graal-0.5
+3b60f720b955c466d913abb0113af9b38962950b graal-0.6
+1b0ef9634252c422b6f9839fc62eebc112545486 gpu-0.1
+9a12234da10cfa6934617274c203672389a1bbdd baseline-0.1
+754f2b20d8bc43053d254826e6b9f09db3f3c992 graal-0.7
+3c622007e098d8905d8e0947362a3894a629a5f1 graal-0.8
+3c622007e098d8905d8e0947362a3894a629a5f1 jvmci-0.8
+b2ca0db145463b6332c0096eaa68fa03e80ee5e8 jvmci-0.9
+12aff370a6368799259a50a0339947d36918a92c jvmci-0.10
+d9cb6983c9a539dc50a9c091903ba57e673f3367 jvmci-0.11
+50465926fbeb0eacbb6d0bcec8fc8d5efebb822b jvmci-0.12
+d814713e3b0288d18a355d7b48bcd300d1e6834f jvmci-0.13
+0d09e13523b4b67528ed1f58e7614cde3bfba052 jvmci-0.14
+54f09016769e23491e4ae268136097873d2c1950 jvmci-0.15
+54f09016769e23491e4ae268136097873d2c1950 jvmci-0.15
+ba5c418b4696d0137a44bc8da3f9b51345925755 jvmci-0.15
+ba5c418b4696d0137a44bc8da3f9b51345925755 jvmci-0.15
+5d149c67c230862fd3270108499cfb8d406412ee jvmci-0.15
+66059526b02119f1400b6fa859b583d8027eb5bf jvmci-0.16
+c61554b3f6df495859a0b188f5752c693ece0dd1 jvmci-0.17
+c61554b3f6df495859a0b188f5752c693ece0dd1 jvmci-0.17
+3db9e47b477ad7e98bf0ca2b7850296fa925f532 jvmci-0.17
+3db9e47b477ad7e98bf0ca2b7850296fa925f532 jvmci-0.17
+5595ab8ba8bd90dbbb8b5a81b7c9a8eb15a24e43 jvmci-0.17
+4a61c3e64ab49a905bf341f52b15168db922377a jvmci-0.18
+4a61c3e64ab49a905bf341f52b15168db922377a jvmci-0.18
+2e17c65dddd724e05027903e51532f9a37a195e1 jvmci-0.18
+1140503536ae082daee2396f3aaa91c004a3ea80 jvmci-0.19
+a67f4d28935f75f6bf99240b444e8e3766688201 jvmci-0.20
+f6de9aff9991a2a473644052ef9323f27c857a0e jvmci-0.21
+f6de9aff9991a2a473644052ef9323f27c857a0e jvmci-0.21
+bf2d00fc162bd388f5683de12adb72591e3453dd jvmci-0.21
+bf2d00fc162bd388f5683de12adb72591e3453dd jvmci-0.21
+c64c9fac1ab97322f82f403daecf693355ced99c jvmci-0.21
+c64c9fac1ab97322f82f403daecf693355ced99c jvmci-0.21
+be0d95e992045ed0e4ffd6846adb7614e2f3d94d jvmci-0.21
+5cf445d2acf6c42e5472e0cd35e6109a79f7f052 jvmci-0.22
+bf96b9e1058342cb726541eb02664bf36e30ab46 jvmci-0.23
+bf96b9e1058342cb726541eb02664bf36e30ab46 jvmci-0.23
+342cab081103e535b9d7a4b2a538afe4f3f6367e jvmci-0.23
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CONTRIBUTING.md	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,2 @@
+Please see http://openjdk.java.net/contribute/ for details of how to contribute
+to OpenJDK projects including GraalVM.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE.EPL	Mon Feb 06 17:18:57 2017 +0100
@@ -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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE.LGPL	Mon Feb 06 17:18:57 2017 +0100
@@ -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.
+
+      <one line to give the library's name and a brief idea of what it does.>
+      Copyright (C) <year>  <name of author>
+
+      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.
+
+    <signature of Ty Coon>, 1 April 1990
+    Ty Coon, President of Vice
+
+  That's all there is to it!
--- a/README	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-README:
-  This file should be located at the top of the hotspot Mercurial repository.
-
-  See http://openjdk.java.net/ for more information about the OpenJDK.
-
-  See ../README-builds.html for complete details on build machine requirements.
-
-Simple Build Instructions:
-
-    cd make && gnumake
-     
-  The files that will be imported into the jdk build will be in the "build"
-  directory.
-
--- a/agent/src/os/linux/libproc.h	Mon Dec 05 13:09:39 2016 -0800
+++ b/agent/src/os/linux/libproc.h	Mon Feb 06 17:18:57 2017 +0100
@@ -34,7 +34,11 @@
 #include "libproc_md.h"
 #endif
 
+#if defined(sparcv9) && defined(linux)
+#include <asm/ptrace.h>
+#else
 #include <sys/ptrace.h>
+#endif
 
 /************************************************************************************
 
--- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java	Mon Feb 06 17:18:57 2017 +0100
@@ -65,9 +65,6 @@
       }
     }
 
-    public void visitValueLocation(Address valueAddr) {
-    }
-
     public void visitNarrowOopLocation(Address narrowOopAddr) {
       addressVisitor.visitCompOopAddress(narrowOopAddr);
     }
@@ -198,9 +195,9 @@
       }
     }
 
-    // We want narow oop, value and oop oop_types
+    // We want narow oop and  oop oop_types
     OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] {
-      OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
+      OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
     };
 
     {
@@ -213,8 +210,6 @@
             // to detect in the debugging system
             // assert(Universe::is_heap_or_null(*loc), "found non oop pointer");
             visitor.visitOopLocation(loc);
-          } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) {
-            visitor.visitValueLocation(loc);
           } else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) {
             visitor.visitNarrowOopLocation(loc);
           }
--- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java	Mon Feb 06 17:18:57 2017 +0100
@@ -49,7 +49,6 @@
   // Types of OopValues
   static int UNUSED_VALUE;
   static int OOP_VALUE;
-  static int VALUE_VALUE;
   static int NARROWOOP_VALUE;
   static int CALLEE_SAVED_VALUE;
   static int DERIVED_OOP_VALUE;
@@ -73,7 +72,6 @@
     REGISTER_MASK_IN_PLACE = db.lookupIntConstant("OopMapValue::register_mask_in_place").intValue();
     UNUSED_VALUE           = db.lookupIntConstant("OopMapValue::unused_value").intValue();
     OOP_VALUE              = db.lookupIntConstant("OopMapValue::oop_value").intValue();
-    VALUE_VALUE            = db.lookupIntConstant("OopMapValue::value_value").intValue();
     NARROWOOP_VALUE        = db.lookupIntConstant("OopMapValue::narrowoop_value").intValue();
     CALLEE_SAVED_VALUE     = db.lookupIntConstant("OopMapValue::callee_saved_value").intValue();
     DERIVED_OOP_VALUE      = db.lookupIntConstant("OopMapValue::derived_oop_value").intValue();
@@ -82,7 +80,6 @@
   public static abstract class OopTypes {
     public static final OopTypes UNUSED_VALUE       = new OopTypes() { int getValue() { return OopMapValue.UNUSED_VALUE;       }};
     public static final OopTypes OOP_VALUE          = new OopTypes() { int getValue() { return OopMapValue.OOP_VALUE;          }};
-    public static final OopTypes VALUE_VALUE        = new OopTypes() { int getValue() { return OopMapValue.VALUE_VALUE;        }};
     public static final OopTypes NARROWOOP_VALUE    = new OopTypes() { int getValue() { return OopMapValue.NARROWOOP_VALUE;         }};
     public static final OopTypes CALLEE_SAVED_VALUE = new OopTypes() { int getValue() { return OopMapValue.CALLEE_SAVED_VALUE; }};
     public static final OopTypes DERIVED_OOP_VALUE  = new OopTypes() { int getValue() { return OopMapValue.DERIVED_OOP_VALUE;  }};
@@ -105,7 +102,6 @@
 
   // Querying
   public boolean isOop()         { return (getValue() & TYPE_MASK_IN_PLACE) == OOP_VALUE;          }
-  public boolean isValue()       { return (getValue() & TYPE_MASK_IN_PLACE) == VALUE_VALUE;        }
   public boolean isNarrowOop()   { return (getValue() & TYPE_MASK_IN_PLACE) == NARROWOOP_VALUE;    }
   public boolean isCalleeSaved() { return (getValue() & TYPE_MASK_IN_PLACE) == CALLEE_SAVED_VALUE; }
   public boolean isDerivedOop()  { return (getValue() & TYPE_MASK_IN_PLACE) == DERIVED_OOP_VALUE;  }
@@ -117,7 +113,6 @@
     int which = (getValue() & TYPE_MASK_IN_PLACE);
          if (which == UNUSED_VALUE) return OopTypes.UNUSED_VALUE;
     else if (which == OOP_VALUE)    return OopTypes.OOP_VALUE;
-    else if (which == VALUE_VALUE)  return OopTypes.VALUE_VALUE;
     else if (which == NARROWOOP_VALUE)   return OopTypes.NARROWOOP_VALUE;
     else if (which == CALLEE_SAVED_VALUE) return OopTypes.CALLEE_SAVED_VALUE;
     else if (which == DERIVED_OOP_VALUE)  return OopTypes.DERIVED_OOP_VALUE;
--- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java	Mon Feb 06 17:18:57 2017 +0100
@@ -31,6 +31,5 @@
 public interface OopMapVisitor {
   public void visitOopLocation(Address oopAddr);
   public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr);
-  public void visitValueLocation(Address valueAddr);
   public void visitNarrowOopLocation(Address narrowOopAddr);
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java	Mon Feb 06 17:18:57 2017 +0100
@@ -544,9 +544,6 @@
       }
     }
 
-    public void visitValueLocation(Address valueAddr) {
-    }
-
     public void visitNarrowOopLocation(Address compOopAddr) {
       addressVisitor.visitCompOopAddress(compOopAddr);
     }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1222,9 +1222,6 @@
       oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
       buf.append(omvIterator.iterate(oms, "NarrowOops:", false));
 
-      oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
-      buf.append(omvIterator.iterate(oms, "Values:", false));
-
       oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE);
       buf.append(omvIterator.iterate(oms, "Callee saved:",  true));
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/.cproject	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,635 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881" moduleId="org.eclipse.cdt.core.settings" name="Default">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577" name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.1866612258" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.2075405295" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="Run this in shell: mx build --no-java" autoBuildTarget="" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="echo" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.81453037" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1094883386" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1342888057" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.801956928" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/jdk.vm.ci.hotspot/src_gen/hotspot}&quot;"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.634868600" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+									<listOptionValue builtIn="false" value="LINUX=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_linux=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
+									<listOptionValue builtIn="false" value="INCLUDE_JVMCI=1"/>
+									<listOptionValue builtIn="false" value="COMPILER2=1"/>
+									<listOptionValue builtIn="false" value="COMPILERJVMCI=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.2137486146" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.866181452" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1535888880" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.825962493" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.906671119" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1271041307" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.550499946" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.274517766" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.554053529" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1055083385" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162" moduleId="org.eclipse.cdt.core.settings" name="Server">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="Server VM with JVMCI enabled (Tiered)" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162" name="Server" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.1741231788" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.1058861512" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build --no-java" autoBuildTarget="" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.1971483913" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.446231503" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.677873708" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.2060190160" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/jdk.vm.ci.hotspot/src_gen/hotspot}&quot;"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.270375031" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+									<listOptionValue builtIn="false" value="LINUX=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_linux=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
+									<listOptionValue builtIn="false" value="INCLUDE_JVMCI=1"/>
+									<listOptionValue builtIn="false" value="COMPILER2=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.553556482" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.429177901" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1536145259" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.664112776" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1935913022" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.190805864" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.661896739" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1889460576" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.770549769" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.2130492397" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162" moduleId="org.eclipse.cdt.core.settings" name="Client">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="Client VM with JVMCI enabled" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162" name="Client" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.1944635494" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.760397453" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build --no-java" autoBuildTarget="" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.2024267298" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.805698881" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1673917487" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.1395828869" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/jdk.vm.ci.hotspot/src_gen/hotspot}&quot;"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.1699174802" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+									<listOptionValue builtIn="false" value="LINUX=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_linux=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
+									<listOptionValue builtIn="false" value="INCLUDE_JVMCI=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.2019710410" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.931461388" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1862778408" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.327213605" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.29080811" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.499906465" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.367432319" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1206523880" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.43198633" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.757957452" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp|shared/vm/opto" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004" moduleId="org.eclipse.cdt.core.settings" name="JVMCI">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="Graal VM (Tiered)" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004" name="JVMCI" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.1790873354" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.2087199731" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build --no-java" autoBuildTarget="" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.1107701476" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.111821059" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.501581878" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.1285141101" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/jdk.vm.ci.hotspot/src_gen/hotspot}&quot;"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.1301765451" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+									<listOptionValue builtIn="false" value="LINUX=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_linux=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
+									<listOptionValue builtIn="false" value="INCLUDE_JVMCI=1"/>
+									<listOptionValue builtIn="false" value="COMPILERJVMCI=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.1682796822" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1552002453" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.647707969" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.824582057" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1613323394" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1066932337" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.23923928" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.92649386" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.856169124" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1667718151" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051" moduleId="org.eclipse.cdt.core.settings" name="Server no JVMCI">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="Server VM without JVMCI extentions (Tiered)" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051" name="Server no JVMCI" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.264813073" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.555589372" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build --no-java" autoBuildTarget="" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.1661210962" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.832885832" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1920567990" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.839069865" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/jdk.vm.ci.hotspot/src_gen/hotspot}&quot;"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.1804264717" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+									<listOptionValue builtIn="false" value="LINUX=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_linux=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER2=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.438887425" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1463421641" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.592469102" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.829508688" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1891927256" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.349030735" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.1778058716" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1044422632" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.967152326" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.983789158" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225" moduleId="org.eclipse.cdt.core.settings" name="Client no JVMCI">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="Client VM without JVMCI extentions" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225" name="Client no JVMCI" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.237868264" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.819675926" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build --no-java" autoBuildTarget="" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.1052794537" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1406128591" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1404788740" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.701589205" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/jdk.vm.ci.hotspot/src_gen/hotspot}&quot;"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.815907884" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+									<listOptionValue builtIn="false" value="LINUX=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_linux=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.1580814100" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1175382997" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.961579870" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.1147358177" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1710196852" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1903854315" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.496829534" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1852502664" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.2132345407" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.140899416" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp|shared/vm/opto|shared/vm/jvmci" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952" moduleId="org.eclipse.cdt.core.settings" name="JVMCI_SPARC">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="Graal VM (Tiered) SPARC" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952" name="JVMCI_SPARC" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.371608063" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.590465959" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build --no-java" autoBuildTarget="" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.1027675600" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1899389289" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1356687693" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.426953005" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/jdk.vm.ci.hotspot/src_gen/hotspot}&quot;"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.838569633" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="INCLUDE_JVMCI=1"/>
+									<listOptionValue builtIn="false" value="COMPILERJVMCI=1"/>
+									<listOptionValue builtIn="false" value="SPARC=1"/>
+									<listOptionValue builtIn="false" value="SOLARIS=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_sparc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_sparcv9=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_solaris=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_solaris_sparc=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.1816416368" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1780717993" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.360408773" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.1966602549" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="SPARC=1"/>
+									<listOptionValue builtIn="false" value="SOLARIS=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1496179991" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.507690497" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.240664373" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.765928890" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.2086131553" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.819779769" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="hotspot.null.1712822257" name="hotspot"/>
+	</storageModule>
+	<storageModule moduleId="refreshScope" versionNumber="2">
+		<configuration configurationName="Server no JVMCI"/>
+		<configuration configurationName="Server"/>
+		<configuration configurationName="Client no JVMCI"/>
+		<configuration configurationName="JVMCI_SPARC"/>
+		<configuration configurationName="Client">
+			<resource resourceType="PROJECT" workspacePath="/hotspot"/>
+		</configuration>
+		<configuration configurationName="JVMCI"/>
+		<configuration configurationName="Default">
+			<resource resourceType="PROJECT" workspacePath="/hotspot"/>
+		</configuration>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+	<storageModule moduleId="scannerConfiguration">
+		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162.;cdt.managedbuild.tool.gnu.c.compiler.base.1862778408;cdt.managedbuild.tool.gnu.c.compiler.input.29080811">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.;cdt.managedbuild.tool.gnu.cpp.compiler.base.501581878;cdt.managedbuild.tool.gnu.cpp.compiler.input.1552002453">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.388217325;cdt.managedbuild.tool.gnu.solaris.cpp.compiler.base.377383651;cdt.managedbuild.tool.gnu.cpp.compiler.input.103897085">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.solaris.c.compiler.base.351149667;cdt.managedbuild.tool.gnu.c.compiler.input.820447325">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.388217325;cdt.managedbuild.tool.gnu.solaris.c.compiler.base.212558466;cdt.managedbuild.tool.gnu.c.compiler.input.1115218695">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.c.compiler.base.1535888880;cdt.managedbuild.tool.gnu.c.compiler.input.906671119">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051.;cdt.managedbuild.tool.gnu.c.compiler.base.592469102;cdt.managedbuild.tool.gnu.c.compiler.input.1891927256">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.solaris.cpp.compiler.base.429326045;cdt.managedbuild.tool.gnu.cpp.compiler.input.1860785837">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.;cdt.managedbuild.tool.gnu.c.compiler.base.647707969;cdt.managedbuild.tool.gnu.c.compiler.input.1613323394">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162.;cdt.managedbuild.tool.gnu.c.compiler.base.1536145259;cdt.managedbuild.tool.gnu.c.compiler.input.1935913022">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.cpp.compiler.base.1342888057;cdt.managedbuild.tool.gnu.cpp.compiler.input.866181452">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225.;cdt.managedbuild.tool.gnu.cpp.compiler.base.1404788740;cdt.managedbuild.tool.gnu.cpp.compiler.input.1175382997">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162.;cdt.managedbuild.tool.gnu.cpp.compiler.base.677873708;cdt.managedbuild.tool.gnu.cpp.compiler.input.429177901">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051.;cdt.managedbuild.tool.gnu.cpp.compiler.base.1920567990;cdt.managedbuild.tool.gnu.cpp.compiler.input.1463421641">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225.;cdt.managedbuild.tool.gnu.c.compiler.base.961579870;cdt.managedbuild.tool.gnu.c.compiler.input.1710196852">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162.;cdt.managedbuild.tool.gnu.cpp.compiler.base.1673917487;cdt.managedbuild.tool.gnu.cpp.compiler.input.931461388">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+	</storageModule>
+</cproject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/.project	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>hotspot</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>auto,</triggers>
+			<arguments>
+				<dictionary>
+					<key>?children?</key>
+					<value>?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|\||</value>
+				</dictionary>
+				<dictionary>
+					<key>?name?</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.append_environment</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
+					<value>ide-build-target</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildArguments</key>
+					<value>${workspace_loc:/hotspot}/../mxtool/mx build</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildCommand</key>
+					<value>bash</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildLocation</key>
+					<value>${workspace_loc:/hotspot}/..</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
+					<value>clean</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.contents</key>
+					<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableFullBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
+					<value>jvmg1</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.stopOnError</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+					<value>false</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>agent</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/agent</locationURI>
+		</link>
+		<link>
+			<name>build</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/build</locationURI>
+		</link>
+		<link>
+			<name>make</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/make</locationURI>
+		</link>
+		<link>
+			<name>src</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/src</locationURI>
+		</link>
+		<link>
+			<name>test</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/test</locationURI>
+		</link>
+	</linkedResources>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/.settings/org.eclipse.cdt.core.prefs	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,198 @@
+eclipse.preferences.version=1
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/BUILDING_FROM_IDE/delimiter=\:
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/BUILDING_FROM_IDE/operation=append
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/BUILDING_FROM_IDE/value=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/append=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/appendContributed=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/BUILDING_FROM_IDE/delimiter=\:
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/BUILDING_FROM_IDE/operation=append
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/BUILDING_FROM_IDE/value=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/append=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/appendContributed=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/BUILDING_FROM_IDE/delimiter=\:
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/BUILDING_FROM_IDE/operation=append
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/BUILDING_FROM_IDE/value=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/append=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/appendContributed=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/BUILDING_FROM_IDE/delimiter=\:
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/BUILDING_FROM_IDE/operation=append
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/BUILDING_FROM_IDE/value=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/append=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/appendContributed=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/BUILDING_FROM_IDE/delimiter=\:
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/BUILDING_FROM_IDE/operation=append
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/BUILDING_FROM_IDE/value=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/append=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/appendContributed=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/BUILDING_FROM_IDE/delimiter=\:
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/BUILDING_FROM_IDE/operation=append
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/BUILDING_FROM_IDE/value=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/append=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/appendContributed=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/BUILDING_FROM_IDE/delimiter=\:
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/BUILDING_FROM_IDE/operation=append
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/BUILDING_FROM_IDE/value=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/append=true
+environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/appendContributed=true
+org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.cdt.core.formatter.alignment_for_assignment=16
+org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
+org.eclipse.cdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.cdt.core.formatter.alignment_for_compact_if=0
+org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18
+org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=0
+org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
+org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
+org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
+org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.cdt.core.formatter.alignment_for_member_access=0
+org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain=16
+org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment=1
+org.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column=true
+org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.cdt.core.formatter.compact_else_if=true
+org.eclipse.cdt.core.formatter.continuation_indentation=2
+org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
+org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces=0
+org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
+org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false
+org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false
+org.eclipse.cdt.core.formatter.indent_empty_lines=false
+org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.cdt.core.formatter.indentation.size=2
+org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.join_wrapped_lines=true
+org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=true
+org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.cdt.core.formatter.lineSplit=160
+org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.cdt.core.formatter.tabulation.char=space
+org.eclipse.cdt.core.formatter.tabulation.size=2
+org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/.settings/org.eclipse.cdt.ui.prefs	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,5 @@
+#Wed Sep 01 16:21:02 PDT 2010
+eclipse.preferences.version=1
+formatter_profile=_hotspotStyle
+formatter_settings_version=1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/.settings/org.eclipse.core.runtime.prefs	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,6 @@
+#Wed Sep 01 16:13:40 PDT 2010
+content-types/enabled=true
+content-types/org.eclipse.cdt.core.cxxHeader/file-extensions=hpp,incl
+content-types/org.eclipse.cdt.core.cxxSource/file-extensions=cpp
+eclipse.preferences.version=1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.aarch64;
+
+import java.nio.ByteOrder;
+import java.util.EnumSet;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterArray;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.PlatformKind;
+
+/**
+ * Represents the AArch64 architecture.
+ */
+public class AArch64 extends Architecture {
+
+    public static final RegisterCategory CPU = new RegisterCategory("CPU");
+
+    // General purpose CPU registers
+    public static final Register r0 = new Register(0, 0, "r0", CPU);
+    public static final Register r1 = new Register(1, 1, "r1", CPU);
+    public static final Register r2 = new Register(2, 2, "r2", CPU);
+    public static final Register r3 = new Register(3, 3, "r3", CPU);
+    public static final Register r4 = new Register(4, 4, "r4", CPU);
+    public static final Register r5 = new Register(5, 5, "r5", CPU);
+    public static final Register r6 = new Register(6, 6, "r6", CPU);
+    public static final Register r7 = new Register(7, 7, "r7", CPU);
+    public static final Register r8 = new Register(8, 8, "r8", CPU);
+    public static final Register r9 = new Register(9, 9, "r9", CPU);
+    public static final Register r10 = new Register(10, 10, "r10", CPU);
+    public static final Register r11 = new Register(11, 11, "r11", CPU);
+    public static final Register r12 = new Register(12, 12, "r12", CPU);
+    public static final Register r13 = new Register(13, 13, "r13", CPU);
+    public static final Register r14 = new Register(14, 14, "r14", CPU);
+    public static final Register r15 = new Register(15, 15, "r15", CPU);
+    public static final Register r16 = new Register(16, 16, "r16", CPU);
+    public static final Register r17 = new Register(17, 17, "r17", CPU);
+    public static final Register r18 = new Register(18, 18, "r18", CPU);
+    public static final Register r19 = new Register(19, 19, "r19", CPU);
+    public static final Register r20 = new Register(20, 20, "r20", CPU);
+    public static final Register r21 = new Register(21, 21, "r21", CPU);
+    public static final Register r22 = new Register(22, 22, "r22", CPU);
+    public static final Register r23 = new Register(23, 23, "r23", CPU);
+    public static final Register r24 = new Register(24, 24, "r24", CPU);
+    public static final Register r25 = new Register(25, 25, "r25", CPU);
+    public static final Register r26 = new Register(26, 26, "r26", CPU);
+    public static final Register r27 = new Register(27, 27, "r27", CPU);
+    public static final Register r28 = new Register(28, 28, "r28", CPU);
+    public static final Register r29 = new Register(29, 29, "r29", CPU);
+    public static final Register r30 = new Register(30, 30, "r30", CPU);
+
+    /*
+     * r31 is not a general purpose register, but represents either the stackpointer or the
+     * zero/discard register depending on the instruction. So we represent those two uses as two
+     * different registers. The register numbers are kept in sync with register_aarch64.hpp and have
+     * to be sequential, hence we also need a general r31 register here, which is never used.
+     */
+    public static final Register r31 = new Register(31, 31, "r31", CPU);
+    public static final Register zr = new Register(32, 31, "zr", CPU);
+    public static final Register sp = new Register(33, 31, "sp", CPU);
+
+    public static final Register lr = r30;
+
+    // @formatter:off
+    public static final RegisterArray cpuRegisters = new RegisterArray(
+        r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
+        r8,  r9,  r10, r11, r12, r13, r14, r15,
+        r16, r17, r18, r19, r20, r21, r22, r23,
+        r24, r25, r26, r27, r28, r29, r30, r31,
+        zr,  sp
+    );
+    // @formatter:on
+
+    public static final RegisterCategory SIMD = new RegisterCategory("SIMD");
+
+    // Simd registers
+    public static final Register v0 = new Register(34, 0, "v0", SIMD);
+    public static final Register v1 = new Register(35, 1, "v1", SIMD);
+    public static final Register v2 = new Register(36, 2, "v2", SIMD);
+    public static final Register v3 = new Register(37, 3, "v3", SIMD);
+    public static final Register v4 = new Register(38, 4, "v4", SIMD);
+    public static final Register v5 = new Register(39, 5, "v5", SIMD);
+    public static final Register v6 = new Register(40, 6, "v6", SIMD);
+    public static final Register v7 = new Register(41, 7, "v7", SIMD);
+    public static final Register v8 = new Register(42, 8, "v8", SIMD);
+    public static final Register v9 = new Register(43, 9, "v9", SIMD);
+    public static final Register v10 = new Register(44, 10, "v10", SIMD);
+    public static final Register v11 = new Register(45, 11, "v11", SIMD);
+    public static final Register v12 = new Register(46, 12, "v12", SIMD);
+    public static final Register v13 = new Register(47, 13, "v13", SIMD);
+    public static final Register v14 = new Register(48, 14, "v14", SIMD);
+    public static final Register v15 = new Register(49, 15, "v15", SIMD);
+    public static final Register v16 = new Register(50, 16, "v16", SIMD);
+    public static final Register v17 = new Register(51, 17, "v17", SIMD);
+    public static final Register v18 = new Register(52, 18, "v18", SIMD);
+    public static final Register v19 = new Register(53, 19, "v19", SIMD);
+    public static final Register v20 = new Register(54, 20, "v20", SIMD);
+    public static final Register v21 = new Register(55, 21, "v21", SIMD);
+    public static final Register v22 = new Register(56, 22, "v22", SIMD);
+    public static final Register v23 = new Register(57, 23, "v23", SIMD);
+    public static final Register v24 = new Register(58, 24, "v24", SIMD);
+    public static final Register v25 = new Register(59, 25, "v25", SIMD);
+    public static final Register v26 = new Register(60, 26, "v26", SIMD);
+    public static final Register v27 = new Register(61, 27, "v27", SIMD);
+    public static final Register v28 = new Register(62, 28, "v28", SIMD);
+    public static final Register v29 = new Register(63, 29, "v29", SIMD);
+    public static final Register v30 = new Register(64, 30, "v30", SIMD);
+    public static final Register v31 = new Register(65, 31, "v31", SIMD);
+
+    // @formatter:off
+    public static final RegisterArray simdRegisters = new RegisterArray(
+        v0,  v1,  v2,  v3,  v4,  v5,  v6,  v7,
+        v8,  v9,  v10, v11, v12, v13, v14, v15,
+        v16, v17, v18, v19, v20, v21, v22, v23,
+        v24, v25, v26, v27, v28, v29, v30, v31
+    );
+    // @formatter:on
+
+    // @formatter:off
+    public static final RegisterArray allRegisters = new RegisterArray(
+        r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
+        r8,  r9,  r10, r11, r12, r13, r14, r15,
+        r16, r17, r18, r19, r20, r21, r22, r23,
+        r24, r25, r26, r27, r28, r29, r30, r31,
+        zr,  sp,
+
+        v0,  v1,  v2,  v3,  v4,  v5,  v6,  v7,
+        v8,  v9,  v10, v11, v12, v13, v14, v15,
+        v16, v17, v18, v19, v20, v21, v22, v23,
+        v24, v25, v26, v27, v28, v29, v30, v31
+    );
+    // @formatter:on
+
+    /**
+     * Basic set of CPU features mirroring what is returned from the cpuid instruction. See:
+     * {@code VM_Version::cpuFeatureFlags}.
+     */
+    public enum CPUFeature {
+        FP,
+        ASIMD,
+        EVTSTRM,
+        AES,
+        PMULL,
+        SHA1,
+        SHA2,
+        CRC32,
+        A53MAC,
+        DMB_ATOMICS
+    }
+
+    private final EnumSet<CPUFeature> features;
+
+    /**
+     * Set of flags to control code emission.
+     */
+    public enum Flag {
+        UseBarriersForVolatile,
+        UseCRC32,
+        UseNeon
+    }
+
+    private final EnumSet<Flag> flags;
+
+    public AArch64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
+        super("aarch64", AArch64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, 0, 0, 0);
+        this.features = features;
+        this.flags = flags;
+    }
+
+    public EnumSet<CPUFeature> getFeatures() {
+        return features;
+    }
+
+    public EnumSet<Flag> getFlags() {
+        return flags;
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(JavaKind javaKind) {
+        switch (javaKind) {
+            case Boolean:
+            case Byte:
+                return AArch64Kind.BYTE;
+            case Short:
+            case Char:
+                return AArch64Kind.WORD;
+            case Int:
+                return AArch64Kind.DWORD;
+            case Long:
+            case Object:
+                return AArch64Kind.QWORD;
+            case Float:
+                return AArch64Kind.SINGLE;
+            case Double:
+                return AArch64Kind.DOUBLE;
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
+        AArch64Kind kind = (AArch64Kind) platformKind;
+        if (kind.isInteger()) {
+            return category.equals(CPU);
+        } else if (kind.isSIMD()) {
+            return category.equals(SIMD);
+        }
+        return false;
+    }
+
+    @Override
+    public AArch64Kind getLargestStorableKind(RegisterCategory category) {
+        if (category.equals(CPU)) {
+            return AArch64Kind.QWORD;
+        } else if (category.equals(SIMD)) {
+            return AArch64Kind.V128_QWORD;
+        } else {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64Kind.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.aarch64;
+
+import jdk.vm.ci.meta.PlatformKind;
+
+public enum AArch64Kind implements PlatformKind {
+
+    // scalar
+    BYTE(1),
+    WORD(2),
+    DWORD(4),
+    QWORD(8),
+    SINGLE(4),
+    DOUBLE(8),
+
+    // SIMD
+    V32_BYTE(4, BYTE),
+    V32_WORD(4, WORD),
+    V64_BYTE(8, BYTE),
+    V64_WORD(8, WORD),
+    V64_DWORD(8, DWORD),
+    V128_BYTE(16, BYTE),
+    V128_WORD(16, WORD),
+    V128_DWORD(16, DWORD),
+    V128_QWORD(16, QWORD),
+    V128_SINGLE(16, SINGLE),
+    V128_DOUBLE(16, DOUBLE);
+
+    private final int size;
+    private final int vectorLength;
+
+    private final AArch64Kind scalar;
+    private final EnumKey<AArch64Kind> key = new EnumKey<>(this);
+
+    AArch64Kind(int size) {
+        this.size = size;
+        this.scalar = this;
+        this.vectorLength = 1;
+    }
+
+    AArch64Kind(int size, AArch64Kind scalar) {
+        this.size = size;
+        this.scalar = scalar;
+
+        assert size % scalar.size == 0;
+        this.vectorLength = size / scalar.size;
+    }
+
+    public AArch64Kind getScalar() {
+        return scalar;
+    }
+
+    public int getSizeInBytes() {
+        return size;
+    }
+
+    public int getVectorLength() {
+        return vectorLength;
+    }
+
+    public Key getKey() {
+        return key;
+    }
+
+    public boolean isInteger() {
+        switch (this) {
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case QWORD:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public boolean isSIMD() {
+        switch (this) {
+            case SINGLE:
+            case DOUBLE:
+            case V32_BYTE:
+            case V32_WORD:
+            case V64_BYTE:
+            case V64_WORD:
+            case V64_DWORD:
+            case V128_BYTE:
+            case V128_WORD:
+            case V128_DWORD:
+            case V128_QWORD:
+            case V128_SINGLE:
+            case V128_DOUBLE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public char getTypeChar() {
+        switch (this) {
+            case BYTE:
+                return 'b';
+            case WORD:
+                return 'w';
+            case DWORD:
+                return 'd';
+            case QWORD:
+                return 'q';
+            case SINGLE:
+                return 'S';
+            case DOUBLE:
+                return 'D';
+            case V32_BYTE:
+            case V32_WORD:
+            case V64_BYTE:
+            case V64_WORD:
+            case V64_DWORD:
+            case V128_BYTE:
+            case V128_WORD:
+            case V128_DWORD:
+            case V128_QWORD:
+            case V128_SINGLE:
+            case V128_DOUBLE:
+                return 'v';
+            default:
+                return '-';
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.amd64;
+
+import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD;
+import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
+import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
+import static jdk.vm.ci.code.Register.SPECIAL;
+
+import java.nio.ByteOrder;
+import java.util.EnumSet;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterArray;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.PlatformKind;
+
+/**
+ * Represents the AMD64 architecture.
+ */
+public class AMD64 extends Architecture {
+
+    public static final RegisterCategory CPU = new RegisterCategory("CPU");
+
+    // @formatter:off
+
+    // General purpose CPU registers
+    public static final Register rax = new Register(0, 0, "rax", CPU);
+    public static final Register rcx = new Register(1, 1, "rcx", CPU);
+    public static final Register rdx = new Register(2, 2, "rdx", CPU);
+    public static final Register rbx = new Register(3, 3, "rbx", CPU);
+    public static final Register rsp = new Register(4, 4, "rsp", CPU);
+    public static final Register rbp = new Register(5, 5, "rbp", CPU);
+    public static final Register rsi = new Register(6, 6, "rsi", CPU);
+    public static final Register rdi = new Register(7, 7, "rdi", CPU);
+
+    public static final Register r8  = new Register(8,  8,  "r8", CPU);
+    public static final Register r9  = new Register(9,  9,  "r9", CPU);
+    public static final Register r10 = new Register(10, 10, "r10", CPU);
+    public static final Register r11 = new Register(11, 11, "r11", CPU);
+    public static final Register r12 = new Register(12, 12, "r12", CPU);
+    public static final Register r13 = new Register(13, 13, "r13", CPU);
+    public static final Register r14 = new Register(14, 14, "r14", CPU);
+    public static final Register r15 = new Register(15, 15, "r15", CPU);
+
+    public static final Register[] cpuRegisters = {
+        rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
+        r8, r9, r10, r11, r12, r13, r14, r15
+    };
+
+    public static final RegisterCategory XMM = new RegisterCategory("XMM");
+
+    // XMM registers
+    public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
+    public static final Register xmm1 = new Register(17, 1, "xmm1", XMM);
+    public static final Register xmm2 = new Register(18, 2, "xmm2", XMM);
+    public static final Register xmm3 = new Register(19, 3, "xmm3", XMM);
+    public static final Register xmm4 = new Register(20, 4, "xmm4", XMM);
+    public static final Register xmm5 = new Register(21, 5, "xmm5", XMM);
+    public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
+    public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
+
+    public static final Register xmm8  = new Register(24,  8, "xmm8",  XMM);
+    public static final Register xmm9  = new Register(25,  9, "xmm9",  XMM);
+    public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
+    public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
+    public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
+    public static final Register xmm13 = new Register(29, 13, "xmm13", XMM);
+    public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
+    public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
+
+    public static final Register xmm16 = new Register(32, 16, "xmm16", XMM);
+    public static final Register xmm17 = new Register(33, 17, "xmm17", XMM);
+    public static final Register xmm18 = new Register(34, 18, "xmm18", XMM);
+    public static final Register xmm19 = new Register(35, 19, "xmm19", XMM);
+    public static final Register xmm20 = new Register(36, 20, "xmm20", XMM);
+    public static final Register xmm21 = new Register(37, 21, "xmm21", XMM);
+    public static final Register xmm22 = new Register(38, 22, "xmm22", XMM);
+    public static final Register xmm23 = new Register(39, 23, "xmm23", XMM);
+
+    public static final Register xmm24 = new Register(40, 24, "xmm24", XMM);
+    public static final Register xmm25 = new Register(41, 25, "xmm25", XMM);
+    public static final Register xmm26 = new Register(42, 26, "xmm26", XMM);
+    public static final Register xmm27 = new Register(43, 27, "xmm27", XMM);
+    public static final Register xmm28 = new Register(44, 28, "xmm28", XMM);
+    public static final Register xmm29 = new Register(45, 29, "xmm29", XMM);
+    public static final Register xmm30 = new Register(46, 30, "xmm30", XMM);
+    public static final Register xmm31 = new Register(47, 31, "xmm31", XMM);
+
+    public static final Register[] xmmRegistersSSE = {
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+    };
+
+    public static final Register[] xmmRegistersAVX512 = {
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
+        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31
+    };
+
+    public static final RegisterCategory MASK = new RegisterCategory("MASK", false);
+
+    public static final Register k0 = new Register(48, 0, "k0", MASK);
+    public static final Register k1 = new Register(49, 1, "k1", MASK);
+    public static final Register k2 = new Register(50, 2, "k2", MASK);
+    public static final Register k3 = new Register(51, 3, "k3", MASK);
+    public static final Register k4 = new Register(52, 4, "k4", MASK);
+    public static final Register k5 = new Register(53, 5, "k5", MASK);
+    public static final Register k6 = new Register(54, 6, "k6", MASK);
+    public static final Register k7 = new Register(55, 7, "k7", MASK);
+
+    public static final RegisterArray valueRegistersSSE = new RegisterArray(
+        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
+        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+    );
+
+    public static final RegisterArray valueRegistersAVX512 = new RegisterArray(
+        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
+        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
+        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
+        k0, k1, k2, k3, k4, k5, k6, k7
+    );
+
+    /**
+     * Register used to construct an instruction-relative address.
+     */
+    public static final Register rip = new Register(56, -1, "rip", SPECIAL);
+
+    public static final RegisterArray allRegisters = new RegisterArray(
+        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
+        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
+        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
+        k0, k1, k2, k3, k4, k5, k6, k7,
+        rip
+    );
+
+    // @formatter:on
+
+    /**
+     * Basic set of CPU features mirroring what is returned from the cpuid instruction. See:
+     * {@code VM_Version::cpuFeatureFlags}.
+     */
+    public enum CPUFeature {
+        CX8,
+        CMOV,
+        FXSR,
+        HT,
+        MMX,
+        AMD_3DNOW_PREFETCH,
+        SSE,
+        SSE2,
+        SSE3,
+        SSSE3,
+        SSE4A,
+        SSE4_1,
+        SSE4_2,
+        POPCNT,
+        LZCNT,
+        TSC,
+        TSCINV,
+        AVX,
+        AVX2,
+        AES,
+        ERMS,
+        CLMUL,
+        BMI1,
+        BMI2,
+        RTM,
+        ADX,
+        AVX512F,
+        AVX512DQ,
+        AVX512PF,
+        AVX512ER,
+        AVX512CD,
+        AVX512BW,
+        AVX512VL,
+        SHA
+    }
+
+    private final EnumSet<CPUFeature> features;
+
+    /**
+     * Set of flags to control code emission.
+     */
+    public enum Flag {
+        UseCountLeadingZerosInstruction,
+        UseCountTrailingZerosInstruction
+    }
+
+    private final EnumSet<Flag> flags;
+
+    private final AMD64Kind largestKind;
+
+    public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
+        super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8);
+        this.features = features;
+        this.flags = flags;
+        assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
+
+        if (features.contains(CPUFeature.AVX512F)) {
+            largestKind = AMD64Kind.V512_QWORD;
+        } else if (features.contains(CPUFeature.AVX)) {
+            largestKind = AMD64Kind.V256_QWORD;
+        } else {
+            largestKind = AMD64Kind.V128_QWORD;
+        }
+    }
+
+    public EnumSet<CPUFeature> getFeatures() {
+        return features;
+    }
+
+    public EnumSet<Flag> getFlags() {
+        return flags;
+    }
+
+    @Override
+    public RegisterArray getAvailableValueRegisters() {
+        if (features.contains(CPUFeature.AVX512F)) {
+            return valueRegistersAVX512;
+        } else {
+            return valueRegistersSSE;
+        }
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(JavaKind javaKind) {
+        switch (javaKind) {
+            case Boolean:
+            case Byte:
+                return AMD64Kind.BYTE;
+            case Short:
+            case Char:
+                return AMD64Kind.WORD;
+            case Int:
+                return AMD64Kind.DWORD;
+            case Long:
+            case Object:
+                return AMD64Kind.QWORD;
+            case Float:
+                return AMD64Kind.SINGLE;
+            case Double:
+                return AMD64Kind.DOUBLE;
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
+        AMD64Kind kind = (AMD64Kind) platformKind;
+        if (kind.isInteger()) {
+            return category.equals(CPU);
+        } else if (kind.isXMM()) {
+            return category.equals(XMM);
+        } else {
+            assert kind.isMask();
+            return category.equals(MASK);
+        }
+    }
+
+    @Override
+    public AMD64Kind getLargestStorableKind(RegisterCategory category) {
+        if (category.equals(CPU)) {
+            return AMD64Kind.QWORD;
+        } else if (category.equals(XMM)) {
+            return largestKind;
+        } else if (category.equals(MASK)) {
+            return AMD64Kind.MASK64;
+        } else {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.amd64;
+
+import jdk.vm.ci.meta.PlatformKind;
+
+public enum AMD64Kind implements PlatformKind {
+
+    // scalar
+    BYTE(1),
+    WORD(2),
+    DWORD(4),
+    QWORD(8),
+    SINGLE(4),
+    DOUBLE(8),
+
+    // SSE2
+    V32_BYTE(4, BYTE),
+    V32_WORD(4, WORD),
+    V64_BYTE(8, BYTE),
+    V64_WORD(8, WORD),
+    V64_DWORD(8, DWORD),
+    V128_BYTE(16, BYTE),
+    V128_WORD(16, WORD),
+    V128_DWORD(16, DWORD),
+    V128_QWORD(16, QWORD),
+    V128_SINGLE(16, SINGLE),
+    V128_DOUBLE(16, DOUBLE),
+
+    // AVX
+    V256_BYTE(32, BYTE),
+    V256_WORD(32, WORD),
+    V256_DWORD(32, DWORD),
+    V256_QWORD(32, QWORD),
+    V256_SINGLE(32, SINGLE),
+    V256_DOUBLE(32, DOUBLE),
+
+    // AVX512
+    V512_BYTE(64, BYTE),
+    V512_WORD(64, WORD),
+    V512_DWORD(64, DWORD),
+    V512_QWORD(64, QWORD),
+    V512_SINGLE(64, SINGLE),
+    V512_DOUBLE(64, DOUBLE),
+
+    MASK8(1),
+    MASK16(2),
+    MASK32(4),
+    MASK64(8);
+
+    private final int size;
+    private final int vectorLength;
+
+    private final AMD64Kind scalar;
+    private final EnumKey<AMD64Kind> key = new EnumKey<>(this);
+
+    AMD64Kind(int size) {
+        this.size = size;
+        this.scalar = this;
+        this.vectorLength = 1;
+    }
+
+    AMD64Kind(int size, AMD64Kind scalar) {
+        this.size = size;
+        this.scalar = scalar;
+
+        assert size % scalar.size == 0;
+        this.vectorLength = size / scalar.size;
+    }
+
+    public AMD64Kind getScalar() {
+        return scalar;
+    }
+
+    public int getSizeInBytes() {
+        return size;
+    }
+
+    public int getVectorLength() {
+        return vectorLength;
+    }
+
+    public Key getKey() {
+        return key;
+    }
+
+    public boolean isInteger() {
+        switch (this) {
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case QWORD:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public boolean isXMM() {
+        switch (this) {
+            case SINGLE:
+            case DOUBLE:
+            case V32_BYTE:
+            case V32_WORD:
+            case V64_BYTE:
+            case V64_WORD:
+            case V64_DWORD:
+            case V128_BYTE:
+            case V128_WORD:
+            case V128_DWORD:
+            case V128_QWORD:
+            case V128_SINGLE:
+            case V128_DOUBLE:
+            case V256_BYTE:
+            case V256_WORD:
+            case V256_DWORD:
+            case V256_QWORD:
+            case V256_SINGLE:
+            case V256_DOUBLE:
+            case V512_BYTE:
+            case V512_WORD:
+            case V512_DWORD:
+            case V512_QWORD:
+            case V512_SINGLE:
+            case V512_DOUBLE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public boolean isMask() {
+        switch (this) {
+            case MASK8:
+            case MASK16:
+            case MASK32:
+            case MASK64:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public char getTypeChar() {
+        switch (this) {
+            case BYTE:
+                return 'b';
+            case WORD:
+                return 'w';
+            case DWORD:
+                return 'd';
+            case QWORD:
+                return 'q';
+            case SINGLE:
+                return 'S';
+            case DOUBLE:
+                return 'D';
+            case V32_BYTE:
+            case V32_WORD:
+            case V64_BYTE:
+            case V64_WORD:
+            case V64_DWORD:
+                return 'v';
+            case V128_BYTE:
+            case V128_WORD:
+            case V128_DWORD:
+            case V128_QWORD:
+            case V128_SINGLE:
+            case V128_DOUBLE:
+                return 'x';
+            case V256_BYTE:
+            case V256_WORD:
+            case V256_DWORD:
+            case V256_QWORD:
+            case V256_SINGLE:
+            case V256_DOUBLE:
+                return 'y';
+            case V512_BYTE:
+            case V512_WORD:
+            case V512_DWORD:
+            case V512_QWORD:
+            case V512_SINGLE:
+            case V512_DOUBLE:
+                return 'z';
+            case MASK8:
+            case MASK16:
+            case MASK32:
+            case MASK64:
+                return 'k';
+            default:
+                return '-';
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/overview.html	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+</head>
+<body>
+
+The <code>jdk.vm.ci.code</code> project provides an API to the runtime's native code cache.
+It allows installation and execution of native code.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.nio.ByteOrder;
+
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.PlatformKind;
+
+/**
+ * Represents a CPU architecture, including information such as its endianness, CPU registers, word
+ * width, etc.
+ */
+public abstract class Architecture {
+
+    /**
+     * The architecture specific type of a native word.
+     */
+    private final PlatformKind wordKind;
+
+    /**
+     * The name of this architecture (e.g. "AMD64", "SPARCv9").
+     */
+    private final String name;
+
+    /**
+     * List of all available registers on this architecture. The index of each register in this list
+     * is equal to its {@linkplain Register#number number}.
+     */
+    private final RegisterArray registers;
+
+    /**
+     * The byte ordering can be either little or big endian.
+     */
+    private final ByteOrder byteOrder;
+
+    /**
+     * Whether the architecture supports unaligned memory accesses.
+     */
+    private final boolean unalignedMemoryAccess;
+
+    /**
+     * Mask of the barrier constants denoting the barriers that are not required to be explicitly
+     * inserted under this architecture.
+     */
+    private final int implicitMemoryBarriers;
+
+    /**
+     * Offset in bytes from the beginning of a call instruction to the displacement.
+     */
+    private final int machineCodeCallDisplacementOffset;
+
+    /**
+     * The size of the return address pushed to the stack by a call instruction. A value of 0
+     * denotes that call linkage uses registers instead (e.g. SPARC).
+     */
+    private final int returnAddressSize;
+
+    protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, RegisterArray registers, int implicitMemoryBarriers,
+                    int nativeCallDisplacementOffset,
+                    int returnAddressSize) {
+        this.name = name;
+        this.registers = registers;
+        this.wordKind = wordKind;
+        this.byteOrder = byteOrder;
+        this.unalignedMemoryAccess = unalignedMemoryAccess;
+        this.implicitMemoryBarriers = implicitMemoryBarriers;
+        this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
+        this.returnAddressSize = returnAddressSize;
+    }
+
+    /**
+     * Converts this architecture to a string.
+     *
+     * @return the string representation of this architecture
+     */
+    @Override
+    public final String toString() {
+        return getName().toLowerCase();
+    }
+
+    /**
+     * Gets the natural size of words (typically registers and pointers) of this architecture, in
+     * bytes.
+     */
+    public int getWordSize() {
+        return wordKind.getSizeInBytes();
+    }
+
+    public PlatformKind getWordKind() {
+        return wordKind;
+    }
+
+    /**
+     * Gets the name of this architecture.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the list of all registers that exist on this architecture. This contains all registers
+     * that exist in the specification of this architecture. Not all of them may be available on
+     * this particular architecture instance. The index of each register in this list is equal to
+     * its {@linkplain Register#number number}.
+     */
+    public RegisterArray getRegisters() {
+        return registers;
+    }
+
+    /**
+     * Gets a list of all registers available for storing values on this architecture. This may be a
+     * subset of {@link #getRegisters()}, depending on the capabilities of this particular CPU.
+     */
+    public RegisterArray getAvailableValueRegisters() {
+        return getRegisters();
+    }
+
+    public ByteOrder getByteOrder() {
+        return byteOrder;
+    }
+
+    /**
+     * @return true if the architecture supports unaligned memory accesses.
+     */
+    public boolean supportsUnalignedMemoryAccess() {
+        return unalignedMemoryAccess;
+    }
+
+    /**
+     * Gets the size of the return address pushed to the stack by a call instruction. A value of 0
+     * denotes that call linkage uses registers instead.
+     */
+    public int getReturnAddressSize() {
+        return returnAddressSize;
+    }
+
+    /**
+     * Gets the offset in bytes from the beginning of a call instruction to the displacement.
+     */
+    public int getMachineCodeCallDisplacementOffset() {
+        return machineCodeCallDisplacementOffset;
+    }
+
+    /**
+     * Determines the barriers in a given barrier mask that are explicitly required on this
+     * architecture.
+     *
+     * @param barriers a mask of the barrier constants
+     * @return the value of {@code barriers} minus the barriers unnecessary on this architecture
+     */
+    public final int requiredBarriers(int barriers) {
+        return barriers & ~implicitMemoryBarriers;
+    }
+
+    /**
+     * Determine whether a kind can be stored in a register of a given category.
+     *
+     * @param category the category of the register
+     * @param kind the kind that should be stored in the register
+     */
+    public abstract boolean canStoreValue(RegisterCategory category, PlatformKind kind);
+
+    /**
+     * Return the largest kind that can be stored in a register of a given category.
+     *
+     * @param category the category of the register
+     * @return the largest kind that can be stored in a register {@code category}
+     */
+    public abstract PlatformKind getLargestStorableKind(RegisterCategory category);
+
+    /**
+     * Return the {@link PlatformKind} that is used to store values of a given {@link JavaKind}.
+     */
+    public abstract PlatformKind getPlatformKind(JavaKind javaKind);
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof Architecture) {
+            Architecture that = (Architecture) obj;
+            if (this.name.equals(that.name)) {
+                assert this.byteOrder.equals(that.byteOrder);
+                assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
+                assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
+                assert this.registers.equals(that.registers);
+                assert this.returnAddressSize == that.returnAddressSize;
+                assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
+                assert this.wordKind == that.wordKind;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return name.hashCode();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 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 jdk.vm.ci.code;
+
+import java.util.Locale;
+
+/**
+ * Exception thrown when the compiler refuses to compile a method because of problems with the
+ * method. e.g. bytecode wouldn't verify, too big, JSR/ret too complicated, etc. This exception is
+ * <i>not</i> meant to indicate problems with the compiler itself.
+ */
+public class BailoutException extends RuntimeException {
+
+    public static final long serialVersionUID = 8974598793458772L;
+    private final boolean permanent;
+
+    /**
+     * Creates a new {@link BailoutException}.
+     *
+     *
+     * @param args parameters to the formatter
+     */
+    public BailoutException(String format, Object... args) {
+        super(String.format(Locale.ENGLISH, format, args));
+        this.permanent = true;
+    }
+
+    /**
+     * Creates a new {@link BailoutException}.
+     *
+     *
+     * @param args parameters to the formatter
+     */
+    public BailoutException(Throwable cause, String format, Object... args) {
+        super(String.format(Locale.ENGLISH, format, args), cause);
+        this.permanent = true;
+    }
+
+    /**
+     * Creates a new {@link BailoutException}.
+     *
+     * @param permanent specifies whether this exception will occur again if compilation is retried
+     * @param args parameters to the formatter
+     */
+    public BailoutException(boolean permanent, String format, Object... args) {
+        super(String.format(Locale.ENGLISH, format, args));
+        this.permanent = permanent;
+    }
+
+    /**
+     * @return whether this exception will occur again if compilation is retried
+     */
+    public boolean isPermanent() {
+        return permanent;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.Arrays;
+
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.Value;
+
+/**
+ * Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
+ * where to find the local variables, operand stack values and locked objects of the bytecode
+ * frame(s).
+ */
+public final class BytecodeFrame extends BytecodePosition {
+
+    /**
+     * An array of values representing how to reconstruct the state of the Java frame. This is array
+     * is partitioned as follows:
+     * <p>
+     * <table summary="" border="1" cellpadding="5" frame="void" rules="all">
+     * <tr>
+     * <th>Start index (inclusive)</th>
+     * <th>End index (exclusive)</th>
+     * <th>Description</th>
+     * </tr>
+     * <tr>
+     * <td>0</td>
+     * <td>numLocals</td>
+     * <td>Local variables</td>
+     * </tr>
+     * <tr>
+     * <td>numLocals</td>
+     * <td>numLocals + numStack</td>
+     * <td>Operand stack</td>
+     * </tr>
+     * <tr>
+     * <td>numLocals + numStack</td>
+     * <td>values.length</td>
+     * <td>Locked objects</td>
+     * </tr>
+     * </table>
+     * <p>
+     * Note that the number of locals and the number of stack slots may be smaller than the maximum
+     * number of locals and stack slots as specified in the compiled method.
+     *
+     * This field is intentionally exposed as a mutable array that a compiler may modify (e.g.
+     * during register allocation).
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "field is intentionally mutable")//
+    public final JavaValue[] values;
+
+    /**
+     * An array describing the Java kinds in {@link #values}. It records a kind for the locals and
+     * the operand stack.
+     */
+    private final JavaKind[] slotKinds;
+
+    /**
+     * The number of locals in the values array.
+     */
+    public final int numLocals;
+
+    /**
+     * The number of stack slots in the values array.
+     */
+    public final int numStack;
+
+    /**
+     * The number of locks in the values array.
+     */
+    public final int numLocks;
+
+    /**
+     * True if this is a position inside an exception handler before the exception object has been
+     * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int)
+     * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
+     * position, the interpreter will rethrow the exception instead of executing the bytecode
+     * instruction at this position.
+     */
+    public final boolean rethrowException;
+
+    /**
+     * Specifies if this object represents a frame state in the middle of executing a call. If true,
+     * the arguments to the call have been popped from the stack and the return value (for a
+     * non-void call) has not yet been pushed.
+     */
+    public final boolean duringCall;
+
+    /**
+     * This BCI should be used for frame states that are built for code with no meaningful BCI.
+     */
+    public static final int UNKNOWN_BCI = -5;
+
+    /**
+     * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
+     * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized,
+     * the monitor is still held.
+     */
+    public static final int UNWIND_BCI = -1;
+
+    /**
+     * The BCI for the state before starting to execute a method. Note that if the method is
+     * synchronized, the monitor is not yet held.
+     */
+    public static final int BEFORE_BCI = -2;
+
+    /**
+     * The BCI for the state after finishing the execution of a method and returning normally. Note
+     * that if the method was synchronized the monitor is already released.
+     */
+    public static final int AFTER_BCI = -3;
+
+    /**
+     * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
+     * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the
+     * monitor is already released.
+     */
+    public static final int AFTER_EXCEPTION_BCI = -4;
+
+    /**
+     * This BCI should be used for states that cannot be the target of a deoptimization, like
+     * snippet frame states.
+     */
+    public static final int INVALID_FRAMESTATE_BCI = -6;
+
+    /**
+     * Determines if a given BCI matches one of the placeholder BCI constants defined in this class.
+     */
+    public static boolean isPlaceholderBci(int bci) {
+        return bci < 0;
+    }
+
+    /**
+     * Gets the name of a given placeholder BCI.
+     */
+    public static String getPlaceholderBciName(int bci) {
+        assert isPlaceholderBci(bci);
+        if (bci == BytecodeFrame.AFTER_BCI) {
+            return "AFTER_BCI";
+        } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
+            return "AFTER_EXCEPTION_BCI";
+        } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+            return "INVALID_FRAMESTATE_BCI";
+        } else if (bci == BytecodeFrame.BEFORE_BCI) {
+            return "BEFORE_BCI";
+        } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
+            return "UNKNOWN_BCI";
+        } else {
+            assert bci == BytecodeFrame.UNWIND_BCI;
+            return "UNWIND_BCI";
+        }
+    }
+
+    /**
+     * Creates a new frame object.
+     *
+     * @param caller the caller frame (which may be {@code null})
+     * @param method the method
+     * @param bci a BCI within the method
+     * @param rethrowException specifies if the VM should re-throw the pending exception when
+     *            deopt'ing using this frame
+     * @param values the frame state {@link #values}.
+     * @param slotKinds the kinds in {@code values}. This array is now owned by this object and must
+     *            not be mutated by the caller.
+     * @param numLocals the number of local variables
+     * @param numStack the depth of the stack
+     * @param numLocks the number of locked objects
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `slotKinds`")
+    public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, JavaValue[] values, JavaKind[] slotKinds, int numLocals, int numStack,
+                    int numLocks) {
+        super(caller, method, bci);
+        assert values != null;
+        this.rethrowException = rethrowException;
+        this.duringCall = duringCall;
+        this.values = values;
+        this.slotKinds = slotKinds;
+        this.numLocals = numLocals;
+        this.numStack = numStack;
+        this.numLocks = numLocks;
+        assert !rethrowException || numStack == 1 : "must have exception on top of the stack";
+    }
+
+    /**
+     * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the
+     * slot following a double word item. This should really be checked in FrameState itself but
+     * because of Word type rewriting and alternative backends that can't be done.
+     */
+    public boolean validateFormat() {
+        if (caller() != null) {
+            caller().validateFormat();
+        }
+        for (int i = 0; i < numLocals + numStack; i++) {
+            if (values[i] != null) {
+                JavaKind kind = slotKinds[i];
+                if (kind.needsTwoSlots()) {
+                    assert slotKinds.length > i + 1 : String.format("missing second word %s", this);
+                    assert slotKinds[i + 1] == JavaKind.Illegal : this;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Gets the kind of a local variable.
+     *
+     * @param i the local variable to query
+     * @return the kind of local variable {@code i}
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocals}
+     */
+    public JavaKind getLocalValueKind(int i) {
+        if (i < 0 || i >= numLocals) {
+            throw new IndexOutOfBoundsException();
+        }
+        return slotKinds[i];
+    }
+
+    /**
+     * Gets the kind of a stack slot.
+     *
+     * @param i the local variable to query
+     * @return the kind of stack slot {@code i}
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numStack}
+     */
+    public JavaKind getStackValueKind(int i) {
+        if (i < 0 || i >= numStack) {
+            throw new IndexOutOfBoundsException();
+        }
+        return slotKinds[i + numLocals];
+    }
+
+    /**
+     * Gets the value representing the specified local variable.
+     *
+     * @param i the local variable index
+     * @return the value that can be used to reconstruct the local's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocals}
+     */
+    public JavaValue getLocalValue(int i) {
+        if (i < 0 || i >= numLocals) {
+            throw new IndexOutOfBoundsException();
+        }
+        return values[i];
+    }
+
+    /**
+     * Gets the value representing the specified stack slot.
+     *
+     * @param i the stack index
+     * @return the value that can be used to reconstruct the stack slot's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numStack}
+     */
+    public JavaValue getStackValue(int i) {
+        if (i < 0 || i >= numStack) {
+            throw new IndexOutOfBoundsException();
+        }
+        return values[i + numLocals];
+    }
+
+    /**
+     * Gets the value representing the specified lock.
+     *
+     * @param i the lock index
+     * @return the value that can be used to reconstruct the lock's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocks}
+     */
+    public JavaValue getLockValue(int i) {
+        if (i < 0 || i >= numLocks) {
+            throw new IndexOutOfBoundsException();
+        }
+        return values[i + numLocals + numStack];
+    }
+
+    /**
+     * Gets the caller of this frame.
+     *
+     * @return {@code null} if this frame has no caller
+     */
+    public BytecodeFrame caller() {
+        return (BytecodeFrame) getCaller();
+    }
+
+    @Override
+    public int hashCode() {
+        return (numLocals + 1) ^ (numStack + 11) ^ (numLocks + 7);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof BytecodeFrame && super.equals(obj)) {
+            BytecodeFrame that = (BytecodeFrame) obj;
+            // @formatter:off
+            if (this.duringCall == that.duringCall &&
+                this.rethrowException == that.rethrowException &&
+                this.numLocals == that.numLocals &&
+                this.numLocks == that.numLocks &&
+                this.numStack == that.numStack &&
+                Arrays.equals(this.values, that.values)) {
+                return true;
+            }
+            // @formatter:off
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return CodeUtil.append(new StringBuilder(100), this).toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2009, 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 jdk.vm.ci.code;
+
+import java.util.Objects;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Represents a code position, that is, a chain of inlined methods with bytecode locations, that is
+ * communicated from the compiler to the runtime system. A code position can be used by the runtime
+ * system to reconstruct a source-level stack trace for exceptions and to create
+ * {@linkplain BytecodeFrame frames} for deoptimization.
+ */
+public class BytecodePosition {
+
+    private final BytecodePosition caller;
+    private final ResolvedJavaMethod method;
+    private final int bci;
+
+    /**
+     * Constructs a new object representing a given parent/caller, a given method, and a given BCI.
+     *
+     * @param caller the parent position
+     * @param method the method
+     * @param bci a BCI such that {@code method.codeSize() == 0 || bci < method.getCodeSize()}. That
+     *            is, if code size is 0 then allow any value, otherwise the bci must be less than
+     *            the code size.
+     */
+    public BytecodePosition(BytecodePosition caller, ResolvedJavaMethod method, int bci) {
+        assert method != null;
+        this.caller = caller;
+        this.method = method;
+        this.bci = bci;
+        int codeSize = method.getCodeSize();
+        if (codeSize != 0 && bci >= codeSize) {
+            throw new IllegalArgumentException(String.format("bci %d is out of range for %s %d bytes", bci, method.format("%H.%n(%p)"), codeSize));
+        }
+    }
+
+    /**
+     * Converts this code position to a string representation.
+     *
+     * @return a string representation of this code position
+     */
+    @Override
+    public String toString() {
+        return CodeUtil.append(new StringBuilder(100), this).toString();
+    }
+
+    /**
+     * Deep equality test.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj != null && getClass() == obj.getClass()) {
+            BytecodePosition that = (BytecodePosition) obj;
+            if (this.bci == that.bci && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.caller, that.caller)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return getBCI();
+    }
+
+    /**
+     * @return The location within the method, as a bytecode index. The constant {@code -1} may be
+     *         used to indicate the location is unknown, for example within code synthesized by the
+     *         compiler.
+     */
+    public int getBCI() {
+        return bci;
+    }
+
+    /**
+     * @return The runtime interface method for this position.
+     */
+    public ResolvedJavaMethod getMethod() {
+        return method;
+    }
+
+    /**
+     * The position where this position has been called, {@code null} if none.
+     */
+    public BytecodePosition getCaller() {
+        return caller;
+    }
+
+    /**
+     * Adds a caller to the current position returning the new position.
+     */
+    public BytecodePosition addCaller(BytecodePosition link) {
+        if (getCaller() == null) {
+            return new BytecodePosition(link, getMethod(), getBCI());
+        } else {
+            return new BytecodePosition(getCaller().addCaller(link), getMethod(), getBCI());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2009, 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 jdk.vm.ci.code;
+
+import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
+
+/**
+ * A calling convention describes the locations in which the arguments for a call are placed and the
+ * location in which the return value is placed if the call is not void.
+ */
+public class CallingConvention {
+
+    /**
+     * Marker interface denoting the type of a call for which a calling convention is requested.
+     */
+    public interface Type {
+    }
+
+    /**
+     * The amount of stack space (in bytes) required for the stack-based arguments of the call.
+     */
+    private final int stackSize;
+
+    private final AllocatableValue returnLocation;
+
+    /**
+     * The ordered locations in which the arguments are placed.
+     */
+    private final AllocatableValue[] argumentLocations;
+
+    /**
+     * Creates a description of the registers and stack locations used by a call.
+     *
+     * @param stackSize amount of stack space (in bytes) required for the stack-based arguments of
+     *            the call
+     * @param returnLocation the location for the return value or {@link Value#ILLEGAL} if a void
+     *            call
+     * @param argumentLocations the ordered locations in which the arguments are placed
+     */
+    public CallingConvention(int stackSize, AllocatableValue returnLocation, AllocatableValue... argumentLocations) {
+        assert argumentLocations != null;
+        assert returnLocation != null;
+        this.argumentLocations = argumentLocations;
+        this.stackSize = stackSize;
+        this.returnLocation = returnLocation;
+        assert verify();
+    }
+
+    /**
+     * Gets the location for the return value or {@link Value#ILLEGAL} if a void call.
+     */
+    public AllocatableValue getReturn() {
+        return returnLocation;
+    }
+
+    /**
+     * Gets the location for the {@code index}'th argument.
+     */
+    public AllocatableValue getArgument(int index) {
+        return argumentLocations[index];
+    }
+
+    /**
+     * Gets the amount of stack space (in bytes) required for the stack-based arguments of the call.
+     */
+    public int getStackSize() {
+        return stackSize;
+    }
+
+    /**
+     * Gets the number of locations required for the arguments.
+     */
+    public int getArgumentCount() {
+        return argumentLocations.length;
+    }
+
+    /**
+     * Gets the locations required for the arguments.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "FB false positive")
+    public AllocatableValue[] getArguments() {
+        if (argumentLocations.length == 0) {
+            return argumentLocations;
+        }
+        return argumentLocations.clone();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("CallingConvention[");
+        String sep = "";
+        for (Value op : argumentLocations) {
+            sb.append(sep).append(op);
+            sep = ", ";
+        }
+        if (!returnLocation.equals(Value.ILLEGAL)) {
+            sb.append(" -> ").append(returnLocation);
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+
+    private boolean verify() {
+        for (int i = 0; i < argumentLocations.length; i++) {
+            Value location = argumentLocations[i];
+            assert isStackSlot(location) || isAllocatableValue(location);
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.code.site.Call;
+import jdk.vm.ci.code.site.Mark;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.SpeculationLog;
+
+/**
+ * Access to code cache related details and requirements.
+ */
+public interface CodeCacheProvider {
+
+    /**
+     * Installs code for a given method based on a given compilation result without making it the
+     * default implementation of the method.
+     *
+     * @param method a method implemented by the installed code
+     * @param compiledCode the compiled code to be added
+     * @param log the speculation log to be used
+     * @param installedCode a predefined {@link InstalledCode} object to use as a reference to the
+     *            installed code. If {@code null}, a new {@link InstalledCode} object will be
+     *            created.
+     * @return a reference to the ready-to-run code
+     * @throws BailoutException if the code installation failed
+     */
+    default InstalledCode addCode(ResolvedJavaMethod method, CompiledCode compiledCode, SpeculationLog log, InstalledCode installedCode) {
+        return installCode(method, compiledCode, installedCode, log, false);
+    }
+
+    /**
+     * Installs code for a given method based on a given compilation result and makes it the default
+     * implementation of the method.
+     *
+     * @param method a method implemented by the installed code and for which the installed code
+     *            becomes the default implementation
+     * @param compiledCode the compiled code to be added
+     * @return a reference to the ready-to-run code
+     * @throws BailoutException if the code installation failed
+     */
+    default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompiledCode compiledCode) {
+        return installCode(method, compiledCode, null, null, true);
+    }
+
+    /**
+     * Installs code based on a given compilation result.
+     *
+     * @param method the method compiled to produce {@code compiledCode} or {@code null} if the
+     *            input to {@code compResult} was not a {@link ResolvedJavaMethod}
+     * @param compiledCode the compiled code to be added
+     * @param installedCode a pre-allocated {@link InstalledCode} object to use as a reference to
+     *            the installed code. If {@code null}, a new {@link InstalledCode} object will be
+     *            created.
+     * @param log the speculation log to be used
+     * @param isDefault specifies if the installed code should be made the default implementation of
+     *            {@code compRequest.getMethod()}. The default implementation for a method is the
+     *            code executed for standard calls to the method. This argument is ignored if
+     *            {@code compRequest == null}.
+     * @return a reference to the compiled and ready-to-run installed code
+     * @throws BailoutException if the code installation failed
+     */
+    InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault);
+
+    /**
+     * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be
+     * raised the next time {@code installedCode} is
+     * {@linkplain InstalledCode#executeVarargs(Object...) executed}.
+     */
+    void invalidateInstalledCode(InstalledCode installedCode);
+
+    /**
+     * Gets a name for a {@link Mark} mark.
+     */
+    default String getMarkName(Mark mark) {
+        return String.valueOf(mark.id);
+    }
+
+    /**
+     * Gets a name for the {@linkplain Call#target target} of a {@link Call}.
+     */
+    default String getTargetName(Call call) {
+        return String.valueOf(call.target);
+    }
+
+    /**
+     * Gets the register configuration to use when compiling a given method.
+     */
+    RegisterConfig getRegisterConfig();
+
+    /**
+     * Minimum size of the stack area reserved for outgoing parameters. This area is reserved in all
+     * cases, even when the compiled method has no regular call instructions.
+     *
+     * @return the minimum size of the outgoing parameter area in bytes
+     */
+    int getMinimumOutgoingSize();
+
+    /**
+     * Gets a description of the target architecture.
+     */
+    TargetDescription getTarget();
+
+    /**
+     * Create a new speculation log for the target runtime.
+     */
+    SpeculationLog createSpeculationLog();
+
+    /**
+     * Returns the maximum absolute offset of a PC relative call to a given address from any
+     * position in the code cache or -1 when not applicable. Intended for determining the required
+     * size of address/offset fields.
+     */
+    long getMaxCallTargetOffset(long address);
+
+    /**
+     * Determines if debug info should also be emitted at non-safepoint locations.
+     */
+    boolean shouldDebugNonSafepoints();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.MetaUtil;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.Signature;
+
+/**
+ * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.code} and its clients.
+ */
+public class CodeUtil {
+
+    public static final String NEW_LINE = String.format("%n");
+
+    public static final int K = 1024;
+    public static final int M = 1024 * 1024;
+
+    public static boolean isOdd(int n) {
+        return (n & 1) == 1;
+    }
+
+    public static boolean isEven(int n) {
+        return (n & 1) == 0;
+    }
+
+    /**
+     * Checks whether the specified integer is a power of two.
+     *
+     * @param val the value to check
+     * @return {@code true} if the value is a power of two; {@code false} otherwise
+     */
+    public static boolean isPowerOf2(int val) {
+        return val > 0 && (val & val - 1) == 0;
+    }
+
+    /**
+     * Checks whether the specified long is a power of two.
+     *
+     * @param val the value to check
+     * @return {@code true} if the value is a power of two; {@code false} otherwise
+     */
+    public static boolean isPowerOf2(long val) {
+        return val > 0 && (val & val - 1) == 0;
+    }
+
+    /**
+     * Computes the log (base 2) of the specified integer, rounding down. (E.g {@code log2(8) = 3},
+     * {@code log2(21) = 4} )
+     *
+     * @param val the value
+     * @return the log base 2 of the value
+     */
+    public static int log2(int val) {
+        assert val > 0;
+        return (Integer.SIZE - 1) - Integer.numberOfLeadingZeros(val);
+    }
+
+    /**
+     * Computes the log (base 2) of the specified long, rounding down. (E.g {@code log2(8) = 3},
+     * {@code log2(21) = 4})
+     *
+     * @param val the value
+     * @return the log base 2 of the value
+     */
+    public static int log2(long val) {
+        assert val > 0;
+        return (Long.SIZE - 1) - Long.numberOfLeadingZeros(val);
+    }
+
+    /**
+     * Narrow an integer value to a given bit width, and return the result as a signed long.
+     *
+     * @param value the value
+     * @param resultBits the result bit width
+     * @return {@code value} interpreted as {@code resultBits} bit number, encoded as signed long
+     */
+    public static long narrow(long value, int resultBits) {
+        long ret = value & mask(resultBits);
+        return signExtend(ret, resultBits);
+    }
+
+    /**
+     * Sign extend an integer.
+     *
+     * @param value the input value
+     * @param inputBits the bit width of the input value
+     * @return a signed long with the same value as the signed {@code inputBits}-bit number
+     *         {@code value}
+     */
+    public static long signExtend(long value, int inputBits) {
+        if (inputBits < 64) {
+            if ((value >>> (inputBits - 1) & 1) == 1) {
+                return value | (-1L << inputBits);
+            } else {
+                return value & ~(-1L << inputBits);
+            }
+        } else {
+            return value;
+        }
+    }
+
+    /**
+     * Zero extend an integer.
+     *
+     * @param value the input value
+     * @param inputBits the bit width of the input value
+     * @return an unsigned long with the same value as the unsigned {@code inputBits}-bit number
+     *         {@code value}
+     */
+    public static long zeroExtend(long value, int inputBits) {
+        if (inputBits < 64) {
+            return value & ~(-1L << inputBits);
+        } else {
+            return value;
+        }
+    }
+
+    /**
+     * Convert an integer to long.
+     *
+     * @param value the input value
+     * @param inputBits the bit width of the input value
+     * @param unsigned whether the values should be interpreted as signed or unsigned
+     * @return a long with the same value as the {@code inputBits}-bit number {@code value}
+     */
+    public static long convert(long value, int inputBits, boolean unsigned) {
+        if (unsigned) {
+            return zeroExtend(value, inputBits);
+        } else {
+            return signExtend(value, inputBits);
+        }
+    }
+
+    /**
+     * Get a bitmask with the low {@code bits} bit set and the high {@code 64 - bits} bit clear.
+     */
+    public static long mask(int bits) {
+        assert 0 <= bits && bits <= 64;
+        if (bits == 64) {
+            return 0xffffffffffffffffL;
+        } else {
+            return (1L << bits) - 1;
+        }
+    }
+
+    /**
+     * Get the minimum value representable in a {@code bits} bit signed integer.
+     */
+    public static long minValue(int bits) {
+        assert 0 < bits && bits <= 64;
+        return -1L << (bits - 1);
+    }
+
+    /**
+     * Get the maximum value representable in a {@code bits} bit signed integer.
+     */
+    public static long maxValue(int bits) {
+        assert 0 < bits && bits <= 64;
+        return mask(bits - 1);
+    }
+
+    /**
+     * Formats the values in a frame as a tabulated string.
+     *
+     * @param frame
+     * @return the values in {@code frame} as a tabulated string
+     */
+    public static String tabulateValues(BytecodeFrame frame) {
+        int cols = Math.max(frame.numLocals, Math.max(frame.numStack, frame.numLocks));
+        if (frame.values == null || frame.values.length == 0) {
+            assert cols == 0;
+            return null;
+        }
+        if (cols == 0) {
+            return null;
+        }
+        ArrayList<Object> cells = new ArrayList<>();
+        cells.add("");
+        for (int i = 0; i < cols; i++) {
+            cells.add(i);
+        }
+        cols++;
+        if (frame.numLocals != 0) {
+            cells.add("locals:");
+            cells.addAll(Arrays.asList(frame.values).subList(0, frame.numLocals));
+            cells.addAll(Collections.nCopies(cols - frame.numLocals - 1, ""));
+        }
+        if (frame.numStack != 0) {
+            cells.add("stack:");
+            cells.addAll(Arrays.asList(frame.values).subList(frame.numLocals, frame.numLocals + frame.numStack));
+            cells.addAll(Collections.nCopies(cols - frame.numStack - 1, ""));
+        }
+        if (frame.numLocks != 0) {
+            cells.add("locks:");
+            cells.addAll(Arrays.asList(frame.values).subList(frame.numLocals + frame.numStack, frame.values.length));
+            cells.addAll(Collections.nCopies(cols - frame.numLocks - 1, ""));
+        }
+        Object[] cellArray = cells.toArray();
+        for (int i = 0; i < cellArray.length; i++) {
+            if ((i % cols) != 0) {
+                cellArray[i] = "|" + cellArray[i];
+            }
+        }
+        return CodeUtil.tabulate(cellArray, cols, 1, 1);
+    }
+
+    /**
+     * Formats a given table as a string. The value of each cell is produced by
+     * {@link String#valueOf(Object)}.
+     *
+     * @param cells the cells of the table in row-major order
+     * @param cols the number of columns per row
+     * @param lpad the number of space padding inserted before each formatted cell value
+     * @param rpad the number of space padding inserted after each formatted cell value
+     * @return a string with one line per row and each column left-aligned
+     */
+    public static String tabulate(Object[] cells, int cols, int lpad, int rpad) {
+        int rows = (cells.length + (cols - 1)) / cols;
+        int[] colWidths = new int[cols];
+        for (int col = 0; col < cols; col++) {
+            for (int row = 0; row < rows; row++) {
+                int index = col + (row * cols);
+                if (index < cells.length) {
+                    Object cell = cells[index];
+                    colWidths[col] = Math.max(colWidths[col], String.valueOf(cell).length());
+                }
+            }
+        }
+        StringBuilder sb = new StringBuilder();
+        String nl = NEW_LINE;
+        for (int row = 0; row < rows; row++) {
+            for (int col = 0; col < cols; col++) {
+                int index = col + (row * cols);
+                if (index < cells.length) {
+                    for (int i = 0; i < lpad; i++) {
+                        sb.append(' ');
+                    }
+                    Object cell = cells[index];
+                    String s = String.valueOf(cell);
+                    int w = s.length();
+                    sb.append(s);
+                    while (w < colWidths[col]) {
+                        sb.append(' ');
+                        w++;
+                    }
+                    for (int i = 0; i < rpad; i++) {
+                        sb.append(' ');
+                    }
+                }
+            }
+            sb.append(nl);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Appends a formatted code position to a {@link StringBuilder}.
+     *
+     * @param sb the {@link StringBuilder} to append to
+     * @param pos the code position to format and append to {@code sb}
+     * @return the value of {@code sb}
+     */
+    public static StringBuilder append(StringBuilder sb, BytecodePosition pos) {
+        MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
+        if (pos.getCaller() != null) {
+            sb.append(NEW_LINE);
+            append(sb, pos.getCaller());
+        }
+        return sb;
+    }
+
+    /**
+     * Appends a formatted frame to a {@link StringBuilder}.
+     *
+     * @param sb the {@link StringBuilder} to append to
+     * @param frame the frame to format and append to {@code sb}
+     * @return the value of {@code sb}
+     */
+    public static StringBuilder append(StringBuilder sb, BytecodeFrame frame) {
+        MetaUtil.appendLocation(sb.append("at "), frame.getMethod(), frame.getBCI());
+        assert sb.charAt(sb.length() - 1) == ']';
+        sb.deleteCharAt(sb.length() - 1);
+        sb.append(", duringCall: ").append(frame.duringCall).append(", rethrow: ").append(frame.rethrowException).append(']');
+        String table = tabulateValues(frame);
+        if (table != null) {
+            sb.append(NEW_LINE);
+            String[] rows = table.split(NEW_LINE);
+            for (int i = 0; i < rows.length; i++) {
+                String row = rows[i];
+                if (!row.trim().isEmpty()) {
+                    sb.append("  ").append(row);
+                    if (i != rows.length - 1) {
+                        sb.append(NEW_LINE);
+                    }
+                }
+            }
+        }
+        if (frame.caller() != null) {
+            sb.append(NEW_LINE);
+            append(sb, frame.caller());
+        } else if (frame.getCaller() != null) {
+            sb.append(NEW_LINE);
+            append(sb, frame.getCaller());
+        }
+        return sb;
+    }
+
+    public interface RefMapFormatter {
+
+        String formatStackSlot(int frameRefMapIndex);
+    }
+
+    /**
+     * Formats a location present in a reference map.
+     */
+    public static class DefaultRefMapFormatter implements RefMapFormatter {
+
+        /**
+         * The size of a stack slot.
+         */
+        public final int slotSize;
+
+        /**
+         * The register used as the frame pointer.
+         */
+        public final Register fp;
+
+        /**
+         * The offset (in bytes) from the slot pointed to by {@link #fp} to the slot corresponding
+         * to bit 0 in the frame reference map.
+         */
+        public final int refMapToFPOffset;
+
+        public DefaultRefMapFormatter(int slotSize, Register fp, int refMapToFPOffset) {
+            this.slotSize = slotSize;
+            this.fp = fp;
+            this.refMapToFPOffset = refMapToFPOffset;
+        }
+
+        @Override
+        public String formatStackSlot(int frameRefMapIndex) {
+            int refMapOffset = frameRefMapIndex * slotSize;
+            int fpOffset = refMapOffset + refMapToFPOffset;
+            if (fpOffset >= 0) {
+                return fp + "+" + fpOffset;
+            }
+            return fp.name + fpOffset;
+        }
+    }
+
+    public static class NumberedRefMapFormatter implements RefMapFormatter {
+
+        public String formatStackSlot(int frameRefMapIndex) {
+            return "s" + frameRefMapIndex;
+        }
+
+        public String formatRegister(int regRefMapIndex) {
+            return "r" + regRefMapIndex;
+        }
+    }
+
+    /**
+     * Appends a formatted debug info to a {@link StringBuilder}.
+     *
+     * @param sb the {@link StringBuilder} to append to
+     * @param info the debug info to format and append to {@code sb}
+     * @return the value of {@code sb}
+     */
+    public static StringBuilder append(StringBuilder sb, DebugInfo info, RefMapFormatter formatterArg) {
+        RefMapFormatter formatter = formatterArg;
+        if (formatter == null) {
+            formatter = new NumberedRefMapFormatter();
+        }
+        String nl = NEW_LINE;
+        ReferenceMap refMap = info.getReferenceMap();
+        if (refMap != null) {
+            sb.append(refMap.toString());
+        }
+        RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
+        if (calleeSaveInfo != null) {
+            sb.append("callee-save-info:").append(nl);
+            Map<Integer, Register> map = calleeSaveInfo.slotsToRegisters(true);
+            for (Map.Entry<Integer, Register> e : map.entrySet()) {
+                sb.append("    ").append(e.getValue()).append(" -> ").append(formatter.formatStackSlot(e.getKey())).append(nl);
+            }
+        }
+        BytecodeFrame frame = info.frame();
+        if (frame != null) {
+            append(sb, frame);
+        } else if (info.getBytecodePosition() != null) {
+            append(sb, info.getBytecodePosition());
+        }
+        return sb;
+    }
+
+    /**
+     * Create a calling convention from a {@link ResolvedJavaMethod}.
+     */
+    public static CallingConvention getCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, ValueKindFactory<?> valueKindFactory) {
+        Signature sig = method.getSignature();
+        JavaType retType = sig.getReturnType(null);
+        int sigCount = sig.getParameterCount(false);
+        JavaType[] argTypes;
+        int argIndex = 0;
+        if (!method.isStatic()) {
+            argTypes = new JavaType[sigCount + 1];
+            argTypes[argIndex++] = method.getDeclaringClass();
+        } else {
+            argTypes = new JavaType[sigCount];
+        }
+        for (int i = 0; i < sigCount; i++) {
+            argTypes[argIndex++] = sig.getParameterType(i, null);
+        }
+
+        RegisterConfig registerConfig = codeCache.getRegisterConfig();
+        return registerConfig.getCallingConvention(type, retType, argTypes, valueKindFactory);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationRequest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Represents a request to compile a method.
+ */
+public class CompilationRequest {
+
+    private final ResolvedJavaMethod method;
+
+    private final int entryBCI;
+
+    /**
+     * Creates a request to compile a method starting at its entry point.
+     *
+     * @param method the method to be compiled
+     */
+    public CompilationRequest(ResolvedJavaMethod method) {
+        this(method, -1);
+    }
+
+    /**
+     * Creates a request to compile a method starting at a given BCI.
+     *
+     * @param method the method to be compiled
+     * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
+     *            method's entry point
+     */
+    public CompilationRequest(ResolvedJavaMethod method, int entryBCI) {
+        assert method != null;
+        this.method = method;
+        this.entryBCI = entryBCI;
+    }
+
+    /**
+     * Gets the method to be compiled.
+     */
+    public ResolvedJavaMethod getMethod() {
+        return method;
+    }
+
+    /**
+     * Gets the bytecode index (BCI) at which to start compiling where -1 denotes a non-OSR
+     * compilation request and all other values denote an on stack replacement (OSR) compilation
+     * request.
+     */
+    public int getEntryBCI() {
+        return entryBCI;
+    }
+
+    @Override
+    public String toString() {
+        return method.format("%H.%n(%p)@" + entryBCI);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationRequestResult.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Provides information about the result of a {@link CompilationRequest}.
+ */
+public interface CompilationRequestResult {
+
+    /**
+     * Determines if the compilation was successful.
+     *
+     * @return a non-null object whose {@link Object#toString()} describes the failure or null if
+     *         compilation was successful
+     */
+    Object getFailure();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CompiledCode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Marker type for an object containing the output of a compiler in a form suitable for installing
+ * into a managed code heap. Since the details of a code heap are specific to each runtime, this
+ * interface does not specify any methods.
+ */
+public interface CompiledCode {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.Objects;
+
+/**
+ * Represents the debugging information for a particular point of execution. This information
+ * includes:
+ * <ul>
+ * <li>a {@linkplain #getBytecodePosition() bytecode position}</li>
+ * <li>a reference map for registers and stack slots in the current frame</li>
+ * <li>a map from bytecode locals and operand stack slots to their values or locations from which
+ * their values can be read</li>
+ * <li>a map from the registers (in the caller's frame) to the slots where they are saved in the
+ * current frame</li>
+ * </ul>
+ */
+public final class DebugInfo {
+
+    private final BytecodePosition bytecodePosition;
+    private ReferenceMap referenceMap;
+    @SuppressWarnings("unused") private final VirtualObject[] virtualObjectMapping;
+    private RegisterSaveLayout calleeSaveInfo;
+
+    /**
+     * Creates a new {@link DebugInfo} from the given values.
+     *
+     * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame
+     *            frame} info
+     * @param virtualObjectMapping the mapping of {@link VirtualObject}s to their real values. This
+     *            array is now owned by this object and must not be mutated by the caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `virtualObjectMapping`")
+    public DebugInfo(BytecodePosition codePos, VirtualObject[] virtualObjectMapping) {
+        this.bytecodePosition = codePos;
+        this.virtualObjectMapping = virtualObjectMapping;
+    }
+
+    public DebugInfo(BytecodePosition codePos) {
+        this(codePos, null);
+    }
+
+    public void setReferenceMap(ReferenceMap referenceMap) {
+        this.referenceMap = referenceMap;
+    }
+
+    /**
+     * @return {@code true} if this debug information has a frame
+     */
+    public boolean hasFrame() {
+        return getBytecodePosition() instanceof BytecodeFrame;
+    }
+
+    /**
+     * Gets the deoptimization information for each inlined frame (if available).
+     *
+     * @return {@code null} if no frame de-opt info is {@linkplain #hasFrame() available}
+     */
+    public BytecodeFrame frame() {
+        if (hasFrame()) {
+            return (BytecodeFrame) getBytecodePosition();
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return CodeUtil.append(new StringBuilder(100), this, null).toString();
+    }
+
+    /**
+     * @return The code position (including all inlined methods) of this debug info. If this is a
+     *         {@link BytecodeFrame} instance, then it is also the deoptimization information for
+     *         each inlined frame.
+     */
+    public BytecodePosition getBytecodePosition() {
+        return bytecodePosition;
+    }
+
+    public ReferenceMap getReferenceMap() {
+        return referenceMap;
+    }
+
+    /**
+     * Sets the map from the registers (in the caller's frame) to the slots where they are saved in
+     * the current frame.
+     */
+    public void setCalleeSaveInfo(RegisterSaveLayout calleeSaveInfo) {
+        this.calleeSaveInfo = calleeSaveInfo;
+    }
+
+    /**
+     * Gets the map from the registers (in the caller's frame) to the slots where they are saved in
+     * the current frame. If no such information is available, {@code null} is returned.
+     */
+    public RegisterSaveLayout getCalleeSaveInfo() {
+        return calleeSaveInfo;
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException("hashCode");
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DebugInfo) {
+            DebugInfo that = (DebugInfo) obj;
+            if (Objects.equals(this.bytecodePosition, that.bytecodePosition) && Objects.equals(this.calleeSaveInfo, that.calleeSaveInfo) && Objects.equals(this.referenceMap, that.referenceMap)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,130 @@
+/*
+ * 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 jdk.vm.ci.code;
+
+/**
+ * Represents a compiled instance of a method. It may have been invalidated or removed in the
+ * meantime.
+ */
+public class InstalledCode {
+
+    /**
+     * Raw address address of entity representing this installed code.
+     */
+    protected long address;
+
+    /**
+     * Raw address of entryPoint of this installed code.
+     */
+    protected long entryPoint;
+
+    /**
+     * Counts how often the address field was reassigned.
+     */
+    protected long version;
+
+    protected final String name;
+
+    public InstalledCode(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return the address of entity representing this installed code.
+     */
+    public final long getAddress() {
+        return address;
+    }
+
+    /**
+     * @return the address of the normal entry point of the installed code.
+     */
+    public final long getEntryPoint() {
+        return entryPoint;
+    }
+
+    /**
+     * @return the version number of this installed code
+     */
+    public final long getVersion() {
+        return version;
+    }
+
+    /**
+     * Returns the name of this installed code.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the start address of this installed code if it is {@linkplain #isValid() valid}, 0
+     * otherwise.
+     */
+    public long getStart() {
+        return 0;
+    }
+
+    /**
+     * @return true if the code represented by this object is still valid for invocation, false
+     *         otherwise (may happen due to deopt, etc.)
+     */
+    public boolean isValid() {
+        return entryPoint != 0;
+    }
+
+    /**
+     * @return true if the code represented by this object still exists and might have live
+     *         activations, false otherwise (may happen due to deopt, etc.)
+     */
+    public boolean isAlive() {
+        return address != 0;
+    }
+
+    /**
+     * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise.
+     */
+    public byte[] getCode() {
+        return null;
+    }
+
+    /**
+     * Invalidates this installed code such that any subsequent
+     * {@linkplain #executeVarargs(Object...) invocation} will throw an
+     * {@link InvalidInstalledCodeException} and all existing invocations will be deoptimized.
+     */
+    public void invalidate() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Executes the installed code with a variable number of arguments.
+     *
+     * @param args the array of object arguments
+     * @return the value returned by the executed code
+     */
+    @SuppressWarnings("unused")
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/InvalidInstalledCodeException.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Exception thrown by the runtime in case an invalidated machine code is called.
+ */
+public final class InvalidInstalledCodeException extends Exception {
+
+    private static final long serialVersionUID = -3540232440794244844L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Represents a location where a value can be stored. This can be either a {@link Register} or a
+ * stack slot.
+ */
+public final class Location {
+
+    public final Register reg;
+    public final int offset;
+
+    private Location(Register reg, int offset) {
+        this.reg = reg;
+        this.offset = offset;
+    }
+
+    /**
+     * Create a {@link Location} for a register.
+     */
+    public static Location register(Register reg) {
+        return new Location(reg, 0);
+    }
+
+    /**
+     * Create a {@link Location} for a vector subregister.
+     *
+     * @param reg the {@link Register vector register}
+     * @param offset the offset in bytes into the vector register
+     */
+    public static Location subregister(Register reg, int offset) {
+        return new Location(reg, offset);
+    }
+
+    /**
+     * Create a {@link Location} for a stack slot.
+     */
+    public static Location stack(int offset) {
+        return new Location(null, offset);
+    }
+
+    public boolean isRegister() {
+        return reg != null;
+    }
+
+    public boolean isStack() {
+        return reg == null;
+    }
+
+    @Override
+    public String toString() {
+        String regName;
+        if (isRegister()) {
+            regName = reg.name + ":";
+        } else {
+            regName = "stack:";
+        }
+        return regName + offset;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/MemoryBarriers.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011, 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 jdk.vm.ci.code;
+
+/**
+ * Constants and intrinsic definition for memory barriers.
+ *
+ * The documentation for each constant is taken from Doug Lea's
+ * <a href="http://gee.cs.oswego.edu/dl/jmm/cookbook.html">The JSR-133 Cookbook for Compiler
+ * Writers</a>.
+ * <p>
+ * The {@code JMM_*} constants capture the memory barriers necessary to implement the Java Memory
+ * Model with respect to volatile field accesses. Their values are explained by this comment from
+ * templateTable_i486.cpp in the HotSpot source code:
+ *
+ * <pre>
+ * Volatile variables demand their effects be made known to all CPU's in
+ * order.  Store buffers on most chips allow reads &amp; writes to reorder; the
+ * JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of
+ * memory barrier (i.e., it's not sufficient that the interpreter does not
+ * reorder volatile references, the hardware also must not reorder them).
+ *
+ * According to the new Java Memory Model (JMM):
+ * (1) All volatiles are serialized wrt to each other.
+ * ALSO reads &amp; writes act as acquire &amp; release, so:
+ * (2) A read cannot let unrelated NON-volatile memory refs that happen after
+ * the read float up to before the read.  It's OK for non-volatile memory refs
+ * that happen before the volatile read to float down below it.
+ * (3) Similarly, a volatile write cannot let unrelated NON-volatile memory refs
+ * that happen BEFORE the write float down to after the write.  It's OK for
+ * non-volatile memory refs that happen after the volatile write to float up
+ * before it.
+ *
+ * We only put in barriers around volatile refs (they are expensive), not
+ * _between_ memory refs (which would require us to track the flavor of the
+ * previous memory refs).  Requirements (2) and (3) require some barriers
+ * before volatile stores and after volatile loads.  These nearly cover
+ * requirement (1) but miss the volatile-store-volatile-load case.  This final
+ * case is placed after volatile-stores although it could just as well go
+ * before volatile-loads.
+ * </pre>
+ */
+public class MemoryBarriers {
+
+    /**
+     * The sequence {@code Load1; LoadLoad; Load2} ensures that {@code Load1}'s data are loaded
+     * before data accessed by {@code Load2} and all subsequent load instructions are loaded. In
+     * general, explicit {@code LoadLoad} barriers are needed on processors that perform speculative
+     * loads and/or out-of-order processing in which waiting load instructions can bypass waiting
+     * stores. On processors that guarantee to always preserve load ordering, these barriers amount
+     * to no-ops.
+     */
+    public static final int LOAD_LOAD = 0x0001;
+
+    /**
+     * The sequence {@code Load1; LoadStore; Store2} ensures that {@code Load1}'s data are loaded
+     * before all data associated with {@code Store2} and subsequent store instructions are flushed.
+     * {@code LoadStore} barriers are needed only on those out-of-order processors in which waiting
+     * store instructions can bypass loads.
+     */
+    public static final int LOAD_STORE = 0x0002;
+
+    /**
+     * The sequence {@code Store1; StoreLoad; Load2} ensures that {@code Store1}'s data are made
+     * visible to other processors (i.e., flushed to main memory) before data accessed by
+     * {@code Load2} and all subsequent load instructions are loaded. {@code StoreLoad} barriers
+     * protect against a subsequent load incorrectly using {@code Store1}'s data value rather than
+     * that from a more recent store to the same location performed by a different processor.
+     * Because of this, on the processors discussed below, a {@code StoreLoad} is strictly necessary
+     * only for separating stores from subsequent loads of the same location(s) as were stored
+     * before the barrier. {@code StoreLoad} barriers are needed on nearly all recent
+     * multiprocessors, and are usually the most expensive kind. Part of the reason they are
+     * expensive is that they must disable mechanisms that ordinarily bypass cache to satisfy loads
+     * from write-buffers. This might be implemented by letting the buffer fully flush, among other
+     * possible stalls.
+     */
+    public static final int STORE_LOAD = 0x0004;
+
+    /**
+     * The sequence {@code Store1; StoreStore; Store2} ensures that {@code Store1}'s data are
+     * visible to other processors (i.e., flushed to memory) before the data associated with
+     * {@code Store2} and all subsequent store instructions. In general, {@code StoreStore} barriers
+     * are needed on processors that do not otherwise guarantee strict ordering of flushes from
+     * write buffers and/or caches to other processors or main memory.
+     */
+    public static final int STORE_STORE = 0x0008;
+
+    public static final int JMM_PRE_VOLATILE_WRITE = LOAD_STORE | STORE_STORE;
+    public static final int JMM_POST_VOLATILE_WRITE = STORE_LOAD | STORE_STORE;
+    public static final int JMM_PRE_VOLATILE_READ = 0;
+    public static final int JMM_POST_VOLATILE_READ = LOAD_LOAD | LOAD_STORE;
+
+    public static String barriersString(int barriers) {
+        StringBuilder sb = new StringBuilder();
+        sb.append((barriers & LOAD_LOAD) != 0 ? "LOAD_LOAD " : "");
+        sb.append((barriers & LOAD_STORE) != 0 ? "LOAD_STORE " : "");
+        sb.append((barriers & STORE_LOAD) != 0 ? "STORE_LOAD " : "");
+        sb.append((barriers & STORE_STORE) != 0 ? "STORE_STORE " : "");
+        return sb.toString().trim();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/ReferenceMap.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Marker type for an object containing information about where the object references are in machine
+ * state (e.g., registers or stack locations). This is typically associated with an execution point
+ * in compiled code.
+ */
+public abstract class ReferenceMap {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.ValueKind;
+
+/**
+ * Represents a target machine register.
+ */
+public final class Register implements Comparable<Register> {
+
+    public static final RegisterCategory SPECIAL = new RegisterCategory("SPECIAL");
+
+    /**
+     * Invalid register.
+     */
+    public static final Register None = new Register(-1, -1, "noreg", SPECIAL);
+
+    /**
+     * The identifier for this register that is unique across all the registers in a
+     * {@link Architecture}. A valid register has {@code number >= 0}.
+     */
+    public final int number;
+
+    /**
+     * The mnemonic of this register.
+     */
+    public final String name;
+
+    /**
+     * The actual encoding in a target machine instruction for this register, which may or may not
+     * be the same as {@link #number}.
+     */
+    public final int encoding;
+
+    /**
+     * The assembler calls this method to get the register's encoding.
+     */
+    public int encoding() {
+        return encoding;
+    }
+
+    /**
+     * A platform specific register category that describes which values can be stored in a
+     * register.
+     */
+    private final RegisterCategory registerCategory;
+
+    /**
+     * A platform specific register type that describes which values can be stored in a register.
+     */
+    public static class RegisterCategory {
+
+        private final String name;
+        private final boolean mayContainReference;
+
+        public RegisterCategory(String name) {
+            this(name, true);
+        }
+
+        public RegisterCategory(String name, boolean mayContainReference) {
+            this.name = name;
+            this.mayContainReference = mayContainReference;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        @Override
+        public int hashCode() {
+            return 23 + name.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof RegisterCategory) {
+                RegisterCategory that = (RegisterCategory) obj;
+                return this.name.equals(that.name);
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Creates a {@link Register} instance.
+     *
+     * @param number unique identifier for the register
+     * @param encoding the target machine encoding for the register
+     * @param name the mnemonic name for the register
+     * @param registerCategory the register category
+     */
+    public Register(int number, int encoding, String name, RegisterCategory registerCategory) {
+        this.number = number;
+        this.name = name;
+        this.registerCategory = registerCategory;
+        this.encoding = encoding;
+    }
+
+    public RegisterCategory getRegisterCategory() {
+        return registerCategory;
+    }
+
+    /**
+     * Determine whether this register needs to be part of the reference map.
+     */
+    public boolean mayContainReference() {
+        return registerCategory.mayContainReference;
+    }
+
+    /**
+     * Gets this register as a {@linkplain RegisterValue value} with a specified kind.
+     *
+     * @param kind the specified kind
+     * @return the {@link RegisterValue}
+     */
+    public RegisterValue asValue(ValueKind<?> kind) {
+        return new RegisterValue(kind, this);
+    }
+
+    /**
+     * Gets this register as a {@linkplain RegisterValue value} with no particular kind.
+     *
+     * @return a {@link RegisterValue} with {@link ValueKind#Illegal} kind.
+     */
+    public RegisterValue asValue() {
+        return asValue(ValueKind.Illegal);
+    }
+
+    /**
+     * Determines if this is a valid register.
+     *
+     * @return {@code true} iff this register is valid
+     */
+    public boolean isValid() {
+        return number >= 0;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    @Override
+    public int compareTo(Register o) {
+        if (number < o.number) {
+            return -1;
+        }
+        if (number > o.number) {
+            return 1;
+        }
+        return 0;
+    }
+
+    @Override
+    public int hashCode() {
+        return 17 + name.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Register) {
+            Register other = (Register) obj;
+            if (number == other.number) {
+                assert name.equals(other.name);
+                assert encoding == other.encoding;
+                assert registerCategory.equals(other.registerCategory);
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterArray.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * An immutable ordered list of registers. Only required because Java lacks immutable arrays.
+ */
+public final class RegisterArray implements Iterable<Register> {
+
+    private final Register[] registers;
+    private int hash;
+
+    public RegisterArray(Register... registers) {
+        this.registers = registers;
+    }
+
+    public RegisterArray(Collection<Register> registers) {
+        this.registers = registers.toArray(new Register[registers.size()]);
+    }
+
+    /**
+     * Gets the number of registers.
+     */
+    public int size() {
+        return registers.length;
+    }
+
+    /**
+     * Gets the register at a given index.
+     *
+     * @param index the index of the register to retrieve
+     */
+    public Register get(int index) {
+        return registers[index];
+    }
+
+    public void addTo(Collection<Register> collection) {
+        collection.addAll(Arrays.asList(registers));
+    }
+
+    /**
+     * Gets an immutable view of the registers as a list.
+     */
+    public List<Register> asList() {
+        return Collections.unmodifiableList(Arrays.asList(registers));
+    }
+
+    /**
+     * Gets a copy of the registers as an array.
+     */
+    public Register[] toArray() {
+        return registers.clone();
+    }
+
+    public Iterator<Register> iterator() {
+        return Arrays.asList(registers).iterator();
+    }
+
+    @Override
+    public int hashCode() {
+        if (hash == 0 && registers.length > 0) {
+            hash = Arrays.hashCode(registers);
+        }
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof RegisterArray) {
+            return Arrays.equals(registers, ((RegisterArray) obj).registers);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(registers);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2010, 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 jdk.vm.ci.code;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A collection of register attributes. The specific attribute values for a register may be local to
+ * a compilation context. For example, a {@link RegisterConfig} in use during a compilation will
+ * determine which registers are callee saved.
+ */
+public class RegisterAttributes {
+
+    private final boolean callerSave;
+    private final boolean calleeSave;
+    private final boolean allocatable;
+
+    public RegisterAttributes(boolean isCallerSave, boolean isCalleeSave, boolean isAllocatable) {
+        this.callerSave = isCallerSave;
+        this.calleeSave = isCalleeSave;
+        this.allocatable = isAllocatable;
+    }
+
+    public static final RegisterAttributes NONE = new RegisterAttributes(false, false, false);
+
+    /**
+     * Creates a map from register {@linkplain Register#number numbers} to register
+     * {@linkplain RegisterAttributes attributes} for a given register configuration and set of
+     * registers.
+     *
+     * @param registerConfig a register configuration
+     * @param registers a set of registers
+     * @return an array whose length is the max register number in {@code registers} plus 1. An
+     *         element at index i holds the attributes of the register whose number is i.
+     */
+    public static RegisterAttributes[] createMap(RegisterConfig registerConfig, RegisterArray registers) {
+        RegisterAttributes[] map = new RegisterAttributes[registers.size()];
+        List<Register> callerSaveRegisters = registerConfig.getCallerSaveRegisters().asList();
+        List<Register> calleeSaveRegisters = registerConfig.getCalleeSaveRegisters() == null ? Collections.emptyList() : registerConfig.getCalleeSaveRegisters().asList();
+        List<Register> allocatableRegisters = registerConfig.getAllocatableRegisters().asList();
+        for (Register reg : registers) {
+            if (reg != null) {
+                RegisterAttributes attr = new RegisterAttributes(callerSaveRegisters.contains(reg), calleeSaveRegisters.contains(reg), allocatableRegisters.contains(reg));
+                if (map.length <= reg.number) {
+                    map = Arrays.copyOf(map, reg.number + 1);
+                }
+                map[reg.number] = attr;
+            }
+        }
+        for (int i = 0; i < map.length; i++) {
+            if (map[i] == null) {
+                map[i] = NONE;
+            }
+        }
+        return map;
+    }
+
+    /**
+     * @return {@code true} if a register is available for use by a register allocator otherwise
+     *         {@code false}
+     */
+    public boolean isAllocatable() {
+        return allocatable;
+    }
+
+    /**
+     * @return {@code true} if a register whose value preservation (if required) across a call is
+     *         the responsibility of the callee otherwise {@code false}
+     */
+    public boolean isCalleeSave() {
+        return calleeSave;
+    }
+
+    /**
+     * @return {@code true} if a register whose value preservation (if required) across a call is
+     *         the responsibility of the caller otherwise {@code false}
+     */
+    public boolean isCallerSave() {
+        return callerSave;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.code.CallingConvention.Type;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.ValueKind;
+
+/**
+ * A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical
+ * registers.
+ */
+public interface RegisterConfig {
+
+    /**
+     * Gets the register to be used for returning a value of a given kind.
+     */
+    Register getReturnRegister(JavaKind kind);
+
+    /**
+     * Gets the maximum allowed size of the frame.
+     */
+    default int getMaximumFrameSize() {
+        return Integer.MAX_VALUE;
+    }
+
+    /**
+     * Gets the register used as the frame pointer. Spill slots and outgoing stack-based arguments
+     * are addressed relative to this register.
+     */
+    Register getFrameRegister();
+
+    /**
+     * Gets the calling convention describing how arguments are passed.
+     *
+     * @param type the type of calling convention being requested
+     * @param returnType the return type (can be null for methods returning {@code void})
+     * @param parameterTypes the types of the arguments of the call
+     * @param valueKindFactory the factory to create custom {@link ValueKind ValueKinds}
+     */
+    CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory);
+
+    /**
+     * Gets the ordered set of registers that are can be used to pass parameters according to a
+     * given calling convention.
+     *
+     * @param type the type of calling convention
+     * @param kind specifies what kind of registers is being requested
+     * @return the ordered set of registers that may be used to pass parameters in a call conforming
+     *         to {@code type}
+     */
+    RegisterArray getCallingConventionRegisters(Type type, JavaKind kind);
+
+    /**
+     * Gets the set of all registers that might be used by the register allocator.
+     *
+     * To get the set of registers the register allocator is allowed to use see
+     * {@link RegisterAllocationConfig#getAllocatableRegisters()}
+     */
+    @SuppressWarnings("javadoc")
+    RegisterArray getAllocatableRegisters();
+
+    /**
+     * Filters a set of registers and returns only those that can be used by the register allocator
+     * for a value of a particular kind.
+     */
+    RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers);
+
+    /**
+     * Gets the registers whose values must be preserved by a method across any call it makes.
+     */
+    RegisterArray getCallerSaveRegisters();
+
+    /**
+     * Gets the registers whose values must be preserved by the callee.
+     */
+    RegisterArray getCalleeSaveRegisters();
+
+    /**
+     * Gets a map from register {@linkplain Register#number numbers} to register
+     * {@linkplain RegisterAttributes attributes} for this register configuration.
+     *
+     * @return an array where an element at index i holds the attributes of the register whose
+     *         number is i
+     */
+    RegisterAttributes[] getAttributesMap();
+
+    /**
+     * Determines if all {@link #getAllocatableRegisters() allocatable} registers are
+     * {@link #getCallerSaveRegisters() caller saved}.
+     */
+    boolean areAllAllocatableRegistersCallerSaved();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * A map from registers to frame slots. This can be used to describe where callee saved registers
+ * are saved in a callee's frame.
+ */
+public final class RegisterSaveLayout {
+
+    /**
+     * Keys.
+     */
+    private final Register[] registers;
+
+    /**
+     * Slot indexes relative to stack pointer.
+     */
+    private final int[] slots;
+
+    /**
+     * Creates a map from registers to frame slots.
+     *
+     * @param registers the keys in the map
+     * @param slots frame slot index for each register in {@code registers}
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `registers` and `slots`")
+    public RegisterSaveLayout(Register[] registers, int[] slots) {
+        assert registers.length == slots.length;
+        this.registers = registers;
+        this.slots = slots;
+        assert registersToSlots(false).size() == registers.length : "non-unique registers";
+        assert new HashSet<>(registersToSlots(false).values()).size() == slots.length : "non-unqiue slots";
+    }
+
+    /**
+     * Gets the frame slot index for a given register.
+     *
+     * @param register register to get the frame slot index for
+     * @return frame slot index
+     */
+    public int registerToSlot(Register register) {
+        for (int i = 0; i < registers.length; i++) {
+            if (register.equals(registers[i])) {
+                return slots[i];
+            }
+        }
+        throw new IllegalArgumentException(register + " not saved by this layout: " + this);
+    }
+
+    /**
+     * Gets this layout information as a {@link Map} from registers to slots.
+     */
+    public Map<Register, Integer> registersToSlots(boolean sorted) {
+        Map<Register, Integer> result;
+        if (sorted) {
+            result = new TreeMap<>();
+        } else {
+            result = new HashMap<>();
+        }
+        for (int i = 0; i < registers.length; i++) {
+            result.put(registers[i], slots[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Gets this layout information as a {@link Map} from slots to registers.
+     */
+    public Map<Integer, Register> slotsToRegisters(boolean sorted) {
+        Map<Integer, Register> result;
+        if (sorted) {
+            result = new TreeMap<>();
+        } else {
+            result = new HashMap<>();
+        }
+        for (int i = 0; i < registers.length; i++) {
+            result.put(slots[i], registers[i]);
+        }
+        return result;
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof RegisterSaveLayout) {
+            RegisterSaveLayout that = (RegisterSaveLayout) obj;
+            if (Arrays.equals(registers, that.registers) && Arrays.equals(slots, that.slots)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return registersToSlots(true).toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.ValueKind;
+
+/**
+ * Denotes a register that stores a value of a fixed kind.
+ */
+public final class RegisterValue extends AllocatableValue {
+
+    private final Register reg;
+
+    protected RegisterValue(ValueKind<?> kind, Register register) {
+        super(kind);
+        this.reg = register;
+    }
+
+    @Override
+    public String toString() {
+        return getRegister().name + getKindSuffix();
+    }
+
+    /**
+     * @return the register that contains the value
+     */
+    public Register getRegister() {
+        return reg;
+    }
+
+    @Override
+    public int hashCode() {
+        return 29 * super.hashCode() + reg.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof RegisterValue) {
+            RegisterValue other = (RegisterValue) obj;
+            return super.equals(obj) && reg.equals(other.reg);
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.Value;
+
+/**
+ * Represents lock information in the debug information.
+ */
+public final class StackLockValue implements JavaValue {
+
+    private JavaValue owner;
+    private AllocatableValue slot;
+    private final boolean eliminated;
+
+    public StackLockValue(JavaValue object, AllocatableValue slot, boolean eliminated) {
+        this.owner = object;
+        this.slot = slot;
+        this.eliminated = eliminated;
+    }
+
+    public JavaValue getOwner() {
+        return owner;
+    }
+
+    public void setOwner(JavaValue newOwner) {
+        this.owner = newOwner;
+    }
+
+    public Value getSlot() {
+        return slot;
+    }
+
+    public boolean isEliminated() {
+        return eliminated;
+    }
+
+    @Override
+    public String toString() {
+        return "monitor[" + owner + (slot != null ? ", " + slot : "") + (eliminated ? ", eliminated" : "") + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 43;
+        int result = super.hashCode();
+        result = prime * result + (eliminated ? 1231 : 1237);
+        result = prime * result + owner.hashCode();
+        result = prime * result + slot.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof StackLockValue) {
+            StackLockValue other = (StackLockValue) obj;
+            return super.equals(obj) && eliminated == other.eliminated && owner.equals(other.owner) && slot.equals(other.slot);
+        }
+        return false;
+    }
+
+    public void setSlot(AllocatableValue stackSlot) {
+        slot = stackSlot;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.ValueKind;
+
+/**
+ * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an
+ * incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}.
+ */
+public final class StackSlot extends AllocatableValue {
+
+    private final int offset;
+    private final boolean addFrameSize;
+
+    /**
+     * Gets a {@link StackSlot} instance representing a stack slot at a given index holding a value
+     * of a given kind.
+     *
+     * @param kind The kind of the value stored in the stack slot.
+     * @param offset The offset of the stack slot (in bytes)
+     * @param addFrameSize Specifies if the offset is relative to the stack pointer, or the
+     *            beginning of the frame (stack pointer + total frame size).
+     */
+    public static StackSlot get(ValueKind<?> kind, int offset, boolean addFrameSize) {
+        assert addFrameSize || offset >= 0;
+        return new StackSlot(kind, offset, addFrameSize);
+    }
+
+    /**
+     * Private constructor to enforce use of {@link #get(ValueKind, int, boolean)} so that a cache
+     * can be used.
+     */
+    private StackSlot(ValueKind<?> kind, int offset, boolean addFrameSize) {
+        super(kind);
+        this.offset = offset;
+        this.addFrameSize = addFrameSize;
+    }
+
+    /**
+     * Gets the offset of this stack slot, relative to the stack pointer.
+     *
+     * @return The offset of this slot (in bytes).
+     */
+    public int getOffset(int totalFrameSize) {
+        assert totalFrameSize > 0 || !addFrameSize;
+        int result = offset + (addFrameSize ? totalFrameSize : 0);
+        assert result >= 0;
+        return result;
+    }
+
+    public boolean isInCallerFrame() {
+        return addFrameSize && offset >= 0;
+    }
+
+    public int getRawOffset() {
+        return offset;
+    }
+
+    public boolean getRawAddFrameSize() {
+        return addFrameSize;
+    }
+
+    @Override
+    public String toString() {
+        if (!addFrameSize) {
+            return "out:" + offset + getKindSuffix();
+        } else if (offset >= 0) {
+            return "in:" + offset + getKindSuffix();
+        } else {
+            return "stack:" + (-offset) + getKindSuffix();
+        }
+    }
+
+    /**
+     * Gets this stack slot used to pass an argument from the perspective of a caller.
+     */
+    public StackSlot asOutArg() {
+        assert offset >= 0;
+        if (addFrameSize) {
+            return get(getValueKind(), offset, false);
+        }
+        return this;
+    }
+
+    /**
+     * Gets this stack slot used to pass an argument from the perspective of a callee.
+     */
+    public StackSlot asInArg() {
+        assert offset >= 0;
+        if (!addFrameSize) {
+            return get(getValueKind(), offset, true);
+        }
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 37;
+        int result = super.hashCode();
+        result = prime * result + (addFrameSize ? 1231 : 1237);
+        result = prime * result + offset;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof StackSlot) {
+            StackSlot other = (StackSlot) obj;
+            return super.equals(obj) && addFrameSize == other.addFrameSize && offset == other.offset;
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/SuppressFBWarnings.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+@interface SuppressFBWarnings {
+    /**
+     * The set of FindBugs
+     * <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+     * suppressed in annotated element. The value can be a bug category, kind or pattern.
+     */
+    String[] value();
+
+    /**
+     * Reason why the warning is suppressed.
+     */
+    String justification();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
+
+import jdk.vm.ci.meta.JavaKind;
+
+/**
+ * Represents the target machine for a compiler, including the CPU architecture, the size of
+ * pointers and references, alignment of stacks, caches, etc.
+ */
+public class TargetDescription {
+
+    public final Architecture arch;
+
+    /**
+     * Specifies if this is a multi-processor system.
+     */
+    public final boolean isMP;
+
+    /**
+     * Specifies if this target supports encoding objects inline in the machine code.
+     */
+    public final boolean inlineObjects;
+
+    /**
+     * The machine word size on this target.
+     */
+    public final int wordSize;
+
+    /**
+     * The {@link JavaKind} to be used for representing raw pointers and CPU registers in Java code.
+     */
+    public final JavaKind wordJavaKind;
+
+    /**
+     * The stack alignment requirement of the platform. For example, from Appendix D of
+     * <a href="http://www.intel.com/Assets/PDF/manual/248966.pdf">Intel 64 and IA-32 Architectures
+     * Optimization Reference Manual</a>:
+     *
+     * <pre>
+     *     "It is important to ensure that the stack frame is aligned to a
+     *      16-byte boundary upon function entry to keep local __m128 data,
+     *      parameters, and XMM register spill locations aligned throughout
+     *      a function invocation."
+     * </pre>
+     */
+    public final int stackAlignment;
+
+    /**
+     * Maximum constant displacement at which a memory access can no longer be an implicit null
+     * check.
+     */
+    public final int implicitNullCheckLimit;
+
+    public TargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects) {
+        this.arch = arch;
+        this.isMP = isMP;
+        this.wordSize = arch.getWordSize();
+        this.wordJavaKind = JavaKind.fromWordSize(wordSize);
+        this.stackAlignment = stackAlignment;
+        this.implicitNullCheckLimit = implicitNullCheckLimit;
+        this.inlineObjects = inlineObjects;
+
+        assert arch.getPlatformKind(wordJavaKind).equals(arch.getWordKind());
+    }
+
+    @Override
+    public final int hashCode() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof TargetDescription) {
+            TargetDescription that = (TargetDescription) obj;
+            // @formatter:off
+            if (this.implicitNullCheckLimit == that.implicitNullCheckLimit &&
+                this.inlineObjects == that.inlineObjects &&
+                this.isMP == that.isMP &&
+                this.stackAlignment == that.stackAlignment &&
+                this.wordJavaKind.equals(that.wordJavaKind) &&
+                this.wordSize == that.wordSize &&
+                this.arch.equals(that.arch)) {
+                return true;
+            }
+            // @formatter:on
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return identityHashCodeString(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueKindFactory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ValueKind;
+
+/**
+ * Can be implemented by compilers to create custom {@link ValueKind} subclasses.
+ */
+public interface ValueKindFactory<K extends ValueKind<K>> {
+
+    K getValueKind(JavaKind javaKind);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.Value;
+
+/**
+ * Utility class for working with the {@link Value} class and its subclasses.
+ */
+public final class ValueUtil {
+
+    public static boolean isIllegal(Value value) {
+        assert value != null;
+        return Value.ILLEGAL.equals(value);
+    }
+
+    public static boolean isIllegalJavaValue(JavaValue value) {
+        assert value != null;
+        return Value.ILLEGAL.equals(value);
+    }
+
+    public static boolean isLegal(Value value) {
+        return !isIllegal(value);
+    }
+
+    public static boolean isVirtualObject(JavaValue value) {
+        assert value != null;
+        return value instanceof VirtualObject;
+    }
+
+    public static VirtualObject asVirtualObject(JavaValue value) {
+        assert value != null;
+        return (VirtualObject) value;
+    }
+
+    public static boolean isConstantJavaValue(JavaValue value) {
+        assert value != null;
+        return value instanceof JavaConstant;
+    }
+
+    public static JavaConstant asConstantJavaValue(JavaValue value) {
+        assert value != null;
+        return (JavaConstant) value;
+    }
+
+    public static boolean isAllocatableValue(Value value) {
+        assert value != null;
+        return value instanceof AllocatableValue;
+    }
+
+    public static AllocatableValue asAllocatableValue(Value value) {
+        assert value != null;
+        return (AllocatableValue) value;
+    }
+
+    public static boolean isStackSlot(Value value) {
+        assert value != null;
+        return value instanceof StackSlot;
+    }
+
+    public static StackSlot asStackSlot(Value value) {
+        assert value != null;
+        return (StackSlot) value;
+    }
+
+    public static boolean isRegister(Value value) {
+        assert value != null;
+        return value instanceof RegisterValue;
+    }
+
+    public static Register asRegister(Value value) {
+        return asRegisterValue(value).getRegister();
+    }
+
+    public static RegisterValue asRegisterValue(Value value) {
+        assert value != null;
+        return (RegisterValue) value;
+    }
+
+    public static Register asRegister(Value value, PlatformKind kind) {
+        if (value.getPlatformKind() != kind) {
+            throw new InternalError("needed: " + kind + " got: " + value.getPlatformKind());
+        } else {
+            return asRegister(value);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Set;
+
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * An instance of this class represents an object whose allocation was removed by escape analysis.
+ * The information stored in the {@link VirtualObject} is used during deoptimization to recreate the
+ * object.
+ */
+public final class VirtualObject implements JavaValue {
+
+    private final ResolvedJavaType type;
+    private JavaValue[] values;
+    private JavaKind[] slotKinds;
+    private final int id;
+
+    /**
+     * Creates a new {@link VirtualObject} for the given type, with the given fields. If
+     * {@code type} is an instance class then {@code values} provides the values for the fields
+     * returned by {@link ResolvedJavaType#getInstanceFields(boolean) getInstanceFields(true)}. If
+     * {@code type} is an array then the length of the values array determines the reallocated array
+     * length.
+     *
+     * @param type the type of the object whose allocation was removed during compilation. This can
+     *            be either an instance of an array type.
+     * @param id a unique id that identifies the object within the debug information for one
+     *            position in the compiled code.
+     * @return a new {@link VirtualObject} instance.
+     */
+    public static VirtualObject get(ResolvedJavaType type, int id) {
+        return new VirtualObject(type, id);
+    }
+
+    private VirtualObject(ResolvedJavaType type, int id) {
+        this.type = type;
+        this.id = id;
+    }
+
+    private static StringBuilder appendValue(StringBuilder buf, JavaValue value, Set<VirtualObject> visited) {
+        if (value instanceof VirtualObject) {
+            VirtualObject vo = (VirtualObject) value;
+            buf.append("vobject:").append(vo.type.toJavaName(false)).append(':').append(vo.id);
+            if (!visited.contains(vo)) {
+                visited.add(vo);
+                buf.append('{');
+                if (vo.values == null) {
+                    buf.append("<uninitialized>");
+                } else {
+                    if (vo.type.isArray()) {
+                        for (int i = 0; i < vo.values.length; i++) {
+                            if (i != 0) {
+                                buf.append(',');
+                            }
+                            buf.append(i).append('=');
+                            appendValue(buf, vo.values[i], visited);
+                        }
+                    } else {
+                        ResolvedJavaField[] fields = vo.type.getInstanceFields(true);
+                        assert fields.length == vo.values.length : vo.type + ", fields=" + Arrays.toString(fields) + ", values=" + Arrays.toString(vo.values);
+                        for (int i = 0; i < vo.values.length; i++) {
+                            if (i != 0) {
+                                buf.append(',');
+                            }
+                            buf.append(fields[i].getName()).append('=');
+                            appendValue(buf, vo.values[i], visited);
+                        }
+                    }
+                }
+                buf.append('}');
+            }
+        } else {
+            buf.append(value);
+        }
+        return buf;
+    }
+
+    @Override
+    public String toString() {
+        Set<VirtualObject> visited = Collections.newSetFromMap(new IdentityHashMap<VirtualObject, Boolean>());
+        return appendValue(new StringBuilder(), this, visited).toString();
+    }
+
+    /**
+     * Returns the type of the object whose allocation was removed during compilation. This can be
+     * either an instance of an array type.
+     */
+    public ResolvedJavaType getType() {
+        return type;
+    }
+
+    /**
+     * Returns the array containing all the values to be stored into the object when it is
+     * recreated. This field is intentional exposed as a mutable array that a compiler may modify
+     * (e.g. during register allocation).
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "`values` is intentional mutable")//
+    public JavaValue[] getValues() {
+        return values;
+    }
+
+    /**
+     * Returns the kind of the value at {@code index}.
+     */
+    public JavaKind getSlotKind(int index) {
+        return slotKinds[index];
+    }
+
+    /**
+     * Returns the unique id that identifies the object within the debug information for one
+     * position in the compiled code.
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * Overwrites the current set of values with a new one.
+     *
+     * @param values an array containing all the values to be stored into the object when it is
+     *            recreated.
+     * @param slotKinds an array containing the Java kinds of the values. This must have the same
+     *            length as {@code values}. This array is now owned by this object and must not be
+     *            mutated by the caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `slotKinds`")
+    public void setValues(JavaValue[] values, JavaKind[] slotKinds) {
+        assert values.length == slotKinds.length;
+        this.values = values;
+        this.slotKinds = slotKinds;
+    }
+
+    @Override
+    public int hashCode() {
+        return 42 + type.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o instanceof VirtualObject) {
+            VirtualObject l = (VirtualObject) o;
+            if (!l.type.equals(type) || l.values.length != values.length) {
+                return false;
+            }
+            for (int i = 0; i < values.length; i++) {
+                /*
+                 * Virtual objects can form cycles. Calling equals() could therefore lead to
+                 * infinite recursion.
+                 */
+                if (!same(values[i], l.values[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean same(Object o1, Object o2) {
+        return o1 == o2;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/**
+ * Package that defines the interface between a Java application that wants to install code and the
+ * runtime. The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider}
+ * interface. The method
+ * {@link jdk.vm.ci.code.CodeCacheProvider#addCode(jdk.vm.ci.meta.ResolvedJavaMethod, CompiledCode, jdk.vm.ci.meta.SpeculationLog, InstalledCode)}
+ * can be used to install code.
+ */
+package jdk.vm.ci.code;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/Call.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+import java.util.Objects;
+
+import jdk.vm.ci.code.DebugInfo;
+import jdk.vm.ci.meta.InvokeTarget;
+
+/**
+ * Represents a call in the code.
+ */
+public final class Call extends Infopoint {
+
+    /**
+     * The target of the call.
+     */
+    public final InvokeTarget target;
+
+    /**
+     * The size of the call instruction.
+     */
+    public final int size;
+
+    /**
+     * Specifies if this call is direct or indirect. A direct call has an immediate operand encoding
+     * the absolute or relative (to the call itself) address of the target. An indirect call has a
+     * register or memory operand specifying the target address of the call.
+     */
+    public final boolean direct;
+
+    public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) {
+        super(pcOffset, debugInfo, InfopointReason.CALL);
+        this.size = size;
+        this.target = target;
+        this.direct = direct;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof Call && super.equals(obj)) {
+            Call that = (Call) obj;
+            if (this.size == that.size && this.direct == that.direct && Objects.equals(this.target, that.target)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(pcOffset);
+        sb.append('[');
+        sb.append(target);
+        sb.append(']');
+
+        if (debugInfo != null) {
+            appendDebugInfo(sb, debugInfo);
+        }
+
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/ConstantReference.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+import java.util.Objects;
+
+import jdk.vm.ci.meta.VMConstant;
+
+/**
+ * Represents an embedded {@link VMConstant} in the code or data section that needs to be
+ * {@link DataPatch patched} by the VM (e.g. an embedded pointer to a Java object).
+ */
+public final class ConstantReference extends Reference {
+
+    private final VMConstant constant;
+
+    public ConstantReference(VMConstant constant) {
+        this.constant = constant;
+    }
+
+    public VMConstant getConstant() {
+        return constant;
+    }
+
+    @Override
+    public String toString() {
+        return constant.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return constant.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ConstantReference) {
+            ConstantReference that = (ConstantReference) obj;
+            return Objects.equals(this.constant, that.constant);
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/DataPatch.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+import java.util.Objects;
+
+import jdk.vm.ci.meta.VMConstant;
+
+/**
+ * Represents a code site that references some data. The associated data can be either a
+ * {@link DataSectionReference reference} to the data section, or it may be an inlined
+ * {@link VMConstant} that needs to be patched.
+ */
+public final class DataPatch extends Site {
+
+    public Reference reference;
+    public Object note;
+
+    public DataPatch(int pcOffset, Reference reference) {
+        super(pcOffset);
+        this.reference = reference;
+        this.note = null;
+    }
+
+    public DataPatch(int pcOffset, Reference reference, Object note) {
+        super(pcOffset);
+        this.reference = reference;
+        this.note = note;
+    }
+
+    @Override
+    public String toString() {
+        if (note != null) {
+            return String.format("%d[<data patch referring to %s>, note: %s]", pcOffset, reference.toString(), note.toString());
+        } else {
+            return String.format("%d[<data patch referring to %s>]", pcOffset, reference.toString());
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DataPatch) {
+            DataPatch that = (DataPatch) obj;
+            if (this.pcOffset == that.pcOffset && Objects.equals(this.reference, that.reference) && Objects.equals(this.note, that.note)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/DataSectionReference.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+/**
+ * Represents a pointer to some location in the data section that should be {@link DataPatch
+ * patched} into the code.
+ */
+public final class DataSectionReference extends Reference {
+
+    private boolean initialized;
+    private int offset;
+
+    public DataSectionReference() {
+        // will be set after the data section layout is fixed
+        offset = 0xDEADDEAD;
+    }
+
+    public int getOffset() {
+        assert initialized;
+
+        return offset;
+    }
+
+    public void setOffset(int offset) {
+        assert !initialized;
+        initialized = true;
+
+        this.offset = offset;
+    }
+
+    @Override
+    public int hashCode() {
+        return offset;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DataSectionReference) {
+            DataSectionReference that = (DataSectionReference) obj;
+            return this.offset == that.offset;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        if (initialized) {
+            return String.format("DataSection[0x%x]", offset);
+        } else {
+            return "DataSection[?]";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/ExceptionHandler.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+/**
+ * Represents exception handler information for a specific code position. It includes the catch code
+ * position as well as the caught exception type.
+ */
+public final class ExceptionHandler extends Site {
+
+    public final int handlerPos;
+
+    public ExceptionHandler(int pcOffset, int handlerPos) {
+        super(pcOffset);
+        this.handlerPos = handlerPos;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%d[<exception edge to %d>]", pcOffset, handlerPos);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ExceptionHandler) {
+            ExceptionHandler that = (ExceptionHandler) obj;
+            if (this.pcOffset == that.pcOffset && this.handlerPos == that.handlerPos) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/Infopoint.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+import java.util.Map;
+import java.util.Objects;
+
+import jdk.vm.ci.code.BytecodePosition;
+import jdk.vm.ci.code.DebugInfo;
+import jdk.vm.ci.code.ReferenceMap;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterSaveLayout;
+import jdk.vm.ci.meta.MetaUtil;
+
+/**
+ * Represents an infopoint with associated debug info. Note that safepoints are also infopoints.
+ */
+public class Infopoint extends Site implements Comparable<Infopoint> {
+
+    public final DebugInfo debugInfo;
+
+    public final InfopointReason reason;
+
+    public Infopoint(int pcOffset, DebugInfo debugInfo, InfopointReason reason) {
+        super(pcOffset);
+        this.debugInfo = debugInfo;
+        this.reason = reason;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(pcOffset);
+        sb.append("[<infopoint>]");
+        appendDebugInfo(sb, debugInfo);
+        return sb.toString();
+    }
+
+    @Override
+    public int compareTo(Infopoint o) {
+        if (pcOffset < o.pcOffset) {
+            return -1;
+        } else if (pcOffset > o.pcOffset) {
+            return 1;
+        }
+        return this.reason.compareTo(o.reason);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj != null && obj.getClass() == getClass()) {
+            Infopoint that = (Infopoint) obj;
+            if (this.pcOffset == that.pcOffset && Objects.equals(this.debugInfo, that.debugInfo) && Objects.equals(this.reason, that.reason)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected static void appendDebugInfo(StringBuilder sb, DebugInfo info) {
+        if (info != null) {
+            ReferenceMap refMap = info.getReferenceMap();
+            if (refMap != null) {
+                sb.append(refMap.toString());
+                sb.append(']');
+            }
+            RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
+            if (calleeSaveInfo != null) {
+                sb.append(" callee-save-info[");
+                String sep = "";
+                for (Map.Entry<Register, Integer> e : calleeSaveInfo.registersToSlots(true).entrySet()) {
+                    sb.append(sep).append(e.getKey()).append("->").append(e.getValue());
+                    sep = ", ";
+                }
+                sb.append(']');
+            }
+            BytecodePosition codePos = info.getBytecodePosition();
+            if (codePos != null) {
+                MetaUtil.appendLocation(sb.append(" "), codePos.getMethod(), codePos.getBCI());
+                if (info.hasFrame()) {
+                    sb.append(" #locals=").append(info.frame().numLocals).append(" #expr=").append(info.frame().numStack);
+                    if (info.frame().numLocks > 0) {
+                        sb.append(" #locks=").append(info.frame().numLocks);
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/InfopointReason.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+/**
+ * A reason for infopoint insertion.
+ */
+public enum InfopointReason {
+
+    SAFEPOINT,
+    CALL,
+    IMPLICIT_EXCEPTION,
+    METHOD_START,
+    METHOD_END,
+    BYTECODE_POSITION;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/Mark.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+import java.util.Objects;
+
+/**
+ * Associates arbitrary information with a position in machine code. For example, HotSpot specific
+ * code in a compiler backend may use this to denote the position of a safepoint, exception handler
+ * entry point, verified entry point etc.
+ */
+public final class Mark extends Site {
+
+    /**
+     * An object denoting extra semantic information about the machine code position of this mark.
+     */
+    public final Object id;
+
+    /**
+     * Creates a mark that associates {@code id} with the machine code position {@code pcOffset}.
+     *
+     * @param pcOffset
+     * @param id
+     */
+    public Mark(int pcOffset, Object id) {
+        super(pcOffset);
+        this.id = id;
+    }
+
+    @Override
+    public String toString() {
+        if (id == null) {
+            return String.format("%d[<mark>]", pcOffset);
+        } else if (id instanceof Integer) {
+            return String.format("%d[<mark with id %s>]", pcOffset, Integer.toHexString((Integer) id));
+        } else {
+            return String.format("%d[<mark with id %s>]", pcOffset, id.toString());
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof Mark) {
+            Mark that = (Mark) obj;
+            if (this.pcOffset == that.pcOffset && Objects.equals(this.id, that.id)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/Reference.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+/**
+ * Represents some external data that is referenced by the code.
+ */
+public abstract class Reference {
+
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public abstract boolean equals(Object obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/site/Site.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.site;
+
+import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
+
+/**
+ * Represents a code position with associated additional information.
+ */
+public abstract class Site {
+
+    /**
+     * The position (or offset) of this site with respect to the start of the target method.
+     */
+    public final int pcOffset;
+
+    public Site(int pos) {
+        this.pcOffset = pos;
+    }
+
+    @Override
+    public final int hashCode() {
+        throw new UnsupportedOperationException("hashCode");
+    }
+
+    @Override
+    public String toString() {
+        return identityHashCodeString(this);
+    }
+
+    @Override
+    public abstract boolean equals(Object obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.stack;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Access to the object variables in a stack frame.
+ */
+public interface InspectedFrame {
+
+    /**
+     * Returns the value of the object local at {@code index}. This value is a copy iff
+     * {@link #isVirtual(int)} is true.
+     */
+    Object getLocal(int index);
+
+    /**
+     * Returns whether the local at {@code index} is a virtual object, and therefore the object
+     * returned by {@link #getLocal(int)} is a copy.
+     */
+    boolean isVirtual(int index);
+
+    /**
+     * Returns true if the stack frame is a compiled stack frame and there are virtual objects
+     * anywhere in the current state of the compiled method. This can return true even if
+     * {@link #isVirtual(int)} return false for all locals.
+     */
+    boolean hasVirtualObjects();
+
+    /**
+     * This method will materialize all virtual objects, deoptimize the stack frame and make sure
+     * that subsequent execution of the deoptimized frame uses the materialized values.
+     */
+    void materializeVirtualObjects(boolean invalidateCode);
+
+    /**
+     * @return the current bytecode index
+     */
+    int getBytecodeIndex();
+
+    /**
+     * @return the current method
+     */
+    ResolvedJavaMethod getMethod();
+
+    /**
+     * Checks if the current method is equal to the given method. This is semantically equivalent to
+     * {@code method.equals(getMethod())}, but can be implemented more efficiently.
+     */
+    boolean isMethod(ResolvedJavaMethod method);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrameVisitor.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.stack;
+
+/**
+ * Callback interface for {@link StackIntrospection#iterateFrames}. Implementations of
+ * {@link #visitFrame} return null to indicate that frame iteration should continue and the next
+ * caller frame should be visited; and return any non-null value to indicate that frame iteration
+ * should stop.
+ */
+public interface InspectedFrameVisitor<T> {
+
+    T visitFrame(InspectedFrame frame);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code.stack;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public interface StackIntrospection {
+
+    /**
+     * Accesses the current stack, providing {@link InspectedFrame}s to the visitor that can be used
+     * to inspect the stack frames' contents. Iteration continues as long as
+     * {@link InspectedFrameVisitor#visitFrame}, which is invoked for every {@link InspectedFrame},
+     * returns null. Any non-null result of the visitor indicates that frame iteration should stop.
+     *
+     * @param initialMethods if this is non-{@code null}, then the stack trace will start at these
+     *            methods
+     * @param matchingMethods if this is non-{@code null}, then only matching stack frames are
+     *            returned
+     * @param initialSkip the number of matching methods to skip (including the initial method)
+     * @param visitor the visitor that is called for every matching method
+     * @return the last result returned by the visitor (which is non-null to indicate that iteration
+     *         should stop), or null if the whole stack was iterated.
+     */
+    <T> T iterateFrames(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip, InspectedFrameVisitor<T> visitor);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.common;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A facility for timing a step in the runtime initialization sequence. This is independent from all
+ * other JVMCI code so as to not perturb the initialization sequence. It is enabled by setting the
+ * {@code "jvmci.inittimer"} system property to {@code "true"}.
+ */
+public final class InitTimer implements AutoCloseable {
+    private final String name;
+    private final long start;
+
+    private InitTimer(String name) {
+        int n = nesting.getAndIncrement();
+        if (n == 0) {
+            initializingThread = Thread.currentThread();
+            System.out.println("INITIALIZING THREAD: " + initializingThread);
+        } else {
+            assert Thread.currentThread() == initializingThread : Thread.currentThread() + " != " + initializingThread;
+        }
+        this.name = name;
+        this.start = System.currentTimeMillis();
+        System.out.println("START: " + SPACES.substring(0, n * 2) + name);
+    }
+
+    @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "only the initializing thread accesses this field")
+    public void close() {
+        final long end = System.currentTimeMillis();
+        int n = nesting.decrementAndGet();
+        System.out.println(" DONE: " + SPACES.substring(0, n * 2) + name + " [" + (end - start) + " ms]");
+        if (n == 0) {
+            initializingThread = null;
+        }
+    }
+
+    public static InitTimer timer(String name) {
+        return ENABLED ? new InitTimer(name) : null;
+    }
+
+    public static InitTimer timer(String name, Object suffix) {
+        return ENABLED ? new InitTimer(name + suffix) : null;
+    }
+
+    /**
+     * Specifies if initialization timing is enabled. Note: This property cannot use
+     * {@code HotSpotJVMCIRuntime.Option} since that class is not visible from this package.
+     */
+    private static final boolean ENABLED = Boolean.getBoolean("jvmci.InitTimer");
+
+    public static final AtomicInteger nesting = ENABLED ? new AtomicInteger() : null;
+    public static final String SPACES = "                                            ";
+
+    /**
+     * Used to assert the invariant that all related initialization happens on the same thread.
+     */
+    static Thread initializingThread;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.common;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+/**
+ * Indicates a condition in JVMCI related code that should never occur during normal operation.
+ */
+public class JVMCIError extends Error {
+
+    private static final long serialVersionUID = 531632331813456233L;
+
+    public static RuntimeException unimplemented() {
+        throw new JVMCIError("unimplemented");
+    }
+
+    public static RuntimeException unimplemented(String msg) {
+        throw new JVMCIError("unimplemented: %s", msg);
+    }
+
+    public static RuntimeException shouldNotReachHere() {
+        throw new JVMCIError("should not reach here");
+    }
+
+    public static RuntimeException shouldNotReachHere(String msg) {
+        throw new JVMCIError("should not reach here: %s", msg);
+    }
+
+    public static RuntimeException shouldNotReachHere(Throwable cause) {
+        throw new JVMCIError(cause);
+    }
+
+    /**
+     * Checks a given condition and throws a {@link JVMCIError} if it is false. Guarantees are
+     * stronger than assertions in that they are always checked. Error messages for guarantee
+     * violations should clearly indicate the nature of the problem as well as a suggested solution
+     * if possible.
+     *
+     * @param condition the condition to check
+     * @param msg the message that will be associated with the error, in
+     *            {@link String#format(String, Object...)} syntax
+     * @param args arguments to the format string
+     */
+    public static void guarantee(boolean condition, String msg, Object... args) {
+        if (!condition) {
+            throw new JVMCIError("failed guarantee: " + msg, args);
+        }
+    }
+
+    /**
+     * This constructor creates a {@link JVMCIError} with a given message.
+     *
+     * @param msg the message that will be associated with the error
+     */
+    public JVMCIError(String msg) {
+        super(msg);
+    }
+
+    /**
+     * This constructor creates a {@link JVMCIError} with a message assembled via
+     * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to
+     * always generate the same output.
+     *
+     * @param msg the message that will be associated with the error, in String.format syntax
+     * @param args parameters to String.format - parameters that implement {@link Iterable} will be
+     *            expanded into a [x, x, ...] representation.
+     */
+    public JVMCIError(String msg, Object... args) {
+        super(format(msg, args));
+    }
+
+    /**
+     * This constructor creates a {@link JVMCIError} for a given causing Throwable instance.
+     *
+     * @param cause the original exception that contains additional information on this error
+     */
+    public JVMCIError(Throwable cause) {
+        super(cause);
+    }
+
+    private static String format(String msg, Object... args) {
+        if (args != null) {
+            // expand Iterable parameters into a list representation
+            for (int i = 0; i < args.length; i++) {
+                if (args[i] instanceof Iterable<?>) {
+                    ArrayList<Object> list = new ArrayList<>();
+                    for (Object o : (Iterable<?>) args[i]) {
+                        list.add(o);
+                    }
+                    args[i] = list.toString();
+                }
+            }
+        }
+        return String.format(Locale.ENGLISH, msg, args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.common/src/jdk/vm/ci/common/SuppressFBWarnings.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.common;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+@interface SuppressFBWarnings {
+    /**
+     * The set of FindBugs
+     * <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+     * suppressed in annotated element. The value can be a bug category, kind or pattern.
+     */
+    String[] value();
+
+    /**
+     * Reason why the warning is suppressed.
+     */
+    String justification();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.aarch64/src/META-INF/services/jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.aarch64;
+
+import static jdk.vm.ci.common.InitTimer.timer;
+
+import java.util.EnumSet;
+
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
+import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
+import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
+import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.runtime.JVMCIBackend;
+
+public class AArch64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
+
+    protected EnumSet<AArch64.CPUFeature> computeFeatures(@SuppressWarnings("unused") AArch64HotSpotVMConfig config) {
+        // Configure the feature set using the HotSpot flag settings.
+        EnumSet<AArch64.CPUFeature> features = EnumSet.noneOf(AArch64.CPUFeature.class);
+        return features;
+    }
+
+    protected EnumSet<AArch64.Flag> computeFlags(@SuppressWarnings("unused") AArch64HotSpotVMConfig config) {
+        EnumSet<AArch64.Flag> flags = EnumSet.noneOf(AArch64.Flag.class);
+        return flags;
+    }
+
+    protected TargetDescription createTarget(AArch64HotSpotVMConfig config) {
+        final int stackFrameAlignment = 16;
+        final int implicitNullCheckLimit = 4096;
+        final boolean inlineObjects = true;
+        Architecture arch = new AArch64(computeFeatures(config), computeFlags(config));
+        return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+    }
+
+    protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) {
+        return new HotSpotConstantReflectionProvider(runtime);
+    }
+
+    protected RegisterConfig createRegisterConfig(AArch64HotSpotVMConfig config, TargetDescription target) {
+        return new AArch64HotSpotRegisterConfig(target, config.useCompressedOops);
+    }
+
+    protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
+        return new HotSpotCodeCacheProvider(runtime, runtime.getConfig(), target, regConfig);
+    }
+
+    protected HotSpotMetaAccessProvider createMetaAccess(HotSpotJVMCIRuntimeProvider runtime) {
+        return new HotSpotMetaAccessProvider(runtime);
+    }
+
+    @Override
+    public String getArchitecture() {
+        return "aarch64";
+    }
+
+    @Override
+    public String toString() {
+        return "JVMCIBackend:" + getArchitecture();
+    }
+
+    @SuppressWarnings("try")
+    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
+
+        assert host == null;
+        AArch64HotSpotVMConfig config = new AArch64HotSpotVMConfig(runtime.getConfigStore());
+        TargetDescription target = createTarget(config);
+
+        RegisterConfig regConfig;
+        HotSpotCodeCacheProvider codeCache;
+        ConstantReflectionProvider constantReflection;
+        HotSpotMetaAccessProvider metaAccess;
+        StackIntrospection stackIntrospection;
+        try (InitTimer t = timer("create providers")) {
+            try (InitTimer rt = timer("create MetaAccess provider")) {
+                metaAccess = createMetaAccess(runtime);
+            }
+            try (InitTimer rt = timer("create RegisterConfig")) {
+                regConfig = createRegisterConfig(config, target);
+            }
+            try (InitTimer rt = timer("create CodeCache provider")) {
+                codeCache = createCodeCache(runtime, target, regConfig);
+            }
+            try (InitTimer rt = timer("create ConstantReflection provider")) {
+                constantReflection = createConstantReflection(runtime);
+            }
+            try (InitTimer rt = timer("create StackIntrospection provider")) {
+                stackIntrospection = new HotSpotStackIntrospection(runtime);
+            }
+        }
+        try (InitTimer rt = timer("instantiate backend")) {
+            return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
+        }
+    }
+
+    protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection,
+                    StackIntrospection stackIntrospection) {
+        return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.aarch64;
+
+import static jdk.vm.ci.aarch64.AArch64.lr;
+import static jdk.vm.ci.aarch64.AArch64.r0;
+import static jdk.vm.ci.aarch64.AArch64.r1;
+import static jdk.vm.ci.aarch64.AArch64.r12;
+import static jdk.vm.ci.aarch64.AArch64.r2;
+import static jdk.vm.ci.aarch64.AArch64.r27;
+import static jdk.vm.ci.aarch64.AArch64.r28;
+import static jdk.vm.ci.aarch64.AArch64.r29;
+import static jdk.vm.ci.aarch64.AArch64.r3;
+import static jdk.vm.ci.aarch64.AArch64.r31;
+import static jdk.vm.ci.aarch64.AArch64.r4;
+import static jdk.vm.ci.aarch64.AArch64.r5;
+import static jdk.vm.ci.aarch64.AArch64.r6;
+import static jdk.vm.ci.aarch64.AArch64.r7;
+import static jdk.vm.ci.aarch64.AArch64.r9;
+import static jdk.vm.ci.aarch64.AArch64.sp;
+import static jdk.vm.ci.aarch64.AArch64.v0;
+import static jdk.vm.ci.aarch64.AArch64.v1;
+import static jdk.vm.ci.aarch64.AArch64.v2;
+import static jdk.vm.ci.aarch64.AArch64.v3;
+import static jdk.vm.ci.aarch64.AArch64.v4;
+import static jdk.vm.ci.aarch64.AArch64.v5;
+import static jdk.vm.ci.aarch64.AArch64.v6;
+import static jdk.vm.ci.aarch64.AArch64.v7;
+import static jdk.vm.ci.aarch64.AArch64.zr;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.CallingConvention.Type;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
+import jdk.vm.ci.code.RegisterAttributes;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.ValueKindFactory;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.Value;
+import jdk.vm.ci.meta.ValueKind;
+
+public class AArch64HotSpotRegisterConfig implements RegisterConfig {
+
+    private final TargetDescription target;
+
+    private final RegisterArray allocatable;
+
+    /**
+     * The caller saved registers always include all parameter registers.
+     */
+    private final RegisterArray callerSaved;
+
+    private final boolean allAllocatableAreCallerSaved;
+
+    private final RegisterAttributes[] attributesMap;
+
+    @Override
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
+    }
+
+    @Override
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
+        ArrayList<Register> list = new ArrayList<>();
+        for (Register reg : registers) {
+            if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
+                list.add(reg);
+            }
+        }
+
+        return new RegisterArray(list);
+    }
+
+    @Override
+    public RegisterAttributes[] getAttributesMap() {
+        return attributesMap.clone();
+    }
+
+    private final RegisterArray javaGeneralParameterRegisters = new RegisterArray(r1, r2, r3, r4, r5, r6, r7, r0);
+    private final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(r0, r1, r2, r3, r4, r5, r6, r7);
+    private final RegisterArray simdParameterRegisters = new RegisterArray(v0, v1, v2, v3, v4, v5, v6, v7);
+
+    public static final Register inlineCacheRegister = r9;
+
+    /**
+     * Vtable stubs expect the metaspace Method in r12.
+     */
+    public static final Register metaspaceMethodRegister = r12;
+
+    public static final Register heapBaseRegister = r27;
+    public static final Register threadRegister = r28;
+    public static final Register fp = r29;
+
+    private static final RegisterArray reservedRegisters = new RegisterArray(threadRegister, fp, lr, r31, zr, sp);
+
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
+
+        int idx = 0;
+        for (Register reg : allRegisters) {
+            if (reservedRegistersList.contains(reg)) {
+                // skip reserved registers
+                continue;
+            }
+            assert !(reg.equals(threadRegister) || reg.equals(fp) || reg.equals(lr) || reg.equals(r31) || reg.equals(zr) || reg.equals(sp));
+            if (reserveForHeapBase && reg.equals(heapBaseRegister)) {
+                // skip heap base register
+                continue;
+            }
+
+            registers[idx++] = reg;
+        }
+
+        assert idx == registers.length;
+        return new RegisterArray(registers);
+    }
+
+    public AArch64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
+        this(target, initAllocatable(target.arch, useCompressedOops));
+        assert callerSaved.size() >= allocatable.size();
+    }
+
+    public AArch64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
+        this.target = target;
+
+        this.allocatable = allocatable;
+        Set<Register> callerSaveSet = new HashSet<>();
+        allocatable.addTo(callerSaveSet);
+        simdParameterRegisters.addTo(callerSaveSet);
+        javaGeneralParameterRegisters.addTo(callerSaveSet);
+        nativeGeneralParameterRegisters.addTo(callerSaveSet);
+        callerSaved = new RegisterArray(callerSaveSet);
+
+        allAllocatableAreCallerSaved = true;
+        attributesMap = RegisterAttributes.createMap(this, AArch64.allRegisters);
+    }
+
+    @Override
+    public RegisterArray getCallerSaveRegisters() {
+        return callerSaved;
+    }
+
+    public RegisterArray getCalleeSaveRegisters() {
+        return null;
+    }
+
+    @Override
+    public boolean areAllAllocatableRegistersCallerSaved() {
+        return allAllocatableAreCallerSaved;
+    }
+
+    @Override
+    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
+        HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
+        if (type == HotSpotCallingConventionType.NativeCall) {
+            return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
+        }
+        // On x64, parameter locations are the same whether viewed
+        // from the caller or callee perspective
+        return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
+    }
+
+    @Override
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
+        HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
+            case Int:
+            case Long:
+            case Object:
+                return hotspotType == HotSpotCallingConventionType.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters;
+            case Float:
+            case Double:
+                return simdParameterRegisters;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+                    ValueKindFactory<?> valueKindFactory) {
+        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+        int currentGeneral = 0;
+        int currentSIMD = 0;
+        int currentStackOffset = 0;
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
+
+            switch (kind) {
+                case Byte:
+                case Boolean:
+                case Short:
+                case Char:
+                case Int:
+                case Long:
+                case Object:
+                    if (currentGeneral < generalParameterRegisters.size()) {
+                        Register register = generalParameterRegisters.get(currentGeneral++);
+                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                    }
+                    break;
+                case Float:
+                case Double:
+                    if (currentSIMD < simdParameterRegisters.size()) {
+                        Register register = simdParameterRegisters.get(currentSIMD++);
+                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                    }
+                    break;
+                default:
+                    throw JVMCIError.shouldNotReachHere();
+            }
+
+            if (locations[i] == null) {
+                ValueKind<?> valueKind = valueKindFactory.getValueKind(kind);
+                locations[i] = StackSlot.get(valueKind, currentStackOffset, !type.out);
+                currentStackOffset += Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize);
+            }
+        }
+
+        JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
+        AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
+    }
+
+    @Override
+    public Register getReturnRegister(JavaKind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+            case Object:
+                return r0;
+            case Float:
+            case Double:
+                return v0;
+            case Void:
+            case Illegal:
+                return null;
+            default:
+                throw new UnsupportedOperationException("no return register for type " + kind);
+        }
+    }
+
+    @Override
+    public Register getFrameRegister() {
+        return sp;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.aarch64;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * Used to access AArch64 specific native configuration details.
+ */
+class AArch64HotSpotVMConfig extends HotSpotVMConfigAccess {
+
+    AArch64HotSpotVMConfig(HotSpotVMConfigStore config) {
+        super(config);
+    }
+
+    final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
+
+    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.amd64/src/META-INF/services/jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.amd64;
+
+import static jdk.vm.ci.common.InitTimer.timer;
+
+import java.util.EnumSet;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
+import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
+import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
+import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.runtime.JVMCIBackend;
+
+public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
+
+    protected EnumSet<AMD64.CPUFeature> computeFeatures(AMD64HotSpotVMConfig config) {
+        // Configure the feature set using the HotSpot flag settings.
+        EnumSet<AMD64.CPUFeature> features = EnumSet.noneOf(AMD64.CPUFeature.class);
+        if ((config.vmVersionFeatures & config.amd643DNOWPREFETCH) != 0) {
+            features.add(AMD64.CPUFeature.AMD_3DNOW_PREFETCH);
+        }
+        assert config.useSSE >= 2 : "minimum config for x64";
+        features.add(AMD64.CPUFeature.SSE);
+        features.add(AMD64.CPUFeature.SSE2);
+        if ((config.vmVersionFeatures & config.amd64SSE3) != 0) {
+            features.add(AMD64.CPUFeature.SSE3);
+        }
+        if ((config.vmVersionFeatures & config.amd64SSSE3) != 0) {
+            features.add(AMD64.CPUFeature.SSSE3);
+        }
+        if ((config.vmVersionFeatures & config.amd64SSE4A) != 0) {
+            features.add(AMD64.CPUFeature.SSE4A);
+        }
+        if ((config.vmVersionFeatures & config.amd64SSE41) != 0) {
+            features.add(AMD64.CPUFeature.SSE4_1);
+        }
+        if ((config.vmVersionFeatures & config.amd64SSE42) != 0) {
+            features.add(AMD64.CPUFeature.SSE4_2);
+        }
+        if ((config.vmVersionFeatures & config.amd64POPCNT) != 0) {
+            features.add(AMD64.CPUFeature.POPCNT);
+        }
+        if ((config.vmVersionFeatures & config.amd64LZCNT) != 0) {
+            features.add(AMD64.CPUFeature.LZCNT);
+        }
+        if ((config.vmVersionFeatures & config.amd64ERMS) != 0) {
+            features.add(AMD64.CPUFeature.ERMS);
+        }
+        if ((config.vmVersionFeatures & config.amd64AVX) != 0) {
+            features.add(AMD64.CPUFeature.AVX);
+        }
+        if ((config.vmVersionFeatures & config.amd64AVX2) != 0) {
+            features.add(AMD64.CPUFeature.AVX2);
+        }
+        if ((config.vmVersionFeatures & config.amd64AES) != 0) {
+            features.add(AMD64.CPUFeature.AES);
+        }
+        if ((config.vmVersionFeatures & config.amd643DNOWPREFETCH) != 0) {
+            features.add(AMD64.CPUFeature.AMD_3DNOW_PREFETCH);
+        }
+        if ((config.vmVersionFeatures & config.amd64BMI1) != 0) {
+            features.add(AMD64.CPUFeature.BMI1);
+        }
+        if ((config.vmVersionFeatures & config.amd64BMI2) != 0) {
+            features.add(AMD64.CPUFeature.BMI2);
+        }
+        if ((config.vmVersionFeatures & config.amd64RTM) != 0) {
+            features.add(AMD64.CPUFeature.RTM);
+        }
+        if ((config.vmVersionFeatures & config.amd64ADX) != 0) {
+            features.add(AMD64.CPUFeature.ADX);
+        }
+        return features;
+    }
+
+    protected EnumSet<AMD64.Flag> computeFlags(AMD64HotSpotVMConfig config) {
+        EnumSet<AMD64.Flag> flags = EnumSet.noneOf(AMD64.Flag.class);
+        if (config.useCountLeadingZerosInstruction) {
+            flags.add(AMD64.Flag.UseCountLeadingZerosInstruction);
+        }
+        if (config.useCountTrailingZerosInstruction) {
+            flags.add(AMD64.Flag.UseCountTrailingZerosInstruction);
+        }
+        return flags;
+    }
+
+    protected TargetDescription createTarget(AMD64HotSpotVMConfig config) {
+        final int stackFrameAlignment = 16;
+        final int implicitNullCheckLimit = 4096;
+        final boolean inlineObjects = true;
+        Architecture arch = new AMD64(computeFeatures(config), computeFlags(config));
+        return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+    }
+
+    protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) {
+        return new HotSpotConstantReflectionProvider(runtime);
+    }
+
+    protected RegisterConfig createRegisterConfig(AMD64HotSpotVMConfig config, TargetDescription target) {
+        return new AMD64HotSpotRegisterConfig(target, config.useCompressedOops, config.windowsOs);
+    }
+
+    protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
+        return new HotSpotCodeCacheProvider(runtime, runtime.getConfig(), target, regConfig);
+    }
+
+    protected HotSpotMetaAccessProvider createMetaAccess(HotSpotJVMCIRuntimeProvider runtime) {
+        return new HotSpotMetaAccessProvider(runtime);
+    }
+
+    @Override
+    public String getArchitecture() {
+        return "AMD64";
+    }
+
+    @Override
+    public String toString() {
+        return "JVMCIBackend:" + getArchitecture();
+    }
+
+    @SuppressWarnings("try")
+    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
+        assert host == null;
+        AMD64HotSpotVMConfig config = new AMD64HotSpotVMConfig(runtime.getConfigStore());
+        TargetDescription target = createTarget(config);
+
+        RegisterConfig regConfig;
+        HotSpotCodeCacheProvider codeCache;
+        ConstantReflectionProvider constantReflection;
+        HotSpotMetaAccessProvider metaAccess;
+        StackIntrospection stackIntrospection;
+        try (InitTimer t = timer("create providers")) {
+            try (InitTimer rt = timer("create MetaAccess provider")) {
+                metaAccess = createMetaAccess(runtime);
+            }
+            try (InitTimer rt = timer("create RegisterConfig")) {
+                regConfig = createRegisterConfig(config, target);
+            }
+            try (InitTimer rt = timer("create CodeCache provider")) {
+                codeCache = createCodeCache(runtime, target, regConfig);
+            }
+            try (InitTimer rt = timer("create ConstantReflection provider")) {
+                constantReflection = createConstantReflection(runtime);
+            }
+            try (InitTimer rt = timer("create StackIntrospection provider")) {
+                stackIntrospection = new HotSpotStackIntrospection(runtime);
+            }
+        }
+        try (InitTimer rt = timer("instantiate backend")) {
+            return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
+        }
+    }
+
+    protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection,
+                    StackIntrospection stackIntrospection) {
+        return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.amd64;
+
+import static jdk.vm.ci.amd64.AMD64.r12;
+import static jdk.vm.ci.amd64.AMD64.r15;
+import static jdk.vm.ci.amd64.AMD64.r8;
+import static jdk.vm.ci.amd64.AMD64.r9;
+import static jdk.vm.ci.amd64.AMD64.rax;
+import static jdk.vm.ci.amd64.AMD64.rcx;
+import static jdk.vm.ci.amd64.AMD64.rdi;
+import static jdk.vm.ci.amd64.AMD64.rdx;
+import static jdk.vm.ci.amd64.AMD64.rsi;
+import static jdk.vm.ci.amd64.AMD64.rsp;
+import static jdk.vm.ci.amd64.AMD64.xmm0;
+import static jdk.vm.ci.amd64.AMD64.xmm1;
+import static jdk.vm.ci.amd64.AMD64.xmm2;
+import static jdk.vm.ci.amd64.AMD64.xmm3;
+import static jdk.vm.ci.amd64.AMD64.xmm4;
+import static jdk.vm.ci.amd64.AMD64.xmm5;
+import static jdk.vm.ci.amd64.AMD64.xmm6;
+import static jdk.vm.ci.amd64.AMD64.xmm7;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.CallingConvention.Type;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
+import jdk.vm.ci.code.RegisterAttributes;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.ValueKindFactory;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.Value;
+import jdk.vm.ci.meta.ValueKind;
+
+public class AMD64HotSpotRegisterConfig implements RegisterConfig {
+
+    private final TargetDescription target;
+
+    private final RegisterArray allocatable;
+
+    /**
+     * The caller saved registers always include all parameter registers.
+     */
+    private final RegisterArray callerSaved;
+
+    private final boolean allAllocatableAreCallerSaved;
+
+    private final RegisterAttributes[] attributesMap;
+
+    @Override
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
+    }
+
+    @Override
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
+        ArrayList<Register> list = new ArrayList<>();
+        for (Register reg : registers) {
+            if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
+                list.add(reg);
+            }
+        }
+
+        RegisterArray ret = new RegisterArray(list);
+        return ret;
+    }
+
+    @Override
+    public RegisterAttributes[] getAttributesMap() {
+        return attributesMap.clone();
+    }
+
+    private final RegisterArray javaGeneralParameterRegisters;
+    private final RegisterArray nativeGeneralParameterRegisters;
+    private final RegisterArray javaXMMParameterRegisters;
+    private final RegisterArray nativeXMMParameterRegisters;
+    private final boolean windowsOS;
+
+    /*
+     * Some ABIs (e.g. Windows) require a so-called "home space", that is a save area on the stack
+     * to store the argument registers
+     */
+    private final boolean needsNativeStackHomeSpace;
+
+    private static final RegisterArray reservedRegisters = new RegisterArray(rsp, r15);
+
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
+
+        int idx = 0;
+        for (Register reg : allRegisters) {
+            if (reservedRegistersList.contains(reg)) {
+                // skip reserved registers
+                continue;
+            }
+            if (reserveForHeapBase && reg.equals(r12)) {
+                // skip heap base register
+                continue;
+            }
+
+            registers[idx++] = reg;
+        }
+
+        assert idx == registers.length;
+        return new RegisterArray(registers);
+    }
+
+    public AMD64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops, boolean windowsOs) {
+        this(target, initAllocatable(target.arch, useCompressedOops), windowsOs);
+        assert callerSaved.size() >= allocatable.size();
+    }
+
+    public AMD64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable, boolean windowsOS) {
+        this.target = target;
+        this.windowsOS = windowsOS;
+
+        if (windowsOS) {
+            javaGeneralParameterRegisters = new RegisterArray(rdx, r8, r9, rdi, rsi, rcx);
+            nativeGeneralParameterRegisters = new RegisterArray(rcx, rdx, r8, r9);
+            nativeXMMParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3);
+            this.needsNativeStackHomeSpace = true;
+        } else {
+            javaGeneralParameterRegisters = new RegisterArray(rsi, rdx, rcx, r8, r9, rdi);
+            nativeGeneralParameterRegisters = new RegisterArray(rdi, rsi, rdx, rcx, r8, r9);
+            nativeXMMParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
+            this.needsNativeStackHomeSpace = false;
+        }
+        javaXMMParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
+
+        this.allocatable = allocatable;
+        Set<Register> callerSaveSet = new HashSet<>();
+        allocatable.addTo(callerSaveSet);
+        javaXMMParameterRegisters.addTo(callerSaveSet);
+        callerSaveSet.addAll(javaGeneralParameterRegisters.asList());
+        nativeGeneralParameterRegisters.addTo(callerSaveSet);
+        callerSaved = new RegisterArray(callerSaveSet);
+
+        allAllocatableAreCallerSaved = true;
+        attributesMap = RegisterAttributes.createMap(this, target.arch.getRegisters());
+    }
+
+    @Override
+    public RegisterArray getCallerSaveRegisters() {
+        return callerSaved;
+    }
+
+    @Override
+    public RegisterArray getCalleeSaveRegisters() {
+        return null;
+    }
+
+    @Override
+    public boolean areAllAllocatableRegistersCallerSaved() {
+        return allAllocatableAreCallerSaved;
+    }
+
+    @Override
+    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
+        HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
+        if (type == HotSpotCallingConventionType.NativeCall) {
+            return callingConvention(nativeGeneralParameterRegisters, nativeXMMParameterRegisters, windowsOS, returnType, parameterTypes, hotspotType, valueKindFactory);
+        }
+        // On x64, parameter locations are the same whether viewed
+        // from the caller or callee perspective
+        return callingConvention(javaGeneralParameterRegisters, javaXMMParameterRegisters, false, returnType, parameterTypes, hotspotType, valueKindFactory);
+    }
+
+    @Override
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
+        HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
+            case Int:
+            case Long:
+            case Object:
+                return hotspotType == HotSpotCallingConventionType.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters;
+            case Float:
+            case Double:
+                return hotspotType == HotSpotCallingConventionType.NativeCall ? nativeXMMParameterRegisters : javaXMMParameterRegisters;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    /**
+     * Hand out registers matching the calling convention from the {@code generalParameterRegisters}
+     * and {@code xmmParameterRegisters} sets. Normally registers are handed out from each set
+     * individually based on the type of the argument. If the {@code unified} flag is true then hand
+     * out registers in a single sequence, selecting between the sets based on the type. This is to
+     * support the Windows calling convention which only ever passes 4 arguments in registers, no
+     * matter their types.
+     *
+     * @param generalParameterRegisters
+     * @param xmmParameterRegisters
+     * @param unified
+     * @param returnType
+     * @param parameterTypes
+     * @param type
+     * @param valueKindFactory
+     * @return the resulting calling convention
+     */
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, RegisterArray xmmParameterRegisters, boolean unified, JavaType returnType, JavaType[] parameterTypes,
+                    HotSpotCallingConventionType type,
+                    ValueKindFactory<?> valueKindFactory) {
+        assert !unified || generalParameterRegisters.size() == xmmParameterRegisters.size() : "must be same size in unified mode";
+        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+        int currentGeneral = 0;
+        int currentXMM = 0;
+        int currentStackOffset = type == HotSpotCallingConventionType.NativeCall && needsNativeStackHomeSpace ? generalParameterRegisters.size() * target.wordSize : 0;
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
+
+            switch (kind) {
+                case Byte:
+                case Boolean:
+                case Short:
+                case Char:
+                case Int:
+                case Long:
+                case Object:
+                    if (currentGeneral < generalParameterRegisters.size()) {
+                        Register register = generalParameterRegisters.get(currentGeneral++);
+                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                    }
+                    break;
+                case Float:
+                case Double:
+                    if ((unified ? currentGeneral : currentXMM) < xmmParameterRegisters.size()) {
+                        Register register = xmmParameterRegisters.get(unified ? currentGeneral++ : currentXMM++);
+                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                    }
+                    break;
+                default:
+                    throw JVMCIError.shouldNotReachHere();
+            }
+
+            if (locations[i] == null) {
+                ValueKind<?> valueKind = valueKindFactory.getValueKind(kind);
+                locations[i] = StackSlot.get(valueKind, currentStackOffset, !type.out);
+                currentStackOffset += Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize);
+            }
+        }
+        assert !unified || currentXMM == 0 : "shouldn't be used in unified mode";
+
+        JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
+        AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
+    }
+
+    @Override
+    public Register getReturnRegister(JavaKind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+            case Object:
+                return rax;
+            case Float:
+            case Double:
+                return xmm0;
+            case Void:
+            case Illegal:
+                return null;
+            default:
+                throw new UnsupportedOperationException("no return register for type " + kind);
+        }
+    }
+
+    @Override
+    public Register getFrameRegister() {
+        return rsp;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.amd64;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * Used to access AMD64 specific native configuration details.
+ */
+class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess {
+
+    AMD64HotSpotVMConfig(HotSpotVMConfigStore config) {
+        super(config);
+    }
+
+    final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
+
+    final boolean useCountLeadingZerosInstruction = getFlag("UseCountLeadingZerosInstruction", Boolean.class);
+    final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class);
+    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
+
+    // CPU capabilities
+    final int useSSE = getFlag("UseSSE", Integer.class);
+    final int useAVX = getFlag("UseAVX", Integer.class);
+
+    final long vmVersionFeatures = getFieldValue("VM_Version::_cpuFeatures", Long.class, "int");
+
+    // CPU feature flags
+    final long amd64CX8 = getConstant("VM_Version::CPU_CX8", Long.class);
+    final long amd64CMOV = getConstant("VM_Version::CPU_CMOV", Long.class);
+    final long amd64FXSR = getConstant("VM_Version::CPU_FXSR", Long.class);
+    final long amd64HT = getConstant("VM_Version::CPU_HT", Long.class);
+    final long amd64MMX = getConstant("VM_Version::CPU_MMX", Long.class);
+    final long amd643DNOWPREFETCH = getConstant("VM_Version::CPU_3DNOW_PREFETCH", Long.class);
+    final long amd64SSE = getConstant("VM_Version::CPU_SSE", Long.class);
+    final long amd64SSE2 = getConstant("VM_Version::CPU_SSE2", Long.class);
+    final long amd64SSE3 = getConstant("VM_Version::CPU_SSE3", Long.class);
+    final long amd64SSSE3 = getConstant("VM_Version::CPU_SSSE3", Long.class);
+    final long amd64SSE4A = getConstant("VM_Version::CPU_SSE4A", Long.class);
+    final long amd64SSE41 = getConstant("VM_Version::CPU_SSE4_1", Long.class);
+    final long amd64SSE42 = getConstant("VM_Version::CPU_SSE4_2", Long.class);
+    final long amd64POPCNT = getConstant("VM_Version::CPU_POPCNT", Long.class);
+    final long amd64LZCNT = getConstant("VM_Version::CPU_LZCNT", Long.class);
+    final long amd64TSC = getConstant("VM_Version::CPU_TSC", Long.class);
+    final long amd64TSCINV = getConstant("VM_Version::CPU_TSCINV", Long.class);
+    final long amd64AVX = getConstant("VM_Version::CPU_AVX", Long.class);
+    final long amd64AVX2 = getConstant("VM_Version::CPU_AVX2", Long.class);
+    final long amd64AES = getConstant("VM_Version::CPU_AES", Long.class);
+    final long amd64ERMS = getConstant("VM_Version::CPU_ERMS", Long.class);
+    final long amd64CLMUL = getConstant("VM_Version::CPU_CLMUL", Long.class);
+    final long amd64BMI1 = getConstant("VM_Version::CPU_BMI1", Long.class);
+    final long amd64BMI2 = getConstant("VM_Version::CPU_BMI2", Long.class);
+    final long amd64RTM = getConstant("VM_Version::CPU_RTM", Long.class);
+    final long amd64ADX = getConstant("VM_Version::CPU_ADX", Long.class);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.jfr/src/META-INF/services/jdk.vm.ci.services.JVMCIServiceLocator	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+jdk.vm.ci.hotspot.jfr.events.JFREventProvider$Locator
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.jfr/src/jdk/vm/ci/hotspot/jfr/events/JFREventProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.jfr.events;
+
+import java.net.URISyntaxException;
+
+import jdk.vm.ci.hotspot.EventProvider;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.services.JVMCIServiceLocator;
+
+/**
+ * A JFR implementation for {@link EventProvider}. This implementation is used when Flight Recorder
+ * is turned on.
+ *
+ * Note: The use of fully qualified names for deprecated types is a workaround for
+ * <a href="https://bugs.openjdk.java.net/browse/JDK-8032211">JDK-8032211</a>.
+ */
+@SuppressWarnings("deprecation")
+public final class JFREventProvider implements EventProvider {
+
+    private final boolean enabled;
+
+    public static class Locator extends JVMCIServiceLocator {
+
+        @Override
+        public <S> S getProvider(Class<S> service) {
+            if (service == EventProvider.class) {
+                return service.cast(new JFREventProvider());
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Need to store the producer in a field so that it doesn't disappear.
+     */
+    @SuppressWarnings("unused") private final com.oracle.jrockit.jfr.Producer producer;
+
+    public JFREventProvider() {
+        HotSpotVMConfigAccess config = new HotSpotVMConfigAccess(HotSpotJVMCIRuntime.runtime().getConfigStore());
+        enabled = config.getFlag("FlightRecorder", Boolean.class, false);
+        com.oracle.jrockit.jfr.Producer p = null;
+        if (enabled) {
+            try {
+                /*
+                 * The "HotSpot JVM" producer is a native producer and we cannot use it. So we
+                 * create our own. This has the downside that Mission Control is confused and
+                 * doesn't show JVMCI events in the "Code" tab. There are plans to revise the JFR
+                 * code for JDK 9.
+                 */
+                p = new com.oracle.jrockit.jfr.Producer("HotSpot JVM", "Oracle Hotspot JVM", "http://www.oracle.com/hotspot/jvm/");
+                p.register();
+                // Register event classes with Producer.
+                for (Class<?> c : JFREventProvider.class.getDeclaredClasses()) {
+                    if (c.isAnnotationPresent(com.oracle.jrockit.jfr.EventDefinition.class)) {
+                        assert com.oracle.jrockit.jfr.InstantEvent.class.isAssignableFrom(c) : c;
+                        registerEvent(p, c);
+                    }
+                }
+            } catch (URISyntaxException e) {
+                throw new InternalError(e);
+            }
+        }
+        this.producer = p;
+    }
+
+    /**
+     * Register an event class with the {@link com.oracle.jrockit.jfr.Producer}.
+     *
+     * @param c event class
+     * @return the {@link EventToken event token}
+     */
+    @SuppressWarnings({"javadoc", "unchecked"})
+    private static com.oracle.jrockit.jfr.EventToken registerEvent(com.oracle.jrockit.jfr.Producer producer, Class<?> c) {
+        try {
+            return producer.addEvent((Class<? extends com.oracle.jrockit.jfr.InstantEvent>) c);
+        } catch (com.oracle.jrockit.jfr.InvalidEventDefinitionException | com.oracle.jrockit.jfr.InvalidValueException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public CompilationEvent newCompilationEvent() {
+        if (enabled) {
+            return new JFRCompilationEvent();
+        }
+        return EventProvider.createEmptyCompilationEvent();
+    }
+
+    /**
+     * A JFR compilation event.
+     *
+     * <p>
+     * See: event {@code Compilation} in {@code src/share/vm/trace/trace.xml}
+     */
+    @com.oracle.jrockit.jfr.EventDefinition(name = "Compilation", path = "vm/compiler/compilation")
+    public static class JFRCompilationEvent extends com.oracle.jrockit.jfr.DurationEvent implements CompilationEvent {
+
+        /**
+         * Should be a {@code Method*} but we can't express that in Java.
+         */
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "Java Method") public String method;
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "Compilation ID", relationKey = "COMP_ID") public int compileId;
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "Compilation Level") public short compileLevel;
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "Succeeded") public boolean succeeded;
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "On Stack Replacement") public boolean isOsr;
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "Compiled Code Size", contentType = com.oracle.jrockit.jfr.ContentType.Bytes) public int codeSize;
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "Inlined Code Size", contentType = com.oracle.jrockit.jfr.ContentType.Bytes) public int inlinedBytes;
+
+        public void setMethod(String method) {
+            this.method = method;
+        }
+
+        public void setCompileId(int id) {
+            this.compileId = id;
+        }
+
+        public void setCompileLevel(int compileLevel) {
+            this.compileLevel = (short) compileLevel;
+        }
+
+        public void setSucceeded(boolean succeeded) {
+            this.succeeded = succeeded;
+        }
+
+        public void setIsOsr(boolean isOsr) {
+            this.isOsr = isOsr;
+        }
+
+        public void setCodeSize(int codeSize) {
+            this.codeSize = codeSize;
+        }
+
+        public void setInlinedBytes(int inlinedBytes) {
+            this.inlinedBytes = inlinedBytes;
+        }
+    }
+
+    @Override
+    public CompilerFailureEvent newCompilerFailureEvent() {
+        if (enabled) {
+            return new JFRCompilerFailureEvent();
+        }
+        return EventProvider.createEmptyCompilerFailureEvent();
+    }
+
+    /**
+     * A JFR compiler failure event.
+     *
+     * <p>
+     * See: event {@code CompilerFailure} in {@code src/share/vm/trace/trace.xml}
+     */
+    @com.oracle.jrockit.jfr.EventDefinition(name = "Compilation Failure", path = "vm/compiler/failure")
+    public static class JFRCompilerFailureEvent extends com.oracle.jrockit.jfr.InstantEvent implements CompilerFailureEvent {
+
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "Compilation ID", relationKey = "COMP_ID") public int compileId;
+        @com.oracle.jrockit.jfr.ValueDefinition(name = "Message", description = "The failure message") public String failure;
+
+        public void setCompileId(int id) {
+            this.compileId = id;
+        }
+
+        public void setMessage(String message) {
+            this.failure = message;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.sparc/src/META-INF/services/jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.sparc;
+
+import static jdk.vm.ci.common.InitTimer.timer;
+
+import java.util.EnumSet;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
+import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
+import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
+import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
+import jdk.vm.ci.runtime.JVMCIBackend;
+import jdk.vm.ci.sparc.SPARC;
+import jdk.vm.ci.sparc.SPARC.CPUFeature;
+
+public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
+
+    protected TargetDescription createTarget(SPARCHotSpotVMConfig config) {
+        final int stackFrameAlignment = 16;
+        final int implicitNullCheckLimit = 4096;
+        final boolean inlineObjects = false;
+        Architecture arch = new SPARC(computeFeatures(config));
+        return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+    }
+
+    protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
+        return new HotSpotCodeCacheProvider(runtime, runtime.getConfig(), target, regConfig);
+    }
+
+    protected EnumSet<CPUFeature> computeFeatures(SPARCHotSpotVMConfig config) {
+        EnumSet<CPUFeature> features = EnumSet.noneOf(CPUFeature.class);
+        if ((config.vmVersionFeatures & config.sparcVis1Instructions) != 0) {
+            features.add(CPUFeature.VIS1);
+        }
+        if ((config.vmVersionFeatures & config.sparcVis2Instructions) != 0) {
+            features.add(CPUFeature.VIS2);
+        }
+        if ((config.vmVersionFeatures & config.sparcVis3Instructions) != 0) {
+            features.add(CPUFeature.VIS3);
+        }
+        if ((config.vmVersionFeatures & config.sparcCbcondInstructions) != 0) {
+            features.add(CPUFeature.CBCOND);
+        }
+        if ((config.vmVersionFeatures & config.sparcV8Instructions) != 0) {
+            features.add(CPUFeature.V8);
+        }
+        if ((config.vmVersionFeatures & config.sparcHardwareMul32) != 0) {
+            features.add(CPUFeature.HARDWARE_MUL32);
+        }
+        if ((config.vmVersionFeatures & config.sparcHardwareDiv32) != 0) {
+            features.add(CPUFeature.HARDWARE_DIV32);
+        }
+        if ((config.vmVersionFeatures & config.sparcHardwareFsmuld) != 0) {
+            features.add(CPUFeature.HARDWARE_FSMULD);
+        }
+        if ((config.vmVersionFeatures & config.sparcHardwarePopc) != 0) {
+            features.add(CPUFeature.HARDWARE_POPC);
+        }
+        if ((config.vmVersionFeatures & config.sparcV9Instructions) != 0) {
+            features.add(CPUFeature.V9);
+        }
+        if ((config.vmVersionFeatures & config.sparcSun4v) != 0) {
+            features.add(CPUFeature.SUN4V);
+        }
+        if ((config.vmVersionFeatures & config.sparcBlkInitInstructions) != 0) {
+            features.add(CPUFeature.BLK_INIT_INSTRUCTIONS);
+        }
+        if ((config.vmVersionFeatures & config.sparcFmafInstructions) != 0) {
+            features.add(CPUFeature.FMAF);
+        }
+        if ((config.vmVersionFeatures & config.sparcFmauInstructions) != 0) {
+            features.add(CPUFeature.FMAU);
+        }
+        if ((config.vmVersionFeatures & config.sparcSparc64Family) != 0) {
+            features.add(CPUFeature.SPARC64_FAMILY);
+        }
+        if ((config.vmVersionFeatures & config.sparcMFamily) != 0) {
+            features.add(CPUFeature.M_FAMILY);
+        }
+        if ((config.vmVersionFeatures & config.sparcTFamily) != 0) {
+            features.add(CPUFeature.T_FAMILY);
+        }
+        if ((config.vmVersionFeatures & config.sparcT1Model) != 0) {
+            features.add(CPUFeature.T1_MODEL);
+        }
+        if ((config.vmVersionFeatures & config.sparcSparc5Instructions) != 0) {
+            features.add(CPUFeature.SPARC5);
+        }
+        if ((config.vmVersionFeatures & config.sparcAesInstructions) != 0) {
+            features.add(CPUFeature.SPARC64_FAMILY);
+        }
+        if ((config.vmVersionFeatures & config.sparcSha1Instruction) != 0) {
+            features.add(CPUFeature.SHA1);
+        }
+        if ((config.vmVersionFeatures & config.sparcSha256Instruction) != 0) {
+            features.add(CPUFeature.SHA256);
+        }
+        if ((config.vmVersionFeatures & config.sparcSha512Instruction) != 0) {
+            features.add(CPUFeature.SHA512);
+        }
+        return features;
+    }
+
+    @Override
+    public String getArchitecture() {
+        return "SPARC";
+    }
+
+    @Override
+    public String toString() {
+        return "JVMCIBackend:" + getArchitecture();
+    }
+
+    @SuppressWarnings("try")
+    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
+        assert host == null;
+        SPARCHotSpotVMConfig config = new SPARCHotSpotVMConfig(runtime.getConfigStore());
+        TargetDescription target = createTarget(config);
+
+        HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
+        RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target, config.useCompressedOops);
+        HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target, regConfig);
+        HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
+        StackIntrospection stackIntrospection = new HotSpotStackIntrospection(runtime);
+        try (InitTimer rt = timer("instantiate backend")) {
+            return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
+        }
+    }
+
+    protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection,
+                    StackIntrospection stackIntrospection) {
+        return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.sparc;
+
+import static jdk.vm.ci.meta.JavaKind.Void;
+import static jdk.vm.ci.meta.Value.ILLEGAL;
+import static jdk.vm.ci.sparc.SPARC.REGISTER_SAFE_AREA_SIZE;
+import static jdk.vm.ci.sparc.SPARC.d0;
+import static jdk.vm.ci.sparc.SPARC.d10;
+import static jdk.vm.ci.sparc.SPARC.d12;
+import static jdk.vm.ci.sparc.SPARC.d14;
+import static jdk.vm.ci.sparc.SPARC.d16;
+import static jdk.vm.ci.sparc.SPARC.d18;
+import static jdk.vm.ci.sparc.SPARC.d2;
+import static jdk.vm.ci.sparc.SPARC.d20;
+import static jdk.vm.ci.sparc.SPARC.d22;
+import static jdk.vm.ci.sparc.SPARC.d24;
+import static jdk.vm.ci.sparc.SPARC.d26;
+import static jdk.vm.ci.sparc.SPARC.d28;
+import static jdk.vm.ci.sparc.SPARC.d30;
+import static jdk.vm.ci.sparc.SPARC.d4;
+import static jdk.vm.ci.sparc.SPARC.d6;
+import static jdk.vm.ci.sparc.SPARC.d8;
+import static jdk.vm.ci.sparc.SPARC.f0;
+import static jdk.vm.ci.sparc.SPARC.f1;
+import static jdk.vm.ci.sparc.SPARC.f11;
+import static jdk.vm.ci.sparc.SPARC.f13;
+import static jdk.vm.ci.sparc.SPARC.f15;
+import static jdk.vm.ci.sparc.SPARC.f17;
+import static jdk.vm.ci.sparc.SPARC.f19;
+import static jdk.vm.ci.sparc.SPARC.f2;
+import static jdk.vm.ci.sparc.SPARC.f21;
+import static jdk.vm.ci.sparc.SPARC.f23;
+import static jdk.vm.ci.sparc.SPARC.f25;
+import static jdk.vm.ci.sparc.SPARC.f27;
+import static jdk.vm.ci.sparc.SPARC.f29;
+import static jdk.vm.ci.sparc.SPARC.f3;
+import static jdk.vm.ci.sparc.SPARC.f31;
+import static jdk.vm.ci.sparc.SPARC.f4;
+import static jdk.vm.ci.sparc.SPARC.f5;
+import static jdk.vm.ci.sparc.SPARC.f6;
+import static jdk.vm.ci.sparc.SPARC.f7;
+import static jdk.vm.ci.sparc.SPARC.f9;
+import static jdk.vm.ci.sparc.SPARC.g0;
+import static jdk.vm.ci.sparc.SPARC.g2;
+import static jdk.vm.ci.sparc.SPARC.g6;
+import static jdk.vm.ci.sparc.SPARC.i0;
+import static jdk.vm.ci.sparc.SPARC.i1;
+import static jdk.vm.ci.sparc.SPARC.i2;
+import static jdk.vm.ci.sparc.SPARC.i3;
+import static jdk.vm.ci.sparc.SPARC.i4;
+import static jdk.vm.ci.sparc.SPARC.i5;
+import static jdk.vm.ci.sparc.SPARC.i6;
+import static jdk.vm.ci.sparc.SPARC.i7;
+import static jdk.vm.ci.sparc.SPARC.l0;
+import static jdk.vm.ci.sparc.SPARC.l1;
+import static jdk.vm.ci.sparc.SPARC.l2;
+import static jdk.vm.ci.sparc.SPARC.l3;
+import static jdk.vm.ci.sparc.SPARC.l4;
+import static jdk.vm.ci.sparc.SPARC.l5;
+import static jdk.vm.ci.sparc.SPARC.l6;
+import static jdk.vm.ci.sparc.SPARC.l7;
+import static jdk.vm.ci.sparc.SPARC.o0;
+import static jdk.vm.ci.sparc.SPARC.o1;
+import static jdk.vm.ci.sparc.SPARC.o2;
+import static jdk.vm.ci.sparc.SPARC.o3;
+import static jdk.vm.ci.sparc.SPARC.o4;
+import static jdk.vm.ci.sparc.SPARC.o5;
+import static jdk.vm.ci.sparc.SPARC.sp;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.CallingConvention.Type;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
+import jdk.vm.ci.code.RegisterAttributes;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.ValueKindFactory;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.ValueKind;
+import jdk.vm.ci.sparc.SPARC;
+
+public class SPARCHotSpotRegisterConfig implements RegisterConfig {
+
+    private final TargetDescription target;
+
+    private final RegisterArray allocatable;
+
+    private final RegisterAttributes[] attributesMap;
+
+    @Override
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
+    }
+
+    @Override
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
+        ArrayList<Register> list = new ArrayList<>();
+        for (Register reg : registers) {
+            if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
+                list.add(reg);
+            }
+        }
+        return new RegisterArray(list);
+    }
+
+    @Override
+    public RegisterAttributes[] getAttributesMap() {
+        return attributesMap.clone();
+    }
+
+    private final RegisterArray cpuCallerParameterRegisters = new RegisterArray(o0, o1, o2, o3, o4, o5);
+    private final RegisterArray cpuCalleeParameterRegisters = new RegisterArray(i0, i1, i2, i3, i4, i5);
+
+    private final RegisterArray fpuFloatJavaParameterRegisters = new RegisterArray(f0, f1, f2, f3, f4, f5, f6, f7);
+    private final RegisterArray fpuDoubleJavaParameterRegisters = new RegisterArray(d0, null, d2, null, d4, null, d6, null);
+
+    // @formatter:off
+    private final RegisterArray fpuFloatNativeParameterRegisters = new RegisterArray(
+                    f1,   f3,  f5,  f7,  f9, f11, f13, f15,
+                    f17, f19, f21, f23, f25, f27, f29, f31);
+
+    private final RegisterArray fpuDoubleNativeParameterRegisters = new RegisterArray(
+                     d0,  d2,  d4,  d6,  d8, d10, d12, d14,
+                    d16, d18, d20, d22, d24, d26, d28, d30);
+
+    private final RegisterArray callerSaveRegisters;
+
+    /**
+     * This lists all L and I registers which are saved in the register window.
+     */
+    private final RegisterArray windowSaveRegisters = new RegisterArray(
+                    l0, l1, l2, l3, l4, l5, l6, l7,
+                    i0, i1, i2, i3, i4, i5, i6, i7);
+    // @formatter:on
+
+    private static final RegisterArray reservedRegisters = new RegisterArray(sp, g0, g2);
+
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
+
+        int idx = 0;
+        for (Register reg : allRegisters) {
+            if (reservedRegistersList.contains(reg)) {
+                // skip reserved registers
+                continue;
+            }
+            if (reserveForHeapBase && reg.equals(g6)) {
+                // skip heap base register
+                continue;
+            }
+
+            registers[idx++] = reg;
+        }
+
+        assert idx == registers.length;
+        return new RegisterArray(registers);
+    }
+
+    public SPARCHotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
+        this(target, initAllocatable(target.arch, useCompressedOops));
+    }
+
+    public SPARCHotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
+        this.target = target;
+        this.allocatable = allocatable;
+        HashSet<Register> callerSaveSet = new HashSet<>(target.arch.getAvailableValueRegisters().asList());
+        for (Register cs : windowSaveRegisters) {
+            callerSaveSet.remove(cs);
+        }
+        this.callerSaveRegisters = new RegisterArray(callerSaveSet);
+        attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
+    }
+
+    @Override
+    public RegisterArray getCallerSaveRegisters() {
+        return callerSaveRegisters;
+    }
+
+    @Override
+    public RegisterArray getCalleeSaveRegisters() {
+        return null;
+    }
+
+    @Override
+    public boolean areAllAllocatableRegistersCallerSaved() {
+        return false;
+    }
+
+    @Override
+    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
+        HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
+        if (type == HotSpotCallingConventionType.JavaCall || type == HotSpotCallingConventionType.NativeCall) {
+            return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
+        }
+        if (type == HotSpotCallingConventionType.JavaCallee) {
+            return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
+        }
+        throw JVMCIError.shouldNotReachHere();
+    }
+
+    @Override
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
+        HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
+            case Int:
+            case Long:
+            case Object:
+                return hotspotType == HotSpotCallingConventionType.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
+            case Double:
+            case Float:
+                return fpuFloatJavaParameterRegisters;
+            default:
+                throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind);
+        }
+    }
+
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+                    ValueKindFactory<?> valueKindFactory) {
+        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+        int currentGeneral = 0;
+        int currentFloating = 0;
+        int currentStackOffset = 0;
+        boolean isNative = type == HotSpotCallingConventionType.NativeCall;
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
+            if (isNative) {
+                RegisterArray registerSet;
+                switch (kind) {
+                    case Byte:
+                    case Boolean:
+                    case Short:
+                    case Char:
+                    case Int:
+                    case Long:
+                    case Object:
+                        registerSet = generalParameterRegisters;
+                        break;
+                    case Double:
+                        registerSet = fpuDoubleNativeParameterRegisters;
+                        break;
+                    case Float:
+                        registerSet = fpuFloatNativeParameterRegisters;
+                        break;
+                    default:
+                        throw JVMCIError.shouldNotReachHere();
+                }
+                if (i < registerSet.size()) {
+                    locations[i] = registerSet.get(i).asValue(valueKindFactory.getValueKind(kind));
+                    currentStackOffset += target.arch.getWordSize();
+                }
+            } else {
+                switch (kind) {
+                    case Byte:
+                    case Boolean:
+                    case Short:
+                    case Char:
+                    case Int:
+                    case Long:
+                    case Object:
+                        if (currentGeneral < generalParameterRegisters.size()) {
+                            Register register = generalParameterRegisters.get(currentGeneral++);
+                            locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                        }
+                        break;
+                    case Double:
+                        if (currentFloating < fpuFloatJavaParameterRegisters.size()) {
+                            if (currentFloating % 2 != 0) {
+                                // Make register number even to be a double reg
+                                currentFloating++;
+                            }
+                            Register register = fpuDoubleJavaParameterRegisters.get(currentFloating);
+                            currentFloating += 2; // Only every second is a double register
+                            locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                        }
+                        break;
+                    case Float:
+                        if (currentFloating < fpuFloatJavaParameterRegisters.size()) {
+                            Register register = fpuFloatJavaParameterRegisters.get(currentFloating++);
+                            locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                        }
+                        break;
+                    default:
+                        throw JVMCIError.shouldNotReachHere();
+                }
+            }
+
+            if (locations[i] == null) {
+                ValueKind<?> valueKind = valueKindFactory.getValueKind(kind);
+                int typeSize = valueKind.getPlatformKind().getSizeInBytes();
+                if (isNative) {
+                    currentStackOffset += target.arch.getWordSize() - typeSize;
+                }
+                currentStackOffset = roundUp(currentStackOffset, typeSize);
+                int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE;
+                locations[i] = StackSlot.get(valueKind, slotOffset, !type.out);
+                currentStackOffset += typeSize;
+            }
+        }
+
+        JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind();
+        AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
+    }
+
+    private static int roundUp(int number, int mod) {
+        return ((number + mod - 1) / mod) * mod;
+    }
+
+    @Override
+    public Register getReturnRegister(JavaKind kind) {
+        return getReturnRegister(kind, HotSpotCallingConventionType.JavaCallee);
+    }
+
+    private static Register getReturnRegister(JavaKind kind, HotSpotCallingConventionType type) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+            case Object:
+                return type == HotSpotCallingConventionType.JavaCallee ? i0 : o0;
+            case Float:
+                return f0;
+            case Double:
+                return d0;
+            case Void:
+            case Illegal:
+                return null;
+            default:
+                throw new UnsupportedOperationException("no return register for type " + kind);
+        }
+    }
+
+    @Override
+    public Register getFrameRegister() {
+        return sp;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot.sparc;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * Used to access SPARC specific native configuration details.
+ */
+class SPARCHotSpotVMConfig extends HotSpotVMConfigAccess {
+
+    SPARCHotSpotVMConfig(HotSpotVMConfigStore config) {
+        super(config);
+    }
+
+    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
+
+    // CPU capabilities
+    final int vmVersionFeatures = getFieldValue("VM_Version::_features", Integer.class, "int");
+
+    // SPARC specific values
+    final int sparcVis3Instructions = getConstant("VM_Version::vis3_instructions_m", Integer.class);
+    final int sparcVis2Instructions = getConstant("VM_Version::vis2_instructions_m", Integer.class);
+    final int sparcVis1Instructions = getConstant("VM_Version::vis1_instructions_m", Integer.class);
+    final int sparcCbcondInstructions = getConstant("VM_Version::cbcond_instructions_m", Integer.class);
+    final int sparcV8Instructions = getConstant("VM_Version::v8_instructions_m", Integer.class);
+    final int sparcHardwareMul32 = getConstant("VM_Version::hardware_mul32_m", Integer.class);
+    final int sparcHardwareDiv32 = getConstant("VM_Version::hardware_div32_m", Integer.class);
+    final int sparcHardwareFsmuld = getConstant("VM_Version::hardware_fsmuld_m", Integer.class);
+    final int sparcHardwarePopc = getConstant("VM_Version::hardware_popc_m", Integer.class);
+    final int sparcV9Instructions = getConstant("VM_Version::v9_instructions_m", Integer.class);
+    final int sparcSun4v = getConstant("VM_Version::sun4v_m", Integer.class);
+    final int sparcBlkInitInstructions = getConstant("VM_Version::blk_init_instructions_m", Integer.class);
+    final int sparcFmafInstructions = getConstant("VM_Version::fmaf_instructions_m", Integer.class);
+    final int sparcFmauInstructions = getConstant("VM_Version::fmau_instructions_m", Integer.class);
+    final int sparcSparc64Family = getConstant("VM_Version::sparc64_family_m", Integer.class);
+    final int sparcMFamily = getConstant("VM_Version::M_family_m", Integer.class);
+    final int sparcTFamily = getConstant("VM_Version::T_family_m", Integer.class);
+    final int sparcT1Model = getConstant("VM_Version::T1_model_m", Integer.class);
+    final int sparcSparc5Instructions = getConstant("VM_Version::sparc5_instructions_m", Integer.class);
+    final int sparcAesInstructions = getConstant("VM_Version::aes_instructions_m", Integer.class);
+    final int sparcSha1Instruction = getConstant("VM_Version::sha1_instruction_m", Integer.class);
+    final int sparcSha256Instruction = getConstant("VM_Version::sha256_instruction_m", Integer.class);
+    final int sparcSha512Instruction = getConstant("VM_Version::sha512_instruction_m", Integer.class);
+
+    final boolean useBlockZeroing = getFlag("UseBlockZeroing", Boolean.class);
+    final int blockZeroingLowLimit = getFlag("BlockZeroingLowLimit", Integer.class);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.common.InitTimer.timer;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+
+import java.lang.reflect.Executable;
+
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import sun.misc.Unsafe;
+
+/**
+ * Calls from Java into HotSpot. The behavior of all the methods in this class that take a native
+ * pointer as an argument (e.g., {@link #getSymbol(long)}) is undefined if the argument does not
+ * denote a valid native object.
+ */
+final class CompilerToVM {
+    /**
+     * Initializes the native part of the JVMCI runtime.
+     */
+    private static native void registerNatives();
+
+    static {
+        initialize();
+    }
+
+    @SuppressWarnings("try")
+    private static void initialize() {
+        try (InitTimer t = timer("CompilerToVM.registerNatives")) {
+            registerNatives();
+        }
+    }
+
+    /**
+     * Gets the {@link CompilerToVM} instance associated with the singleton
+     * {@link HotSpotJVMCIRuntime} instance.
+     */
+    public static CompilerToVM compilerToVM() {
+        return runtime().getCompilerToVM();
+    }
+
+    /**
+     * Copies the original bytecode of {@code method} into a new byte array and returns it.
+     *
+     * @return a new byte array containing the original bytecode of {@code method}
+     */
+    native byte[] getBytecode(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Gets the number of entries in {@code method}'s exception handler table or 0 if it has no
+     * exception handler table.
+     */
+    native int getExceptionTableLength(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Gets the address of the first entry in {@code method}'s exception handler table.
+     *
+     * Each entry is a native object described by these fields:
+     *
+     * <ul>
+     * <li>{@link HotSpotVMConfig#exceptionTableElementSize}</li>
+     * <li>{@link HotSpotVMConfig#exceptionTableElementStartPcOffset}</li>
+     * <li>{@link HotSpotVMConfig#exceptionTableElementEndPcOffset}</li>
+     * <li>{@link HotSpotVMConfig#exceptionTableElementHandlerPcOffset}</li>
+     * <li>{@link HotSpotVMConfig#exceptionTableElementCatchTypeIndexOffset}
+     * </ul>
+     *
+     * @return 0 if {@code method} has no exception handlers (i.e.
+     *         {@code getExceptionTableLength(method) == 0})
+     */
+    native long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Determines whether {@code method} is currently compilable by the JVMCI compiler being used by
+     * the VM. This can return false if JVMCI compilation failed earlier for {@code method}, a
+     * breakpoint is currently set in {@code method} or {@code method} contains other bytecode
+     * features that require special handling by the VM.
+     */
+    native boolean isCompilable(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Determines if {@code method} is targeted by a VM directive (e.g.,
+     * {@code -XX:CompileCommand=dontinline,<pattern>}) or annotation (e.g.,
+     * {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
+     */
+    native boolean hasNeverInlineDirective(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Determines if {@code method} should be inlined at any cost. This could be because:
+     * <ul>
+     * <li>a CompileOracle directive may forces inlining of this methods</li>
+     * <li>an annotation forces inlining of this method</li>
+     * </ul>
+     */
+    native boolean shouldInlineMethod(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Used to implement {@link ResolvedJavaType#findUniqueConcreteMethod(ResolvedJavaMethod)}.
+     *
+     * @param method the method on which to base the search
+     * @param actualHolderType the best known type of receiver
+     * @return the method result or 0 is there is no unique concrete method for {@code method}
+     */
+    native HotSpotResolvedJavaMethodImpl findUniqueConcreteMethod(HotSpotResolvedObjectTypeImpl actualHolderType, HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Gets the implementor for the interface class {@code type}.
+     *
+     * @return the implementor if there is a single implementor, 0 if there is no implementor, or
+     *         {@code type} itself if there is more than one implementor
+     */
+    native HotSpotResolvedObjectTypeImpl getImplementor(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Determines if {@code method} is ignored by security stack walks.
+     */
+    native boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Converts a name to a type.
+     *
+     * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
+     * @param accessingClass the context of resolution (must not be null)
+     * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
+     *            either return a {@link ResolvedJavaType} or throw an exception
+     * @return the type for {@code name} or 0 if resolution failed and {@code resolve == false}
+     * @throws LinkageError if {@code resolve == true} and the resolution failed
+     */
+    native HotSpotResolvedObjectTypeImpl lookupType(String name, Class<?> accessingClass, boolean resolve);
+
+    /**
+     * Resolves the entry at index {@code cpi} in {@code constantPool} to an object.
+     *
+     * The behavior of this method is undefined if {@code cpi} does not denote one of the following
+     * entry types: {@code JVM_CONSTANT_MethodHandle}, {@code JVM_CONSTANT_MethodHandleInError},
+     * {@code JVM_CONSTANT_MethodType} and {@code JVM_CONSTANT_MethodTypeInError}.
+     */
+    native Object resolveConstantInPool(HotSpotConstantPool constantPool, int cpi);
+
+    /**
+     * Resolves the entry at index {@code cpi} in {@code constantPool} to an object, looking in the
+     * constant pool cache first.
+     *
+     * The behavior of this method is undefined if {@code cpi} does not denote a
+     * {@code JVM_CONSTANT_String} entry.
+     */
+    native Object resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi);
+
+    /**
+     * Gets the {@code JVM_CONSTANT_NameAndType} index from the entry at index {@code cpi} in
+     * {@code constantPool}.
+     *
+     * The behavior of this method is undefined if {@code cpi} does not denote an entry containing a
+     * {@code JVM_CONSTANT_NameAndType} index.
+     */
+    native int lookupNameAndTypeRefIndexInPool(HotSpotConstantPool constantPool, int cpi);
+
+    /**
+     * Gets the name of the {@code JVM_CONSTANT_NameAndType} entry referenced by another entry
+     * denoted by {@code which} in {@code constantPool}.
+     *
+     * The behavior of this method is undefined if {@code which} does not denote a entry that
+     * references a {@code JVM_CONSTANT_NameAndType} entry.
+     */
+    native String lookupNameInPool(HotSpotConstantPool constantPool, int which);
+
+    /**
+     * Gets the signature of the {@code JVM_CONSTANT_NameAndType} entry referenced by another entry
+     * denoted by {@code which} in {@code constantPool}.
+     *
+     * The behavior of this method is undefined if {@code which} does not denote a entry that
+     * references a {@code JVM_CONSTANT_NameAndType} entry.
+     */
+    native String lookupSignatureInPool(HotSpotConstantPool constantPool, int which);
+
+    /**
+     * Gets the {@code JVM_CONSTANT_Class} index from the entry at index {@code cpi} in
+     * {@code constantPool}.
+     *
+     * The behavior of this method is undefined if {@code cpi} does not denote an entry containing a
+     * {@code JVM_CONSTANT_Class} index.
+     */
+    native int lookupKlassRefIndexInPool(HotSpotConstantPool constantPool, int cpi);
+
+    /**
+     * Looks up a class denoted by the {@code JVM_CONSTANT_Class} entry at index {@code cpi} in
+     * {@code constantPool}. This method does not perform any resolution.
+     *
+     * The behavior of this method is undefined if {@code cpi} does not denote a
+     * {@code JVM_CONSTANT_Class} entry.
+     *
+     * @return the resolved class entry or a String otherwise
+     */
+    native Object lookupKlassInPool(HotSpotConstantPool constantPool, int cpi);
+
+    /**
+     * Looks up a method denoted by the entry at index {@code cpi} in {@code constantPool}. This
+     * method does not perform any resolution.
+     *
+     * The behavior of this method is undefined if {@code cpi} does not denote an entry representing
+     * a method.
+     *
+     * @param opcode the opcode of the instruction for which the lookup is being performed or
+     *            {@code -1}. If non-negative, then resolution checks specific to the bytecode it
+     *            denotes are performed if the method is already resolved. Should any of these
+     *            checks fail, 0 is returned.
+     * @return the resolved method entry, 0 otherwise
+     */
+    native HotSpotResolvedJavaMethodImpl lookupMethodInPool(HotSpotConstantPool constantPool, int cpi, byte opcode);
+
+    /**
+     * Ensures that the type referenced by the specified {@code JVM_CONSTANT_InvokeDynamic} entry at
+     * index {@code cpi} in {@code constantPool} is loaded and initialized.
+     *
+     * The behavior of this method is undefined if {@code cpi} does not denote a
+     * {@code JVM_CONSTANT_InvokeDynamic} entry.
+     */
+    native void resolveInvokeDynamicInPool(HotSpotConstantPool constantPool, int cpi);
+
+    /**
+     * If {@code cpi} denotes an entry representing a
+     * <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">signature
+     * polymorphic</a> method, this method ensures that the type referenced by the entry is loaded
+     * and initialized. It {@code cpi} does not denote a signature polymorphic method, this method
+     * does nothing.
+     */
+    native void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
+
+    /**
+     * Gets the list of type names (in the format of {@link JavaType#getName()}) denoting the
+     * classes that define signature polymorphic methods.
+     */
+    native String[] getSignaturePolymorphicHolders();
+
+    /**
+     * Gets the resolved type denoted by the entry at index {@code cpi} in {@code constantPool}.
+     *
+     * The behavior of this method is undefined if {@code cpi} does not denote an entry representing
+     * a class.
+     *
+     * @throws LinkageError if resolution failed
+     */
+    native HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool, int cpi) throws LinkageError;
+
+    /**
+     * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry at index {@code cpi} in
+     * {@code constantPool}. The values returned in {@code info} are:
+     *
+     * <pre>
+     *     [ flags,  // fieldDescriptor::access_flags()
+     *       offset, // fieldDescriptor::offset()
+     *       index   // fieldDescriptor::index()
+     *     ]
+     * </pre>
+     *
+     * The values encoded in {@code info} are only valid if the field is resolved. The behavior of
+     * this method is undefined if {@code cpi} does not denote a {@code JVM_CONSTANT_Field} entry.
+     *
+     * @param info an array in which the details of the field are returned
+     * @return the type defining the field if resolution is successful, 0 otherwise
+     */
+    native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, byte opcode, int[] info);
+
+    /**
+     * Converts {@code cpci} from an index into the cache for {@code constantPool} to an index
+     * directly into {@code constantPool}.
+     *
+     * The behavior of this method is undefined if {@code ccpi} is an invalid constant pool cache
+     * index.
+     */
+    native int constantPoolRemapInstructionOperandFromCache(HotSpotConstantPool constantPool, int cpci);
+
+    /**
+     * Gets the appendix object (if any) associated with the entry at index {@code cpi} in
+     * {@code constantPool}.
+     */
+    native Object lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi);
+
+    /**
+     * Installs the result of a compilation into the code cache.
+     *
+     * @param target the target where this code should be installed
+     * @param compiledCode the result of a compilation
+     * @param code the details of the installed CodeBlob are written to this object
+     * @return the outcome of the installation which will be one of
+     *         {@link HotSpotVMConfig#codeInstallResultOk},
+     *         {@link HotSpotVMConfig#codeInstallResultCacheFull},
+     *         {@link HotSpotVMConfig#codeInstallResultCodeTooLarge},
+     *         {@link HotSpotVMConfig#codeInstallResultDependenciesFailed} or
+     *         {@link HotSpotVMConfig#codeInstallResultDependenciesInvalid}.
+     * @throws JVMCIError if there is something wrong with the compiled code or the associated
+     *             metadata.
+     */
+    native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog);
+
+    /**
+     * Resets all compilation statistics.
+     */
+    native void resetCompilationStatistics();
+
+    /**
+     * Reads the database of VM info. The return value encodes the info in a nested object array
+     * that is described by the pseudo Java object {@code info} below:
+     *
+     * <pre>
+     *     info = [
+     *         VMField[] vmFields,
+     *         [String name, Long size, ...] vmTypeSizes,
+     *         [String name, Long value, ...] vmConstants,
+     *         [String name, Long value, ...] vmAddresses,
+     *         VMFlag[] vmFlags
+     *         VMIntrinsicMethod[] vmIntrinsics
+     *     ]
+     * </pre>
+     *
+     * @return VM info as encoded above
+     */
+    native Object[] readConfiguration();
+
+    /**
+     * Resolves the implementation of {@code method} for virtual dispatches on objects of dynamic
+     * type {@code exactReceiver}. This resolution process only searches "up" the class hierarchy of
+     * {@code exactReceiver}.
+     *
+     * @param caller the caller or context type used to perform access checks
+     * @return the link-time resolved method (might be abstract) or {@code 0} if it can not be
+     *         linked
+     */
+    native HotSpotResolvedJavaMethodImpl resolveMethod(HotSpotResolvedObjectTypeImpl exactReceiver, HotSpotResolvedJavaMethodImpl method, HotSpotResolvedObjectTypeImpl caller);
+
+    /**
+     * Gets the static initializer of {@code type}.
+     *
+     * @return 0 if {@code type} has no static initializer
+     */
+    native HotSpotResolvedJavaMethodImpl getClassInitializer(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Determines if {@code type} or any of its currently loaded subclasses overrides
+     * {@code Object.finalize()}.
+     */
+    native boolean hasFinalizableSubclass(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Gets the method corresponding to {@code executable}.
+     */
+    native HotSpotResolvedJavaMethodImpl asResolvedJavaMethod(Executable executable);
+
+    /**
+     * Gets the maximum absolute offset of a PC relative call to {@code address} from any position
+     * in the code cache.
+     *
+     * @param address an address that may be called from any code in the code cache
+     * @return -1 if {@code address == 0}
+     */
+    native long getMaxCallTargetOffset(long address);
+
+    /**
+     * Gets a textual disassembly of {@code codeBlob}.
+     *
+     * @return a non-zero length string containing a disassembly of {@code codeBlob} or null if
+     *         {@code codeBlob} could not be disassembled for some reason
+     */
+    // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage
+    synchronized native String disassembleCodeBlob(InstalledCode installedCode);
+
+    /**
+     * Gets a stack trace element for {@code method} at bytecode index {@code bci}.
+     */
+    native StackTraceElement getStackTraceElement(HotSpotResolvedJavaMethodImpl method, int bci);
+
+    /**
+     * Executes some {@code installedCode} with arguments {@code args}.
+     *
+     * @return the result of executing {@code installedCode}
+     * @throws InvalidInstalledCodeException if {@code installedCode} has been invalidated
+     */
+    native Object executeInstalledCode(Object[] args, InstalledCode installedCode) throws InvalidInstalledCodeException;
+
+    /**
+     * Gets the line number table for {@code method}. The line number table is encoded as (bci,
+     * source line number) pairs.
+     *
+     * @return the line number table for {@code method} or null if it doesn't have one
+     */
+    native long[] getLineNumberTable(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Gets the number of entries in the local variable table for {@code method}.
+     *
+     * @return the number of entries in the local variable table for {@code method}
+     */
+    native int getLocalVariableTableLength(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Gets the address of the first entry in the local variable table for {@code method}.
+     *
+     * Each entry is a native object described by these fields:
+     *
+     * <ul>
+     * <li>{@link HotSpotVMConfig#localVariableTableElementSize}</li>
+     * <li>{@link HotSpotVMConfig#localVariableTableElementLengthOffset}</li>
+     * <li>{@link HotSpotVMConfig#localVariableTableElementNameCpIndexOffset}</li>
+     * <li>{@link HotSpotVMConfig#localVariableTableElementDescriptorCpIndexOffset}</li>
+     * <li>{@link HotSpotVMConfig#localVariableTableElementSlotOffset}
+     * <li>{@link HotSpotVMConfig#localVariableTableElementStartBciOffset}
+     * </ul>
+     *
+     * @return 0 if {@code method} does not have a local variable table
+     */
+    native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Reads an object pointer within a VM data structure. That is, any {@link VMField} whose
+     * {@link VMField#type type} is {@code "oop"} (e.g., {@code ArrayKlass::_component_mirror},
+     * {@code Klass::_java_mirror}, {@code JavaThread::_threadObj}).
+     *
+     * Note that {@link Unsafe#getObject(Object, long)} cannot be used for this since it does a
+     * {@code narrowOop} read if the VM is using compressed oops whereas oops within VM data
+     * structures are (currently) always uncompressed.
+     *
+     * @param address address of an oop field within a VM data structure
+     */
+    native Object readUncompressedOop(long address);
+
+    /**
+     * Determines if {@code method} should not be inlined or compiled.
+     */
+    native void doNotInlineOrCompile(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Invalidates the profiling information for {@code method} and (re)initializes it such that
+     * profiling restarts upon its next invocation.
+     */
+    native void reprofile(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be
+     * raised the next time {@code installedCode} is executed.
+     */
+    native void invalidateInstalledCode(InstalledCode installedCode);
+
+    /**
+     * Collects the current values of all JVMCI benchmark counters, summed up over all threads.
+     */
+    native long[] collectCounters();
+
+    /**
+     * Determines if {@code metaspaceMethodData} is mature.
+     */
+    native boolean isMature(long metaspaceMethodData);
+
+    /**
+     * Generate a unique id to identify the result of the compile.
+     */
+    native int allocateCompileId(HotSpotResolvedJavaMethodImpl method, int entryBCI);
+
+    /**
+     * Determines if {@code method} has OSR compiled code identified by {@code entryBCI} for
+     * compilation level {@code level}.
+     */
+    native boolean hasCompiledCodeForOSR(HotSpotResolvedJavaMethodImpl method, int entryBCI, int level);
+
+    /**
+     * Gets the value of {@code metaspaceSymbol} as a String.
+     */
+    native String getSymbol(long metaspaceSymbol);
+
+    /**
+     * Looks for the next Java stack frame matching an entry in {@code methods}.
+     *
+     * @param frame the starting point of the search, where {@code null} refers to the topmost frame
+     * @param methods the methods to look for, where {@code null} means that any frame is returned
+     * @return the frame, or {@code null} if the end of the stack was reached during the search
+     */
+    native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, ResolvedJavaMethod[] methods, int initialSkip);
+
+    /**
+     * Materializes all virtual objects within {@code stackFrame} and updates its locals.
+     *
+     * @param invalidate if {@code true}, the compiled method for the stack frame will be
+     *            invalidated
+     */
+    native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
+
+    /**
+     * Gets the v-table index for interface method {@code method} in the receiver {@code type} or
+     * {@link HotSpotVMConfig#invalidVtableIndex} if {@code method} is not in {@code type}'s
+     * v-table.
+     *
+     * @throws InternalError if {@code type} is an interface or {@code method} is not held by an
+     *             interface or class represented by {@code type} is not initialized
+     */
+    native int getVtableIndexForInterfaceMethod(HotSpotResolvedObjectTypeImpl type, HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Determines if debug info should also be emitted at non-safepoint locations.
+     */
+    native boolean shouldDebugNonSafepoints();
+
+    /**
+     * Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to the
+     * HotSpot's log stream.
+     *
+     * @exception NullPointerException if {@code bytes == null}
+     * @exception IndexOutOfBoundsException if copying would cause access of data outside array
+     *                bounds
+     */
+    native void writeDebugOutput(byte[] bytes, int offset, int length);
+
+    /**
+     * Flush HotSpot's log stream.
+     */
+    native void flushDebugOutput();
+
+    /**
+     * Read a HotSpot Method* value from the memory location described by {@code base} plus
+     * {@code displacement} and return the {@link HotSpotResolvedJavaMethodImpl} wrapping it. This
+     * method does no checking that the memory location actually contains a valid pointer and may
+     * crash the VM if an invalid location is provided. If the {@code base} is null then
+     * {@code displacement} is used by itself. If {@code base} is a
+     * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
+     * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
+     * and added to {@code displacement}. Any other non-null object type causes an
+     * {@link IllegalArgumentException} to be thrown.
+     *
+     * @param base an object to read from or null
+     * @param displacement
+     * @return null or the resolved method for this location
+     */
+    native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, long displacement);
+
+    /**
+     * Gets the {@code ConstantPool*} associated with {@code object} and returns a
+     * {@link HotSpotConstantPool} wrapping it.
+     *
+     * @param object a {@link HotSpotResolvedJavaMethodImpl} or
+     *            {@link HotSpotResolvedObjectTypeImpl} object
+     * @return a {@link HotSpotConstantPool} wrapping the {@code ConstantPool*} associated with
+     *         {@code object}
+     * @throws NullPointerException if {@code object == null}
+     * @throws IllegalArgumentException if {@code object} is neither a
+     *             {@link HotSpotResolvedJavaMethodImpl} nor a {@link HotSpotResolvedObjectTypeImpl}
+     */
+    native HotSpotConstantPool getConstantPool(Object object);
+
+    /**
+     * Read a HotSpot Klass* value from the memory location described by {@code base} plus
+     * {@code displacement} and return the {@link HotSpotResolvedObjectTypeImpl} wrapping it. This
+     * method does no checking that the memory location actually contains a valid pointer and may
+     * crash the VM if an invalid location is provided. If the {@code base} is null then
+     * {@code displacement} is used by itself. If {@code base} is a
+     * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
+     * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
+     * and added to {@code displacement}. Any other non-null object type causes an
+     * {@link IllegalArgumentException} to be thrown.
+     *
+     * @param base an object to read from or null
+     * @param displacement
+     * @param compressed true if the location contains a compressed Klass*
+     * @return null or the resolved method for this location
+     */
+    native HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement, boolean compressed);
+
+    /**
+     * Return the size of the HotSpot ProfileData* pointed at by {@code position}. If
+     * {@code position} is outside the space of the MethodData then an
+     * {@link IllegalArgumentException} is thrown. A {@code position} inside the MethodData but that
+     * isn't pointing at a valid ProfileData will crash the VM.
+     *
+     * @param metaspaceMethodData
+     * @param position
+     * @return the size of the ProfileData item pointed at by {@code position}
+     * @throws IllegalArgumentException if an out of range position is given
+     */
+    native int methodDataProfileDataSize(long metaspaceMethodData, int position);
+
+    /**
+     * Return the amount of native stack required for the interpreter frames represented by
+     * {@code frame}. This is used when emitting the stack banging code to ensure that there is
+     * enough space for the frames during deoptimization.
+     *
+     * @param frame
+     * @return the number of bytes required for deoptimization of this frame state
+     */
+    native int interpreterFrameSize(BytecodeFrame frame);
+
+    /**
+     * Invokes non-public method {@code java.lang.invoke.LambdaForm.compileToBytecode()} on
+     * {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance).
+     */
+    native void compileToBytecode(Object lambdaForm);
+
+    /**
+     * Gets the value of the VM flag named {@code name}.
+     *
+     * @param name name of a VM option
+     * @return {@code this} if the named VM option doesn't exist, a {@link String} or {@code null}
+     *         if its type is {@code ccstr} or {@code ccstrlist}, a {@link Double} if its type is
+     *         {@code double}, a {@link Boolean} if its type is {@code bool} otherwise a
+     *         {@link Long}
+     */
+    native Object getFlagValue(String name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/EmptyEventProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * An empty implementation for {@link EventProvider}. This implementation is used when no logging is
+ * requested.
+ */
+final class EmptyEventProvider implements EventProvider {
+
+    static InternalError shouldNotReachHere() {
+        throw new InternalError("should not reach here");
+    }
+
+    @Override
+    public CompilationEvent newCompilationEvent() {
+        return new EmptyCompilationEvent();
+    }
+
+    static class EmptyCompilationEvent implements CompilationEvent {
+        public void commit() {
+            throw shouldNotReachHere();
+        }
+
+        public boolean shouldWrite() {
+            // Events of this class should never been written.
+            return false;
+        }
+
+        public void begin() {
+        }
+
+        public void end() {
+        }
+
+        public void setMethod(String method) {
+            throw shouldNotReachHere();
+        }
+
+        public void setCompileId(int compileId) {
+            throw shouldNotReachHere();
+        }
+
+        public void setCompileLevel(int compileLevel) {
+            throw shouldNotReachHere();
+        }
+
+        public void setSucceeded(boolean succeeded) {
+            throw shouldNotReachHere();
+        }
+
+        public void setIsOsr(boolean isOsr) {
+            throw shouldNotReachHere();
+        }
+
+        public void setCodeSize(int codeSize) {
+            throw shouldNotReachHere();
+        }
+
+        public void setInlinedBytes(int inlinedBytes) {
+            throw shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public CompilerFailureEvent newCompilerFailureEvent() {
+        return new EmptyCompilerFailureEvent();
+    }
+
+    static class EmptyCompilerFailureEvent implements CompilerFailureEvent {
+        public void commit() {
+            throw shouldNotReachHere();
+        }
+
+        public boolean shouldWrite() {
+            // Events of this class should never been written.
+            return false;
+        }
+
+        public void setCompileId(int compileId) {
+            throw shouldNotReachHere();
+        }
+
+        public void setMessage(String message) {
+            throw shouldNotReachHere();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/EventProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.hotspot.EmptyEventProvider.EmptyCompilationEvent;
+import jdk.vm.ci.hotspot.EmptyEventProvider.EmptyCompilerFailureEvent;
+
+/**
+ * Service for logging compiler related events.
+ */
+public interface EventProvider {
+
+    /**
+     * Creates and returns an empty implementation for {@link EventProvider}. This implementation
+     * can be used when no logging is requested.
+     */
+    static EventProvider createEmptyEventProvider() {
+        return new EmptyEventProvider();
+    }
+
+    /**
+     * Creates and returns an empty implementation for {@link CompilationEvent}.
+     */
+    static CompilationEvent createEmptyCompilationEvent() {
+        return new EmptyCompilationEvent();
+    }
+
+    /**
+     * Creates and returns an empty implementation for {@link CompilationEvent}.
+     */
+    static CompilerFailureEvent createEmptyCompilerFailureEvent() {
+        return new EmptyCompilerFailureEvent();
+    }
+
+    /**
+     * An instant event is an event that is not considered to have taken any time.
+     */
+    public interface InstantEvent {
+        /**
+         * Commits the event.
+         */
+        void commit();
+
+        /**
+         * Determines if this particular event instance would be committed to the data stream right
+         * now if application called {@link #commit()}. This in turn depends on whether the event is
+         * enabled and possible other factors.
+         *
+         * @return if this event would be committed on a call to {@link #commit()}.
+         */
+        boolean shouldWrite();
+    }
+
+    /**
+     * Timed events describe an operation that somehow consumes time.
+     */
+    public interface TimedEvent extends InstantEvent {
+        /**
+         * Starts the timing for this event.
+         */
+        void begin();
+
+        /**
+         * Ends the timing period for this event.
+         */
+        void end();
+    }
+
+    /**
+     * Creates a new {@link CompilationEvent}.
+     *
+     * @return a compilation event
+     */
+    CompilationEvent newCompilationEvent();
+
+    /**
+     * A compilation event.
+     */
+    public interface CompilationEvent extends TimedEvent {
+        void setMethod(String method);
+
+        void setCompileId(int compileId);
+
+        void setCompileLevel(int compileLevel);
+
+        void setSucceeded(boolean succeeded);
+
+        void setIsOsr(boolean isOsr);
+
+        void setCodeSize(int codeSize);
+
+        void setInlinedBytes(int inlinedBytes);
+    }
+
+    /**
+     * Creates a new {@link CompilerFailureEvent}.
+     *
+     * @return a compiler failure event
+     */
+    CompilerFailureEvent newCompilerFailureEvent();
+
+    /**
+     * A compiler failure event.
+     */
+    public interface CompilerFailureEvent extends InstantEvent {
+        void setCompileId(int compileId);
+
+        void setMessage(String message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.CallingConvention.Type;
+
+public enum HotSpotCallingConventionType implements CallingConvention.Type {
+    /**
+     * A request for the outgoing argument locations at a call site to Java code.
+     */
+    JavaCall(true),
+
+    /**
+     * A request for the incoming argument locations.
+     */
+    JavaCallee(false),
+
+    /**
+     * A request for the outgoing argument locations at a call site to external native code that
+     * complies with the platform ABI.
+     */
+    NativeCall(true);
+
+    /**
+     * Determines if this is a request for the outgoing argument locations at a call site.
+     */
+    public final boolean out;
+
+    public static final Type[] VALUES = values();
+
+    HotSpotCallingConventionType(boolean out) {
+        this.out = out;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.Map;
+
+import jdk.vm.ci.code.BailoutException;
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.CompiledCode;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.site.Call;
+import jdk.vm.ci.code.site.Mark;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.SpeculationLog;
+
+/**
+ * HotSpot implementation of {@link CodeCacheProvider}.
+ */
+public class HotSpotCodeCacheProvider implements CodeCacheProvider {
+
+    protected final HotSpotJVMCIRuntimeProvider runtime;
+    protected final HotSpotVMConfig config;
+    protected final TargetDescription target;
+    protected final RegisterConfig regConfig;
+
+    public HotSpotCodeCacheProvider(HotSpotJVMCIRuntimeProvider runtime, HotSpotVMConfig config, TargetDescription target, RegisterConfig regConfig) {
+        this.runtime = runtime;
+        this.config = config;
+        this.target = target;
+        this.regConfig = regConfig;
+    }
+
+    @Override
+    public String getMarkName(Mark mark) {
+        int markId = (int) mark.id;
+        HotSpotVMConfigStore store = runtime.getConfigStore();
+        for (Map.Entry<String, Long> e : store.getConstants().entrySet()) {
+            String name = e.getKey();
+            if (name.startsWith("MARKID_") && e.getValue() == markId) {
+                return name;
+            }
+        }
+        return CodeCacheProvider.super.getMarkName(mark);
+    }
+
+    /**
+     * Decodes a call target to a mnemonic if possible.
+     */
+    @Override
+    public String getTargetName(Call call) {
+        if (call.target instanceof HotSpotForeignCallTarget) {
+            long address = ((HotSpotForeignCallTarget) call.target).address;
+            HotSpotVMConfigStore store = runtime.getConfigStore();
+            for (Map.Entry<String, VMField> e : store.getFields().entrySet()) {
+                VMField field = e.getValue();
+                if (field.isStatic() && field.value != null && field.value == address) {
+                    return e.getValue() + ":0x" + Long.toHexString(address);
+                }
+            }
+        }
+        return CodeCacheProvider.super.getTargetName(call);
+    }
+
+    @Override
+    public RegisterConfig getRegisterConfig() {
+        return regConfig;
+    }
+
+    @Override
+    public int getMinimumOutgoingSize() {
+        return runtime.getConfig().runtimeCallStackSize;
+    }
+
+    private InstalledCode logOrDump(InstalledCode installedCode, CompiledCode compiledCode) {
+        ((HotSpotJVMCIRuntime) runtime).notifyInstall(this, installedCode, compiledCode);
+        return installedCode;
+    }
+
+    public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) {
+        InstalledCode resultInstalledCode;
+        if (installedCode == null) {
+            if (method == null) {
+                // Must be a stub
+                resultInstalledCode = new HotSpotRuntimeStub(((HotSpotCompiledCode) compiledCode).getName());
+            } else {
+                resultInstalledCode = new HotSpotNmethod((HotSpotResolvedJavaMethod) method, ((HotSpotCompiledCode) compiledCode).getName(), isDefault);
+            }
+        } else {
+            resultInstalledCode = installedCode;
+        }
+
+        HotSpotSpeculationLog speculationLog = (log != null && log.hasSpeculations()) ? (HotSpotSpeculationLog) log : null;
+
+        int result = runtime.getCompilerToVM().installCode(target, (HotSpotCompiledCode) compiledCode, resultInstalledCode, speculationLog);
+        if (result != config.codeInstallResultOk) {
+            String resultDesc = config.getCodeInstallResultDescription(result);
+            if (compiledCode instanceof HotSpotCompiledNmethod) {
+                HotSpotCompiledNmethod compiledNmethod = (HotSpotCompiledNmethod) compiledCode;
+                String msg = compiledNmethod.getInstallationFailureMessage();
+                if (msg != null) {
+                    msg = String.format("Code installation failed: %s%n%s", resultDesc, msg);
+                } else {
+                    msg = String.format("Code installation failed: %s", resultDesc);
+                }
+                if (result == config.codeInstallResultDependenciesInvalid) {
+                    throw new AssertionError(resultDesc + " " + msg);
+                }
+                throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg);
+            } else {
+                throw new BailoutException("Error installing %s: %s", ((HotSpotCompiledCode) compiledCode).getName(), resultDesc);
+            }
+        }
+        return logOrDump(resultInstalledCode, compiledCode);
+    }
+
+    public void invalidateInstalledCode(InstalledCode installedCode) {
+        runtime.getCompilerToVM().invalidateInstalledCode(installedCode);
+    }
+
+    @Override
+    public TargetDescription getTarget() {
+        return target;
+    }
+
+    public String disassemble(InstalledCode code) {
+        if (code.isValid()) {
+            return runtime.getCompilerToVM().disassembleCodeBlob(code);
+        }
+        return null;
+    }
+
+    public SpeculationLog createSpeculationLog() {
+        return new HotSpotSpeculationLog();
+    }
+
+    public long getMaxCallTargetOffset(long address) {
+        return runtime.getCompilerToVM().getMaxCallTargetOffset(address);
+    }
+
+    public boolean shouldDebugNonSafepoints() {
+        return runtime.getCompilerToVM().shouldDebugNonSafepoints();
+    }
+
+    public int interpreterFrameSize(BytecodeFrame pos) {
+        return runtime.getCompilerToVM().interpreterFrameSize(pos);
+    }
+
+    /**
+     * Resets all compilation statistics.
+     */
+    public void resetCompilationStatistics() {
+        runtime.getCompilerToVM().resetCompilationStatistics();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.CompilationRequest;
+
+/**
+ * A compilation request with extra HotSpot specific context such as a compilation identifier and
+ * the address of a {@code JVMCIEnv} object that provides native context for a compilation.
+ */
+public class HotSpotCompilationRequest extends CompilationRequest {
+    private final long jvmciEnv;
+    private final int id;
+
+    /**
+     * Creates a request to compile a method starting at a given BCI and allocates an identifier to
+     * the request.
+     *
+     * @param method the method to be compiled
+     * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
+     *            method's entry point
+     * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L
+     */
+    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv) {
+        this(method, entryBCI, jvmciEnv, method.allocateCompileId(entryBCI));
+    }
+
+    /**
+     * Creates a request to compile a method starting at a given BCI.
+     *
+     * @param method the method to be compiled
+     * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
+     *            method's entry point
+     * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L
+     * @param id an identifier for the request
+     */
+    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+        super(method, entryBCI);
+        this.jvmciEnv = jvmciEnv;
+        this.id = id;
+    }
+
+    @Override
+    public HotSpotResolvedJavaMethod getMethod() {
+        return (HotSpotResolvedJavaMethod) super.getMethod();
+    }
+
+    /**
+     * Gets the address of the native {@code JVMCIEnv} object or 0L if no such object exists.
+     */
+    public long getJvmciEnv() {
+        return jvmciEnv;
+    }
+
+    /**
+     * Gets the VM allocated identifier for this compilation.
+     */
+    public int getId() {
+        return id;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequestResult.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.CompilationRequest;
+import jdk.vm.ci.code.CompilationRequestResult;
+
+/**
+ * HotSpot specific information about the result of a {@link CompilationRequest}.
+ */
+public final class HotSpotCompilationRequestResult implements CompilationRequestResult {
+
+    /**
+     * A user readable description of the failure.
+     *
+     * This field is read by the VM.
+     */
+    private final String failureMessage;
+
+    /**
+     * Whether this is a transient failure where retrying would help.
+     *
+     * This field is read by the VM.
+     */
+    private final boolean retry;
+
+    /**
+     * Number of bytecodes inlined into the compilation, exclusive of the bytecodes in the root
+     * method.
+     *
+     * This field is read by the VM.
+     */
+    private final int inlinedBytecodes;
+
+    private HotSpotCompilationRequestResult(String failureMessage, boolean retry, int inlinedBytecodes) {
+        this.failureMessage = failureMessage;
+        this.retry = retry;
+        this.inlinedBytecodes = inlinedBytecodes;
+    }
+
+    public Object getFailure() {
+        return failureMessage;
+    }
+
+    /**
+     * Creates a result representing a successful compilation.
+     *
+     * @param inlinedBytecodes number of bytecodes inlined into the compilation, exclusive of the
+     *            bytecodes in the root method
+     */
+    public static HotSpotCompilationRequestResult success(int inlinedBytecodes) {
+        return new HotSpotCompilationRequestResult(null, true, inlinedBytecodes);
+    }
+
+    /**
+     * Creates a result representing a failed compilation.
+     *
+     * @param failureMessage a description of the failure
+     * @param retry whether this is a transient failure where retrying may succeed
+     */
+    public static HotSpotCompilationRequestResult failure(String failureMessage, boolean retry) {
+        return new HotSpotCompilationRequestResult(failureMessage, retry, 0);
+    }
+
+    public String getFailureMessage() {
+        return failureMessage;
+    }
+
+    public boolean getRetry() {
+        return retry;
+    }
+
+    public int getInlinedBytecodes() {
+        return inlinedBytecodes;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.code.CompiledCode;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.code.site.DataPatch;
+import jdk.vm.ci.code.site.Infopoint;
+import jdk.vm.ci.code.site.Site;
+import jdk.vm.ci.meta.Assumptions.Assumption;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * A {@link CompiledCode} with additional HotSpot-specific information required for installing the
+ * code in HotSpot's code cache.
+ */
+public class HotSpotCompiledCode implements CompiledCode {
+
+    /**
+     * The name of this compilation unit.
+     */
+    protected final String name;
+
+    /**
+     * The buffer containing the emitted machine code.
+     */
+    protected final byte[] targetCode;
+
+    /**
+     * The leading number of bytes in {@link #targetCode} containing the emitted machine code.
+     */
+    protected final int targetCodeSize;
+
+    /**
+     * A list of code annotations describing special sites in {@link #targetCode}.
+     */
+    protected final Site[] sites;
+
+    /**
+     * A list of {@link Assumption} this code relies on.
+     */
+    protected final Assumption[] assumptions;
+
+    /**
+     * The list of the methods whose bytecodes were used as input to the compilation. If
+     * {@code null}, then the compilation did not record method dependencies. Otherwise, the first
+     * element of this array is the root method of the compilation.
+     */
+    protected final ResolvedJavaMethod[] methods;
+
+    /**
+     * A list of comments that will be included in code dumps.
+     */
+    protected final Comment[] comments;
+
+    /**
+     * The data section containing serialized constants for the emitted machine code.
+     */
+    protected final byte[] dataSection;
+
+    /**
+     * The minimum alignment of the data section.
+     */
+    protected final int dataSectionAlignment;
+
+    /**
+     * A list of relocations in the {@link #dataSection}.
+     */
+    protected final DataPatch[] dataSectionPatches;
+
+    /**
+     * A flag determining whether this code is immutable and position independent.
+     */
+    protected final boolean isImmutablePIC;
+
+    /**
+     * The total size of the stack frame of this compiled method.
+     */
+    protected final int totalFrameSize;
+
+    /**
+     * The deopt rescue slot. Must be non-null if there is a safepoint in the method.
+     */
+    protected final StackSlot deoptRescueSlot;
+
+    public static class Comment {
+
+        public final String text;
+        public final int pcOffset;
+
+        public Comment(int pcOffset, String text) {
+            this.text = text;
+            this.pcOffset = pcOffset;
+        }
+    }
+
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `sites`, `targetCode`, `comments`, `methods`, `dataSection`, `dataSectionPatches` and `assumptions`")
+    public HotSpotCompiledCode(String name, byte[] targetCode, int targetCodeSize, Site[] sites, Assumption[] assumptions, ResolvedJavaMethod[] methods, Comment[] comments, byte[] dataSection,
+                    int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, StackSlot deoptRescueSlot) {
+        this.name = name;
+        this.targetCode = targetCode;
+        this.targetCodeSize = targetCodeSize;
+        this.sites = sites;
+        this.assumptions = assumptions;
+        this.methods = methods;
+
+        this.comments = comments;
+        this.dataSection = dataSection;
+        this.dataSectionAlignment = dataSectionAlignment;
+        this.dataSectionPatches = dataSectionPatches;
+        this.isImmutablePIC = isImmutablePIC;
+        this.totalFrameSize = totalFrameSize;
+        this.deoptRescueSlot = deoptRescueSlot;
+
+        assert validateFrames();
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    /**
+     * Ensure that all the frames passed into the VM are properly formatted with an empty or illegal
+     * slot following double word slots.
+     */
+    private boolean validateFrames() {
+        for (Site site : sites) {
+            if (site instanceof Infopoint) {
+                Infopoint info = (Infopoint) site;
+                if (info.debugInfo != null) {
+                    BytecodeFrame frame = info.debugInfo.frame();
+                    assert frame == null || frame.validateFormat();
+                }
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.code.site.DataPatch;
+import jdk.vm.ci.code.site.Site;
+import jdk.vm.ci.meta.Assumptions.Assumption;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * {@link HotSpotCompiledCode} destined for installation as an nmethod.
+ */
+public final class HotSpotCompiledNmethod extends HotSpotCompiledCode {
+
+    protected final HotSpotResolvedJavaMethod method;
+    protected final int entryBCI;
+
+    /**
+     * Compilation identifier.
+     */
+    protected final int id;
+
+    /**
+     * Address of a native {@code JVMCIEnv} object or 0L if no such object exists.
+     */
+    protected final long jvmciEnv;
+
+    protected final boolean hasUnsafeAccess;
+
+    /**
+     * May be set by VM if code installation fails. It will describe in more detail why installation
+     * failed (e.g., exactly which dependency failed).
+     */
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "set by the VM") private String installationFailureMessage;
+
+    public HotSpotCompiledNmethod(String name, byte[] targetCode, int targetCodeSize, Site[] sites, Assumption[] assumptions, ResolvedJavaMethod[] methods, Comment[] comments, byte[] dataSection,
+                    int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, StackSlot deoptRescueSlot, HotSpotResolvedJavaMethod method, int entryBCI,
+                    int id, long jvmciEnv, boolean hasUnsafeAccess) {
+        super(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, totalFrameSize, deoptRescueSlot);
+        this.method = method;
+        this.entryBCI = entryBCI;
+        this.id = id;
+        this.jvmciEnv = jvmciEnv;
+        this.hasUnsafeAccess = hasUnsafeAccess;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + id + ":" + method.format("%H.%n(%p)%r@") + entryBCI + "]";
+    }
+
+    public String getInstallationFailureMessage() {
+        return installationFailureMessage;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+
+/**
+ * The compressed representation of the {@link JavaConstant#NULL_POINTER null constant}.
+ */
+public final class HotSpotCompressedNullConstant implements JavaConstant, HotSpotConstant {
+
+    public static final JavaConstant COMPRESSED_NULL = new HotSpotCompressedNullConstant();
+
+    private HotSpotCompressedNullConstant() {
+    }
+
+    public JavaKind getJavaKind() {
+        return JavaKind.Object;
+    }
+
+    @Override
+    public boolean isNull() {
+        return true;
+    }
+
+    @Override
+    public boolean isCompressed() {
+        return true;
+    }
+
+    public Constant compress() {
+        throw new IllegalArgumentException();
+    }
+
+    public Constant uncompress() {
+        return NULL_POINTER;
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return true;
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public int asInt() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public boolean asBoolean() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public long asLong() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public float asFloat() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public double asDouble() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public String toString() {
+        return JavaConstant.toString(this);
+    }
+
+    @Override
+    public String toValueString() {
+        return "null";
+    }
+
+    @Override
+    public int hashCode() {
+        return System.identityHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof HotSpotCompressedNullConstant;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.Constant;
+
+/**
+ * Marker interface for hotspot specific constants.
+ */
+public interface HotSpotConstant extends Constant {
+
+    boolean isCompressed();
+
+    Constant compress();
+
+    Constant uncompress();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,740 @@
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.invoke.MethodHandle;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaField;
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+
+/**
+ * Implementation of {@link ConstantPool} for HotSpot.
+ */
+final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject {
+
+    /**
+     * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}.
+     */
+    public static class Bytecodes {
+        public static final int LDC = 18; // 0x12
+        public static final int LDC_W = 19; // 0x13
+        public static final int LDC2_W = 20; // 0x14
+        public static final int GETSTATIC = 178; // 0xB2
+        public static final int PUTSTATIC = 179; // 0xB3
+        public static final int GETFIELD = 180; // 0xB4
+        public static final int PUTFIELD = 181; // 0xB5
+        public static final int INVOKEVIRTUAL = 182; // 0xB6
+        public static final int INVOKESPECIAL = 183; // 0xB7
+        public static final int INVOKESTATIC = 184; // 0xB8
+        public static final int INVOKEINTERFACE = 185; // 0xB9
+        public static final int INVOKEDYNAMIC = 186; // 0xBA
+        public static final int NEW = 187; // 0xBB
+        public static final int NEWARRAY = 188; // 0xBC
+        public static final int ANEWARRAY = 189; // 0xBD
+        public static final int CHECKCAST = 192; // 0xC0
+        public static final int INSTANCEOF = 193; // 0xC1
+        public static final int MULTIANEWARRAY = 197; // 0xC5
+
+        static boolean isInvoke(int opcode) {
+            switch (opcode) {
+                case INVOKEVIRTUAL:
+                case INVOKESPECIAL:
+                case INVOKESTATIC:
+                case INVOKEINTERFACE:
+                case INVOKEDYNAMIC:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        /**
+         * See: {@code Rewriter::maybe_rewrite_invokehandle}.
+         */
+        static boolean isInvokeHandleAlias(int opcode) {
+            switch (opcode) {
+                case INVOKEVIRTUAL:
+                case INVOKESPECIAL:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+    }
+
+    /**
+     * Enum of all {@code JVM_CONSTANT} constants used in the VM. This includes the public and
+     * internal ones.
+     */
+    private enum JVM_CONSTANT {
+        // @formatter:off
+        Utf8(config().jvmConstantUtf8),
+        Integer(config().jvmConstantInteger),
+        Long(config().jvmConstantLong),
+        Float(config().jvmConstantFloat),
+        Double(config().jvmConstantDouble),
+        Class(config().jvmConstantClass),
+        UnresolvedClass(config().jvmConstantUnresolvedClass),
+        UnresolvedClassInError(config().jvmConstantUnresolvedClassInError),
+        String(config().jvmConstantString),
+        Fieldref(config().jvmConstantFieldref),
+        MethodRef(config().jvmConstantMethodref),
+        InterfaceMethodref(config().jvmConstantInterfaceMethodref),
+        NameAndType(config().jvmConstantNameAndType),
+        MethodHandle(config().jvmConstantMethodHandle),
+        MethodHandleInError(config().jvmConstantMethodHandleInError),
+        MethodType(config().jvmConstantMethodType),
+        MethodTypeInError(config().jvmConstantMethodTypeInError),
+        InvokeDynamic(config().jvmConstantInvokeDynamic);
+        // @formatter:on
+
+        private final int tag;
+
+        private static final int ExternalMax = config().jvmConstantExternalMax;
+        private static final int InternalMin = config().jvmConstantInternalMin;
+        private static final int InternalMax = config().jvmConstantInternalMax;
+
+        JVM_CONSTANT(int tag) {
+            this.tag = tag;
+        }
+
+        /**
+         * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy
+         * initialization.
+         */
+        static class TagValueMap {
+            private static final JVM_CONSTANT[] table = new JVM_CONSTANT[ExternalMax + 1 + (InternalMax - InternalMin) + 1];
+
+            static {
+                assert InternalMin > ExternalMax;
+                for (JVM_CONSTANT e : values()) {
+                    table[indexOf(e.tag)] = e;
+                }
+            }
+
+            private static int indexOf(int tag) {
+                if (tag >= InternalMin) {
+                    return tag - InternalMin + ExternalMax + 1;
+                } else {
+                    assert tag <= ExternalMax;
+                }
+                return tag;
+            }
+
+            static JVM_CONSTANT get(int tag) {
+                JVM_CONSTANT res = table[indexOf(tag)];
+                if (res != null) {
+                    return res;
+                }
+                throw new JVMCIError("Unknown JVM_CONSTANT tag %s", tag);
+            }
+        }
+
+        public static JVM_CONSTANT getEnum(int tag) {
+            return TagValueMap.get(tag);
+        }
+    }
+
+    private static class LookupTypeCacheElement {
+        int lastCpi = Integer.MIN_VALUE;
+        JavaType javaType;
+
+        LookupTypeCacheElement(int lastCpi, JavaType javaType) {
+            super();
+            this.lastCpi = lastCpi;
+            this.javaType = javaType;
+        }
+    }
+
+    /**
+     * Reference to the C++ ConstantPool object.
+     */
+    private final long metaspaceConstantPool;
+    private volatile LookupTypeCacheElement lastLookupType;
+
+    /**
+     * Gets the JVMCI mirror from a HotSpot constant pool.The VM is responsible for ensuring that
+     * the ConstantPool is kept alive for the duration of this call and the
+     * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that.
+     *
+     * Called from the VM.
+     *
+     * @param metaspaceConstantPool a metaspace ConstantPool object
+     * @return the {@link HotSpotConstantPool} corresponding to {@code metaspaceConstantPool}
+     */
+    @SuppressWarnings("unused")
+    private static HotSpotConstantPool fromMetaspace(long metaspaceConstantPool) {
+        HotSpotConstantPool cp = new HotSpotConstantPool(metaspaceConstantPool);
+        runtime().metaAccessContext.add(cp);
+        return cp;
+    }
+
+    private HotSpotConstantPool(long metaspaceConstantPool) {
+        this.metaspaceConstantPool = metaspaceConstantPool;
+    }
+
+    /**
+     * Gets the holder for this constant pool as {@link HotSpotResolvedObjectTypeImpl}.
+     *
+     * @return holder for this constant pool
+     */
+    private HotSpotResolvedObjectType getHolder() {
+        return compilerToVM().getResolvedJavaType(this, config().constantPoolHolderOffset, false);
+    }
+
+    /**
+     * Converts a raw index from the bytecodes to a constant pool index by adding a
+     * {@link HotSpotVMConfig#constantPoolCpCacheIndexTag constant}.
+     *
+     * @param rawIndex index from the bytecode
+     * @param opcode bytecode to convert the index for
+     * @return constant pool index
+     */
+    private static int rawIndexToConstantPoolIndex(int rawIndex, int opcode) {
+        int index;
+        if (opcode == Bytecodes.INVOKEDYNAMIC) {
+            index = rawIndex;
+            // See: ConstantPool::is_invokedynamic_index
+            assert index < 0 : "not an invokedynamic constant pool index " + index;
+        } else {
+            assert opcode == Bytecodes.GETFIELD || opcode == Bytecodes.PUTFIELD || opcode == Bytecodes.GETSTATIC || opcode == Bytecodes.PUTSTATIC || opcode == Bytecodes.INVOKEINTERFACE ||
+                            opcode == Bytecodes.INVOKEVIRTUAL || opcode == Bytecodes.INVOKESPECIAL || opcode == Bytecodes.INVOKESTATIC : "unexpected invoke opcode " + opcode;
+            index = rawIndex + config().constantPoolCpCacheIndexTag;
+        }
+        return index;
+    }
+
+    /**
+     * Decode a constant pool cache index to a constant pool index.
+     *
+     * See {@code ConstantPool::decode_cpcache_index}.
+     *
+     * @param index constant pool cache index
+     * @return decoded index
+     */
+    private static int decodeConstantPoolCacheIndex(int index) {
+        if (isInvokedynamicIndex(index)) {
+            return decodeInvokedynamicIndex(index);
+        } else {
+            return index - config().constantPoolCpCacheIndexTag;
+        }
+    }
+
+    /**
+     * See {@code ConstantPool::is_invokedynamic_index}.
+     */
+    private static boolean isInvokedynamicIndex(int index) {
+        return index < 0;
+    }
+
+    /**
+     * See {@code ConstantPool::decode_invokedynamic_index}.
+     */
+    private static int decodeInvokedynamicIndex(int i) {
+        assert isInvokedynamicIndex(i) : i;
+        return ~i;
+    }
+
+    long getMetaspaceConstantPool() {
+        return metaspaceConstantPool;
+    }
+
+    public long getMetaspacePointer() {
+        return getMetaspaceConstantPool();
+    }
+
+    /**
+     * Gets the constant pool tag at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return constant pool tag
+     */
+    private JVM_CONSTANT getTagAt(int index) {
+        assert checkBounds(index);
+        HotSpotVMConfig config = config();
+        final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset);
+        final int tag = UNSAFE.getByteVolatile(null, metaspaceConstantPoolTags + config.arrayU1DataOffset + index);
+        if (tag == 0) {
+            return null;
+        }
+        return JVM_CONSTANT.getEnum(tag);
+    }
+
+    /**
+     * Gets the constant pool entry at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return constant pool entry
+     */
+    long getEntryAt(int index) {
+        assert checkBounds(index);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + offset);
+    }
+
+    /**
+     * Gets the integer constant pool entry at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return integer constant pool entry at index
+     */
+    private int getIntAt(int index) {
+        assert checkTag(index, JVM_CONSTANT.Integer);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
+    }
+
+    /**
+     * Gets the long constant pool entry at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return long constant pool entry
+     */
+    private long getLongAt(int index) {
+        assert checkTag(index, JVM_CONSTANT.Long);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + offset);
+    }
+
+    /**
+     * Gets the float constant pool entry at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return float constant pool entry
+     */
+    private float getFloatAt(int index) {
+        assert checkTag(index, JVM_CONSTANT.Float);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + offset);
+    }
+
+    /**
+     * Gets the double constant pool entry at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return float constant pool entry
+     */
+    private double getDoubleAt(int index) {
+        assert checkTag(index, JVM_CONSTANT.Double);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + offset);
+    }
+
+    /**
+     * Gets the {@code JVM_CONSTANT_NameAndType} constant pool entry at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return {@code JVM_CONSTANT_NameAndType} constant pool entry
+     */
+    private int getNameAndTypeAt(int index) {
+        assert checkTag(index, JVM_CONSTANT.NameAndType);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
+    }
+
+    /**
+     * Gets the {@code JVM_CONSTANT_NameAndType} reference index constant pool entry at index
+     * {@code index}.
+     *
+     * @param index constant pool index
+     * @return {@code JVM_CONSTANT_NameAndType} reference constant pool entry
+     */
+    private int getNameAndTypeRefIndexAt(int index) {
+        return compilerToVM().lookupNameAndTypeRefIndexInPool(this, index);
+    }
+
+    /**
+     * Gets the name of a {@code JVM_CONSTANT_NameAndType} constant pool entry referenced by another
+     * entry denoted by {@code which}.
+     *
+     * @param which constant pool index or constant pool cache index
+     * @return name as {@link String}
+     */
+    private String getNameOf(int which) {
+        return compilerToVM().lookupNameInPool(this, which);
+    }
+
+    /**
+     * Gets the name reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry at
+     * index {@code index}.
+     *
+     * @param index constant pool index
+     * @return name reference index
+     */
+    private int getNameRefIndexAt(int index) {
+        final int refIndex = getNameAndTypeAt(index);
+        // name ref index is in the low 16-bits.
+        return refIndex & 0xFFFF;
+    }
+
+    /**
+     * Gets the signature of a {@code JVM_CONSTANT_NameAndType} constant pool entry referenced by
+     * another entry denoted by {@code which}.
+     *
+     * @param which constant pool index or constant pool cache index
+     * @return signature as {@link String}
+     */
+    private String getSignatureOf(int which) {
+        return compilerToVM().lookupSignatureInPool(this, which);
+    }
+
+    /**
+     * Gets the signature reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry
+     * at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return signature reference index
+     */
+    private int getSignatureRefIndexAt(int index) {
+        final int refIndex = getNameAndTypeAt(index);
+        // signature ref index is in the high 16-bits.
+        return refIndex >>> 16;
+    }
+
+    /**
+     * Gets the klass reference index constant pool entry at index {@code index}.
+     *
+     * @param index constant pool index
+     * @return klass reference index
+     */
+    private int getKlassRefIndexAt(int index) {
+        return compilerToVM().lookupKlassRefIndexInPool(this, index);
+    }
+
+    /**
+     * Gets the uncached klass reference index constant pool entry at index {@code index}. See:
+     * {@code ConstantPool::uncached_klass_ref_index_at}.
+     *
+     * @param index constant pool index
+     * @return klass reference index
+     */
+    private int getUncachedKlassRefIndexAt(int index) {
+        assert checkTagIsFieldOrMethod(index);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
+        // klass ref index is in the low 16-bits.
+        return refIndex & 0xFFFF;
+    }
+
+    /**
+     * Checks that the constant pool index {@code index} is in the bounds of the constant pool.
+     *
+     * @param index constant pool index
+     * @throws AssertionError if the check fails
+     */
+    private boolean checkBounds(int index) {
+        assert 0 <= index && index < length() : "index " + index + " not between 0 and " + length();
+        return true;
+    }
+
+    /**
+     * Checks that the constant pool tag at index {@code index} is equal to {@code tag}.
+     *
+     * @param index constant pool index
+     * @param tag expected tag
+     * @throws AssertionError if the check fails
+     */
+    private boolean checkTag(int index, JVM_CONSTANT tag) {
+        final JVM_CONSTANT tagAt = getTagAt(index);
+        assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag;
+        return true;
+    }
+
+    /**
+     * Asserts that the constant pool tag at index {@code index} is a {@link JVM_CONSTANT#Fieldref},
+     * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}.
+     *
+     * @param index constant pool index
+     * @throws AssertionError if the check fails
+     */
+    private boolean checkTagIsFieldOrMethod(int index) {
+        final JVM_CONSTANT tagAt = getTagAt(index);
+        assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt;
+        return true;
+    }
+
+    @Override
+    public int length() {
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolLengthOffset);
+    }
+
+    @Override
+    public Object lookupConstant(int cpi) {
+        assert cpi != 0;
+        final JVM_CONSTANT tag = getTagAt(cpi);
+        switch (tag) {
+            case Integer:
+                return JavaConstant.forInt(getIntAt(cpi));
+            case Long:
+                return JavaConstant.forLong(getLongAt(cpi));
+            case Float:
+                return JavaConstant.forFloat(getFloatAt(cpi));
+            case Double:
+                return JavaConstant.forDouble(getDoubleAt(cpi));
+            case Class:
+            case UnresolvedClass:
+            case UnresolvedClassInError:
+                final int opcode = -1;  // opcode is not used
+                return lookupType(cpi, opcode);
+            case String:
+                /*
+                 * Normally, we would expect a String here, but anonymous classes can have
+                 * "pseudo strings" (arbitrary live objects) patched into a String entry. Such
+                 * entries do not have a symbol in the constant pool slot.
+                 */
+                Object string = compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
+                return HotSpotObjectConstantImpl.forObject(string);
+            case MethodHandle:
+            case MethodHandleInError:
+            case MethodType:
+            case MethodTypeInError:
+                Object obj = compilerToVM().resolveConstantInPool(this, cpi);
+                return HotSpotObjectConstantImpl.forObject(obj);
+            default:
+                throw new JVMCIError("Unknown constant pool tag %s", tag);
+        }
+    }
+
+    @Override
+    public String lookupUtf8(int cpi) {
+        assert checkTag(cpi, JVM_CONSTANT.Utf8);
+        return compilerToVM().getSymbol(getEntryAt(cpi));
+    }
+
+    @Override
+    public Signature lookupSignature(int cpi) {
+        return new HotSpotSignature(runtime(), lookupUtf8(cpi));
+    }
+
+    @Override
+    public JavaConstant lookupAppendix(int cpi, int opcode) {
+        assert Bytecodes.isInvoke(opcode);
+        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+        Object appendix = compilerToVM().lookupAppendixInPool(this, index);
+        if (appendix == null) {
+            return null;
+        } else {
+            return HotSpotObjectConstantImpl.forObject(appendix);
+        }
+    }
+
+    /**
+     * Gets a {@link JavaType} corresponding a given resolved or unresolved type.
+     *
+     * @param type either a ResolvedJavaType or a String naming a unresolved type.
+     */
+    private static JavaType getJavaType(final Object type) {
+        if (type instanceof String) {
+            String name = (String) type;
+            return HotSpotUnresolvedJavaType.create(runtime(), "L" + name + ";");
+        } else {
+            return (JavaType) type;
+        }
+    }
+
+    @Override
+    public JavaMethod lookupMethod(int cpi, int opcode) {
+        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+        final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, index, (byte) opcode);
+        if (method != null) {
+            return method;
+        } else {
+            // Get the method's name and signature.
+            String name = getNameOf(index);
+            HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureOf(index));
+            if (opcode == Bytecodes.INVOKEDYNAMIC) {
+                HotSpotResolvedObjectType holder = HotSpotResolvedObjectTypeImpl.fromObjectClass(MethodHandle.class);
+                return new HotSpotMethodUnresolved(name, signature, holder);
+            } else {
+                final int klassIndex = getKlassRefIndexAt(index);
+                final Object type = compilerToVM().lookupKlassInPool(this, klassIndex);
+                JavaType holder = getJavaType(type);
+                return new HotSpotMethodUnresolved(name, signature, holder);
+            }
+        }
+    }
+
+    @Override
+    public JavaType lookupType(int cpi, int opcode) {
+        final LookupTypeCacheElement elem = this.lastLookupType;
+        if (elem != null && elem.lastCpi == cpi) {
+            return elem.javaType;
+        } else {
+            final Object type = compilerToVM().lookupKlassInPool(this, cpi);
+            JavaType result = getJavaType(type);
+            if (result instanceof ResolvedJavaType) {
+                this.lastLookupType = new LookupTypeCacheElement(cpi, result);
+            }
+            return result;
+        }
+    }
+
+    @Override
+    public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
+        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+        final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
+        final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
+        String typeName = lookupUtf8(typeIndex);
+        JavaType type = runtime().lookupType(typeName, getHolder(), false);
+
+        final int holderIndex = getKlassRefIndexAt(index);
+        JavaType holder = lookupType(holderIndex, opcode);
+
+        if (holder instanceof HotSpotResolvedObjectTypeImpl) {
+            int[] info = new int[3];
+            HotSpotResolvedObjectTypeImpl resolvedHolder;
+            try {
+                resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (byte) opcode, info);
+            } catch (Throwable t) {
+                /*
+                 * If there was an exception resolving the field we give up and return an unresolved
+                 * field.
+                 */
+                return new HotSpotUnresolvedField(holder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
+            }
+            final int flags = info[0];
+            final int offset = info[1];
+            final int fieldIndex = info[2];
+            HotSpotResolvedJavaField result = resolvedHolder.createField(type, offset, flags, fieldIndex);
+            return result;
+        } else {
+            return new HotSpotUnresolvedField(holder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
+        }
+    }
+
+    @Override
+    @SuppressWarnings("fallthrough")
+    public void loadReferencedType(int cpi, int opcode) {
+        int index;
+        switch (opcode) {
+            case Bytecodes.CHECKCAST:
+            case Bytecodes.INSTANCEOF:
+            case Bytecodes.NEW:
+            case Bytecodes.ANEWARRAY:
+            case Bytecodes.MULTIANEWARRAY:
+            case Bytecodes.LDC:
+            case Bytecodes.LDC_W:
+            case Bytecodes.LDC2_W:
+                index = cpi;
+                break;
+            case Bytecodes.INVOKEDYNAMIC: {
+                // invokedynamic instructions point to a constant pool cache entry.
+                index = decodeConstantPoolCacheIndex(cpi) + config().constantPoolCpCacheIndexTag;
+                index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
+                break;
+            }
+            case Bytecodes.GETSTATIC:
+            case Bytecodes.PUTSTATIC:
+            case Bytecodes.GETFIELD:
+            case Bytecodes.PUTFIELD:
+            case Bytecodes.INVOKEVIRTUAL:
+            case Bytecodes.INVOKESPECIAL:
+            case Bytecodes.INVOKESTATIC:
+            case Bytecodes.INVOKEINTERFACE: {
+                // invoke and field instructions point to a constant pool cache entry.
+                index = rawIndexToConstantPoolIndex(cpi, opcode);
+                index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
+                break;
+            }
+            default:
+                throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
+        }
+
+        final JVM_CONSTANT tag = getTagAt(index);
+        if (tag == null) {
+            assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long;
+            return;
+        }
+        switch (tag) {
+            case MethodRef:
+            case Fieldref:
+            case InterfaceMethodref:
+                index = getUncachedKlassRefIndexAt(index);
+                // Read the tag only once because it could change between multiple reads.
+                final JVM_CONSTANT klassTag = getTagAt(index);
+                assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag;
+                // fall through
+            case Class:
+            case UnresolvedClass:
+            case UnresolvedClassInError:
+                final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, index);
+                Class<?> klass = type.mirror();
+                if (!klass.isPrimitive() && !klass.isArray()) {
+                    UNSAFE.ensureClassInitialized(klass);
+                }
+                if (tag == JVM_CONSTANT.MethodRef) {
+                    if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) {
+                        final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
+                        assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+                        compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
+                    }
+                }
+
+                break;
+            case InvokeDynamic:
+                if (isInvokedynamicIndex(cpi)) {
+                    compilerToVM().resolveInvokeDynamicInPool(this, cpi);
+                }
+                break;
+            default:
+                // nothing
+                break;
+        }
+
+    }
+
+    static class Lazy {
+        static final String[] signaturePolymorphicHolders = compilerToVM().getSignaturePolymorphicHolders();
+    }
+
+    /**
+     * Determines if {@code type} contains signature polymorphic methods.
+     */
+    private static boolean isSignaturePolymorphicHolder(final HotSpotResolvedObjectTypeImpl type) {
+        String name = type.getName();
+        for (String holder : Lazy.signaturePolymorphicHolders) {
+            if (name.equals(holder)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        HotSpotResolvedObjectType holder = getHolder();
+        return "HotSpotConstantPool<" + holder.toJavaName() + ">";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.reflect.Array;
+import java.util.Objects;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MemoryAccessProvider;
+import jdk.vm.ci.meta.MethodHandleAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * HotSpot implementation of {@link ConstantReflectionProvider}.
+ */
+public class HotSpotConstantReflectionProvider implements ConstantReflectionProvider {
+
+    protected final HotSpotJVMCIRuntimeProvider runtime;
+    protected final HotSpotMethodHandleAccessProvider methodHandleAccess;
+    protected final HotSpotMemoryAccessProviderImpl memoryAccess;
+
+    public HotSpotConstantReflectionProvider(HotSpotJVMCIRuntimeProvider runtime) {
+        this.runtime = runtime;
+        this.methodHandleAccess = new HotSpotMethodHandleAccessProvider(this);
+        this.memoryAccess = new HotSpotMemoryAccessProviderImpl(runtime);
+    }
+
+    public MethodHandleAccessProvider getMethodHandleAccess() {
+        return methodHandleAccess;
+    }
+
+    @Override
+    public MemoryAccessProvider getMemoryAccessProvider() {
+        return memoryAccess;
+    }
+
+    @Override
+    public Boolean constantEquals(Constant x, Constant y) {
+        if (x == y) {
+            return true;
+        } else if (x instanceof HotSpotObjectConstantImpl) {
+            return y instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) x).object() == ((HotSpotObjectConstantImpl) y).object();
+        } else {
+            return Objects.equals(x, y);
+        }
+    }
+
+    @Override
+    public Integer readArrayLength(JavaConstant array) {
+        if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) {
+            return null;
+        }
+
+        Object arrayObject = ((HotSpotObjectConstantImpl) array).object();
+        if (!arrayObject.getClass().isArray()) {
+            return null;
+        }
+        return Array.getLength(arrayObject);
+    }
+
+    @Override
+    public JavaConstant readArrayElement(JavaConstant array, int index) {
+        if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) {
+            return null;
+        }
+        Object a = ((HotSpotObjectConstantImpl) array).object();
+
+        if (!a.getClass().isArray() || index < 0 || index >= Array.getLength(a)) {
+            return null;
+        }
+
+        if (a instanceof Object[]) {
+            Object element = ((Object[]) a)[index];
+            return HotSpotObjectConstantImpl.forObject(element);
+        } else {
+            if (a instanceof int[]) {
+                return JavaConstant.forInt(((int[]) a)[index]);
+            } else if (a instanceof char[]) {
+                return JavaConstant.forChar(((char[]) a)[index]);
+            } else if (a instanceof byte[]) {
+                return JavaConstant.forByte(((byte[]) a)[index]);
+            } else if (a instanceof long[]) {
+                return JavaConstant.forLong(((long[]) a)[index]);
+            } else if (a instanceof short[]) {
+                return JavaConstant.forShort(((short[]) a)[index]);
+            } else if (a instanceof float[]) {
+                return JavaConstant.forFloat(((float[]) a)[index]);
+            } else if (a instanceof double[]) {
+                return JavaConstant.forDouble(((double[]) a)[index]);
+            } else if (a instanceof boolean[]) {
+                return JavaConstant.forBoolean(((boolean[]) a)[index]);
+            } else {
+                throw new JVMCIError("Should not reach here");
+            }
+        }
+    }
+
+    /**
+     * Check if the constant is a boxed value that is guaranteed to be cached by the platform.
+     * Otherwise the generated code might be the only reference to the boxed value and since object
+     * references from nmethods are weak this can cause GC problems.
+     *
+     * @param source
+     * @return true if the box is cached
+     */
+    private static boolean isBoxCached(JavaConstant source) {
+        switch (source.getJavaKind()) {
+            case Boolean:
+                return true;
+            case Char:
+                return source.asInt() <= 127;
+            case Byte:
+            case Short:
+            case Int:
+                return source.asInt() >= -128 && source.asInt() <= 127;
+            case Long:
+                return source.asLong() >= -128 && source.asLong() <= 127;
+            case Float:
+            case Double:
+                return false;
+            default:
+                throw new IllegalArgumentException("unexpected kind " + source.getJavaKind());
+        }
+    }
+
+    @Override
+    public JavaConstant boxPrimitive(JavaConstant source) {
+        if (source == null || !source.getJavaKind().isPrimitive() || !isBoxCached(source)) {
+            return null;
+        }
+        return HotSpotObjectConstantImpl.forObject(source.asBoxedPrimitive());
+    }
+
+    @Override
+    public JavaConstant unboxPrimitive(JavaConstant source) {
+        if (source == null || !source.getJavaKind().isObject()) {
+            return null;
+        }
+        if (source.isNull()) {
+            return null;
+        }
+        return JavaConstant.forBoxedPrimitive(((HotSpotObjectConstantImpl) source).object());
+    }
+
+    public JavaConstant forString(String value) {
+        return HotSpotObjectConstantImpl.forObject(value);
+    }
+
+    public JavaConstant forObject(Object value) {
+        return HotSpotObjectConstantImpl.forObject(value);
+    }
+
+    @Override
+    public ResolvedJavaType asJavaType(Constant constant) {
+        if (constant instanceof HotSpotObjectConstant) {
+            Object obj = ((HotSpotObjectConstantImpl) constant).object();
+            if (obj instanceof Class) {
+                return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType((Class<?>) obj);
+            }
+        }
+        if (constant instanceof HotSpotMetaspaceConstant) {
+            MetaspaceWrapperObject obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant);
+            if (obj instanceof HotSpotResolvedObjectTypeImpl) {
+                return (ResolvedJavaType) obj;
+            }
+        }
+        return null;
+    }
+
+    public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) {
+        HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
+        if (hotspotField.isStatic()) {
+            HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass();
+            if (holder.isInitialized()) {
+                return memoryAccess.readUnsafeConstant(hotspotField.getJavaKind(), HotSpotObjectConstantImpl.forObject(holder.mirror()), hotspotField.offset());
+            }
+        } else {
+            if (receiver.isNonNull() && hotspotField.isInObject(((HotSpotObjectConstantImpl) receiver).object())) {
+                return memoryAccess.readUnsafeConstant(hotspotField.getJavaKind(), receiver, hotspotField.offset());
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public JavaConstant asJavaClass(ResolvedJavaType type) {
+        return HotSpotObjectConstantImpl.forObject(((HotSpotResolvedJavaType) type).mirror());
+    }
+
+    @Override
+    public Constant asObjectHub(ResolvedJavaType type) {
+        if (type instanceof HotSpotResolvedObjectType) {
+            return ((HotSpotResolvedObjectType) type).klass();
+        } else {
+            throw JVMCIError.unimplemented();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.InvokeTarget;
+
+public class HotSpotForeignCallTarget implements InvokeTarget {
+
+    /**
+     * The entry point address of this call's target.
+     */
+    protected long address;
+
+    public HotSpotForeignCallTarget(long address) {
+        this.address = address;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,82 @@
+/*
+ * 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 jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import jdk.vm.ci.code.InstalledCode;
+import sun.misc.Unsafe;
+
+/**
+ * Implementation of {@link InstalledCode} for HotSpot.
+ */
+public abstract class HotSpotInstalledCode extends InstalledCode {
+
+    /**
+     * Total size of the code blob.
+     */
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int size;
+
+    /**
+     * Start address of the code.
+     */
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private long codeStart;
+
+    /**
+     * Size of the code.
+     */
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int codeSize;
+
+    public HotSpotInstalledCode(String name) {
+        super(name);
+    }
+
+    /**
+     * @return the total size of this code blob
+     */
+    public int getSize() {
+        return size;
+    }
+
+    @Override
+    public abstract String toString();
+
+    @Override
+    public long getStart() {
+        return codeStart;
+    }
+
+    public long getCodeSize() {
+        return codeSize;
+    }
+
+    @Override
+    public byte[] getCode() {
+        if (!isValid()) {
+            return null;
+        }
+        byte[] code = new byte[codeSize];
+        UNSAFE.copyMemory(null, codeStart, code, Unsafe.ARRAY_BYTE_BASE_OFFSET, codeSize);
+        return code;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.runtime.JVMCIBackend;
+
+public interface HotSpotJVMCIBackendFactory {
+
+    JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host);
+
+    /**
+     * Gets the CPU architecture of this backend.
+     */
+    String getArchitecture();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.CompilationRequest;
+import jdk.vm.ci.code.CompilationRequestResult;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
+import jdk.vm.ci.runtime.JVMCICompiler;
+import jdk.vm.ci.runtime.JVMCICompilerFactory;
+import jdk.vm.ci.runtime.JVMCIRuntime;
+import jdk.vm.ci.services.JVMCIServiceLocator;
+import jdk.vm.ci.services.JVMCIPermission;
+
+final class HotSpotJVMCICompilerConfig {
+
+    /**
+     * This factory allows JVMCI initialization to succeed but raises an error if the VM asks JVMCI
+     * to perform a compilation. This allows the reflective parts of the JVMCI API to be used
+     * without requiring a compiler implementation to be available.
+     */
+    private static class DummyCompilerFactory implements JVMCICompilerFactory, JVMCICompiler {
+
+        public CompilationRequestResult compileMethod(CompilationRequest request) {
+            throw new JVMCIError("no JVMCI compiler selected");
+        }
+
+        @Override
+        public String getCompilerName() {
+            return "<none>";
+        }
+
+        @Override
+        public JVMCICompiler createCompiler(JVMCIRuntime runtime) {
+            return this;
+        }
+    }
+
+    /**
+     * Factory of the selected system compiler.
+     */
+    private static JVMCICompilerFactory compilerFactory;
+
+    /**
+     * Gets the selected system compiler factory.
+     *
+     * @return the selected system compiler factory
+     * @throws SecurityException if a security manager is present and it denies
+     *             {@link JVMCIPermission} for any {@link JVMCIServiceLocator} loaded by this method
+     */
+    static JVMCICompilerFactory getCompilerFactory() {
+        if (compilerFactory == null) {
+            JVMCICompilerFactory factory = null;
+            String compilerName = Option.Compiler.getString();
+            if (compilerName != null) {
+                for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
+                    if (f.getCompilerName().equals(compilerName)) {
+                        factory = f;
+                    }
+                }
+                if (factory == null) {
+                    throw new JVMCIError("JVMCI compiler '%s' not found", compilerName);
+                }
+            } else {
+                // Auto select a single available compiler
+                for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
+                    if (factory == null) {
+                        factory = f;
+                    } else {
+                        // Multiple factories seen - cancel auto selection
+                        factory = null;
+                        break;
+                    }
+                }
+                if (factory == null) {
+                    factory = new DummyCompilerFactory();
+                }
+            }
+            factory.onSelection();
+            compilerFactory = factory;
+        }
+        return compilerFactory;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerFactory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.runtime.JVMCICompilerFactory;
+
+/**
+ * HotSpot extensions to {@link JVMCICompilerFactory}.
+ */
+public abstract class HotSpotJVMCICompilerFactory implements JVMCICompilerFactory {
+
+    /**
+     * Gets 0 or more prefixes identifying classes that should by compiled by C1 in simple mode
+     * (i.e., {@code CompLevel_simple}) when HotSpot is running with tiered compilation. The
+     * prefixes should be class or package names using "/" as the separator, e.g. "jdk/vm/ci".
+     *
+     * @return 0 or more Strings identifying packages that should by compiled by the first tier only
+     *         or null if no redirection to C1 should be performed.
+     */
+    public String[] getTrivialPrefixes() {
+        return null;
+    }
+
+    public enum CompilationLevelAdjustment {
+        /**
+         * No adjustment.
+         */
+        None,
+
+        /**
+         * Adjust based on declaring class of method.
+         */
+        ByHolder,
+
+        /**
+         * Adjust based on declaring class, name and signature of method.
+         */
+        ByFullSignature
+    }
+
+    /**
+     * Determines if this object may want to adjust the compilation level for a method that is being
+     * scheduled by the VM for compilation.
+     */
+    public CompilationLevelAdjustment getCompilationLevelAdjustment() {
+        return CompilationLevelAdjustment.None;
+    }
+
+    public enum CompilationLevel {
+        None,
+        Simple,
+        LimitedProfile,
+        FullProfile,
+        FullOptimization
+    }
+
+    /**
+     * Potentially modifies the compilation level currently selected by the VM compilation policy
+     * for a method.
+     *
+     * @param declaringClass the class in which the method is declared
+     * @param name the name of the method or {@code null} depending on the value that was returned
+     *            by {@link #getCompilationLevelAdjustment()}
+     * @param signature the signature of the method or {@code null} depending on the value that was
+     *            returned by {@link #getCompilationLevelAdjustment()}
+     * @param isOsr specifies if the compilation being scheduled in an OSR compilation
+     * @param level the compilation level currently selected by the VM compilation policy
+     * @return the compilation level to use for the compilation being scheduled (must be a valid
+     *         {@code CompLevel} enum value)
+     */
+    public CompilationLevel adjustCompilationLevel(Class<?> declaringClass, String name, String signature, boolean isOsr, CompilationLevel level) {
+        throw new InternalError("Should not reach here");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * This class manages the set of metadata roots that must be scanned during garbage collection.
+ * Because of class redefinition Method* and ConstantPool* can be freed if they don't appear to be
+ * in use so they must be tracked when there are live references to them from Java.
+ *
+ * The general theory of operation is that all {@link MetaspaceWrapperObject}s are created by
+ * calling into the VM which calls back out to actually create the wrapper instance. During the call
+ * the VM keeps the metadata reference alive through the use of metadata handles. Once the call
+ * completes the wrapper object is registered here and will be scanned during metadata scanning. The
+ * weakness of the reference to the wrapper object allows them to be reclaimed when they are no
+ * longer used.
+ *
+ */
+public class HotSpotJVMCIMetaAccessContext {
+
+    /**
+     * The set of currently live contexts used for tracking of live metadata. Examined from the VM
+     * during garbage collection.
+     */
+    private static WeakReference<?>[] allContexts = new WeakReference<?>[0];
+
+    /**
+     * This is a chunked list of metadata roots. It can be read from VM native code so it's been
+     * marked volatile to ensure the order of updates are respected.
+     */
+    private volatile Object[] metadataRoots;
+
+    private ChunkedList<WeakReference<MetaspaceWrapperObject>> list = new ChunkedList<>();
+
+    /**
+     * The number of weak references freed since the last time the list was shrunk.
+     */
+    private int freed;
+
+    /**
+     * The {@link ReferenceQueue} tracking the weak references created by this context.
+     */
+    private final ReferenceQueue<MetaspaceWrapperObject> queue = new ReferenceQueue<>();
+
+    static synchronized void add(HotSpotJVMCIMetaAccessContext context) {
+        for (int i = 0; i < allContexts.length; i++) {
+            if (allContexts[i] == null || allContexts[i].get() == null) {
+                allContexts[i] = new WeakReference<>(context);
+                return;
+            }
+        }
+        int index = allContexts.length;
+        allContexts = Arrays.copyOf(allContexts, index + 2);
+        allContexts[index] = new WeakReference<>(context);
+    }
+
+    HotSpotJVMCIMetaAccessContext() {
+        add(this);
+    }
+
+    /**
+     * Periodically trim the list of tracked metadata. A new list is created to replace the old to
+     * avoid concurrent scanning issues.
+     */
+    private void clean() {
+        Reference<?> ref = queue.poll();
+        if (ref == null) {
+            return;
+        }
+        while (ref != null) {
+            freed++;
+            ref = queue.poll();
+        }
+        if (freed > list.size() / 2) {
+            ChunkedList<WeakReference<MetaspaceWrapperObject>> newList = new ChunkedList<>();
+            for (WeakReference<MetaspaceWrapperObject> element : list) {
+                /*
+                 * The referent could become null anywhere in here but it doesn't matter. It will
+                 * get cleaned up next time.
+                 */
+                if (element != null && element.get() != null) {
+                    newList.add(element);
+                }
+            }
+            list = newList;
+            metadataRoots = list.getHead();
+            freed = 0;
+        }
+    }
+
+    /**
+     * Add a {@link MetaspaceWrapperObject} to tracked by the GC. It's assumed that the caller is
+     * responsible for keeping the reference alive for the duration of the call. Once registration
+     * is complete then the VM will ensure it's kept alive.
+     *
+     * @param metaspaceObject
+     */
+
+    public synchronized void add(MetaspaceWrapperObject metaspaceObject) {
+        clean();
+        list.add(new WeakReference<>(metaspaceObject, queue));
+        if (list.getHead() != metadataRoots) {
+            /*
+             * The list enlarged so update the head.
+             */
+            metadataRoots = list.getHead();
+        }
+        assert isRegistered(metaspaceObject);
+    }
+
+    protected ResolvedJavaType createClass(Class<?> javaClass) {
+        if (javaClass.isPrimitive()) {
+            JavaKind kind = JavaKind.fromJavaClass(javaClass);
+            return new HotSpotResolvedPrimitiveType(kind);
+        } else {
+            return new HotSpotResolvedObjectTypeImpl(javaClass, this);
+        }
+    }
+
+    private final ClassValue<WeakReference<ResolvedJavaType>> resolvedJavaType = new ClassValue<WeakReference<ResolvedJavaType>>() {
+        @Override
+        protected WeakReference<ResolvedJavaType> computeValue(Class<?> type) {
+            return new WeakReference<>(createClass(type));
+        }
+    };
+
+    /**
+     * Gets the JVMCI mirror for a {@link Class} object.
+     *
+     * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
+     */
+    public ResolvedJavaType fromClass(Class<?> javaClass) {
+        ResolvedJavaType javaType = null;
+        while (javaType == null) {
+            WeakReference<ResolvedJavaType> type = resolvedJavaType.get(javaClass);
+            javaType = type.get();
+            if (javaType == null) {
+                resolvedJavaType.remove(javaClass);
+            }
+        }
+        return javaType;
+    }
+
+    /**
+     * A very simple append only chunked list implementation.
+     */
+    static class ChunkedList<T> implements Iterable<T> {
+        private static final int CHUNK_SIZE = 32;
+
+        private static final int NEXT_CHUNK_INDEX = CHUNK_SIZE - 1;
+
+        private Object[] head;
+        private int index;
+        private int size;
+
+        ChunkedList() {
+            head = new Object[CHUNK_SIZE];
+            index = 0;
+        }
+
+        void add(T element) {
+            if (index == NEXT_CHUNK_INDEX) {
+                Object[] newHead = new Object[CHUNK_SIZE];
+                newHead[index] = head;
+                head = newHead;
+                index = 0;
+            }
+            head[index++] = element;
+            size++;
+        }
+
+        Object[] getHead() {
+            return head;
+        }
+
+        public Iterator<T> iterator() {
+            return new ChunkIterator<>();
+        }
+
+        int size() {
+            return size;
+        }
+
+        class ChunkIterator<V> implements Iterator<V> {
+
+            ChunkIterator() {
+                currentChunk = head;
+                currentIndex = -1;
+                next = findNext();
+            }
+
+            Object[] currentChunk;
+            int currentIndex;
+            V next;
+
+            @SuppressWarnings("unchecked")
+            V findNext() {
+                V result;
+                do {
+                    currentIndex++;
+                    if (currentIndex == NEXT_CHUNK_INDEX) {
+                        currentChunk = (Object[]) currentChunk[currentIndex];
+                        currentIndex = 0;
+                        if (currentChunk == null) {
+                            return null;
+                        }
+                    }
+                    result = (V) currentChunk[currentIndex];
+                } while (result == null);
+                return result;
+            }
+
+            public boolean hasNext() {
+                return next != null;
+            }
+
+            public V next() {
+                V result = next;
+                next = findNext();
+                return result;
+            }
+
+        }
+
+    }
+
+    synchronized boolean isRegistered(MetaspaceWrapperObject wrapper) {
+        for (WeakReference<MetaspaceWrapperObject> m : list) {
+            if (m != null && m.get() == wrapper) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,553 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.common.InitTimer.timer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.TreeMap;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CompilationRequestResult;
+import jdk.vm.ci.code.CompiledCode;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevel;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
+import jdk.vm.ci.runtime.JVMCIBackend;
+import jdk.vm.ci.runtime.JVMCICompiler;
+import jdk.vm.ci.runtime.JVMCICompilerFactory;
+import jdk.vm.ci.services.JVMCIServiceLocator;
+import jdk.vm.ci.services.Services;
+import sun.misc.VM;
+
+/**
+ * HotSpot implementation of a JVMCI runtime.
+ *
+ * The initialization of this class is very fragile since it's initialized both through
+ * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and
+ * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class
+ * can't have a static initializer and any required initialization must be done as part of
+ * {@link #runtime()}. This allows the initialization to funnel back through
+ * {@link JVMCI#initialize()} without deadlocking.
+ */
+public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider {
+
+    @SuppressWarnings("try")
+    static class DelayedInit {
+        private static final HotSpotJVMCIRuntime instance;
+
+        static {
+            try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
+                instance = new HotSpotJVMCIRuntime();
+            }
+        }
+    }
+
+    /**
+     * Gets the singleton {@link HotSpotJVMCIRuntime} object.
+     */
+    public static HotSpotJVMCIRuntime runtime() {
+        JVMCI.initialize();
+        return DelayedInit.instance;
+    }
+
+    /**
+     * A list of all supported JVMCI options.
+     */
+    public enum Option {
+        // @formatter:off
+        Compiler(String.class, null, "Selects the system compiler."),
+        // Note: The following one is not used (see InitTimer.ENABLED). It is added here
+        // so that -XX:+JVMCIPrintProperties shows the option.
+        InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
+        PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
+        TraceMethodDataFilter(String.class, null,
+                        "Enables tracing of profiling info when read by JVMCI.",
+                        "Empty value: trace all methods",
+                        "Non-empty value: trace methods whose fully qualified name contains the value.");
+        // @formatter:on
+
+        /**
+         * The prefix for system properties that are JVMCI options.
+         */
+        private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
+
+        /**
+         * Marker for uninitialized flags.
+         */
+        private static final String UNINITIALIZED = "UNINITIALIZED";
+
+        private final Class<?> type;
+        private Object value;
+        private final Object defaultValue;
+        private boolean isDefault;
+        private final String[] helpLines;
+
+        Option(Class<?> type, Object defaultValue, String... helpLines) {
+            assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
+            this.type = type;
+            this.value = UNINITIALIZED;
+            this.defaultValue = defaultValue;
+            this.helpLines = helpLines;
+        }
+
+        @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
+        private Object getValue() {
+            if (value == UNINITIALIZED) {
+                String propertyValue = VM.getSavedProperty(getPropertyName());
+                if (propertyValue == null) {
+                    this.value = defaultValue;
+                    this.isDefault = true;
+                } else {
+                    if (type == Boolean.class) {
+                        this.value = Boolean.parseBoolean(propertyValue);
+                    } else if (type == String.class) {
+                        this.value = propertyValue;
+                    } else {
+                        throw new JVMCIError("Unexpected option type " + type);
+                    }
+                    this.isDefault = false;
+                }
+                // Saved properties should not be interned - let's be sure
+                assert value != UNINITIALIZED;
+            }
+            return value;
+        }
+
+        /**
+         * Gets the name of system property from which this option gets its value.
+         */
+        public String getPropertyName() {
+            return JVMCI_OPTION_PROPERTY_PREFIX + name();
+        }
+
+        /**
+         * Returns the option's value as boolean.
+         *
+         * @return option's value
+         */
+        public boolean getBoolean() {
+            return (boolean) getValue();
+        }
+
+        /**
+         * Returns the option's value as String.
+         *
+         * @return option's value
+         */
+        public String getString() {
+            return (String) getValue();
+        }
+
+        private static final int PROPERTY_LINE_WIDTH = 80;
+        private static final int PROPERTY_HELP_INDENT = 10;
+
+        /**
+         * Prints a description of the properties used to configure shared JVMCI code.
+         *
+         * @param out stream to print to
+         */
+        public static void printProperties(PrintStream out) {
+            out.println("[JVMCI properties]");
+            Option[] values = values();
+            for (Option option : values) {
+                Object value = option.getValue();
+                if (value instanceof String) {
+                    value = '"' + String.valueOf(value) + '"';
+                }
+
+                String name = option.getPropertyName();
+                String assign = option.isDefault ? "=" : ":=";
+                String typeName = option.type.getSimpleName();
+                String linePrefix = String.format("%s %s %s ", name, assign, value);
+                int typeStartPos = PROPERTY_LINE_WIDTH - typeName.length();
+                int linePad = typeStartPos - linePrefix.length();
+                if (linePad > 0) {
+                    out.printf("%s%-" + linePad + "s[%s]%n", linePrefix, "", typeName);
+                } else {
+                    out.printf("%s[%s]%n", linePrefix, typeName);
+                }
+                for (String line : option.helpLines) {
+                    out.printf("%" + PROPERTY_HELP_INDENT + "s%s%n", "", line);
+                }
+            }
+        }
+    }
+
+    public static HotSpotJVMCIBackendFactory findFactory(String architecture) {
+        for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) {
+            if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
+                return factory;
+            }
+        }
+
+        throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
+    }
+
+    /**
+     * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend.
+     */
+    public static JavaKind getHostWordKind() {
+        return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind;
+    }
+
+    protected final CompilerToVM compilerToVm;
+
+    protected final HotSpotVMConfigStore configStore;
+    protected final HotSpotVMConfig config;
+    private final JVMCIBackend hostBackend;
+
+    private final JVMCICompilerFactory compilerFactory;
+    private final HotSpotJVMCICompilerFactory hsCompilerFactory;
+    private volatile JVMCICompiler compiler;
+    protected final HotSpotJVMCIMetaAccessContext metaAccessContext;
+
+    /**
+     * Stores the result of {@link HotSpotJVMCICompilerFactory#getCompilationLevelAdjustment} so
+     * that it can be read from the VM.
+     */
+    @SuppressWarnings("unused") private final int compilationLevelAdjustment;
+
+    private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
+
+    private volatile List<HotSpotVMEventListener> vmEventListeners;
+
+    private Iterable<HotSpotVMEventListener> getVmEventListeners() {
+        if (vmEventListeners == null) {
+            synchronized (this) {
+                if (vmEventListeners == null) {
+                    vmEventListeners = JVMCIServiceLocator.getProviders(HotSpotVMEventListener.class);
+                }
+            }
+        }
+        return vmEventListeners;
+    }
+
+    /**
+     * Stores the result of {@link HotSpotJVMCICompilerFactory#getTrivialPrefixes()} so that it can
+     * be read from the VM.
+     */
+    @SuppressWarnings("unused") private final String[] trivialPrefixes;
+
+    @SuppressWarnings("try")
+    private HotSpotJVMCIRuntime() {
+        compilerToVm = new CompilerToVM();
+
+        try (InitTimer t = timer("HotSpotVMConfig<init>")) {
+            configStore = new HotSpotVMConfigStore(compilerToVm);
+            config = new HotSpotVMConfig(configStore);
+        }
+
+        String hostArchitecture = config.getHostArchitectureName();
+
+        HotSpotJVMCIBackendFactory factory;
+        try (InitTimer t = timer("find factory:", hostArchitecture)) {
+            factory = findFactory(hostArchitecture);
+        }
+
+        try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
+            hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
+        }
+
+        metaAccessContext = new HotSpotJVMCIMetaAccessContext();
+
+        compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
+        if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
+            hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
+            trivialPrefixes = hsCompilerFactory.getTrivialPrefixes();
+            switch (hsCompilerFactory.getCompilationLevelAdjustment()) {
+                case None:
+                    compilationLevelAdjustment = config.compLevelAdjustmentNone;
+                    break;
+                case ByHolder:
+                    compilationLevelAdjustment = config.compLevelAdjustmentByHolder;
+                    break;
+                case ByFullSignature:
+                    compilationLevelAdjustment = config.compLevelAdjustmentByFullSignature;
+                    break;
+                default:
+                    compilationLevelAdjustment = config.compLevelAdjustmentNone;
+                    break;
+            }
+        } else {
+            hsCompilerFactory = null;
+            trivialPrefixes = null;
+            compilationLevelAdjustment = config.compLevelAdjustmentNone;
+        }
+
+        if (config.getFlag("JVMCIPrintProperties", Boolean.class)) {
+            PrintStream out = new PrintStream(getLogStream());
+            Option.printProperties(out);
+            compilerFactory.printProperties(out);
+            System.exit(0);
+        }
+
+        if (Option.PrintConfig.getBoolean()) {
+            printConfig(configStore, compilerToVm);
+        }
+    }
+
+    private JVMCIBackend registerBackend(JVMCIBackend backend) {
+        Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass();
+        JVMCIBackend oldValue = backends.put(arch, backend);
+        assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName();
+        return backend;
+    }
+
+    public ResolvedJavaType fromClass(Class<?> javaClass) {
+        return metaAccessContext.fromClass(javaClass);
+    }
+
+    public HotSpotVMConfigStore getConfigStore() {
+        return configStore;
+    }
+
+    public HotSpotVMConfig getConfig() {
+        return config;
+    }
+
+    public CompilerToVM getCompilerToVM() {
+        return compilerToVm;
+    }
+
+    public JVMCICompiler getCompiler() {
+        if (compiler == null) {
+            synchronized (this) {
+                if (compiler == null) {
+                    compiler = compilerFactory.createCompiler(this);
+                }
+            }
+        }
+        return compiler;
+    }
+
+    public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
+        Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
+        // If the name represents a primitive type we can short-circuit the lookup.
+        if (name.length() == 1) {
+            JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
+            return fromClass(kind.toJavaClass());
+        }
+
+        // Resolve non-primitive types in the VM.
+        HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType;
+        final HotSpotResolvedObjectTypeImpl klass = compilerToVm.lookupType(name, hsAccessingType.mirror(), resolve);
+
+        if (klass == null) {
+            assert resolve == false;
+            return HotSpotUnresolvedJavaType.create(this, name);
+        }
+        return klass;
+    }
+
+    public JVMCIBackend getHostJVMCIBackend() {
+        return hostBackend;
+    }
+
+    public <T extends Architecture> JVMCIBackend getJVMCIBackend(Class<T> arch) {
+        assert arch != Architecture.class;
+        return backends.get(arch);
+    }
+
+    public Map<Class<? extends Architecture>, JVMCIBackend> getJVMCIBackends() {
+        return Collections.unmodifiableMap(backends);
+    }
+
+    /**
+     * Called from the VM.
+     */
+    @SuppressWarnings({"unused"})
+    private int adjustCompilationLevel(Class<?> declaringClass, String name, String signature, boolean isOsr, int level) {
+        CompilationLevel curLevel;
+        if (level == config.compilationLevelNone) {
+            curLevel = CompilationLevel.None;
+        } else if (level == config.compilationLevelSimple) {
+            curLevel = CompilationLevel.Simple;
+        } else if (level == config.compilationLevelLimitedProfile) {
+            curLevel = CompilationLevel.LimitedProfile;
+        } else if (level == config.compilationLevelFullProfile) {
+            curLevel = CompilationLevel.FullProfile;
+        } else if (level == config.compilationLevelFullOptimization) {
+            curLevel = CompilationLevel.FullOptimization;
+        } else {
+            throw JVMCIError.shouldNotReachHere();
+        }
+
+        switch (hsCompilerFactory.adjustCompilationLevel(declaringClass, name, signature, isOsr, curLevel)) {
+            case None:
+                return config.compilationLevelNone;
+            case Simple:
+                return config.compilationLevelSimple;
+            case LimitedProfile:
+                return config.compilationLevelLimitedProfile;
+            case FullProfile:
+                return config.compilationLevelFullProfile;
+            case FullOptimization:
+                return config.compilationLevelFullOptimization;
+            default:
+                return level;
+        }
+    }
+
+    /**
+     * Called from the VM.
+     */
+    @SuppressWarnings({"unused"})
+    private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+        CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id));
+        assert result != null : "compileMethod must always return something";
+        HotSpotCompilationRequestResult hsResult;
+        if (result instanceof HotSpotCompilationRequestResult) {
+            hsResult = (HotSpotCompilationRequestResult) result;
+        } else {
+            Object failure = result.getFailure();
+            if (failure != null) {
+                boolean retry = false; // Be conservative with unknown compiler
+                hsResult = HotSpotCompilationRequestResult.failure(failure.toString(), retry);
+            } else {
+                int inlinedBytecodes = -1;
+                hsResult = HotSpotCompilationRequestResult.success(inlinedBytecodes);
+            }
+        }
+
+        return hsResult;
+    }
+
+    /**
+     * Shuts down the runtime.
+     *
+     * Called from the VM.
+     */
+    @SuppressWarnings({"unused"})
+    private void shutdown() throws Exception {
+        for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
+            vmEventListener.notifyShutdown();
+        }
+    }
+
+    /**
+     * Notify on completion of a bootstrap.
+     *
+     * Called from the VM.
+     */
+    @SuppressWarnings({"unused"})
+    private void bootstrapFinished() throws Exception {
+        for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
+            vmEventListener.notifyBootstrapFinished();
+        }
+    }
+
+    /**
+     * Notify on successful install into the CodeCache.
+     *
+     * @param hotSpotCodeCacheProvider
+     * @param installedCode
+     * @param compiledCode
+     */
+    void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
+        for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
+            vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compiledCode);
+        }
+    }
+
+    @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
+    private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
+        String line = String.format(format, args);
+        byte[] lineBytes = line.getBytes();
+        vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
+        vm.flushDebugOutput();
+    }
+
+    private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
+        TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
+        for (VMField field : fields.values()) {
+            if (!field.isStatic()) {
+                printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
+            } else {
+                String value = field.value == null ? "null" : String.format("%d[0x%x]", field.value, field.value);
+                printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
+            }
+        }
+        TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
+        for (VMFlag flag : flags.values()) {
+            printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
+        }
+        TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
+        for (Map.Entry<String, Long> e : addresses.entrySet()) {
+            printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
+        }
+        TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
+        for (Map.Entry<String, Long> e : constants.entrySet()) {
+            printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
+        }
+        for (VMIntrinsicMethod e : store.getIntrinsics()) {
+            printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
+        }
+    }
+
+    public OutputStream getLogStream() {
+        return new OutputStream() {
+
+            @Override
+            public void write(byte[] b, int off, int len) throws IOException {
+                if (b == null) {
+                    throw new NullPointerException();
+                } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length || (off + len) < 0) {
+                    throw new IndexOutOfBoundsException();
+                } else if (len == 0) {
+                    return;
+                }
+                compilerToVm.writeDebugOutput(b, off, len);
+            }
+
+            @Override
+            public void write(int b) throws IOException {
+                write(new byte[]{(byte) b}, 0, 1);
+            }
+
+            @Override
+            public void flush() throws IOException {
+                compilerToVm.flushDebugOutput();
+            }
+        };
+    }
+
+    /**
+     * Collects the current values of all JVMCI benchmark counters, summed up over all threads.
+     */
+    public long[] collectCounters() {
+        return compilerToVm.collectCounters();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.io.OutputStream;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCIRuntime;
+import sun.misc.Unsafe;
+
+/**
+ * Configuration information for the HotSpot JVMCI runtime.
+ */
+public interface HotSpotJVMCIRuntimeProvider extends JVMCIRuntime {
+
+    HotSpotVMConfigStore getConfigStore();
+
+    HotSpotVMConfig getConfig();
+
+    CompilerToVM getCompilerToVM();
+
+    /**
+     * Gets an output stream that writes to the HotSpot's {@code tty} stream.
+     */
+    OutputStream getLogStream();
+
+    /**
+     * Converts a name to a Java type. This method attempts to resolve {@code name} to a
+     * {@link ResolvedJavaType}.
+     *
+     * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
+     * @param accessingType the context of resolution which must be non-null
+     * @param resolve specifies whether resolution failure results in an unresolved type being
+     *            return or a {@link LinkageError} being thrown
+     * @return a Java type for {@code name} which is guaranteed to be of type
+     *         {@link ResolvedJavaType} if {@code resolve == true}
+     * @throws LinkageError if {@code resolve == true} and the resolution failed
+     * @throws NullPointerException if {@code accessingClass} is {@code null}
+     */
+    JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve);
+
+    /**
+     * Gets the JVMCI mirror for a {@link Class} object.
+     *
+     * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
+     */
+    ResolvedJavaType fromClass(Class<?> clazz);
+
+    /**
+     * The offset from the origin of an array to the first element.
+     *
+     * @return the offset in bytes
+     */
+    static int getArrayBaseOffset(JavaKind kind) {
+        switch (kind) {
+            case Boolean:
+                return Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
+            case Byte:
+                return Unsafe.ARRAY_BYTE_BASE_OFFSET;
+            case Char:
+                return Unsafe.ARRAY_CHAR_BASE_OFFSET;
+            case Short:
+                return Unsafe.ARRAY_SHORT_BASE_OFFSET;
+            case Int:
+                return Unsafe.ARRAY_INT_BASE_OFFSET;
+            case Long:
+                return Unsafe.ARRAY_LONG_BASE_OFFSET;
+            case Float:
+                return Unsafe.ARRAY_FLOAT_BASE_OFFSET;
+            case Double:
+                return Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
+            case Object:
+                return Unsafe.ARRAY_OBJECT_BASE_OFFSET;
+            default:
+                throw new JVMCIError("%s", kind);
+        }
+    }
+
+    /**
+     * The scale used for the index when accessing elements of an array of this kind.
+     *
+     * @return the scale in order to convert the index into a byte offset
+     */
+    static int getArrayIndexScale(JavaKind kind) {
+        switch (kind) {
+            case Boolean:
+                return Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
+            case Byte:
+                return Unsafe.ARRAY_BYTE_INDEX_SCALE;
+            case Char:
+                return Unsafe.ARRAY_CHAR_INDEX_SCALE;
+            case Short:
+                return Unsafe.ARRAY_SHORT_INDEX_SCALE;
+            case Int:
+                return Unsafe.ARRAY_INT_INDEX_SCALE;
+            case Long:
+                return Unsafe.ARRAY_LONG_INDEX_SCALE;
+            case Float:
+                return Unsafe.ARRAY_FLOAT_INDEX_SCALE;
+            case Double:
+                return Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
+            case Object:
+                return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
+            default:
+                throw new JVMCIError("%s", kind);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,42 @@
+/*
+ * 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 jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaType;
+
+/**
+ * Common base class for all HotSpot {@link JavaType} implementations.
+ */
+public abstract class HotSpotJavaType implements JavaType {
+
+    private final String name;
+
+    public HotSpotJavaType(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public final String getName() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.MemoryAccessProvider;
+
+/**
+ * HotSpot specific extension of {@link MemoryAccessProvider}.
+ */
+public interface HotSpotMemoryAccessProvider extends MemoryAccessProvider {
+
+    JavaConstant readNarrowOopConstant(Constant base, long displacement);
+
+    Constant readKlassPointerConstant(Constant base, long displacement);
+
+    Constant readNarrowKlassPointerConstant(Constant base, long displacement);
+
+    Constant readMethodPointerConstant(Constant base, long displacement);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MemoryAccessProvider;
+import jdk.vm.ci.meta.PrimitiveConstant;
+
+/**
+ * HotSpot implementation of {@link MemoryAccessProvider}.
+ */
+class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
+
+    protected final HotSpotJVMCIRuntimeProvider runtime;
+
+    HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntimeProvider runtime) {
+        this.runtime = runtime;
+    }
+
+    private static Object asObject(Constant base) {
+        if (base instanceof HotSpotObjectConstantImpl) {
+            return ((HotSpotObjectConstantImpl) base).object();
+        } else {
+            return null;
+        }
+    }
+
+    private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
+        if (base instanceof HotSpotMetaspaceConstant) {
+            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
+                if (displacement == runtime.getConfig().classMirrorOffset) {
+                    // Klass::_java_mirror is valid for all Klass* values
+                    return true;
+                } else if (displacement == runtime.getConfig().arrayKlassComponentMirrorOffset) {
+                    // ArrayKlass::_component_mirror is only valid for all ArrayKlass* values
+                    return ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror().isArray();
+                }
+            } else {
+                throw new IllegalArgumentException(String.valueOf(metaspaceObject));
+            }
+        }
+        return false;
+    }
+
+    private static long asRawPointer(Constant base) {
+        if (base instanceof HotSpotMetaspaceConstantImpl) {
+            MetaspaceWrapperObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            return meta.getMetaspacePointer();
+        } else if (base instanceof PrimitiveConstant) {
+            PrimitiveConstant prim = (PrimitiveConstant) base;
+            if (prim.getJavaKind().isNumericInteger()) {
+                return prim.asLong();
+            }
+        }
+        throw new IllegalArgumentException(String.valueOf(base));
+    }
+
+    private static long readRawValue(Constant baseConstant, long displacement, int bits) {
+        Object base = asObject(baseConstant);
+        if (base != null) {
+            switch (bits) {
+                case Byte.SIZE:
+                    return UNSAFE.getByte(base, displacement);
+                case Short.SIZE:
+                    return UNSAFE.getShort(base, displacement);
+                case Integer.SIZE:
+                    return UNSAFE.getInt(base, displacement);
+                case Long.SIZE:
+                    return UNSAFE.getLong(base, displacement);
+                default:
+                    throw new IllegalArgumentException(String.valueOf(bits));
+            }
+        } else {
+            long pointer = asRawPointer(baseConstant);
+            switch (bits) {
+                case Byte.SIZE:
+                    return UNSAFE.getByte(pointer + displacement);
+                case Short.SIZE:
+                    return UNSAFE.getShort(pointer + displacement);
+                case Integer.SIZE:
+                    return UNSAFE.getInt(pointer + displacement);
+                case Long.SIZE:
+                    return UNSAFE.getLong(pointer + displacement);
+                default:
+                    throw new IllegalArgumentException(String.valueOf(bits));
+            }
+        }
+    }
+
+    private boolean verifyReadRawObject(Object expected, Constant base, long displacement) {
+        if (base instanceof HotSpotMetaspaceConstant) {
+            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
+                if (displacement == runtime.getConfig().classMirrorOffset) {
+                    assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror();
+                } else if (displacement == runtime.getConfig().arrayKlassComponentMirrorOffset) {
+                    assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror().getComponentType();
+                }
+            }
+        }
+        return true;
+    }
+
+    private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
+        long displacement = initialDisplacement;
+
+        Object ret;
+        Object base = asObject(baseConstant);
+        if (base == null) {
+            assert !compressed;
+            displacement += asRawPointer(baseConstant);
+            ret = runtime.getCompilerToVM().readUncompressedOop(displacement);
+            assert verifyReadRawObject(ret, baseConstant, initialDisplacement);
+        } else {
+            assert runtime.getConfig().useCompressedOops == compressed;
+            ret = UNSAFE.getObject(base, displacement);
+        }
+        return ret;
+    }
+
+    /**
+     * Reads a value of this kind using a base address and a displacement. No bounds checking or
+     * type checking is performed. Returns {@code null} if the value is not available at this point.
+     *
+     * @param baseConstant the base address from which the value is read.
+     * @param displacement the displacement within the object in bytes
+     * @return the read value encapsulated in a {@link JavaConstant} object, or {@code null} if the
+     *         value cannot be read.
+     * @throws IllegalArgumentException if {@code kind} is {@code null}, {@link JavaKind#Void}, not
+     *             {@link JavaKind#Object} or not {@linkplain JavaKind#isPrimitive() primitive} kind
+     */
+    JavaConstant readUnsafeConstant(JavaKind kind, JavaConstant baseConstant, long displacement) {
+        if (kind == null) {
+            throw new IllegalArgumentException("null JavaKind");
+        }
+        if (kind == JavaKind.Object) {
+            Object o = readRawObject(baseConstant, displacement, runtime.getConfig().useCompressedOops);
+            return HotSpotObjectConstantImpl.forObject(o);
+        } else {
+            int bits = kind.getByteCount() * Byte.SIZE;
+            return readPrimitiveConstant(kind, baseConstant, displacement, bits);
+        }
+    }
+
+    @Override
+    public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) {
+        try {
+            long rawValue = readRawValue(baseConstant, initialDisplacement, bits);
+            switch (kind) {
+                case Boolean:
+                    return JavaConstant.forBoolean(rawValue != 0);
+                case Byte:
+                    return JavaConstant.forByte((byte) rawValue);
+                case Char:
+                    return JavaConstant.forChar((char) rawValue);
+                case Short:
+                    return JavaConstant.forShort((short) rawValue);
+                case Int:
+                    return JavaConstant.forInt((int) rawValue);
+                case Long:
+                    return JavaConstant.forLong(rawValue);
+                case Float:
+                    return JavaConstant.forFloat(Float.intBitsToFloat((int) rawValue));
+                case Double:
+                    return JavaConstant.forDouble(Double.longBitsToDouble(rawValue));
+                default:
+                    throw new IllegalArgumentException("Unsupported kind: " + kind);
+            }
+        } catch (NullPointerException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public JavaConstant readObjectConstant(Constant base, long displacement) {
+        if (base instanceof HotSpotObjectConstantImpl) {
+            Object o = readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
+            return HotSpotObjectConstantImpl.forObject(o);
+        }
+        if (!isValidObjectFieldDisplacement(base, displacement)) {
+            return null;
+        }
+        return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, false));
+    }
+
+    @Override
+    public JavaConstant readNarrowOopConstant(Constant base, long displacement) {
+        return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, true), true);
+    }
+
+    private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) {
+        assert (base instanceof HotSpotMetaspaceConstantImpl) || (base instanceof HotSpotObjectConstantImpl) : base.getClass();
+        Object baseObject = (base instanceof HotSpotMetaspaceConstantImpl) ? ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType() : ((HotSpotObjectConstantImpl) base).object();
+        return runtime.getCompilerToVM().getResolvedJavaType(baseObject, displacement, compressed);
+    }
+
+    @Override
+    public Constant readKlassPointerConstant(Constant base, long displacement) {
+        HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, false);
+        if (klass == null) {
+            return JavaConstant.NULL_POINTER;
+        }
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, false);
+    }
+
+    @Override
+    public Constant readNarrowKlassPointerConstant(Constant base, long displacement) {
+        HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, true);
+        if (klass == null) {
+            return HotSpotCompressedNullConstant.COMPRESSED_NULL;
+        }
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, true);
+    }
+
+    @Override
+    public Constant readMethodPointerConstant(Constant base, long displacement) {
+        assert (base instanceof HotSpotObjectConstantImpl);
+        Object baseObject = ((HotSpotObjectConstantImpl) base).object();
+        HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod(baseObject, displacement);
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
+import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Objects;
+
+import jdk.vm.ci.code.CodeUtil;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.DeoptimizationAction;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+
+// JaCoCo Exclude
+
+/**
+ * HotSpot implementation of {@link MetaAccessProvider}.
+ */
+public class HotSpotMetaAccessProvider implements MetaAccessProvider {
+
+    protected final HotSpotJVMCIRuntimeProvider runtime;
+
+    public HotSpotMetaAccessProvider(HotSpotJVMCIRuntimeProvider runtime) {
+        this.runtime = runtime;
+    }
+
+    public ResolvedJavaType lookupJavaType(Class<?> clazz) {
+        if (clazz == null) {
+            throw new IllegalArgumentException("Class parameter was null");
+        }
+        return runtime.fromClass(clazz);
+    }
+
+    public HotSpotResolvedObjectType lookupJavaType(JavaConstant constant) {
+        if (constant.isNull() || !(constant instanceof HotSpotObjectConstant)) {
+            return null;
+        }
+        return ((HotSpotObjectConstant) constant).getType();
+    }
+
+    public Signature parseMethodDescriptor(String signature) {
+        return new HotSpotSignature(runtime, signature);
+    }
+
+    public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) {
+        return runtime.getCompilerToVM().asResolvedJavaMethod(Objects.requireNonNull(reflectionMethod));
+    }
+
+    public ResolvedJavaField lookupJavaField(Field reflectionField) {
+        Class<?> fieldHolder = reflectionField.getDeclaringClass();
+
+        HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder);
+        if (Modifier.isStatic(reflectionField.getModifiers())) {
+            final long offset = UNSAFE.staticFieldOffset(reflectionField);
+            for (ResolvedJavaField field : holder.getStaticFields()) {
+                if (offset == ((HotSpotResolvedJavaField) field).offset()) {
+                    return field;
+                }
+            }
+        } else {
+            final long offset = UNSAFE.objectFieldOffset(reflectionField);
+            for (ResolvedJavaField field : holder.getInstanceFields(false)) {
+                if (offset == ((HotSpotResolvedJavaField) field).offset()) {
+                    return field;
+                }
+            }
+        }
+
+        throw new JVMCIError("unresolved field %s", reflectionField);
+    }
+
+    private static int intMaskRight(int n) {
+        assert n <= 32;
+        return n == 32 ? -1 : (1 << n) - 1;
+    }
+
+    @Override
+    public JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) {
+        HotSpotVMConfig config = runtime.getConfig();
+        int actionValue = convertDeoptAction(action);
+        int reasonValue = convertDeoptReason(reason);
+        int debugValue = debugId & intMaskRight(config.deoptimizationDebugIdBits);
+        JavaConstant c = JavaConstant.forInt(
+                        ~((debugValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift)));
+        assert c.asInt() < 0;
+        return c;
+    }
+
+    public DeoptimizationReason decodeDeoptReason(JavaConstant constant) {
+        HotSpotVMConfig config = runtime.getConfig();
+        int reasonValue = ((~constant.asInt()) >> config.deoptimizationReasonShift) & intMaskRight(config.deoptimizationReasonBits);
+        DeoptimizationReason reason = convertDeoptReason(reasonValue);
+        return reason;
+    }
+
+    public DeoptimizationAction decodeDeoptAction(JavaConstant constant) {
+        HotSpotVMConfig config = runtime.getConfig();
+        int actionValue = ((~constant.asInt()) >> config.deoptimizationActionShift) & intMaskRight(config.deoptimizationActionBits);
+        DeoptimizationAction action = convertDeoptAction(actionValue);
+        return action;
+    }
+
+    public int decodeDebugId(JavaConstant constant) {
+        HotSpotVMConfig config = runtime.getConfig();
+        return ((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits);
+    }
+
+    public int convertDeoptAction(DeoptimizationAction action) {
+        HotSpotVMConfig config = runtime.getConfig();
+        switch (action) {
+            case None:
+                return config.deoptActionNone;
+            case RecompileIfTooManyDeopts:
+                return config.deoptActionMaybeRecompile;
+            case InvalidateReprofile:
+                return config.deoptActionReinterpret;
+            case InvalidateRecompile:
+                return config.deoptActionMakeNotEntrant;
+            case InvalidateStopCompiling:
+                return config.deoptActionMakeNotCompilable;
+            default:
+                throw new JVMCIError("%s", action);
+        }
+    }
+
+    public DeoptimizationAction convertDeoptAction(int action) {
+        HotSpotVMConfig config = runtime.getConfig();
+        if (action == config.deoptActionNone) {
+            return DeoptimizationAction.None;
+        }
+        if (action == config.deoptActionMaybeRecompile) {
+            return DeoptimizationAction.RecompileIfTooManyDeopts;
+        }
+        if (action == config.deoptActionReinterpret) {
+            return DeoptimizationAction.InvalidateReprofile;
+        }
+        if (action == config.deoptActionMakeNotEntrant) {
+            return DeoptimizationAction.InvalidateRecompile;
+        }
+        if (action == config.deoptActionMakeNotCompilable) {
+            return DeoptimizationAction.InvalidateStopCompiling;
+        }
+        throw new JVMCIError("%d", action);
+    }
+
+    public int convertDeoptReason(DeoptimizationReason reason) {
+        HotSpotVMConfig config = runtime.getConfig();
+        switch (reason) {
+            case None:
+                return config.deoptReasonNone;
+            case NullCheckException:
+                return config.deoptReasonNullCheck;
+            case BoundsCheckException:
+                return config.deoptReasonRangeCheck;
+            case ClassCastException:
+                return config.deoptReasonClassCheck;
+            case ArrayStoreException:
+                return config.deoptReasonArrayCheck;
+            case UnreachedCode:
+                return config.deoptReasonUnreached0;
+            case TypeCheckedInliningViolated:
+                return config.deoptReasonTypeCheckInlining;
+            case OptimizedTypeCheckViolated:
+                return config.deoptReasonOptimizedTypeCheck;
+            case NotCompiledExceptionHandler:
+                return config.deoptReasonNotCompiledExceptionHandler;
+            case Unresolved:
+                return config.deoptReasonUnresolved;
+            case JavaSubroutineMismatch:
+                return config.deoptReasonJsrMismatch;
+            case ArithmeticException:
+                return config.deoptReasonDiv0Check;
+            case RuntimeConstraint:
+                return config.deoptReasonConstraint;
+            case LoopLimitCheck:
+                return config.deoptReasonLoopLimitCheck;
+            case Aliasing:
+                return config.deoptReasonAliasing;
+            case TransferToInterpreter:
+                return config.deoptReasonTransferToInterpreter;
+            default:
+                throw new JVMCIError("%s", reason);
+        }
+    }
+
+    public DeoptimizationReason convertDeoptReason(int reason) {
+        HotSpotVMConfig config = runtime.getConfig();
+        if (reason == config.deoptReasonNone) {
+            return DeoptimizationReason.None;
+        }
+        if (reason == config.deoptReasonNullCheck) {
+            return DeoptimizationReason.NullCheckException;
+        }
+        if (reason == config.deoptReasonRangeCheck) {
+            return DeoptimizationReason.BoundsCheckException;
+        }
+        if (reason == config.deoptReasonClassCheck) {
+            return DeoptimizationReason.ClassCastException;
+        }
+        if (reason == config.deoptReasonArrayCheck) {
+            return DeoptimizationReason.ArrayStoreException;
+        }
+        if (reason == config.deoptReasonUnreached0) {
+            return DeoptimizationReason.UnreachedCode;
+        }
+        if (reason == config.deoptReasonTypeCheckInlining) {
+            return DeoptimizationReason.TypeCheckedInliningViolated;
+        }
+        if (reason == config.deoptReasonOptimizedTypeCheck) {
+            return DeoptimizationReason.OptimizedTypeCheckViolated;
+        }
+        if (reason == config.deoptReasonNotCompiledExceptionHandler) {
+            return DeoptimizationReason.NotCompiledExceptionHandler;
+        }
+        if (reason == config.deoptReasonUnresolved) {
+            return DeoptimizationReason.Unresolved;
+        }
+        if (reason == config.deoptReasonJsrMismatch) {
+            return DeoptimizationReason.JavaSubroutineMismatch;
+        }
+        if (reason == config.deoptReasonDiv0Check) {
+            return DeoptimizationReason.ArithmeticException;
+        }
+        if (reason == config.deoptReasonConstraint) {
+            return DeoptimizationReason.RuntimeConstraint;
+        }
+        if (reason == config.deoptReasonLoopLimitCheck) {
+            return DeoptimizationReason.LoopLimitCheck;
+        }
+        if (reason == config.deoptReasonAliasing) {
+            return DeoptimizationReason.Aliasing;
+        }
+        if (reason == config.deoptReasonTransferToInterpreter) {
+            return DeoptimizationReason.TransferToInterpreter;
+        }
+        throw new JVMCIError("%x", reason);
+    }
+
+    @Override
+    public long getMemorySize(JavaConstant constant) {
+        if (constant.getJavaKind() == JavaKind.Object) {
+            HotSpotResolvedObjectType lookupJavaType = lookupJavaType(constant);
+
+            if (lookupJavaType == null) {
+                return 0;
+            } else {
+                if (lookupJavaType.isArray()) {
+                    int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object());
+                    ResolvedJavaType elementType = lookupJavaType.getComponentType();
+                    JavaKind elementKind = elementType.getJavaKind();
+                    final int headerSize = getArrayBaseOffset(elementKind);
+                    TargetDescription target = runtime.getHostJVMCIBackend().getTarget();
+                    int sizeOfElement = getArrayIndexScale(elementKind);
+                    int alignment = target.wordSize;
+                    int log2ElementSize = CodeUtil.log2(sizeOfElement);
+                    return computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize);
+                }
+                return lookupJavaType.instanceSize();
+            }
+        } else {
+            return constant.getJavaKind().getByteCount();
+        }
+    }
+
+    /**
+     * Computes the size of the memory chunk allocated for an array. This size accounts for the
+     * array header size, body size and any padding after the last element to satisfy object
+     * alignment requirements.
+     *
+     * @param length the number of elements in the array
+     * @param alignment the object alignment requirement
+     * @param headerSize the size of the array header
+     * @param log2ElementSize log2 of the size of an element in the array
+     */
+    public static int computeArrayAllocationSize(int length, int alignment, int headerSize, int log2ElementSize) {
+        int size = (length << log2ElementSize) + headerSize + (alignment - 1);
+        int mask = ~(alignment - 1);
+        return size & mask;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.VMConstant;
+
+public interface HotSpotMetaspaceConstant extends HotSpotConstant, VMConstant {
+
+    HotSpotResolvedObjectType asResolvedJavaType();
+
+    HotSpotResolvedJavaMethod asResolvedJavaMethod();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.Objects;
+
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.VMConstant;
+
+final class HotSpotMetaspaceConstantImpl implements HotSpotMetaspaceConstant, VMConstant {
+
+    static HotSpotMetaspaceConstantImpl forMetaspaceObject(MetaspaceWrapperObject metaspaceObject, boolean compressed) {
+        return new HotSpotMetaspaceConstantImpl(metaspaceObject, compressed);
+    }
+
+    static MetaspaceWrapperObject getMetaspaceObject(Constant constant) {
+        return ((HotSpotMetaspaceConstantImpl) constant).metaspaceObject;
+    }
+
+    private final MetaspaceWrapperObject metaspaceObject;
+    private final boolean compressed;
+
+    private HotSpotMetaspaceConstantImpl(MetaspaceWrapperObject metaspaceObject, boolean compressed) {
+        this.metaspaceObject = metaspaceObject;
+        this.compressed = compressed;
+    }
+
+    @Override
+    public int hashCode() {
+        return System.identityHashCode(metaspaceObject) ^ (compressed ? 1 : 2);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof HotSpotMetaspaceConstantImpl)) {
+            return false;
+        }
+
+        HotSpotMetaspaceConstantImpl other = (HotSpotMetaspaceConstantImpl) o;
+        return Objects.equals(this.metaspaceObject, other.metaspaceObject) && this.compressed == other.compressed;
+    }
+
+    @Override
+    public String toValueString() {
+        return String.format("meta{%s%s}", metaspaceObject, compressed ? ";compressed" : "");
+    }
+
+    @Override
+    public String toString() {
+        return toValueString();
+    }
+
+    public boolean isDefaultForKind() {
+        return false;
+    }
+
+    public boolean isCompressed() {
+        return compressed;
+    }
+
+    public Constant compress() {
+        assert !isCompressed();
+        HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(metaspaceObject, true);
+        assert res.isCompressed();
+        return res;
+    }
+
+    public Constant uncompress() {
+        assert isCompressed();
+        HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(metaspaceObject, false);
+        assert !res.isCompressed();
+        return res;
+    }
+
+    public HotSpotResolvedObjectType asResolvedJavaType() {
+        if (metaspaceObject instanceof HotSpotResolvedObjectType) {
+            return (HotSpotResolvedObjectType) metaspaceObject;
+        }
+        return null;
+    }
+
+    public HotSpotResolvedJavaMethod asResolvedJavaMethod() {
+        if (metaspaceObject instanceof HotSpotResolvedJavaMethod) {
+            return (HotSpotResolvedJavaMethod) metaspaceObject;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.util.FormattableFlags.ALTERNATE;
+import static java.util.FormattableFlags.LEFT_JUSTIFY;
+import static java.util.FormattableFlags.UPPERCASE;
+
+import java.util.Formattable;
+import java.util.Formatter;
+
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+abstract class HotSpotMethod implements JavaMethod, Formattable {
+
+    public static String applyFormattingFlagsAndWidth(String s, int flags, int width) {
+        if (flags == 0 && width < 0) {
+            return s;
+        }
+        StringBuilder sb = new StringBuilder(s);
+
+        // apply width and justification
+        int len = sb.length();
+        if (len < width) {
+            for (int i = 0; i < width - len; i++) {
+                if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) {
+                    sb.append(' ');
+                } else {
+                    sb.insert(0, ' ');
+                }
+            }
+        }
+
+        String res = sb.toString();
+        if ((flags & UPPERCASE) == UPPERCASE) {
+            res = res.toUpperCase();
+        }
+        return res;
+    }
+
+    /**
+     * Controls whether {@link #toString()} includes the qualified or simple name of the class in
+     * which the method is declared.
+     */
+    public static final boolean FULLY_QUALIFIED_METHOD_NAME = false;
+
+    @Override
+    public final String toString() {
+        char h = FULLY_QUALIFIED_METHOD_NAME ? 'H' : 'h';
+        String suffix = this instanceof ResolvedJavaMethod ? "" : ", unresolved";
+        String fmt = String.format("HotSpotMethod<%%%c.%%n(%%p)%s>", h, suffix);
+        return format(fmt);
+    }
+
+    public void formatTo(Formatter formatter, int flags, int width, int precision) {
+        String base = (flags & ALTERNATE) == ALTERNATE ? getName() : toString();
+        formatter.format(applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width));
+    }
+
+    public JavaMethod asJavaMethod() {
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,862 @@
+/*
+ * 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 jdk.vm.ci.hotspot;
+
+import static java.lang.String.format;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.util.Arrays;
+
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaMethodProfile;
+import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod;
+import jdk.vm.ci.meta.JavaTypeProfile;
+import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.TriState;
+import sun.misc.Unsafe;
+
+/**
+ * Access to a HotSpot {@code MethodData} structure (defined in methodData.hpp).
+ */
+final class HotSpotMethodData {
+
+    static final HotSpotVMConfig config = config();
+    static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.FALSE);
+    static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.UNKNOWN);
+
+    /**
+     * Reference to the C++ MethodData object.
+     */
+    final long metaspaceMethodData;
+    private final HotSpotResolvedJavaMethodImpl method;
+
+    HotSpotMethodData(long metaspaceMethodData, HotSpotResolvedJavaMethodImpl method) {
+        this.metaspaceMethodData = metaspaceMethodData;
+        this.method = method;
+    }
+
+    /**
+     * @return value of the MethodData::_data_size field
+     */
+    private int normalDataSize() {
+        return UNSAFE.getInt(metaspaceMethodData + config.methodDataDataSize);
+    }
+
+    /**
+     * Returns the size of the extra data records. This method does the same calculation as
+     * MethodData::extra_data_size().
+     *
+     * @return size of extra data records
+     */
+    private int extraDataSize() {
+        final int extraDataBase = config.methodDataOopDataOffset + normalDataSize();
+        final int extraDataLimit = UNSAFE.getInt(metaspaceMethodData + config.methodDataSize);
+        return extraDataLimit - extraDataBase;
+    }
+
+    public boolean hasNormalData() {
+        return normalDataSize() > 0;
+    }
+
+    public boolean hasExtraData() {
+        return extraDataSize() > 0;
+    }
+
+    public int getExtraDataBeginOffset() {
+        return normalDataSize();
+    }
+
+    public boolean isWithin(int position) {
+        return position >= 0 && position < normalDataSize() + extraDataSize();
+    }
+
+    public int getDeoptimizationCount(DeoptimizationReason reason) {
+        HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
+        int reasonIndex = metaAccess.convertDeoptReason(reason);
+        return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
+    }
+
+    public int getOSRDeoptimizationCount(DeoptimizationReason reason) {
+        HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
+        int reasonIndex = metaAccess.convertDeoptReason(reason);
+        return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + config.deoptReasonOSROffset + reasonIndex) & 0xFF;
+    }
+
+    public int getDecompileCount() {
+        return UNSAFE.getInt(metaspaceMethodData + config.methodDataDecompiles);
+    }
+
+    public int getOverflowRecompileCount() {
+        return UNSAFE.getInt(metaspaceMethodData + config.methodDataOverflowRecompiles);
+    }
+
+    public int getOverflowTrapCount() {
+        return UNSAFE.getInt(metaspaceMethodData + config.methodDataOverflowTraps);
+    }
+
+    public HotSpotMethodDataAccessor getNormalData(int position) {
+        if (position >= normalDataSize()) {
+            return null;
+        }
+
+        return getData(position);
+    }
+
+    public HotSpotMethodDataAccessor getExtraData(int position) {
+        if (position >= normalDataSize() + extraDataSize()) {
+            return null;
+        }
+        HotSpotMethodDataAccessor data = getData(position);
+        if (data != null) {
+            return data;
+        }
+        return data;
+    }
+
+    public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) {
+        if (exceptionPossiblyNotRecorded) {
+            return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR;
+        } else {
+            return NO_DATA_NO_EXCEPTION_ACCESSOR;
+        }
+    }
+
+    private HotSpotMethodDataAccessor getData(int position) {
+        assert position >= 0 : "out of bounds";
+        final int tag = HotSpotMethodDataAccessor.readTag(config, this, position);
+        HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag];
+        assert accessor == null || accessor.getTag() == tag : "wrong data accessor " + accessor + " for tag " + tag;
+        return accessor;
+    }
+
+    int readUnsignedByte(int position, int offsetInBytes) {
+        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        return UNSAFE.getByte(metaspaceMethodData + fullOffsetInBytes) & 0xFF;
+    }
+
+    int readUnsignedShort(int position, int offsetInBytes) {
+        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        return UNSAFE.getShort(metaspaceMethodData + fullOffsetInBytes) & 0xFFFF;
+    }
+
+    /**
+     * Since the values are stored in cells (platform words) this method uses
+     * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
+     */
+    private long readUnsignedInt(int position, int offsetInBytes) {
+        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        return UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes) & 0xFFFFFFFFL;
+    }
+
+    private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) {
+        long value = readUnsignedInt(position, offsetInBytes);
+        return truncateLongToInt(value);
+    }
+
+    /**
+     * Since the values are stored in cells (platform words) this method uses
+     * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
+     */
+    private int readInt(int position, int offsetInBytes) {
+        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        return (int) UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes);
+    }
+
+    private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) {
+        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        return compilerToVM().getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes);
+    }
+
+    private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) {
+        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        return compilerToVM().getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false);
+    }
+
+    private static int truncateLongToInt(long value) {
+        return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
+    }
+
+    private static int computeFullOffset(int position, int offsetInBytes) {
+        return config.methodDataOopDataOffset + position + offsetInBytes;
+    }
+
+    private static int cellIndexToOffset(int cells) {
+        return config.dataLayoutHeaderSize + cellsToBytes(cells);
+    }
+
+    private static int cellsToBytes(int cells) {
+        return cells * config.dataLayoutCellSize;
+    }
+
+    /**
+     * Returns whether profiling ran long enough that the profile information is mature. Other
+     * informational data will still be valid even if the profile isn't mature.
+     */
+    public boolean isProfileMature() {
+        return runtime().getCompilerToVM().isMature(metaspaceMethodData);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        String nl = String.format("%n");
+        String nlIndent = String.format("%n%38s", "");
+        sb.append("Raw method data for ");
+        sb.append(method.format("%H.%n(%p)"));
+        sb.append(":");
+        sb.append(nl);
+        sb.append(String.format("nof_decompiles(%d) nof_overflow_recompiles(%d) nof_overflow_traps(%d)%n",
+                        getDecompileCount(), getOverflowRecompileCount(), getOverflowTrapCount()));
+        if (hasNormalData()) {
+            int pos = 0;
+            HotSpotMethodDataAccessor data;
+            while ((data = getNormalData(pos)) != null) {
+                if (pos != 0) {
+                    sb.append(nl);
+                }
+                int bci = data.getBCI(this, pos);
+                sb.append(String.format("%-6d bci: %-6d%-20s", pos, bci, data.getClass().getSimpleName()));
+                sb.append(data.appendTo(new StringBuilder(), this, pos).toString().replace(nl, nlIndent));
+                pos = pos + data.getSize(this, pos);
+            }
+        }
+
+        if (hasExtraData()) {
+            int pos = getExtraDataBeginOffset();
+            HotSpotMethodDataAccessor data;
+            while ((data = getExtraData(pos)) != null) {
+                if (pos == getExtraDataBeginOffset()) {
+                    sb.append(nl).append("--- Extra data:");
+                }
+                int bci = data.getBCI(this, pos);
+                sb.append(String.format("%n%-6d bci: %-6d%-20s", pos, bci, data.getClass().getSimpleName()));
+                sb.append(data.appendTo(new StringBuilder(), this, pos).toString().replace(nl, nlIndent));
+                pos = pos + data.getSize(this, pos);
+            }
+
+        }
+        return sb.toString();
+    }
+
+    static final int NO_DATA_SIZE = cellIndexToOffset(0);
+
+    static class NoMethodData extends HotSpotMethodDataAccessor {
+
+        private final TriState exceptionSeen;
+
+        protected NoMethodData(HotSpotVMConfig config, int tag, TriState exceptionSeen) {
+            super(config, tag, NO_DATA_SIZE);
+            this.exceptionSeen = exceptionSeen;
+        }
+
+        @Override
+        public int getBCI(HotSpotMethodData data, int position) {
+            return -1;
+        }
+
+        @Override
+        public TriState getExceptionSeen(HotSpotMethodData data, int position) {
+            return exceptionSeen;
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            return sb;
+        }
+    }
+
+    static final int BIT_DATA_SIZE = cellIndexToOffset(0);
+    static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
+
+    static class BitData extends HotSpotMethodDataAccessor {
+
+        private BitData(HotSpotVMConfig config, int tag) {
+            super(config, tag, BIT_DATA_SIZE);
+        }
+
+        protected BitData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
+        }
+
+        @Override
+        public TriState getNullSeen(HotSpotMethodData data, int position) {
+            return TriState.get((getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0);
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            return sb.append(format("exception_seen(%s)", getExceptionSeen(data, pos)));
+        }
+    }
+
+    static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
+    static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
+
+    static class CounterData extends BitData {
+
+        CounterData(HotSpotVMConfig config, int tag) {
+            super(config, tag, COUNTER_DATA_SIZE);
+        }
+
+        protected CounterData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
+        }
+
+        @Override
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            return getCounterValue(data, position);
+        }
+
+        protected int getCounterValue(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET);
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            return sb.append(format("count(%d) null_seen(%s) exception_seen(%s)", getCounterValue(data, pos), getNullSeen(data, pos), getExceptionSeen(data, pos)));
+        }
+    }
+
+    static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
+    static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
+    static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
+
+    static class JumpData extends HotSpotMethodDataAccessor {
+
+        JumpData(HotSpotVMConfig config, int tag) {
+            super(config, tag, JUMP_DATA_SIZE);
+        }
+
+        protected JumpData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
+        }
+
+        @Override
+        public double getBranchTakenProbability(HotSpotMethodData data, int position) {
+            return getExecutionCount(data, position) != 0 ? 1 : 0;
+        }
+
+        @Override
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET);
+        }
+
+        public int getTakenDisplacement(HotSpotMethodData data, int position) {
+            return data.readInt(position, TAKEN_DISPLACEMENT_OFFSET);
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            return sb.append(format("taken(%d) displacement(%d)", getExecutionCount(data, pos), getTakenDisplacement(data, pos)));
+        }
+    }
+
+    static class RawItemProfile<T> {
+        final int entries;
+        final T[] items;
+        final long[] counts;
+        final long totalCount;
+
+        RawItemProfile(int entries, T[] items, long[] counts, long totalCount) {
+            this.entries = entries;
+            this.items = items;
+            this.counts = counts;
+            this.totalCount = totalCount;
+        }
+    }
+
+    static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
+
+    static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
+    static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
+    static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset);
+
+    abstract static class AbstractTypeData extends CounterData {
+
+        protected AbstractTypeData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
+        }
+
+        @Override
+        public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
+            return createTypeProfile(getNullSeen(data, position), getRawTypeProfile(data, position));
+        }
+
+        private RawItemProfile<ResolvedJavaType> getRawTypeProfile(HotSpotMethodData data, int position) {
+            int typeProfileWidth = config.typeProfileWidth;
+
+            ResolvedJavaType[] types = new ResolvedJavaType[typeProfileWidth];
+            long[] counts = new long[typeProfileWidth];
+            long totalCount = 0;
+            int entries = 0;
+
+            outer: for (int i = 0; i < typeProfileWidth; i++) {
+                HotSpotResolvedObjectTypeImpl receiverKlass = data.readKlass(position, getTypeOffset(i));
+                if (receiverKlass != null) {
+                    HotSpotResolvedObjectTypeImpl klass = receiverKlass;
+                    long count = data.readUnsignedInt(position, getTypeCountOffset(i));
+                    /*
+                     * Because of races in the profile collection machinery it's possible for a
+                     * class to appear multiple times so merge them to make the profile look
+                     * rational.
+                     */
+                    for (int j = 0; j < entries; j++) {
+                        if (types[j].equals(klass)) {
+                            totalCount += count;
+                            counts[j] += count;
+                            continue outer;
+                        }
+                    }
+                    types[entries] = klass;
+                    totalCount += count;
+                    counts[entries] = count;
+                    entries++;
+                }
+            }
+
+            totalCount += getTypesNotRecordedExecutionCount(data, position);
+            return new RawItemProfile<>(entries, types, counts, totalCount);
+        }
+
+        protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
+
+        public int getNonprofiledCount(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+        }
+
+        private JavaTypeProfile createTypeProfile(TriState nullSeen, RawItemProfile<ResolvedJavaType> profile) {
+            if (profile.entries <= 0 || profile.totalCount <= 0) {
+                return null;
+            }
+
+            ProfiledType[] ptypes = new ProfiledType[profile.entries];
+            double totalProbability = 0.0;
+            for (int i = 0; i < profile.entries; i++) {
+                double p = profile.counts[i];
+                p = p / profile.totalCount;
+                totalProbability += p;
+                ptypes[i] = new ProfiledType(profile.items[i], p);
+            }
+
+            Arrays.sort(ptypes);
+
+            double notRecordedTypeProbability = profile.entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability));
+            assert notRecordedTypeProbability == 0 || profile.entries == config.typeProfileWidth;
+            return new JavaTypeProfile(nullSeen, notRecordedTypeProbability, ptypes);
+        }
+
+        private static int getTypeOffset(int row) {
+            return TYPE_DATA_FIRST_TYPE_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        }
+
+        protected static int getTypeCountOffset(int row) {
+            return TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            RawItemProfile<ResolvedJavaType> profile = getRawTypeProfile(data, pos);
+            TriState nullSeen = getNullSeen(data, pos);
+            TriState exceptionSeen = getExceptionSeen(data, pos);
+            sb.append(format("count(%d) null_seen(%s) exception_seen(%s) nonprofiled_count(%d) entries(%d)", getCounterValue(data, pos), nullSeen, exceptionSeen,
+                            getNonprofiledCount(data, pos), profile.entries));
+            for (int i = 0; i < profile.entries; i++) {
+                long count = profile.counts[i];
+                sb.append(format("%n  %s (%d, %4.2f)", profile.items[i].toJavaName(), count, (double) count / profile.totalCount));
+            }
+            return sb;
+        }
+    }
+
+    static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+
+    static class ReceiverTypeData extends AbstractTypeData {
+
+        ReceiverTypeData(HotSpotVMConfig config, int tag) {
+            super(config, tag, TYPE_CHECK_DATA_SIZE);
+        }
+
+        protected ReceiverTypeData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
+        }
+
+        @Override
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            return -1;
+        }
+
+        @Override
+        protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+            return getNonprofiledCount(data, position);
+        }
+    }
+
+    static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
+    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+
+    static class VirtualCallData extends ReceiverTypeData {
+
+        VirtualCallData(HotSpotVMConfig config, int tag) {
+            super(config, tag, VIRTUAL_CALL_DATA_SIZE);
+        }
+
+        protected VirtualCallData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
+        }
+
+        @Override
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            final int typeProfileWidth = config.typeProfileWidth;
+
+            long total = 0;
+            for (int i = 0; i < typeProfileWidth; i++) {
+                total += data.readUnsignedInt(position, getTypeCountOffset(i));
+            }
+
+            total += getCounterValue(data, position);
+            return truncateLongToInt(total);
+        }
+
+        @Override
+        protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+            return getCounterValue(data, position);
+        }
+
+        private static long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+        }
+
+        @Override
+        public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
+            return createMethodProfile(getRawMethodProfile(data, position));
+        }
+
+        private RawItemProfile<ResolvedJavaMethod> getRawMethodProfile(HotSpotMethodData data, int position) {
+            int profileWidth = config.methodProfileWidth;
+
+            ResolvedJavaMethod[] methods = new ResolvedJavaMethod[profileWidth];
+            long[] counts = new long[profileWidth];
+            long totalCount = 0;
+            int entries = 0;
+
+            for (int i = 0; i < profileWidth; i++) {
+                HotSpotResolvedJavaMethod method = data.readMethod(position, getMethodOffset(i));
+                if (method != null) {
+                    methods[entries] = method;
+                    long count = data.readUnsignedInt(position, getMethodCountOffset(i));
+                    totalCount += count;
+                    counts[entries] = count;
+
+                    entries++;
+                }
+            }
+
+            totalCount += getMethodsNotRecordedExecutionCount(data, position);
+            return new RawItemProfile<>(entries, methods, counts, totalCount);
+        }
+
+        private JavaMethodProfile createMethodProfile(RawItemProfile<ResolvedJavaMethod> profile) {
+            if (profile.entries <= 0 || profile.totalCount <= 0) {
+                return null;
+            }
+
+            ProfiledMethod[] pmethods = new ProfiledMethod[profile.entries];
+            double totalProbability = 0.0;
+            for (int i = 0; i < profile.entries; i++) {
+                double p = profile.counts[i];
+                p = p / profile.totalCount;
+                totalProbability += p;
+                pmethods[i] = new ProfiledMethod(profile.items[i], p);
+            }
+
+            Arrays.sort(pmethods);
+
+            double notRecordedMethodProbability = profile.entries < config.methodProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability));
+            assert notRecordedMethodProbability == 0 || profile.entries == config.methodProfileWidth;
+            return new JavaMethodProfile(notRecordedMethodProbability, pmethods);
+        }
+
+        private static int getMethodOffset(int row) {
+            return VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        }
+
+        private static int getMethodCountOffset(int row) {
+            return VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            RawItemProfile<ResolvedJavaMethod> profile = getRawMethodProfile(data, pos);
+            super.appendTo(sb.append(format("exception_seen(%s) ", getExceptionSeen(data, pos))), data, pos).append(format("%nmethod_entries(%d)", profile.entries));
+            for (int i = 0; i < profile.entries; i++) {
+                long count = profile.counts[i];
+                sb.append(format("%n  %s (%d, %4.2f)", profile.items[i].format("%H.%n(%p)"), count, (double) count / profile.totalCount));
+            }
+            return sb;
+        }
+    }
+
+    static class VirtualCallTypeData extends VirtualCallData {
+
+        VirtualCallTypeData(HotSpotVMConfig config, int tag) {
+            super(config, tag, 0);
+        }
+
+        @Override
+        protected int getDynamicSize(HotSpotMethodData data, int position) {
+            assert staticSize == 0;
+            return HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
+        }
+    }
+
+    static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
+    static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
+
+    static class RetData extends CounterData {
+
+        RetData(HotSpotVMConfig config, int tag) {
+            super(config, tag, RET_DATA_SIZE);
+        }
+    }
+
+    static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
+    static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
+
+    static class BranchData extends JumpData {
+
+        BranchData(HotSpotVMConfig config, int tag) {
+            super(config, tag, BRANCH_DATA_SIZE);
+        }
+
+        @Override
+        public double getBranchTakenProbability(HotSpotMethodData data, int position) {
+            long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
+            long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
+            long total = takenCount + notTakenCount;
+
+            return total <= 0 ? -1 : takenCount / (double) total;
+        }
+
+        @Override
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            long count = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET) + data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
+            return truncateLongToInt(count);
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            long taken = data.readUnsignedInt(pos, TAKEN_COUNT_OFFSET);
+            long notTaken = data.readUnsignedInt(pos, NOT_TAKEN_COUNT_OFFSET);
+            double takenProbability = getBranchTakenProbability(data, pos);
+            return sb.append(format("taken(%d, %4.2f) not_taken(%d, %4.2f) displacement(%d)", taken, takenProbability, notTaken, 1.0D - takenProbability, getTakenDisplacement(data, pos)));
+        }
+    }
+
+    static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
+    static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
+
+    static class ArrayData extends HotSpotMethodDataAccessor {
+
+        ArrayData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
+        }
+
+        @Override
+        protected int getDynamicSize(HotSpotMethodData data, int position) {
+            return cellsToBytes(getLength(data, position));
+        }
+
+        protected static int getLength(HotSpotMethodData data, int position) {
+            return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET);
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            return sb.append(format("length(%d)", getLength(data, pos)));
+        }
+    }
+
+    static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
+    static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount;
+    static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
+    static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
+    static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
+
+    static class MultiBranchData extends ArrayData {
+
+        MultiBranchData(HotSpotVMConfig config, int tag) {
+            super(config, tag, MULTI_BRANCH_DATA_SIZE);
+        }
+
+        @Override
+        public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
+            int arrayLength = getLength(data, position);
+            assert arrayLength > 0 : "switch must have at least the default case";
+            assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
+
+            int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            long totalCount = 0;
+            double[] result = new double[length];
+
+            // default case is first in HotSpot but last for the compiler
+            long count = readCount(data, position, 0);
+            totalCount += count;
+            result[length - 1] = count;
+
+            for (int i = 1; i < length; i++) {
+                count = readCount(data, position, i);
+                totalCount += count;
+                result[i - 1] = count;
+            }
+
+            if (totalCount <= 0) {
+                return null;
+            } else {
+                for (int i = 0; i < length; i++) {
+                    result[i] = result[i] / totalCount;
+                }
+                return result;
+            }
+        }
+
+        private static long readCount(HotSpotMethodData data, int position, int i) {
+            int offset;
+            long count;
+            offset = getCountOffset(i);
+            count = data.readUnsignedInt(position, offset);
+            return count;
+        }
+
+        @Override
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            int arrayLength = getLength(data, position);
+            assert arrayLength > 0 : "switch must have at least the default case";
+            assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
+
+            int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            long totalCount = 0;
+            for (int i = 0; i < length; i++) {
+                int offset = getCountOffset(i);
+                totalCount += data.readUnsignedInt(position, offset);
+            }
+
+            return truncateLongToInt(totalCount);
+        }
+
+        private static int getCountOffset(int index) {
+            return MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE;
+        }
+
+        private static int getDisplacementOffset(int index) {
+            return MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE;
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            int entries = getLength(data, pos) / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            sb.append(format("entries(%d)", entries));
+            for (int i = 0; i < entries; i++) {
+                sb.append(format("%n  %d: count(%d) displacement(%d)", i, data.readUnsignedInt(pos, getCountOffset(i)), data.readUnsignedInt(pos, getDisplacementOffset(i))));
+            }
+            return sb;
+        }
+    }
+
+    static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
+
+    static class ArgInfoData extends ArrayData {
+
+        ArgInfoData(HotSpotVMConfig config, int tag) {
+            super(config, tag, ARG_INFO_DATA_SIZE);
+        }
+    }
+
+    static class UnknownProfileData extends HotSpotMethodDataAccessor {
+        UnknownProfileData(HotSpotVMConfig config, int tag) {
+            super(config, tag, 0);
+        }
+
+        @Override
+        protected int getDynamicSize(HotSpotMethodData data, int position) {
+            assert staticSize == 0;
+            return HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            sb.append("unknown profile data with tag: " + tag);
+            return sb;
+        }
+    }
+
+    public void setCompiledIRSize(int size) {
+        UNSAFE.putInt(metaspaceMethodData + config.methodDataIRSizeOffset, size);
+    }
+
+    public int getCompiledIRSize() {
+        return UNSAFE.getInt(metaspaceMethodData + config.methodDataIRSizeOffset);
+    }
+
+    // sorted by tag
+    // @formatter:off
+    static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
+        null,
+        new BitData(config, config.dataLayoutBitDataTag),
+        new CounterData(config, config.dataLayoutCounterDataTag),
+        new JumpData(config, config.dataLayoutJumpDataTag),
+        new ReceiverTypeData(config, config.dataLayoutReceiverTypeDataTag),
+        new VirtualCallData(config, config.dataLayoutVirtualCallDataTag),
+        new RetData(config, config.dataLayoutRetDataTag),
+        new BranchData(config, config.dataLayoutBranchDataTag),
+        new MultiBranchData(config, config.dataLayoutMultiBranchDataTag),
+        new ArgInfoData(config, config.dataLayoutArgInfoDataTag),
+        new UnknownProfileData(config, config.dataLayoutCallTypeDataTag),
+        new VirtualCallTypeData(config, config.dataLayoutVirtualCallTypeDataTag),
+        new UnknownProfileData(config, config.dataLayoutParametersTypeDataTag),
+        new UnknownProfileData(config, config.dataLayoutSpeculativeTrapDataTag),
+    };
+
+    private static boolean checkAccessorTags() {
+        int expectedTag = 0;
+        for (HotSpotMethodDataAccessor accessor : PROFILE_DATA_ACCESSORS) {
+            if (expectedTag == 0) {
+                assert accessor == null;
+            } else {
+                assert accessor.tag == expectedTag : expectedTag + " != " + accessor.tag + " " + accessor;
+            }
+            expectedTag++;
+        }
+        return true;
+    }
+
+    static {
+        assert checkAccessorTags();
+    }
+    // @formatter:on
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,151 @@
+/*
+ * 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 jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaMethodProfile;
+import jdk.vm.ci.meta.JavaTypeProfile;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.TriState;
+
+/**
+ * Base class for accessing the different kinds of data in a HotSpot {@code MethodData}. This is
+ * similar to {@link ProfilingInfo}, but most methods require a {@link HotSpotMethodData} and the
+ * exact position within the method data.
+ */
+abstract class HotSpotMethodDataAccessor {
+
+    final int tag;
+    final int staticSize;
+    final HotSpotVMConfig config;
+
+    protected HotSpotMethodDataAccessor(HotSpotVMConfig config, int tag, int staticSize) {
+        this.config = config;
+        this.tag = tag;
+        this.staticSize = staticSize;
+    }
+
+    /**
+     * Returns the tag stored in the LayoutData header.
+     *
+     * @return tag stored in the LayoutData header
+     */
+    int getTag() {
+        return tag;
+    }
+
+    static int readTag(HotSpotVMConfig config, HotSpotMethodData data, int position) {
+        final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
+        assert tag >= config.dataLayoutNoTag && tag <= config.dataLayoutSpeculativeTrapDataTag : "profile data tag out of bounds: " + tag;
+        return tag;
+    }
+
+    /**
+     * Returns the BCI stored in the LayoutData header.
+     *
+     * @return an integer between 0 and {@link Short#MAX_VALUE} inclusive, or -1 if not supported
+     */
+    int getBCI(HotSpotMethodData data, int position) {
+        return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
+    }
+
+    /**
+     * Computes the size for the specific data at the given position.
+     *
+     * @return a value greater than 0
+     */
+    final int getSize(HotSpotMethodData data, int position) {
+        int size = staticSize + getDynamicSize(data, position);
+        // Sanity check against VM
+        int vmSize = HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
+        assert size == vmSize : size + " != " + vmSize;
+        return size;
+    }
+
+    TriState getExceptionSeen(HotSpotMethodData data, int position) {
+        final int exceptionsMask = 1 << config.bitDataExceptionSeenFlag;
+        return TriState.get((getFlags(data, position) & exceptionsMask) != 0);
+    }
+
+    /**
+     * @param data
+     * @param position
+     */
+    JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
+        return null;
+    }
+
+    /**
+     * @param data
+     * @param position
+     */
+    JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
+        return null;
+    }
+
+    /**
+     * @param data
+     * @param position
+     */
+    double getBranchTakenProbability(HotSpotMethodData data, int position) {
+        return -1;
+    }
+
+    /**
+     * @param data
+     * @param position
+     */
+    double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
+        return null;
+    }
+
+    /**
+     * @param data
+     * @param position
+     */
+    int getExecutionCount(HotSpotMethodData data, int position) {
+        return -1;
+    }
+
+    /**
+     * @param data
+     * @param position
+     */
+    TriState getNullSeen(HotSpotMethodData data, int position) {
+        return TriState.UNKNOWN;
+    }
+
+    protected int getFlags(HotSpotMethodData data, int position) {
+        return data.readUnsignedByte(position, config.dataLayoutFlagsOffset);
+    }
+
+    /**
+     * @param data
+     * @param position
+     */
+    protected int getDynamicSize(HotSpotMethodData data, int position) {
+        return 0;
+    }
+
+    abstract StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+
+import java.lang.invoke.MethodHandle;
+import java.util.Objects;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.MethodHandleAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProvider {
+
+    private final ConstantReflectionProvider constantReflection;
+
+    public HotSpotMethodHandleAccessProvider(ConstantReflectionProvider constantReflection) {
+        this.constantReflection = constantReflection;
+    }
+
+    /**
+     * Lazy initialization to break class initialization cycle. Field and method lookup is only
+     * possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
+     */
+    static class LazyInitialization {
+        static final ResolvedJavaType lambdaFormType;
+        static final ResolvedJavaField methodHandleFormField;
+        static final ResolvedJavaField lambdaFormVmentryField;
+        static final HotSpotResolvedJavaField memberNameVmtargetField;
+
+        /**
+         * Search for an instance field with the given name in a class.
+         *
+         * @param declaringType the type declaring the field
+         * @param fieldName name of the field to be searched
+         * @return resolved java field
+         * @throws NoSuchFieldError
+         */
+        private static ResolvedJavaField findFieldInClass(ResolvedJavaType declaringType, String fieldName, ResolvedJavaType fieldType) {
+            ResolvedJavaField[] fields = declaringType.getInstanceFields(false);
+            for (ResolvedJavaField field : fields) {
+                if (field.getName().equals(fieldName)) {
+                    return field;
+                }
+            }
+            throw new NoSuchFieldError(fieldType.getName() + " " + declaringType + "." + fieldName);
+        }
+
+        private static ResolvedJavaType resolveType(Class<?> c) {
+            return runtime().fromClass(c);
+        }
+
+        private static ResolvedJavaType resolveType(String className) throws ClassNotFoundException {
+            return resolveType(Class.forName(className));
+        }
+
+        static {
+            try {
+                ResolvedJavaType methodHandleType = resolveType(MethodHandle.class);
+                ResolvedJavaType memberNameType = resolveType("java.lang.invoke.MemberName");
+                lambdaFormType = resolveType("java.lang.invoke.LambdaForm");
+                methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType);
+                lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType);
+                memberNameVmtargetField = (HotSpotResolvedJavaField) findFieldInClass(memberNameType, "vmtarget", resolveType(long.class));
+            } catch (Throwable ex) {
+                throw new JVMCIError(ex);
+            }
+        }
+    }
+
+    @Override
+    public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) {
+        int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId();
+        if (intrinsicId != 0) {
+            return getMethodHandleIntrinsic(intrinsicId);
+        }
+        return null;
+    }
+
+    public static IntrinsicMethod getMethodHandleIntrinsic(int intrinsicId) {
+        HotSpotVMConfig config = runtime().getConfig();
+        if (intrinsicId == config.vmIntrinsicInvokeBasic) {
+            return IntrinsicMethod.INVOKE_BASIC;
+        } else if (intrinsicId == config.vmIntrinsicLinkToInterface) {
+            return IntrinsicMethod.LINK_TO_INTERFACE;
+        } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) {
+            return IntrinsicMethod.LINK_TO_SPECIAL;
+        } else if (intrinsicId == config.vmIntrinsicLinkToStatic) {
+            return IntrinsicMethod.LINK_TO_STATIC;
+        } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) {
+            return IntrinsicMethod.LINK_TO_VIRTUAL;
+        }
+        return null;
+    }
+
+    @Override
+    public ResolvedJavaMethod resolveInvokeBasicTarget(JavaConstant methodHandle, boolean forceBytecodeGeneration) {
+        if (methodHandle.isNull()) {
+            return null;
+        }
+
+        /* Load non-public field: LambdaForm MethodHandle.form */
+        JavaConstant lambdaForm = constantReflection.readFieldValue(LazyInitialization.methodHandleFormField, methodHandle);
+        if (lambdaForm == null || lambdaForm.isNull()) {
+            return null;
+        }
+
+        JavaConstant memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+        if (memberName.isNull() && forceBytecodeGeneration) {
+            Object lf = ((HotSpotObjectConstant) lambdaForm).asObject(LazyInitialization.lambdaFormType);
+            compilerToVM().compileToBytecode(Objects.requireNonNull(lf));
+            memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+            assert memberName.isNonNull();
+        }
+        return getTargetMethod(memberName);
+    }
+
+    @Override
+    public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) {
+        return getTargetMethod(memberName);
+    }
+
+    /**
+     * Returns the {@link ResolvedJavaMethod} for the vmtarget of a java.lang.invoke.MemberName.
+     */
+    private static ResolvedJavaMethod getTargetMethod(JavaConstant memberName) {
+        if (memberName.isNull()) {
+            return null;
+        }
+
+        Object object = ((HotSpotObjectConstantImpl) memberName).object();
+        /* Read the ResolvedJavaMethod from the injected field MemberName.vmtarget */
+        return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.Signature;
+
+/**
+ * Implementation of {@link JavaMethod} for unresolved HotSpot methods.
+ */
+final class HotSpotMethodUnresolved extends HotSpotMethod {
+
+    private final String name;
+    private final Signature signature;
+    protected JavaType holder;
+
+    HotSpotMethodUnresolved(String name, Signature signature, JavaType holder) {
+        this.name = name;
+        this.holder = holder;
+        this.signature = signature;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public Signature getSignature() {
+        return signature;
+    }
+
+    @Override
+    public JavaType getDeclaringClass() {
+        return holder;
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || !(obj instanceof HotSpotMethodUnresolved)) {
+            return false;
+        }
+        HotSpotMethodUnresolved that = (HotSpotMethodUnresolved) obj;
+        return this.name.equals(that.name) && this.signature.equals(that.signature) && this.holder.equals(that.holder);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotModifiers.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.lang.reflect.Modifier.ABSTRACT;
+import static java.lang.reflect.Modifier.FINAL;
+import static java.lang.reflect.Modifier.INTERFACE;
+import static java.lang.reflect.Modifier.NATIVE;
+import static java.lang.reflect.Modifier.PRIVATE;
+import static java.lang.reflect.Modifier.PROTECTED;
+import static java.lang.reflect.Modifier.PUBLIC;
+import static java.lang.reflect.Modifier.STATIC;
+import static java.lang.reflect.Modifier.STRICT;
+import static java.lang.reflect.Modifier.SYNCHRONIZED;
+import static java.lang.reflect.Modifier.TRANSIENT;
+import static java.lang.reflect.Modifier.VOLATILE;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * The non-public modifiers in {@link Modifier} that need to be retrieved from
+ * {@link HotSpotVMConfig}.
+ */
+public class HotSpotModifiers {
+
+    // @formatter:off
+    public static final int ANNOTATION = config().jvmAccAnnotation;
+    public static final int ENUM       = config().jvmAccEnum;
+    public static final int VARARGS    = config().jvmAccVarargs;
+    public static final int BRIDGE     = config().jvmAccBridge;
+    public static final int SYNTHETIC  = config().jvmAccSynthetic;
+    // @formatter:on
+
+    public static int jvmClassModifiers() {
+        return PUBLIC | FINAL | INTERFACE | ABSTRACT | ANNOTATION | ENUM | SYNTHETIC;
+    }
+
+    public static int jvmMethodModifiers() {
+        return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | SYNCHRONIZED | BRIDGE | VARARGS | NATIVE | ABSTRACT | STRICT | SYNTHETIC;
+    }
+
+    public static int jvmFieldModifiers() {
+        return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | ENUM | SYNTHETIC;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Implementation of {@link InstalledCode} for code installed as an nmethod. The nmethod stores a
+ * weak reference to an instance of this class. This is necessary to keep the nmethod from being
+ * unloaded while the associated {@link HotSpotNmethod} instance is alive.
+ * <p>
+ * Note that there is no (current) way for the reference from an nmethod to a {@link HotSpotNmethod}
+ * instance to be anything but weak. This is due to the fact that HotSpot does not treat nmethods as
+ * strong GC roots.
+ */
+public class HotSpotNmethod extends HotSpotInstalledCode {
+
+    /**
+     * This (indirect) Method* reference is safe since class redefinition preserves all methods
+     * associated with nmethods in the code cache.
+     */
+    private final HotSpotResolvedJavaMethod method;
+
+    private final boolean isDefault;
+
+    public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault) {
+        super(name);
+        this.method = method;
+        this.isDefault = isDefault;
+    }
+
+    public boolean isDefault() {
+        return isDefault;
+    }
+
+    public ResolvedJavaMethod getMethod() {
+        return method;
+    }
+
+    @Override
+    public void invalidate() {
+        compilerToVM().invalidateInstalledCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getAddress(), isDefault, name);
+    }
+
+    protected boolean checkThreeObjectArgs() {
+        assert method.getSignature().getParameterCount(!method.isStatic()) == 3;
+        assert method.getSignature().getParameterKind(0) == JavaKind.Object;
+        assert method.getSignature().getParameterKind(1) == JavaKind.Object;
+        assert !method.isStatic() || method.getSignature().getParameterKind(2) == JavaKind.Object;
+        return true;
+    }
+
+    private boolean checkArgs(Object... args) {
+        JavaType[] sig = method.toParameterTypes();
+        assert args.length == sig.length : method.format("%H.%n(%p): expected ") + sig.length + " args, got " + args.length;
+        for (int i = 0; i < sig.length; i++) {
+            Object arg = args[i];
+            if (arg == null) {
+                assert sig[i].getJavaKind() == JavaKind.Object : method.format("%H.%n(%p): expected arg ") + i + " to be Object, not " + sig[i];
+            } else if (sig[i].getJavaKind() != JavaKind.Object) {
+                assert sig[i].getJavaKind().toBoxedJavaClass() == arg.getClass() : method.format("%H.%n(%p): expected arg ") + i + " to be " + sig[i] + ", not " + arg.getClass();
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        assert checkArgs(args);
+        return compilerToVM().executeInstalledCode(args, this);
+    }
+
+    @Override
+    public long getStart() {
+        return isValid() ? super.getStart() : 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.invoke.CallSite;
+import java.util.Objects;
+
+import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.VMConstant;
+
+/**
+ * Represents a constant non-{@code null} object reference, within the compiler and across the
+ * compiler/runtime interface.
+ */
+public interface HotSpotObjectConstant extends JavaConstant, HotSpotConstant, VMConstant {
+
+    JavaConstant compress();
+
+    JavaConstant uncompress();
+
+    /**
+     * Gets the resolved Java type of the object represented by this constant.
+     */
+    HotSpotResolvedObjectType getType();
+
+    /**
+     * Gets the result of {@link Class#getClassLoader()} for the {@link Class} object represented by
+     * this constant.
+     *
+     * @return {@code null} if this constant does not represent a {@link Class} object
+     */
+    JavaConstant getClassLoader();
+
+    /**
+     * Gets the {@linkplain System#identityHashCode(Object) identity} has code for the object
+     * represented by this constant.
+     */
+    int getIdentityHashCode();
+
+    /**
+     * Gets the result of {@link Class#getComponentType()} for the {@link Class} object represented
+     * by this constant.
+     *
+     * @return {@code null} if this constant does not represent a {@link Class} object
+     */
+    JavaConstant getComponentType();
+
+    /**
+     * Gets the result of {@link Class#getSuperclass()} for the {@link Class} object represented by
+     * this constant.
+     *
+     * @return {@code null} if this constant does not represent a {@link Class} object
+     */
+    JavaConstant getSuperclass();
+
+    /**
+     * Gets the result of {@link CallSite#getTarget()} for the {@link CallSite} object represented
+     * by this constant.
+     *
+     * @param assumptions used to register an assumption that the {@link CallSite}'s target does not
+     *            change
+     * @return {@code null} if this constant does not represent a {@link CallSite} object
+     */
+    JavaConstant getCallSiteTarget(Assumptions assumptions);
+
+    /**
+     * Determines if this constant represents an {@linkplain String#intern() interned} string.
+     */
+    boolean isInternedString();
+
+    /**
+     * Gets the object represented by this constant represents if it is of a given type.
+     *
+     * @param type the expected type of the object represented by this constant. If the object is
+     *            required to be of this type, then wrap the call to this method in
+     *            {@link Objects#requireNonNull(Object)}.
+     * @return the object value represented by this constant if it is an
+     *         {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
+     *         {@code null}
+     */
+    <T> T asObject(Class<T> type);
+
+    /**
+     * Gets the object represented by this constant represents if it is of a given type.
+     *
+     * @param type the expected type of the object represented by this constant. If the object is
+     *            required to be of this type, then wrap the call to this method in
+     *            {@link Objects#requireNonNull(Object)}.
+     * @return the object value represented by this constant if it is an
+     *         {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
+     *         {@code null}
+     */
+    Object asObject(ResolvedJavaType type);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+
+import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Represents a constant non-{@code null} object reference, within the compiler and across the
+ * compiler/runtime interface.
+ */
+final class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
+
+    static JavaConstant forObject(Object object) {
+        return forObject(object, false);
+    }
+
+    static JavaConstant forObject(Object object, boolean compressed) {
+        if (object == null) {
+            return compressed ? HotSpotCompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER;
+        } else {
+            return new HotSpotObjectConstantImpl(object, compressed);
+        }
+    }
+
+    public static JavaConstant forBoxedValue(JavaKind kind, Object value) {
+        if (kind == JavaKind.Object) {
+            return HotSpotObjectConstantImpl.forObject(value);
+        } else {
+            return JavaConstant.forBoxedPrimitive(value);
+        }
+    }
+
+    static Object asBoxedValue(Constant constant) {
+        if (JavaConstant.isNull(constant)) {
+            return null;
+        } else if (constant instanceof HotSpotObjectConstantImpl) {
+            return ((HotSpotObjectConstantImpl) constant).object;
+        } else {
+            return ((JavaConstant) constant).asBoxedPrimitive();
+        }
+    }
+
+    private final Object object;
+    private final boolean compressed;
+
+    private HotSpotObjectConstantImpl(Object object, boolean compressed) {
+        this.object = object;
+        this.compressed = compressed;
+        assert object != null;
+    }
+
+    @Override
+    public JavaKind getJavaKind() {
+        return JavaKind.Object;
+    }
+
+    /**
+     * Package-private accessor for the object represented by this constant.
+     */
+    Object object() {
+        return object;
+    }
+
+    public boolean isCompressed() {
+        return compressed;
+    }
+
+    public JavaConstant compress() {
+        assert !compressed;
+        return new HotSpotObjectConstantImpl(object, true);
+    }
+
+    public JavaConstant uncompress() {
+        assert compressed;
+        return new HotSpotObjectConstantImpl(object, false);
+    }
+
+    public HotSpotResolvedObjectType getType() {
+        return fromObjectClass(object.getClass());
+    }
+
+    public JavaConstant getClassLoader() {
+        if (object instanceof Class) {
+            /*
+             * This is an intrinsic for getClassLoader0, which occurs after any security checks. We
+             * can't call that directly so just call getClassLoader.
+             */
+            return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getClassLoader());
+        }
+        return null;
+    }
+
+    public int getIdentityHashCode() {
+        return System.identityHashCode(object);
+    }
+
+    public JavaConstant getComponentType() {
+        if (object instanceof Class) {
+            return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getComponentType());
+        }
+        return null;
+    }
+
+    public JavaConstant getSuperclass() {
+        if (object instanceof Class) {
+            return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getSuperclass());
+        }
+        return null;
+    }
+
+    public JavaConstant getCallSiteTarget(Assumptions assumptions) {
+        if (object instanceof CallSite) {
+            CallSite callSite = (CallSite) object;
+            MethodHandle target = callSite.getTarget();
+            if (!(callSite instanceof ConstantCallSite)) {
+                if (assumptions == null) {
+                    return null;
+                }
+                assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target));
+            }
+            return HotSpotObjectConstantImpl.forObject(target);
+        }
+        return null;
+    }
+
+    @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
+    public boolean isInternedString() {
+        if (object instanceof String) {
+            String s = (String) object;
+            return s.intern() == s;
+        }
+        return false;
+    }
+
+    public <T> T asObject(Class<T> type) {
+        if (type.isInstance(object)) {
+            return type.cast(object);
+        }
+        return null;
+    }
+
+    public Object asObject(ResolvedJavaType type) {
+        if (type.isInstance(this)) {
+            return object;
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isNull() {
+        return false;
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return false;
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public int asInt() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public boolean asBoolean() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public long asLong() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public float asFloat() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public double asDouble() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public int hashCode() {
+        return System.identityHashCode(object);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        } else if (o instanceof HotSpotObjectConstantImpl) {
+            HotSpotObjectConstantImpl other = (HotSpotObjectConstantImpl) o;
+            return object == other.object && compressed == other.compressed;
+        }
+        return false;
+    }
+
+    @Override
+    public String toValueString() {
+        if (object instanceof String) {
+            return "\"" + (String) object + "\"";
+        } else {
+            return JavaKind.Object.format(object);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + JavaKind.Object.format(object) + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,249 @@
+/*
+ * 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 jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaMethodProfile;
+import jdk.vm.ci.meta.JavaTypeProfile;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.TriState;
+
+public final class HotSpotProfilingInfo implements ProfilingInfo {
+
+    private final HotSpotMethodData methodData;
+    private final HotSpotResolvedJavaMethod method;
+
+    private boolean isMature;
+    private int position;
+    private int hintPosition;
+    private int hintBCI;
+    private HotSpotMethodDataAccessor dataAccessor;
+
+    private boolean includeNormal;
+    private boolean includeOSR;
+
+    public HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method, boolean includeNormal, boolean includeOSR) {
+        this.methodData = methodData;
+        this.method = method;
+        this.includeNormal = includeNormal;
+        this.includeOSR = includeOSR;
+        this.isMature = methodData.isProfileMature();
+        hintPosition = 0;
+        hintBCI = -1;
+    }
+
+    @Override
+    public int getCodeSize() {
+        return method.getCodeSize();
+    }
+
+    public int getDecompileCount() {
+        return methodData.getDecompileCount();
+    }
+
+    public int getOverflowRecompileCount() {
+        return methodData.getOverflowRecompileCount();
+    }
+
+    public int getOverflowTrapCount() {
+        return methodData.getOverflowTrapCount();
+    }
+
+    @Override
+    public JavaTypeProfile getTypeProfile(int bci) {
+        if (!isMature) {
+            return null;
+        }
+        findBCI(bci, false);
+        return dataAccessor.getTypeProfile(methodData, position);
+    }
+
+    @Override
+    public JavaMethodProfile getMethodProfile(int bci) {
+        if (!isMature) {
+            return null;
+        }
+        findBCI(bci, false);
+        return dataAccessor.getMethodProfile(methodData, position);
+    }
+
+    @Override
+    public double getBranchTakenProbability(int bci) {
+        if (!isMature) {
+            return -1;
+        }
+        findBCI(bci, false);
+        return dataAccessor.getBranchTakenProbability(methodData, position);
+    }
+
+    @Override
+    public double[] getSwitchProbabilities(int bci) {
+        if (!isMature) {
+            return null;
+        }
+        findBCI(bci, false);
+        return dataAccessor.getSwitchProbabilities(methodData, position);
+    }
+
+    @Override
+    public TriState getExceptionSeen(int bci) {
+        findBCI(bci, true);
+        return dataAccessor.getExceptionSeen(methodData, position);
+    }
+
+    @Override
+    public TriState getNullSeen(int bci) {
+        findBCI(bci, false);
+        return dataAccessor.getNullSeen(methodData, position);
+    }
+
+    @Override
+    public int getExecutionCount(int bci) {
+        if (!isMature) {
+            return -1;
+        }
+        findBCI(bci, false);
+        return dataAccessor.getExecutionCount(methodData, position);
+    }
+
+    @Override
+    public int getDeoptimizationCount(DeoptimizationReason reason) {
+        int count = 0;
+        if (includeNormal) {
+            count += methodData.getDeoptimizationCount(reason);
+        }
+        if (includeOSR) {
+            count += methodData.getOSRDeoptimizationCount(reason);
+        }
+        return count;
+    }
+
+    private void findBCI(int targetBCI, boolean searchExtraData) {
+        assert targetBCI >= 0 : "invalid BCI";
+
+        if (methodData.hasNormalData()) {
+            int currentPosition = targetBCI < hintBCI ? 0 : hintPosition;
+            HotSpotMethodDataAccessor currentAccessor;
+            while ((currentAccessor = methodData.getNormalData(currentPosition)) != null) {
+                int currentBCI = currentAccessor.getBCI(methodData, currentPosition);
+                if (currentBCI == targetBCI) {
+                    normalDataFound(currentAccessor, currentPosition, currentBCI);
+                    return;
+                } else if (currentBCI > targetBCI) {
+                    break;
+                }
+                currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition);
+            }
+        }
+
+        boolean exceptionPossiblyNotRecorded = false;
+        if (searchExtraData && methodData.hasExtraData()) {
+            int currentPosition = methodData.getExtraDataBeginOffset();
+            HotSpotMethodDataAccessor currentAccessor;
+            while ((currentAccessor = methodData.getExtraData(currentPosition)) != null) {
+                int currentBCI = currentAccessor.getBCI(methodData, currentPosition);
+                if (currentBCI == targetBCI) {
+                    extraDataFound(currentAccessor, currentPosition);
+                    return;
+                }
+                currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition);
+            }
+
+            if (!methodData.isWithin(currentPosition)) {
+                exceptionPossiblyNotRecorded = true;
+            }
+        }
+
+        noDataFound(exceptionPossiblyNotRecorded);
+    }
+
+    private void normalDataFound(HotSpotMethodDataAccessor data, int pos, int bci) {
+        setCurrentData(data, pos);
+        this.hintPosition = position;
+        this.hintBCI = bci;
+    }
+
+    private void extraDataFound(HotSpotMethodDataAccessor data, int pos) {
+        setCurrentData(data, pos);
+    }
+
+    private void noDataFound(boolean exceptionPossiblyNotRecorded) {
+        HotSpotMethodDataAccessor accessor = HotSpotMethodData.getNoDataAccessor(exceptionPossiblyNotRecorded);
+        setCurrentData(accessor, -1);
+    }
+
+    private void setCurrentData(HotSpotMethodDataAccessor dataAccessor, int position) {
+        this.dataAccessor = dataAccessor;
+        this.position = position;
+    }
+
+    @Override
+    public boolean isMature() {
+        return isMature;
+    }
+
+    public void ignoreMature() {
+        isMature = true;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotProfilingInfo<" + this.toString(null, "; ") + ">";
+    }
+
+    @Override
+    public void setMature() {
+        isMature = true;
+    }
+
+    /**
+     * {@code MethodData::_jvmci_ir_size} (currently) supports at most one JVMCI compiler IR type
+     * which will be determined by the first JVMCI compiler that calls
+     * {@link #setCompilerIRSize(Class, int)}.
+     */
+    private static volatile Class<?> supportedCompilerIRType;
+
+    @Override
+    public boolean setCompilerIRSize(Class<?> irType, int size) {
+        if (supportedCompilerIRType == null) {
+            synchronized (HotSpotProfilingInfo.class) {
+                if (supportedCompilerIRType == null) {
+                    supportedCompilerIRType = irType;
+                }
+            }
+        }
+        if (supportedCompilerIRType != irType) {
+            return false;
+        }
+        methodData.setCompiledIRSize(size);
+        return true;
+    }
+
+    @Override
+    public int getCompilerIRSize(Class<?> irType) {
+        if (irType == supportedCompilerIRType) {
+            return methodData.getCompiledIRSize();
+        }
+        return -1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.Arrays;
+
+import jdk.vm.ci.code.Location;
+import jdk.vm.ci.code.ReferenceMap;
+
+/**
+ * Describes where the object references are in machine state, compliant with what HotSpot expects.
+ */
+public final class HotSpotReferenceMap extends ReferenceMap {
+
+    private final Location[] objects;
+    private final Location[] derivedBase;
+    private final int[] sizeInBytes;
+    private final int maxRegisterSize;
+
+    /**
+     *
+     * @param objects This array is now owned by this object and must not be mutated by the caller.
+     * @param derivedBase This array is now owned by this object and must not be mutated by the
+     *            caller.
+     * @param sizeInBytes This array is now owned by this object and must not be mutated by the
+     *            caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `objects`, `derivedBase` and `sizeInBytes`")
+    public HotSpotReferenceMap(Location[] objects, Location[] derivedBase, int[] sizeInBytes, int maxRegisterSize) {
+        this.objects = objects;
+        this.derivedBase = derivedBase;
+        this.sizeInBytes = sizeInBytes;
+        this.maxRegisterSize = maxRegisterSize;
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof HotSpotReferenceMap) {
+            HotSpotReferenceMap that = (HotSpotReferenceMap) obj;
+            if (sizeInBytes == that.sizeInBytes && maxRegisterSize == that.maxRegisterSize && Arrays.equals(objects, that.objects) && Arrays.equals(derivedBase, that.derivedBase)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(objects);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.ResolvedJavaField;
+
+/**
+ * Represents a field in a HotSpot type.
+ */
+public interface HotSpotResolvedJavaField extends ResolvedJavaField {
+
+    /**
+     * Determines if a given object contains this field.
+     *
+     * @return true iff this is a non-static field and its declaring class is assignable from
+     *         {@code object}'s class
+     */
+    boolean isInObject(Object object);
+
+    int offset();
+
+    /**
+     * Determines if this field should be treated as a constant.
+     */
+    boolean isStable();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Represents a field in a HotSpot type.
+ */
+class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
+
+    private final HotSpotResolvedObjectTypeImpl holder;
+    private JavaType type;
+    private final int offset;
+    private final short index;
+
+    /**
+     * This value contains all flags as stored in the VM including internal ones.
+     */
+    private final int modifiers;
+
+    HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, JavaType type, long offset, int modifiers, int index) {
+        this.holder = holder;
+        this.type = type;
+        this.index = (short) index;
+        this.offset = (int) offset;
+        this.modifiers = modifiers;
+        assert this.index == index;
+        assert offset != -1;
+        assert offset == (int) offset : "offset larger than int";
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof HotSpotResolvedJavaField) {
+            HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj;
+            if (that.offset != this.offset || that.isStatic() != this.isStatic()) {
+                return false;
+            } else if (this.holder.equals(that.holder)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return offset ^ modifiers;
+    }
+
+    @Override
+    public int getModifiers() {
+        return modifiers & jvmFieldModifiers();
+    }
+
+    @Override
+    public boolean isInternal() {
+        return (modifiers & config().jvmAccFieldInternal) != 0;
+    }
+
+    /**
+     * Determines if a given object contains this field.
+     *
+     * @return true iff this is a non-static field and its declaring class is assignable from
+     *         {@code object}'s class
+     */
+    public boolean isInObject(Object object) {
+        if (isStatic()) {
+            return false;
+        }
+        return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectTypeImpl.fromObjectClass(object.getClass()));
+    }
+
+    @Override
+    public HotSpotResolvedObjectTypeImpl getDeclaringClass() {
+        return holder;
+    }
+
+    @Override
+    public String getName() {
+        return holder.createFieldInfo(index).getName();
+    }
+
+    @Override
+    public JavaType getType() {
+        // Pull field into local variable to prevent a race causing
+        // a ClassCastException below
+        JavaType currentType = type;
+        if (currentType instanceof HotSpotUnresolvedJavaType) {
+            // Don't allow unresolved types to hang around forever
+            HotSpotUnresolvedJavaType unresolvedType = (HotSpotUnresolvedJavaType) currentType;
+            ResolvedJavaType resolved = unresolvedType.reresolve(holder);
+            if (resolved != null) {
+                type = resolved;
+            }
+        }
+        return type;
+    }
+
+    public int offset() {
+        return offset;
+    }
+
+    @Override
+    public String toString() {
+        return format("HotSpotField<%H.%n %t:") + offset + ">";
+    }
+
+    @Override
+    public boolean isSynthetic() {
+        return (config().jvmAccSynthetic & modifiers) != 0;
+    }
+
+    /**
+     * Checks if this field has the {@link Stable} annotation.
+     *
+     * @return true if field has {@link Stable} annotation, false otherwise
+     */
+    public boolean isStable() {
+        return (config().jvmAccFieldStable & modifiers) != 0;
+    }
+
+    @Override
+    public Annotation[] getAnnotations() {
+        Field javaField = toJava();
+        if (javaField != null) {
+            return javaField.getAnnotations();
+        }
+        return new Annotation[0];
+    }
+
+    @Override
+    public Annotation[] getDeclaredAnnotations() {
+        Field javaField = toJava();
+        if (javaField != null) {
+            return javaField.getDeclaredAnnotations();
+        }
+        return new Annotation[0];
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        Field javaField = toJava();
+        if (javaField != null) {
+            return javaField.getAnnotation(annotationClass);
+        }
+        return null;
+    }
+
+    private Field toJava() {
+        if (isInternal()) {
+            return null;
+        }
+        try {
+            return holder.mirror().getDeclaredField(getName());
+        } catch (NoSuchFieldException | NoClassDefFoundError e) {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.reflect.Modifier;
+
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link JavaMethod} for resolved HotSpot methods.
+ */
+public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod {
+
+    /**
+     * Returns true if this method has a {@code CallerSensitive} annotation.
+     *
+     * @return true if CallerSensitive annotation present, false otherwise
+     */
+    boolean isCallerSensitive();
+
+    HotSpotResolvedObjectType getDeclaringClass();
+
+    /**
+     * Returns true if this method has a {@code ForceInline} annotation.
+     *
+     * @return true if ForceInline annotation present, false otherwise
+     */
+    boolean isForceInline();
+
+    /**
+     * Returns true if this method has a {@code ReservedStackAccess} annotation.
+     *
+     * @return true if ReservedStackAccess annotation present, false otherwise
+     */
+    boolean hasReservedStackAccess();
+
+    /**
+     * Manually adds a DontInline annotation to this method.
+     */
+    void setNotInlineable();
+
+    /**
+     * Returns true if this method is one of the special methods that is ignored by security stack
+     * walks.
+     *
+     * @return true if special method ignored by security stack walks, false otherwise
+     */
+    boolean ignoredBySecurityStackWalk();
+
+    ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver);
+
+    /**
+     * Returns whether this method has compiled code.
+     *
+     * @return true if this method has compiled code, false otherwise
+     */
+    boolean hasCompiledCode();
+
+    /**
+     * @param level
+     * @return true if the currently installed code was generated at {@code level}.
+     */
+    boolean hasCompiledCodeAtLevel(int level);
+
+    default boolean isDefault() {
+        if (isConstructor()) {
+            return false;
+        }
+        // Copied from java.lang.Method.isDefault()
+        int mask = Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC;
+        return ((getModifiers() & mask) == Modifier.PUBLIC) && getDeclaringClass().isInterface();
+    }
+
+    /**
+     * Returns the offset of this method into the v-table. The method must have a v-table entry as
+     * indicated by {@link #isInVirtualMethodTable(ResolvedJavaType)}, otherwise an exception is
+     * thrown.
+     *
+     * @return the offset of this method into the v-table
+     */
+    int vtableEntryOffset(ResolvedJavaType resolved);
+
+    int intrinsicId();
+
+    /**
+     * Determines if this method denotes itself as a candidate for intrinsification. As of JDK9,
+     * this is denoted by the {@code HotSpotIntrinsicCandidate} annotation. In earlier JDK versions,
+     * this method returns true.
+     *
+     * @see <a href="https://bugs.openjdk.java.net/browse/JDK-8076112">JDK-8076112</a>
+     */
+    default boolean isIntrinsicCandidate() {
+        return true;
+    }
+
+    /**
+     * Allocates a compile id for this method by asking the VM for one.
+     *
+     * @param entryBCI entry bci
+     * @return compile id
+     */
+    int allocateCompileId(int entryBCI);
+
+    boolean hasCodeAtLevel(int entryBCI, int level);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,778 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotModifiers.BRIDGE;
+import static jdk.vm.ci.hotspot.HotSpotModifiers.SYNTHETIC;
+import static jdk.vm.ci.hotspot.HotSpotModifiers.VARARGS;
+import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmMethodModifiers;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.DefaultProfilingInfo;
+import jdk.vm.ci.meta.ExceptionHandler;
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.LineNumberTable;
+import jdk.vm.ci.meta.Local;
+import jdk.vm.ci.meta.LocalVariableTable;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.TriState;
+
+/**
+ * Implementation of {@link JavaMethod} for resolved HotSpot methods.
+ */
+final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, MetaspaceWrapperObject {
+
+    /**
+     * Reference to metaspace Method object.
+     */
+    private final long metaspaceMethod;
+
+    private final HotSpotResolvedObjectTypeImpl holder;
+    private final HotSpotConstantPool constantPool;
+    private final HotSpotSignature signature;
+    private HotSpotMethodData methodData;
+    private byte[] code;
+    private Executable toJavaCache;
+
+    /**
+     * Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it
+     * lazily and cache it.
+     */
+    private String nameCache;
+
+    /**
+     * Gets the holder of a HotSpot metaspace method native object.
+     *
+     * @param metaspaceMethod a metaspace Method object
+     * @return the {@link ResolvedJavaType} corresponding to the holder of the
+     *         {@code metaspaceMethod}
+     */
+    private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceMethod) {
+        HotSpotVMConfig config = config();
+        final long metaspaceConstMethod = UNSAFE.getAddress(metaspaceMethod + config.methodConstMethodOffset);
+        final long metaspaceConstantPool = UNSAFE.getAddress(metaspaceConstMethod + config.constMethodConstantsOffset);
+        return compilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false);
+    }
+
+    /**
+     * Gets the JVMCI mirror from a HotSpot method. The VM is responsible for ensuring that the
+     * Method* is kept alive for the duration of this call and the
+     * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that.
+     *
+     * Called from the VM.
+     *
+     * @param metaspaceMethod a metaspace Method object
+     * @return the {@link ResolvedJavaMethod} corresponding to {@code metaspaceMethod}
+     */
+    @SuppressWarnings("unused")
+    private static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceMethod) {
+        HotSpotResolvedObjectTypeImpl holder = getHolder(metaspaceMethod);
+        return holder.createMethod(metaspaceMethod);
+    }
+
+    HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceMethod) {
+        this.metaspaceMethod = metaspaceMethod;
+        this.holder = holder;
+
+        HotSpotVMConfig config = config();
+        final long constMethod = getConstMethod();
+
+        /*
+         * Get the constant pool from the metaspace method. Some methods (e.g. intrinsics for
+         * signature-polymorphic method handle methods) have their own constant pool instead of the
+         * one from their holder.
+         */
+        final long metaspaceConstantPool = UNSAFE.getAddress(constMethod + config.constMethodConstantsOffset);
+        if (metaspaceConstantPool == holder.getConstantPool().getMetaspaceConstantPool()) {
+            this.constantPool = holder.getConstantPool();
+        } else {
+            this.constantPool = compilerToVM().getConstantPool(this);
+        }
+
+        final int signatureIndex = UNSAFE.getChar(constMethod + config.constMethodSignatureIndexOffset);
+        this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex);
+    }
+
+    /**
+     * Returns a pointer to this method's constant method data structure (
+     * {@code Method::_constMethod}). This pointer isn't wrapped since it should be safe to use it
+     * within the context of this HotSpotResolvedJavaMethodImpl since the Method* and ConstMethod*
+     * are kept alive as a pair.
+     *
+     * @return pointer to this method's ConstMethod
+     */
+    private long getConstMethod() {
+        assert metaspaceMethod != 0;
+        return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset);
+    }
+
+    public String getName() {
+        if (nameCache == null) {
+            final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset);
+            nameCache = constantPool.lookupUtf8(nameIndex);
+        }
+        return nameCache;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof HotSpotResolvedJavaMethodImpl) {
+            HotSpotResolvedJavaMethodImpl that = (HotSpotResolvedJavaMethodImpl) obj;
+            return that.metaspaceMethod == metaspaceMethod;
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return (int) metaspaceMethod;
+    }
+
+    /**
+     * Returns this method's flags ({@code Method::_flags}).
+     *
+     * @return flags of this method
+     */
+    private int getFlags() {
+        // Important: Size of field changed, JDK8 has u1 and JDK9 u2
+        return UNSAFE.getByte(metaspaceMethod + config().methodFlagsOffset);
+    }
+
+    /**
+     * Returns this method's constant method flags ({@code ConstMethod::_flags}).
+     *
+     * @return flags of this method's ConstMethod
+     */
+    private int getConstMethodFlags() {
+        return UNSAFE.getChar(getConstMethod() + config().constMethodFlagsOffset);
+    }
+
+    @Override
+    public HotSpotResolvedObjectTypeImpl getDeclaringClass() {
+        return holder;
+    }
+
+    /**
+     * Gets the address of the C++ Method object for this method.
+     */
+    public Constant getMetaspaceMethodConstant() {
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
+    }
+
+    public long getMetaspacePointer() {
+        return metaspaceMethod;
+    }
+
+    @Override
+    public Constant getEncoding() {
+        return getMetaspaceMethodConstant();
+    }
+
+    /**
+     * Gets the complete set of modifiers for this method which includes the JVM specification
+     * modifiers as well as the HotSpot internal modifiers.
+     */
+    public int getAllModifiers() {
+        return UNSAFE.getInt(metaspaceMethod + config().methodAccessFlagsOffset);
+    }
+
+    @Override
+    public int getModifiers() {
+        return getAllModifiers() & jvmMethodModifiers();
+    }
+
+    @Override
+    public boolean canBeStaticallyBound() {
+        return (isFinal() || isPrivate() || isStatic() || holder.isLeaf()) && isConcrete();
+    }
+
+    @Override
+    public byte[] getCode() {
+        if (getCodeSize() == 0) {
+            return null;
+        }
+        if (code == null && holder.isLinked()) {
+            code = compilerToVM().getBytecode(this);
+            assert code.length == getCodeSize() : "expected: " + getCodeSize() + ", actual: " + code.length;
+        }
+        return code;
+    }
+
+    @Override
+    public int getCodeSize() {
+        return UNSAFE.getChar(getConstMethod() + config().constMethodCodeSizeOffset);
+    }
+
+    @Override
+    public ExceptionHandler[] getExceptionHandlers() {
+        final boolean hasExceptionTable = (getConstMethodFlags() & config().constMethodHasExceptionTable) != 0;
+        if (!hasExceptionTable) {
+            return new ExceptionHandler[0];
+        }
+
+        HotSpotVMConfig config = config();
+        final int exceptionTableLength = compilerToVM().getExceptionTableLength(this);
+        ExceptionHandler[] handlers = new ExceptionHandler[exceptionTableLength];
+        long exceptionTableElement = compilerToVM().getExceptionTableStart(this);
+
+        for (int i = 0; i < exceptionTableLength; i++) {
+            final int startPc = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementStartPcOffset);
+            final int endPc = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementEndPcOffset);
+            final int handlerPc = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementHandlerPcOffset);
+            int catchTypeIndex = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementCatchTypeIndexOffset);
+
+            JavaType catchType;
+            if (catchTypeIndex == 0) {
+                catchType = null;
+            } else {
+                final int opcode = -1;  // opcode is not used
+                catchType = constantPool.lookupType(catchTypeIndex, opcode);
+
+                // Check for Throwable which catches everything.
+                if (catchType instanceof HotSpotResolvedObjectTypeImpl) {
+                    HotSpotResolvedObjectTypeImpl resolvedType = (HotSpotResolvedObjectTypeImpl) catchType;
+                    if (resolvedType.mirror() == Throwable.class) {
+                        catchTypeIndex = 0;
+                        catchType = null;
+                    }
+                }
+            }
+            handlers[i] = new ExceptionHandler(startPc, endPc, handlerPc, catchTypeIndex, catchType);
+
+            // Go to the next ExceptionTableElement
+            exceptionTableElement += config.exceptionTableElementSize;
+        }
+
+        return handlers;
+    }
+
+    /**
+     * Returns true if this method has a {@code CallerSensitive} annotation.
+     *
+     * @return true if CallerSensitive annotation present, false otherwise
+     */
+    public boolean isCallerSensitive() {
+        return (getFlags() & config().methodFlagsCallerSensitive) != 0;
+    }
+
+    /**
+     * Returns true if this method has a {@code ForceInline} annotation.
+     *
+     * @return true if ForceInline annotation present, false otherwise
+     */
+    public boolean isForceInline() {
+        return (getFlags() & config().methodFlagsForceInline) != 0;
+    }
+
+    /**
+     * Returns true if this method has a {@code ReservedStackAccess} annotation.
+     *
+     * @return true if ReservedStackAccess annotation present, false otherwise
+     */
+    public boolean hasReservedStackAccess() {
+        // Annotation isn't available in JDK8
+        return false;
+    }
+
+    /**
+     * Manually adds a DontInline annotation to this method.
+     */
+    public void setNotInlineable() {
+        compilerToVM().doNotInlineOrCompile(this);
+    }
+
+    /**
+     * Returns true if this method is one of the special methods that is ignored by security stack
+     * walks.
+     *
+     * @return true if special method ignored by security stack walks, false otherwise
+     */
+    public boolean ignoredBySecurityStackWalk() {
+        return compilerToVM().methodIsIgnoredBySecurityStackWalk(this);
+    }
+
+    @Override
+    public boolean isClassInitializer() {
+        if (isStatic()) {
+            final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset);
+            long nameSymbol = constantPool.getEntryAt(nameIndex);
+            long clinitSymbol = config().symbolClinit;
+            return nameSymbol == clinitSymbol;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isConstructor() {
+        if (!isStatic()) {
+            final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset);
+            long nameSymbol = constantPool.getEntryAt(nameIndex);
+            long initSymbol = config().symbolInit;
+            return nameSymbol == initSymbol;
+        }
+        return false;
+    }
+
+    @Override
+    public int getMaxLocals() {
+        if (isAbstract() || isNative()) {
+            return 0;
+        }
+        HotSpotVMConfig config = config();
+        return UNSAFE.getChar(getConstMethod() + config.methodMaxLocalsOffset);
+    }
+
+    @Override
+    public int getMaxStackSize() {
+        if (isAbstract() || isNative()) {
+            return 0;
+        }
+        HotSpotVMConfig config = config();
+        return config.extraStackEntries + UNSAFE.getChar(getConstMethod() + config.constMethodMaxStackOffset);
+    }
+
+    @Override
+    public StackTraceElement asStackTraceElement(int bci) {
+        if (bci < 0 || bci >= getCodeSize()) {
+            // HotSpot code can only construct stack trace elements for valid bcis
+            StackTraceElement ste = compilerToVM().getStackTraceElement(this, 0);
+            return new StackTraceElement(ste.getClassName(), ste.getMethodName(), ste.getFileName(), -1);
+        }
+        return compilerToVM().getStackTraceElement(this, bci);
+    }
+
+    public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) {
+        if (receiver.isInterface()) {
+            // Cannot trust interfaces. Because of:
+            // interface I { void foo(); }
+            // class A { public void foo() {} }
+            // class B extends A implements I { }
+            // class C extends B { public void foo() { } }
+            // class D extends B { }
+            // Would lead to identify C.foo() as the unique concrete method for I.foo() without
+            // seeing A.foo().
+            return null;
+        }
+        if (this.isDefault()) {
+            // CHA for default methods doesn't work and may crash the VM
+            return null;
+        }
+        return compilerToVM().findUniqueConcreteMethod(((HotSpotResolvedObjectTypeImpl) receiver), this);
+    }
+
+    @Override
+    public HotSpotSignature getSignature() {
+        return signature;
+    }
+
+    /**
+     * Gets the value of {@code Method::_code}.
+     *
+     * @return the value of {@code Method::_code}
+     */
+    private long getCompiledCode() {
+        HotSpotVMConfig config = config();
+        return UNSAFE.getAddress(metaspaceMethod + config.methodCodeOffset);
+    }
+
+    /**
+     * Returns whether this method has compiled code.
+     *
+     * @return true if this method has compiled code, false otherwise
+     */
+    public boolean hasCompiledCode() {
+        return getCompiledCode() != 0L;
+    }
+
+    /**
+     * @param level
+     * @return true if the currently installed code was generated at {@code level}.
+     */
+    public boolean hasCompiledCodeAtLevel(int level) {
+        long compiledCode = getCompiledCode();
+        if (compiledCode != 0) {
+            return UNSAFE.getInt(compiledCode + config().nmethodCompLevelOffset) == level;
+        }
+        return false;
+    }
+
+    @Override
+    public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) {
+        ProfilingInfo info;
+
+        if (methodData == null) {
+            long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + config().methodDataOffset);
+            if (metaspaceMethodData != 0) {
+                methodData = new HotSpotMethodData(metaspaceMethodData, this);
+                String methodDataFilter = Option.TraceMethodDataFilter.getString();
+                if (methodDataFilter != null && this.format("%H.%n").contains(methodDataFilter)) {
+                    System.out.println(methodData.toString());
+                }
+            }
+        }
+
+        if (methodData == null || (!methodData.hasNormalData() && !methodData.hasExtraData())) {
+            // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in
+            // case of a deoptimization.
+            info = DefaultProfilingInfo.get(TriState.FALSE);
+        } else {
+            info = new HotSpotProfilingInfo(methodData, this, includeNormal, includeOSR);
+        }
+        return info;
+    }
+
+    @Override
+    public void reprofile() {
+        compilerToVM().reprofile(this);
+    }
+
+    @Override
+    public ConstantPool getConstantPool() {
+        return constantPool;
+    }
+
+    @Override
+    public Parameter[] getParameters() {
+        Executable javaMethod = toJava();
+        if (javaMethod == null) {
+            return null;
+        }
+
+        java.lang.reflect.Parameter[] javaParameters = javaMethod.getParameters();
+        Parameter[] res = new Parameter[javaParameters.length];
+        for (int i = 0; i < res.length; i++) {
+            java.lang.reflect.Parameter src = javaParameters[i];
+            String paramName = src.isNamePresent() ? src.getName() : null;
+            res[i] = new Parameter(paramName, src.getModifiers(), this, i);
+        }
+        return res;
+    }
+
+    @Override
+    public Annotation[][] getParameterAnnotations() {
+        Executable javaMethod = toJava();
+        return javaMethod == null ? new Annotation[signature.getParameterCount(false)][0] : javaMethod.getParameterAnnotations();
+    }
+
+    @Override
+    public Annotation[] getAnnotations() {
+        Executable javaMethod = toJava();
+        if (javaMethod != null) {
+            return javaMethod.getAnnotations();
+        }
+        return new Annotation[0];
+    }
+
+    @Override
+    public Annotation[] getDeclaredAnnotations() {
+        Executable javaMethod = toJava();
+        if (javaMethod != null) {
+            return javaMethod.getDeclaredAnnotations();
+        }
+        return new Annotation[0];
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        Executable javaMethod = toJava();
+        return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass);
+    }
+
+    public boolean isBridge() {
+        return (BRIDGE & getModifiers()) != 0;
+    }
+
+    @Override
+    public boolean isSynthetic() {
+        return (SYNTHETIC & getModifiers()) != 0;
+    }
+
+    public boolean isVarArgs() {
+        return (VARARGS & getModifiers()) != 0;
+    }
+
+    public boolean isDefault() {
+        // Copied from java.lang.Method.isDefault()
+        int mask = Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC;
+        return ((getModifiers() & mask) == Modifier.PUBLIC) && getDeclaringClass().isInterface();
+    }
+
+    @Override
+    public Type[] getGenericParameterTypes() {
+        Executable javaMethod = toJava();
+        return javaMethod == null ? null : javaMethod.getGenericParameterTypes();
+    }
+
+    public Class<?>[] signatureToTypes() {
+        Signature sig = getSignature();
+        int count = sig.getParameterCount(false);
+        Class<?>[] result = new Class<?>[count];
+        for (int i = 0; i < result.length; ++i) {
+            JavaType parameterType = sig.getParameterType(i, holder);
+            HotSpotResolvedJavaType resolvedParameterType = (HotSpotResolvedJavaType) parameterType.resolve(holder);
+            result[i] = resolvedParameterType.mirror();
+        }
+        return result;
+    }
+
+    private static Method searchMethods(Method[] methods, String name, Class<?> returnType, Class<?>[] parameterTypes) {
+        for (Method m : methods) {
+            if (m.getName().equals(name) && returnType.equals(m.getReturnType()) && Arrays.equals(m.getParameterTypes(), parameterTypes)) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    private Executable toJava() {
+        if (toJavaCache != null) {
+            return toJavaCache;
+        }
+        try {
+            Class<?>[] parameterTypes = signatureToTypes();
+            Class<?> returnType = ((HotSpotResolvedJavaType) getSignature().getReturnType(holder).resolve(holder)).mirror();
+
+            Executable result;
+            if (isConstructor()) {
+                result = holder.mirror().getDeclaredConstructor(parameterTypes);
+            } else {
+                // Do not use Method.getDeclaredMethod() as it can return a bridge method
+                // when this.isBridge() is false and vice versa.
+                result = searchMethods(holder.mirror().getDeclaredMethods(), getName(), returnType, parameterTypes);
+            }
+            toJavaCache = result;
+            return result;
+        } catch (NoSuchMethodException | NoClassDefFoundError e) {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean canBeInlined() {
+        if (hasNeverInlineDirective()) {
+            return false;
+        }
+        return compilerToVM().isCompilable(this);
+    }
+
+    @Override
+    public boolean hasNeverInlineDirective() {
+        return compilerToVM().hasNeverInlineDirective(this);
+    }
+
+    @Override
+    public boolean shouldBeInlined() {
+        if (isForceInline()) {
+            return true;
+        }
+        return compilerToVM().shouldInlineMethod(this);
+    }
+
+    @Override
+    public LineNumberTable getLineNumberTable() {
+        final boolean hasLineNumberTable = (getConstMethodFlags() & config().constMethodHasLineNumberTable) != 0;
+        if (!hasLineNumberTable) {
+            return null;
+        }
+
+        long[] values = compilerToVM().getLineNumberTable(this);
+        if (values == null || values.length == 0) {
+            // Empty table so treat is as non-existent
+            return null;
+        }
+        assert values.length % 2 == 0;
+        int[] bci = new int[values.length / 2];
+        int[] line = new int[values.length / 2];
+
+        for (int i = 0; i < values.length / 2; i++) {
+            bci[i] = (int) values[i * 2];
+            line[i] = (int) values[i * 2 + 1];
+        }
+
+        return new LineNumberTable(line, bci);
+    }
+
+    @Override
+    public LocalVariableTable getLocalVariableTable() {
+        final boolean hasLocalVariableTable = (getConstMethodFlags() & config().constMethodHasLocalVariableTable) != 0;
+        if (!hasLocalVariableTable) {
+            return null;
+        }
+
+        HotSpotVMConfig config = config();
+        long localVariableTableElement = compilerToVM().getLocalVariableTableStart(this);
+        final int localVariableTableLength = compilerToVM().getLocalVariableTableLength(this);
+        Local[] locals = new Local[localVariableTableLength];
+
+        for (int i = 0; i < localVariableTableLength; i++) {
+            final int startBci = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementStartBciOffset);
+            final int endBci = startBci + UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementLengthOffset);
+            final int nameCpIndex = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementNameCpIndexOffset);
+            final int typeCpIndex = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementDescriptorCpIndexOffset);
+            final int slot = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementSlotOffset);
+
+            String localName = getConstantPool().lookupUtf8(nameCpIndex);
+            String localType = getConstantPool().lookupUtf8(typeCpIndex);
+
+            locals[i] = new Local(localName, runtime().lookupType(localType, holder, false), startBci, endBci, slot);
+
+            // Go to the next LocalVariableTableElement
+            localVariableTableElement += config.localVariableTableElementSize;
+        }
+
+        return new LocalVariableTable(locals);
+    }
+
+    /**
+     * Returns the offset of this method into the v-table. The method must have a v-table entry as
+     * indicated by {@link #isInVirtualMethodTable(ResolvedJavaType)}, otherwise an exception is
+     * thrown.
+     *
+     * @return the offset of this method into the v-table
+     */
+    public int vtableEntryOffset(ResolvedJavaType resolved) {
+        if (!isInVirtualMethodTable(resolved)) {
+            throw new JVMCIError("%s does not have a vtable entry in type %s", this, resolved);
+        }
+        HotSpotVMConfig config = config();
+        final int vtableIndex = getVtableIndex((HotSpotResolvedObjectTypeImpl) resolved);
+        return config.klassVtableStartOffset + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset;
+    }
+
+    @Override
+    public boolean isInVirtualMethodTable(ResolvedJavaType resolved) {
+        if (resolved instanceof HotSpotResolvedObjectTypeImpl) {
+            HotSpotResolvedObjectTypeImpl hotspotResolved = (HotSpotResolvedObjectTypeImpl) resolved;
+            int vtableIndex = getVtableIndex(hotspotResolved);
+            return vtableIndex >= 0 && vtableIndex < hotspotResolved.getVtableLength();
+        }
+        return false;
+    }
+
+    private int getVtableIndex(HotSpotResolvedObjectTypeImpl resolved) {
+        if (!holder.isLinked()) {
+            return config().invalidVtableIndex;
+        }
+        if (holder.isInterface()) {
+            if (resolved.isInterface()) {
+                return config().invalidVtableIndex;
+            }
+            return getVtableIndexForInterfaceMethod(resolved);
+        }
+        return getVtableIndex();
+    }
+
+    /**
+     * Returns this method's virtual table index.
+     *
+     * @return virtual table index
+     */
+    private int getVtableIndex() {
+        assert !holder.isInterface();
+        HotSpotVMConfig config = config();
+        int result = UNSAFE.getInt(metaspaceMethod + config.methodVtableIndexOffset);
+        assert result >= config.nonvirtualVtableIndex : "must be linked";
+        return result;
+    }
+
+    private int getVtableIndexForInterfaceMethod(ResolvedJavaType resolved) {
+        HotSpotResolvedObjectTypeImpl hotspotType = (HotSpotResolvedObjectTypeImpl) resolved;
+        return compilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this);
+    }
+
+    /**
+     * The {@link SpeculationLog} for methods compiled by JVMCI hang off this per-declaring-type
+     * {@link ClassValue}. The raw Method* value is safe to use as a key in the map as a) it is
+     * never moves and b) we never read from it.
+     * <p>
+     * One implication is that we will preserve {@link SpeculationLog}s for methods that have been
+     * redefined via class redefinition. It's tempting to periodically flush such logs but we cannot
+     * read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods
+     * are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal).
+     */
+    private static final ClassValue<Map<Long, SpeculationLog>> SpeculationLogs = new ClassValue<Map<Long, SpeculationLog>>() {
+        @Override
+        protected Map<Long, SpeculationLog> computeValue(java.lang.Class<?> type) {
+            return new HashMap<>(4);
+        }
+    };
+
+    public SpeculationLog getSpeculationLog() {
+        Map<Long, SpeculationLog> map = SpeculationLogs.get(holder.mirror());
+        synchronized (map) {
+            SpeculationLog log = map.get(this.metaspaceMethod);
+            if (log == null) {
+                log = new HotSpotSpeculationLog();
+                map.put(metaspaceMethod, log);
+            }
+            return log;
+        }
+    }
+
+    public int intrinsicId() {
+        HotSpotVMConfig config = config();
+        // Important: Size of field changed, JDK8 has u1 and JDK9 u2
+        return UNSAFE.getByte(metaspaceMethod + config.methodIntrinsicIdOffset) & 0xff;
+    }
+
+    /**
+     * Allocates a compile id for this method by asking the VM for one.
+     *
+     * @param entryBCI entry bci
+     * @return compile id
+     */
+    public int allocateCompileId(int entryBCI) {
+        return compilerToVM().allocateCompileId(this, entryBCI);
+    }
+
+    public boolean hasCodeAtLevel(int entryBCI, int level) {
+        if (entryBCI == config().invocationEntryBci) {
+            return hasCompiledCodeAtLevel(level);
+        }
+        return compilerToVM().hasCompiledCodeForOSR(this, entryBCI, level);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
+
+    HotSpotResolvedJavaType(String name) {
+        super(name);
+    }
+
+    public abstract Class<?> mirror();
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (!(obj instanceof HotSpotResolvedJavaType)) {
+            return false;
+        }
+        HotSpotResolvedJavaType that = (HotSpotResolvedJavaType) obj;
+        return this.mirror().equals(that.mirror());
+    }
+
+    @Override
+    public final int hashCode() {
+        return getName().hashCode();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
+ */
+public interface HotSpotResolvedObjectType extends ResolvedJavaType {
+
+    /**
+     * Gets the JVMCI mirror for a {@link Class} object.
+     *
+     * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
+     */
+    static HotSpotResolvedObjectType fromObjectClass(Class<?> javaClass) {
+        return HotSpotResolvedObjectTypeImpl.fromObjectClass(javaClass);
+    }
+
+    HotSpotResolvedObjectType getArrayClass();
+
+    ResolvedJavaType getComponentType();
+
+    AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype();
+
+    HotSpotResolvedObjectType getSuperclass();
+
+    HotSpotResolvedObjectType[] getInterfaces();
+
+    HotSpotResolvedObjectType getSupertype();
+
+    HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType);
+
+    default boolean isPrimitive() {
+        return false;
+    }
+
+    default JavaKind getJavaKind() {
+        return JavaKind.Object;
+    }
+
+    ConstantPool getConstantPool();
+
+    /**
+     * Gets the instance size of this type. If an instance of this type cannot be fast path
+     * allocated, then the returned value is negative (its absolute value gives the size). Must not
+     * be called if this is an array or interface type.
+     */
+    int instanceSize();
+
+    int getVtableLength();
+
+    @Override
+    AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method);
+
+    /**
+     * Performs a fast-path check that this type is resolved in the context of a given accessing
+     * class. A negative result does not mean this type is not resolved with respect to
+     * {@code accessingClass}. That can only be determined by
+     * {@linkplain HotSpotJVMCIRuntime#lookupType(String, HotSpotResolvedObjectType, boolean)
+     * re-resolving} the type.
+     */
+    boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass);
+
+    /**
+     * Gets the metaspace Klass boxed in a {@link JavaConstant}.
+     */
+    Constant klass();
+
+    boolean isPrimaryType();
+
+    int superCheckOffset();
+
+    long prototypeMarkWord();
+
+    int layoutHelper();
+
+    HotSpotResolvedObjectType getEnclosingType();
+
+    ResolvedJavaMethod getClassInitializer();
+
+    /**
+     * Gets the fingerprint for this type.
+     *
+     * @return the value of the fingerprint ({@code 0} for arrays and synthetic classes or if the VM
+     *         does not support fingerprints)
+     */
+    default long getFingerprint() {
+        return 0L;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,915 @@
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.util.Objects.requireNonNull;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmClassModifiers;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.nio.ByteOrder;
+import java.util.HashMap;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+import jdk.vm.ci.meta.Assumptions.ConcreteMethod;
+import jdk.vm.ci.meta.Assumptions.ConcreteSubtype;
+import jdk.vm.ci.meta.Assumptions.LeafType;
+import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
+ */
+final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceWrapperObject {
+
+    private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
+    private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
+
+    /**
+     * The Java class this type represents.
+     */
+    private final Class<?> javaClass;
+    private HotSpotResolvedJavaMethodImpl[] methodCacheArray;
+    private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCacheHashMap;
+    private HotSpotResolvedJavaField[] instanceFields;
+    private HotSpotResolvedObjectTypeImpl[] interfaces;
+    private HotSpotConstantPool constantPool;
+    final HotSpotJVMCIMetaAccessContext context;
+    private HotSpotResolvedObjectType arrayOfType;
+
+    /**
+     * Gets the JVMCI mirror for a {@link Class} object.
+     *
+     * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
+     */
+    static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
+        return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass);
+    }
+
+    /**
+     * Gets the JVMCI mirror from a HotSpot type. Since {@link Class} is already a proxy for the
+     * underlying Klass*, it is used instead of the raw Klass*.
+     *
+     * Called from the VM.
+     *
+     * @param javaClass a {@link Class} object
+     * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
+     */
+    @SuppressWarnings("unused")
+    private static HotSpotResolvedObjectTypeImpl fromMetaspace(Class<?> javaClass) {
+        return fromObjectClass(javaClass);
+    }
+
+    /**
+     * Creates the JVMCI mirror for a {@link Class} object.
+     *
+     * <p>
+     * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
+     * {@link Class} type. Use {@link #fromObjectClass(Class)} or {@link #fromMetaspace(Class)}
+     * instead.
+     * </p>
+     *
+     * @param javaClass the Class to create the mirror for
+     * @param context
+     */
+    HotSpotResolvedObjectTypeImpl(Class<?> javaClass, HotSpotJVMCIMetaAccessContext context) {
+        super(getSignatureName(javaClass));
+        this.javaClass = javaClass;
+        this.context = context;
+        assert getName().charAt(0) != '[' || isArray() : getName();
+    }
+
+    /**
+     * Returns the name of this type as it would appear in a signature.
+     */
+    private static String getSignatureName(Class<?> javaClass) {
+        if (javaClass.isArray()) {
+            return javaClass.getName().replace('.', '/');
+        }
+        return "L" + javaClass.getName().replace('.', '/') + ";";
+    }
+
+    /**
+     * Gets the metaspace Klass for this type.
+     */
+    long getMetaspaceKlass() {
+        if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) {
+            return UNSAFE.getLong(javaClass, (long) config().klassOffset);
+        }
+        return UNSAFE.getInt(javaClass, (long) config().klassOffset) & 0xFFFFFFFFL;
+    }
+
+    @Override
+    public long getMetaspacePointer() {
+        return getMetaspaceKlass();
+    }
+
+    /**
+     * The Klass* for this object is kept alive by the direct reference to {@link #javaClass} so no
+     * extra work is required.
+     */
+    @Override
+    public boolean isRegistered() {
+        return true;
+    }
+
+    @Override
+    public int getModifiers() {
+        if (isArray()) {
+            return (getElementalType().getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)) | Modifier.FINAL | Modifier.ABSTRACT;
+        } else {
+            return getAccessFlags() & jvmClassModifiers();
+        }
+    }
+
+    public int getAccessFlags() {
+        HotSpotVMConfig config = config();
+        return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
+    }
+
+    @Override
+    public HotSpotResolvedObjectType getArrayClass() {
+        if (arrayOfType == null) {
+            arrayOfType = fromObjectClass(Array.newInstance(mirror(), 0).getClass());
+        }
+        return arrayOfType;
+    }
+
+    @Override
+    public ResolvedJavaType getComponentType() {
+        Class<?> javaComponentType = mirror().getComponentType();
+        return javaComponentType == null ? null : runtime().fromClass(javaComponentType);
+    }
+
+    @Override
+    public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
+        if (isLeaf()) {
+            // No assumptions are required.
+            return new AssumptionResult<>(this);
+        }
+        HotSpotVMConfig config = config();
+        if (isArray()) {
+            ResolvedJavaType elementalType = getElementalType();
+            AssumptionResult<ResolvedJavaType> elementType = elementalType.findLeafConcreteSubtype();
+            if (elementType != null && elementType.getResult().equals(elementalType)) {
+                /*
+                 * If the elementType is leaf then the array is leaf under the same assumptions but
+                 * only if the element type is exactly the leaf type. The element type can be
+                 * abstract even if there is only one implementor of the abstract type.
+                 */
+                AssumptionResult<ResolvedJavaType> result = new AssumptionResult<>(this);
+                result.add(elementType);
+                return result;
+            }
+            return null;
+        } else if (isInterface()) {
+            HotSpotResolvedObjectTypeImpl implementor = getSingleImplementor();
+            /*
+             * If the implementor field contains itself that indicates that the interface has more
+             * than one implementors (see: InstanceKlass::add_implementor).
+             */
+            if (implementor == null || implementor.equals(this)) {
+                return null;
+            }
+
+            assert !implementor.isInterface();
+            if (implementor.isAbstract() || !implementor.isLeafClass()) {
+                AssumptionResult<ResolvedJavaType> leafConcreteSubtype = implementor.findLeafConcreteSubtype();
+                if (leafConcreteSubtype != null) {
+                    assert !leafConcreteSubtype.getResult().equals(implementor);
+                    AssumptionResult<ResolvedJavaType> newResult = new AssumptionResult<>(leafConcreteSubtype.getResult(), new ConcreteSubtype(this, implementor));
+                    // Accumulate leaf assumptions and return the combined result.
+                    newResult.add(leafConcreteSubtype);
+                    return newResult;
+                }
+                return null;
+            }
+            return concreteSubtype(implementor);
+        } else {
+            HotSpotResolvedObjectTypeImpl type = this;
+            while (type.isAbstract()) {
+                HotSpotResolvedObjectTypeImpl subklass = type.getSubklass();
+                if (subklass == null || UNSAFE.getAddress(subklass.getMetaspaceKlass() + config.nextSiblingOffset) != 0) {
+                    return null;
+                }
+                type = subklass;
+            }
+            if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) {
+                return null;
+            }
+            if (this.isAbstract()) {
+                return concreteSubtype(type);
+            } else {
+                assert this.equals(type);
+                return new AssumptionResult<>(type, new LeafType(type));
+            }
+        }
+    }
+
+    private AssumptionResult<ResolvedJavaType> concreteSubtype(HotSpotResolvedObjectTypeImpl type) {
+        if (type.isLeaf()) {
+            return new AssumptionResult<>(type, new ConcreteSubtype(this, type));
+        } else {
+            return new AssumptionResult<>(type, new LeafType(type), new ConcreteSubtype(this, type));
+        }
+    }
+
+    /**
+     * Returns if type {@code type} is a leaf class. This is the case if the
+     * {@code Klass::_subklass} field of the underlying class is zero.
+     *
+     * @return true if the type is a leaf class
+     */
+    private boolean isLeafClass() {
+        return UNSAFE.getLong(this.getMetaspaceKlass() + config().subklassOffset) == 0;
+    }
+
+    /**
+     * Returns the {@code Klass::_subklass} field of the underlying metaspace klass for the given
+     * type {@code type}.
+     *
+     * @return value of the subklass field as metaspace klass pointer
+     */
+    private HotSpotResolvedObjectTypeImpl getSubklass() {
+        return compilerToVM().getResolvedJavaType(this, config().subklassOffset, false);
+    }
+
+    @Override
+    public HotSpotResolvedObjectTypeImpl getSuperclass() {
+        Class<?> javaSuperclass = mirror().getSuperclass();
+        return javaSuperclass == null ? null : fromObjectClass(javaSuperclass);
+    }
+
+    @Override
+    public HotSpotResolvedObjectTypeImpl[] getInterfaces() {
+        if (interfaces == null) {
+            Class<?>[] javaInterfaces = mirror().getInterfaces();
+            HotSpotResolvedObjectTypeImpl[] result = new HotSpotResolvedObjectTypeImpl[javaInterfaces.length];
+            for (int i = 0; i < javaInterfaces.length; i++) {
+                result[i] = fromObjectClass(javaInterfaces[i]);
+            }
+            interfaces = result;
+        }
+        return interfaces;
+    }
+
+    @Override
+    public HotSpotResolvedObjectTypeImpl getSingleImplementor() {
+        if (!isInterface()) {
+            throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
+        }
+        return compilerToVM().getImplementor(this);
+    }
+
+    public HotSpotResolvedObjectTypeImpl getSupertype() {
+        if (isArray()) {
+            ResolvedJavaType componentType = getComponentType();
+            if (mirror() == Object[].class || componentType.isPrimitive()) {
+                return fromObjectClass(Object.class);
+            }
+            return (HotSpotResolvedObjectTypeImpl) ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype().getArrayClass();
+        }
+        if (isInterface()) {
+            return fromObjectClass(Object.class);
+        }
+        return getSuperclass();
+    }
+
+    @Override
+    public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) {
+        if (otherType.isPrimitive()) {
+            return null;
+        } else {
+            HotSpotResolvedObjectTypeImpl t1 = this;
+            HotSpotResolvedObjectTypeImpl t2 = (HotSpotResolvedObjectTypeImpl) otherType;
+            while (true) {
+                if (t1.isAssignableFrom(t2)) {
+                    return t1;
+                }
+                if (t2.isAssignableFrom(t1)) {
+                    return t2;
+                }
+                t1 = t1.getSupertype();
+                t2 = t2.getSupertype();
+            }
+        }
+    }
+
+    @Override
+    public AssumptionResult<Boolean> hasFinalizableSubclass() {
+        assert !isArray();
+        if (!compilerToVM().hasFinalizableSubclass(this)) {
+            return new AssumptionResult<>(false, new NoFinalizableSubclass(this));
+        }
+        return new AssumptionResult<>(true);
+    }
+
+    @Override
+    public boolean hasFinalizer() {
+        return (getAccessFlags() & config().klassHasFinalizerFlag) != 0;
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return false;
+    }
+
+    @Override
+    public boolean isArray() {
+        return mirror().isArray();
+    }
+
+    @Override
+    public boolean isInitialized() {
+        return isArray() ? true : getInitState() == config().instanceKlassStateFullyInitialized;
+    }
+
+    @Override
+    public boolean isLinked() {
+        return isArray() ? true : getInitState() >= config().instanceKlassStateLinked;
+    }
+
+    /**
+     * Returns the value of the state field {@code InstanceKlass::_init_state} of the metaspace
+     * klass.
+     *
+     * @return state field value of this type
+     */
+    private int getInitState() {
+        assert !isArray() : "_init_state only exists in InstanceKlass";
+        return UNSAFE.getByte(getMetaspaceKlass() + config().instanceKlassInitStateOffset) & 0xFF;
+    }
+
+    @Override
+    public void initialize() {
+        if (!isInitialized()) {
+            UNSAFE.ensureClassInitialized(mirror());
+            assert isInitialized();
+        }
+    }
+
+    @Override
+    public boolean isInstance(JavaConstant obj) {
+        if (obj.getJavaKind() == JavaKind.Object && !obj.isNull()) {
+            return mirror().isInstance(((HotSpotObjectConstantImpl) obj).object());
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isInstanceClass() {
+        return !isArray() && !isInterface();
+    }
+
+    @Override
+    public boolean isInterface() {
+        return mirror().isInterface();
+    }
+
+    @Override
+    public boolean isAssignableFrom(ResolvedJavaType other) {
+        assert other != null;
+        if (other instanceof HotSpotResolvedObjectTypeImpl) {
+            HotSpotResolvedObjectTypeImpl otherType = (HotSpotResolvedObjectTypeImpl) other;
+            return mirror().isAssignableFrom(otherType.mirror());
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isJavaLangObject() {
+        return javaClass.equals(Object.class);
+    }
+
+    @Override
+    public JavaKind getJavaKind() {
+        return JavaKind.Object;
+    }
+
+    @Override
+    public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
+        assert !callerType.isArray();
+        if (isInterface()) {
+            // Methods can only be resolved against concrete types
+            return null;
+        }
+        if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic()) {
+            return method;
+        }
+        if (!method.getDeclaringClass().isAssignableFrom(this)) {
+            return null;
+        }
+        HotSpotResolvedJavaMethodImpl hotSpotMethod = (HotSpotResolvedJavaMethodImpl) method;
+        HotSpotResolvedObjectTypeImpl hotSpotCallerType = (HotSpotResolvedObjectTypeImpl) callerType;
+        return compilerToVM().resolveMethod(this, hotSpotMethod, hotSpotCallerType);
+    }
+
+    public HotSpotConstantPool getConstantPool() {
+        if (constantPool == null || !isArray() && UNSAFE.getAddress(getMetaspaceKlass() + config().instanceKlassConstantsOffset) != constantPool.getMetaspaceConstantPool()) {
+            /*
+             * If the pointer to the ConstantPool has changed since this was last read refresh the
+             * HotSpotConstantPool wrapper object. This ensures that uses of the constant pool are
+             * operating on the latest one and that HotSpotResolvedJavaMethodImpls will be able to
+             * use the shared copy instead of creating their own instance.
+             */
+            constantPool = compilerToVM().getConstantPool(this);
+        }
+        return constantPool;
+    }
+
+    /**
+     * Gets the instance size of this type. If an instance of this type cannot be fast path
+     * allocated, then the returned value is negative (its absolute value gives the size). Must not
+     * be called if this is an array or interface type.
+     */
+    public int instanceSize() {
+        assert !isArray();
+        assert !isInterface();
+
+        HotSpotVMConfig config = config();
+        final int layoutHelper = layoutHelper();
+        assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
+
+        // See: Klass::layout_helper_size_in_bytes
+        int size = layoutHelper & ~config.klassLayoutHelperInstanceSlowPathBit;
+
+        // See: Klass::layout_helper_needs_slow_path
+        boolean needsSlowPath = (layoutHelper & config.klassLayoutHelperInstanceSlowPathBit) != 0;
+
+        return needsSlowPath ? -size : size;
+    }
+
+    public int layoutHelper() {
+        HotSpotVMConfig config = config();
+        return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
+    }
+
+    synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
+        // Maintain cache as array.
+        if (methodCacheArray == null) {
+            methodCacheArray = new HotSpotResolvedJavaMethodImpl[METHOD_CACHE_ARRAY_CAPACITY];
+        }
+
+        int i = 0;
+        for (; i < methodCacheArray.length; ++i) {
+            HotSpotResolvedJavaMethodImpl curMethod = methodCacheArray[i];
+            if (curMethod == null) {
+                HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
+                methodCacheArray[i] = newMethod;
+                context.add(newMethod);
+                return newMethod;
+            } else if (curMethod.getMetaspacePointer() == metaspaceMethod) {
+                return curMethod;
+            }
+        }
+
+        // Fall-back to hash table.
+        if (methodCacheHashMap == null) {
+            methodCacheHashMap = new HashMap<>();
+        }
+
+        HotSpotResolvedJavaMethodImpl lookupResult = methodCacheHashMap.get(metaspaceMethod);
+        if (lookupResult == null) {
+            HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
+            methodCacheHashMap.put(metaspaceMethod, newMethod);
+            context.add(lookupResult);
+            return newMethod;
+        } else {
+            return lookupResult;
+        }
+    }
+
+    public int getVtableLength() {
+        HotSpotVMConfig config = config();
+        if (isInterface() || isArray()) {
+            /* Everything has the core vtable of java.lang.Object */
+            return config.baseVtableLength();
+        }
+        int result = UNSAFE.getInt(getMetaspaceKlass() + config.klassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize);
+        assert result >= config.baseVtableLength() : UNSAFE.getInt(getMetaspaceKlass() + config.klassVtableLengthOffset) + " " + config.vtableEntrySize;
+        return result;
+    }
+
+    synchronized HotSpotResolvedJavaField createField(JavaType type, long offset, int rawFlags, int index) {
+        return new HotSpotResolvedJavaFieldImpl(this, type, offset, rawFlags, index);
+    }
+
+    @Override
+    public AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method) {
+        HotSpotResolvedJavaMethod hmethod = (HotSpotResolvedJavaMethod) method;
+        HotSpotResolvedObjectType declaredHolder = hmethod.getDeclaringClass();
+        /*
+         * Sometimes the receiver type in the graph hasn't stabilized to a subtype of declared
+         * holder, usually because of phis, so make sure that the type is related to the declared
+         * type before using it for lookup. Unlinked types should also be ignored because we can't
+         * resolve the proper method to invoke. Generally unlinked types in invokes should result in
+         * a deopt instead since they can't really be used if they aren't linked yet.
+         */
+        if (!declaredHolder.isAssignableFrom(this) || this.isArray() || this.equals(declaredHolder) || !isLinked() || isInterface()) {
+            ResolvedJavaMethod result = hmethod.uniqueConcreteMethod(declaredHolder);
+            if (result != null) {
+                return new AssumptionResult<>(result, new ConcreteMethod(method, declaredHolder, result));
+            }
+            return null;
+        }
+        /*
+         * The holder may be a subtype of the declaredHolder so make sure to resolve the method to
+         * the correct method for the subtype.
+         */
+        HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) resolveMethod(hmethod, this);
+        if (resolvedMethod == null) {
+            // The type isn't known to implement the method.
+            return null;
+        }
+
+        ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
+        if (result != null) {
+            return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));
+        }
+        return null;
+    }
+
+    FieldInfo createFieldInfo(int index) {
+        return new FieldInfo(index);
+    }
+
+    /**
+     * This class represents the field information for one field contained in the fields array of an
+     * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
+     */
+    class FieldInfo {
+        /**
+         * Native pointer into the array of Java shorts.
+         */
+        private final long metaspaceData;
+
+        /**
+         * Creates a field info for the field in the fields array at index {@code index}.
+         *
+         * @param index index to the fields array
+         */
+        FieldInfo(int index) {
+            HotSpotVMConfig config = config();
+            // Get Klass::_fields
+            final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
+            assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";
+            int offset = config.fieldInfoFieldSlots * Short.BYTES * index;
+            metaspaceData = metaspaceFields + config.arrayU2DataOffset + offset;
+        }
+
+        private int getAccessFlags() {
+            return readFieldSlot(config().fieldInfoAccessFlagsOffset);
+        }
+
+        private int getNameIndex() {
+            return readFieldSlot(config().fieldInfoNameIndexOffset);
+        }
+
+        private int getSignatureIndex() {
+            return readFieldSlot(config().fieldInfoSignatureIndexOffset);
+        }
+
+        public int getOffset() {
+            HotSpotVMConfig config = config();
+            final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset);
+            final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset);
+            final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize;
+            return offset;
+        }
+
+        /**
+         * Helper method to read an entry (slot) from the field array. Currently field info is laid
+         * on top an array of Java shorts.
+         */
+        private int readFieldSlot(int index) {
+            int offset = Short.BYTES * index;
+            return UNSAFE.getChar(metaspaceData + offset);
+        }
+
+        /**
+         * Returns the name of this field as a {@link String}. If the field is an internal field the
+         * name index is pointing into the vmSymbols table.
+         */
+        public String getName() {
+            final int nameIndex = getNameIndex();
+            return isInternal() ? config().symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
+        }
+
+        /**
+         * Returns the signature of this field as {@link String}. If the field is an internal field
+         * the signature index is pointing into the vmSymbols table.
+         */
+        public String getSignature() {
+            final int signatureIndex = getSignatureIndex();
+            return isInternal() ? config().symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
+        }
+
+        public JavaType getType() {
+            String signature = getSignature();
+            return runtime().lookupType(signature, HotSpotResolvedObjectTypeImpl.this, false);
+        }
+
+        private boolean isInternal() {
+            return (getAccessFlags() & config().jvmAccFieldInternal) != 0;
+        }
+
+        public boolean isStatic() {
+            return Modifier.isStatic(getAccessFlags());
+        }
+
+        public boolean hasGenericSignature() {
+            return (getAccessFlags() & config().jvmAccFieldHasGenericSignature) != 0;
+        }
+    }
+
+    @Override
+    public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
+        if (instanceFields == null) {
+            if (isArray() || isInterface()) {
+                instanceFields = NO_FIELDS;
+            } else {
+                HotSpotResolvedJavaField[] prepend = NO_FIELDS;
+                if (getSuperclass() != null) {
+                    prepend = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true);
+                }
+                instanceFields = getFields(false, prepend);
+            }
+        }
+        if (!includeSuperclasses && getSuperclass() != null) {
+            int superClassFieldCount = getSuperclass().getInstanceFields(true).length;
+            if (superClassFieldCount == instanceFields.length) {
+                // This class does not have any instance fields of its own.
+                return NO_FIELDS;
+            } else if (superClassFieldCount != 0) {
+                HotSpotResolvedJavaField[] result = new HotSpotResolvedJavaField[instanceFields.length - superClassFieldCount];
+                System.arraycopy(instanceFields, superClassFieldCount, result, 0, result.length);
+                return result;
+            } else {
+                // The super classes of this class do not have any instance fields.
+            }
+        }
+        return instanceFields;
+    }
+
+    @Override
+    public ResolvedJavaField[] getStaticFields() {
+        if (isArray()) {
+            return new HotSpotResolvedJavaField[0];
+        } else {
+            return getFields(true, NO_FIELDS);
+        }
+    }
+
+    /**
+     * Gets the instance or static fields of this class.
+     *
+     * @param retrieveStaticFields specifies whether to return instance or static fields
+     * @param prepend an array to be prepended to the returned result
+     */
+    private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSpotResolvedJavaField[] prepend) {
+        HotSpotVMConfig config = config();
+        final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
+        int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
+        int resultCount = 0;
+        int index = 0;
+        for (int i = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
+            FieldInfo field = new FieldInfo(index);
+            if (field.hasGenericSignature()) {
+                metaspaceFieldsLength--;
+            }
+
+            if (field.isStatic() == retrieveStaticFields) {
+                resultCount++;
+            }
+        }
+
+        if (resultCount == 0) {
+            return prepend;
+        }
+
+        int prependLength = prepend.length;
+        resultCount += prependLength;
+
+        HotSpotResolvedJavaField[] result = new HotSpotResolvedJavaField[resultCount];
+        if (prependLength != 0) {
+            System.arraycopy(prepend, 0, result, 0, prependLength);
+        }
+
+        int resultIndex = prependLength;
+        for (int i = 0; i < index; ++i) {
+            FieldInfo field = new FieldInfo(i);
+            if (field.isStatic() == retrieveStaticFields) {
+                int offset = field.getOffset();
+                HotSpotResolvedJavaField resolvedJavaField = createField(field.getType(), offset, field.getAccessFlags(), i);
+
+                // Make sure the result is sorted by offset.
+                int j;
+                for (j = resultIndex - 1; j >= prependLength && result[j].offset() > offset; j--) {
+                    result[j + 1] = result[j];
+                }
+                result[j + 1] = resolvedJavaField;
+                resultIndex++;
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public Class<?> mirror() {
+        return javaClass;
+    }
+
+    @Override
+    public String getSourceFileName() {
+        HotSpotVMConfig config = config();
+        final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
+        if (sourceFileNameIndex == 0) {
+            return null;
+        }
+        return getConstantPool().lookupUtf8(sourceFileNameIndex);
+    }
+
+    @Override
+    public Annotation[] getAnnotations() {
+        return mirror().getAnnotations();
+    }
+
+    @Override
+    public Annotation[] getDeclaredAnnotations() {
+        return mirror().getDeclaredAnnotations();
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        return mirror().getAnnotation(annotationClass);
+    }
+
+    /**
+     * Performs a fast-path check that this type is resolved in the context of a given accessing
+     * class. A negative result does not mean this type is not resolved with respect to
+     * {@code accessingClass}. That can only be determined by
+     * {@linkplain HotSpotJVMCIRuntime#lookupType(String, HotSpotResolvedObjectType, boolean)
+     * re-resolving} the type.
+     */
+    public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) {
+        assert accessingClass != null;
+        ResolvedJavaType elementType = getElementalType();
+        if (elementType.isPrimitive()) {
+            // Primitive type resolution is context free.
+            return true;
+        }
+        if (elementType.getName().startsWith("Ljava/")) {
+            // Classes in a java.* package can only be defined by the
+            // boot class loader. This is enforced by ClassLoader.preDefineClass()
+            assert mirror().getClassLoader() == null;
+            return true;
+        }
+        ClassLoader thisCl = mirror().getClassLoader();
+        ClassLoader accessingClassCl = ((HotSpotResolvedObjectTypeImpl) accessingClass).mirror().getClassLoader();
+        return thisCl == accessingClassCl;
+    }
+
+    @Override
+    public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+        if (isDefinitelyResolvedWithRespectTo(requireNonNull(accessingClass))) {
+            return this;
+        }
+        HotSpotResolvedObjectTypeImpl accessingType = (HotSpotResolvedObjectTypeImpl) accessingClass;
+        return (ResolvedJavaType) runtime().lookupType(getName(), accessingType, true);
+    }
+
+    /**
+     * Gets the metaspace Klass boxed in a {@link JavaConstant}.
+     */
+    public Constant klass() {
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
+    }
+
+    public boolean isPrimaryType() {
+        return config().secondarySuperCacheOffset != superCheckOffset();
+    }
+
+    public int superCheckOffset() {
+        HotSpotVMConfig config = config();
+        return UNSAFE.getInt(getMetaspaceKlass() + config.superCheckOffsetOffset);
+    }
+
+    public long prototypeMarkWord() {
+        HotSpotVMConfig config = config();
+        if (isArray()) {
+            return config.arrayPrototypeMarkWord();
+        } else {
+            return UNSAFE.getAddress(getMetaspaceKlass() + config.prototypeMarkWordOffset);
+        }
+    }
+
+    @Override
+    public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedEntryKind) {
+        ResolvedJavaField[] declaredFields = getInstanceFields(true);
+        for (ResolvedJavaField field : declaredFields) {
+            HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field;
+            long resolvedFieldOffset = resolvedField.offset();
+            // @formatter:off
+            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN  &&
+                            expectedEntryKind.isPrimitive() &&
+                            !expectedEntryKind.equals(JavaKind.Void) &&
+                            resolvedField.getJavaKind().isPrimitive()) {
+                resolvedFieldOffset +=
+                                resolvedField.getJavaKind().getByteCount() -
+                                Math.min(resolvedField.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
+            }
+            if (resolvedFieldOffset == offset) {
+                return field;
+            }
+            // @formatter:on
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isLocal() {
+        return mirror().isLocalClass();
+    }
+
+    @Override
+    public boolean isMember() {
+        return mirror().isMemberClass();
+    }
+
+    @Override
+    public HotSpotResolvedObjectTypeImpl getEnclosingType() {
+        final Class<?> encl = mirror().getEnclosingClass();
+        return encl == null ? null : fromObjectClass(encl);
+    }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredConstructors() {
+        Constructor<?>[] constructors = mirror().getDeclaredConstructors();
+        ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
+        for (int i = 0; i < constructors.length; i++) {
+            result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(constructors[i]);
+            assert result[i].isConstructor();
+        }
+        return result;
+    }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredMethods() {
+        Method[] methods = mirror().getDeclaredMethods();
+        ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
+        for (int i = 0; i < methods.length; i++) {
+            result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(methods[i]);
+            assert !result[i].isConstructor();
+        }
+        return result;
+    }
+
+    public ResolvedJavaMethod getClassInitializer() {
+        return compilerToVM().getClassInitializer(this);
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotType<" + getName() + ", resolved>";
+    }
+
+    @Override
+    public boolean isCloneableWithAllocation() {
+        return (getAccessFlags() & config().jvmAccIsCloneable) != 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static java.util.Objects.requireNonNull;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Modifier;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link JavaType} for primitive HotSpot types.
+ */
+public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType {
+
+    private final JavaKind kind;
+
+    /**
+     * Creates the JVMCI mirror for a primitive {@link JavaKind}.
+     *
+     * <p>
+     * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
+     * {@link Class} type. Use {@link HotSpotJVMCIRuntimeProvider#fromClass(Class)} instead.
+     * </p>
+     *
+     * @param kind the Kind to create the mirror for
+     */
+    public HotSpotResolvedPrimitiveType(JavaKind kind) {
+        super(String.valueOf(kind.getTypeChar()));
+        this.kind = kind;
+        assert mirror().isPrimitive() : mirror() + " not a primitive type";
+    }
+
+    @Override
+    public int getModifiers() {
+        return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
+    }
+
+    @Override
+    public HotSpotResolvedObjectTypeImpl getArrayClass() {
+        if (kind == JavaKind.Void) {
+            return null;
+        }
+        Class<?> javaArrayMirror = Array.newInstance(mirror(), 0).getClass();
+        return HotSpotResolvedObjectTypeImpl.fromObjectClass(javaArrayMirror);
+    }
+
+    public ResolvedJavaType getElementalType() {
+        return this;
+    }
+
+    @Override
+    public ResolvedJavaType getComponentType() {
+        return null;
+    }
+
+    @Override
+    public ResolvedJavaType getSuperclass() {
+        return null;
+    }
+
+    @Override
+    public ResolvedJavaType[] getInterfaces() {
+        return new ResolvedJavaType[0];
+    }
+
+    @Override
+    public ResolvedJavaType getSingleImplementor() {
+        throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
+    }
+
+    @Override
+    public ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType) {
+        return null;
+    }
+
+    @Override
+    public AssumptionResult<Boolean> hasFinalizableSubclass() {
+        return new AssumptionResult<>(false);
+    }
+
+    @Override
+    public boolean hasFinalizer() {
+        return false;
+    }
+
+    @Override
+    public boolean isArray() {
+        return false;
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return true;
+    }
+
+    @Override
+    public boolean isInitialized() {
+        return true;
+    }
+
+    public boolean isLinked() {
+        return true;
+    }
+
+    @Override
+    public boolean isInstance(JavaConstant obj) {
+        return false;
+    }
+
+    @Override
+    public boolean isInstanceClass() {
+        return false;
+    }
+
+    @Override
+    public boolean isInterface() {
+        return false;
+    }
+
+    @Override
+    public boolean isAssignableFrom(ResolvedJavaType other) {
+        assert other != null;
+        return other.equals(this);
+    }
+
+    @Override
+    public JavaKind getJavaKind() {
+        return kind;
+    }
+
+    @Override
+    public boolean isJavaLangObject() {
+        return false;
+    }
+
+    @Override
+    public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotResolvedPrimitiveType<" + kind + ">";
+    }
+
+    @Override
+    public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
+        return new AssumptionResult<>(this);
+    }
+
+    @Override
+    public AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method) {
+        return null;
+    }
+
+    @Override
+    public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
+        return new ResolvedJavaField[0];
+    }
+
+    @Override
+    public ResolvedJavaField[] getStaticFields() {
+        return new ResolvedJavaField[0];
+    }
+
+    @Override
+    public Annotation[] getAnnotations() {
+        return new Annotation[0];
+    }
+
+    @Override
+    public Annotation[] getDeclaredAnnotations() {
+        return new Annotation[0];
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        return null;
+    }
+
+    @Override
+    public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+        requireNonNull(accessingClass);
+        return this;
+    }
+
+    @Override
+    public void initialize() {
+    }
+
+    @Override
+    public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedType) {
+        return null;
+    }
+
+    @Override
+    public String getSourceFileName() {
+        throw JVMCIError.unimplemented();
+    }
+
+    @Override
+    public Class<?> mirror() {
+        return kind.toJavaClass();
+    }
+
+    @Override
+    public boolean isLocal() {
+        return false;
+    }
+
+    @Override
+    public boolean isMember() {
+        return false;
+    }
+
+    @Override
+    public ResolvedJavaType getEnclosingType() {
+        return null;
+    }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredConstructors() {
+        return new ResolvedJavaMethod[0];
+    }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredMethods() {
+        return new ResolvedJavaMethod[0];
+    }
+
+    @Override
+    public ResolvedJavaMethod getClassInitializer() {
+        return null;
+    }
+
+    @Override
+    public boolean isCloneableWithAllocation() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * 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 jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Implementation of {@link InstalledCode} for code installed as a RuntimeStub.
+ */
+public class HotSpotRuntimeStub extends HotSpotInstalledCode {
+
+    public HotSpotRuntimeStub(String name) {
+        super(name);
+    }
+
+    public ResolvedJavaMethod getMethod() {
+        return null;
+    }
+
+    @Override
+    public boolean isValid() {
+        return true;
+    }
+
+    @Override
+    public void invalidate() {
+    }
+
+    @Override
+    public String toString() {
+        return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", name, getAddress());
+    }
+
+    @Override
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        throw new InternalError("Cannot call stub " + name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ValueKind;
+import jdk.vm.ci.meta.VMConstant;
+import jdk.vm.ci.meta.Value;
+
+public final class HotSpotSentinelConstant extends Value implements JavaConstant, VMConstant {
+
+    private final JavaKind javaKind;
+
+    public HotSpotSentinelConstant(ValueKind<?> valueKind, JavaKind javaKind) {
+        super(valueKind);
+        this.javaKind = javaKind;
+    }
+
+    public JavaKind getJavaKind() {
+        return javaKind;
+    }
+
+    @Override
+    public boolean isNull() {
+        return true;
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return true;
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public int asInt() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public boolean asBoolean() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public long asLong() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public float asFloat() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public double asDouble() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public String toString() {
+        return JavaConstant.toString(this);
+    }
+
+    @Override
+    public String toValueString() {
+        return "sentinel";
+    }
+
+    @Override
+    public int hashCode() {
+        return 13;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof HotSpotSentinelConstant;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+
+/**
+ * Represents a method signature.
+ */
+public class HotSpotSignature implements Signature {
+
+    private final List<String> parameters = new ArrayList<>();
+    private final String returnType;
+    private final String originalString;
+    private ResolvedJavaType[] parameterTypes;
+    private ResolvedJavaType returnTypeCache;
+    private final HotSpotJVMCIRuntimeProvider runtime;
+
+    public HotSpotSignature(HotSpotJVMCIRuntimeProvider runtime, String signature) {
+        this.runtime = runtime;
+        assert signature.length() > 0;
+        this.originalString = signature;
+
+        if (signature.charAt(0) == '(') {
+            int cur = 1;
+            while (cur < signature.length() && signature.charAt(cur) != ')') {
+                int nextCur = parseSignature(signature, cur);
+                parameters.add(signature.substring(cur, nextCur));
+                cur = nextCur;
+            }
+
+            cur++;
+            int nextCur = parseSignature(signature, cur);
+            returnType = signature.substring(cur, nextCur);
+            assert nextCur == signature.length();
+        } else {
+            returnType = null;
+        }
+    }
+
+    public HotSpotSignature(HotSpotJVMCIRuntimeProvider runtime, ResolvedJavaType returnType, ResolvedJavaType... parameterTypes) {
+        this.runtime = runtime;
+        this.parameterTypes = parameterTypes.clone();
+        this.returnTypeCache = returnType;
+        this.returnType = returnType.getName();
+        StringBuilder sb = new StringBuilder("(");
+        for (JavaType type : parameterTypes) {
+            parameters.add(type.getName());
+            sb.append(type.getName());
+        }
+        sb.append(")").append(returnType.getName());
+        this.originalString = sb.toString();
+        assert new HotSpotSignature(runtime, originalString).equals(this);
+    }
+
+    private static int parseSignature(String signature, int start) {
+        int cur = start;
+        char first;
+        do {
+            first = signature.charAt(cur++);
+        } while (first == '[');
+
+        switch (first) {
+            case 'L':
+                while (signature.charAt(cur) != ';') {
+                    cur++;
+                }
+                cur++;
+                break;
+            case 'V':
+            case 'I':
+            case 'B':
+            case 'C':
+            case 'D':
+            case 'F':
+            case 'J':
+            case 'S':
+            case 'Z':
+                break;
+            default:
+                throw new JVMCIError("Invalid character at index %d in signature: %s", cur, signature);
+        }
+        return cur;
+    }
+
+    @Override
+    public int getParameterCount(boolean withReceiver) {
+        return parameters.size() + (withReceiver ? 1 : 0);
+    }
+
+    @Override
+    public JavaKind getParameterKind(int index) {
+        return JavaKind.fromTypeString(parameters.get(index));
+    }
+
+    private static boolean checkValidCache(ResolvedJavaType type, ResolvedJavaType accessingClass) {
+        assert accessingClass != null;
+        if (type == null) {
+            return false;
+        } else if (type instanceof HotSpotResolvedObjectTypeImpl) {
+            return ((HotSpotResolvedObjectTypeImpl) type).isDefinitelyResolvedWithRespectTo(accessingClass);
+        }
+        return true;
+    }
+
+    private static JavaType getUnresolvedOrPrimitiveType(HotSpotJVMCIRuntimeProvider runtime, String name) {
+        if (name.length() == 1) {
+            JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
+            return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(kind.toJavaClass());
+        }
+        return HotSpotUnresolvedJavaType.create(runtime, name);
+    }
+
+    @Override
+    public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
+        if (accessingClass == null) {
+            // Caller doesn't care about resolution context so return an unresolved
+            // or primitive type (primitive type resolution is context free)
+            return getUnresolvedOrPrimitiveType(runtime, parameters.get(index));
+        }
+        if (parameterTypes == null) {
+            parameterTypes = new ResolvedJavaType[parameters.size()];
+        }
+
+        ResolvedJavaType type = parameterTypes[index];
+        if (!checkValidCache(type, accessingClass)) {
+            JavaType result = runtime.lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, false);
+            if (result instanceof ResolvedJavaType) {
+                type = (ResolvedJavaType) result;
+                parameterTypes[index] = type;
+            } else {
+                return result;
+            }
+        }
+        return type;
+    }
+
+    @Override
+    public String toMethodDescriptor() {
+        assert originalString.equals(Signature.super.toMethodDescriptor());
+        return originalString;
+    }
+
+    @Override
+    public JavaKind getReturnKind() {
+        return JavaKind.fromTypeString(returnType);
+    }
+
+    @Override
+    public JavaType getReturnType(ResolvedJavaType accessingClass) {
+        if (accessingClass == null) {
+            // Caller doesn't care about resolution context so return an unresolved
+            // or primitive type (primitive type resolution is context free)
+            return getUnresolvedOrPrimitiveType(runtime, returnType);
+        }
+        if (!checkValidCache(returnTypeCache, accessingClass)) {
+            JavaType result = runtime.lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, false);
+            if (result instanceof ResolvedJavaType) {
+                returnTypeCache = (ResolvedJavaType) result;
+            } else {
+                return result;
+            }
+        }
+        return returnTypeCache;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotSignature<" + originalString + ">";
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof HotSpotSignature) {
+            HotSpotSignature other = (HotSpotSignature) obj;
+            if (other.originalString.equals(originalString)) {
+                assert other.parameters.equals(parameters);
+                assert other.returnType.equals(returnType);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return originalString.hashCode();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.SpeculationLog;
+
+public class HotSpotSpeculationLog implements SpeculationLog {
+
+    /** Written by the C++ code that performs deoptimization. */
+    private volatile Object lastFailed;
+
+    /** All speculations that have caused a deoptimization. */
+    private Set<SpeculationReason> failedSpeculations;
+
+    /** Strong references to all reasons embedded in the current nmethod. */
+    private volatile Collection<SpeculationReason> speculations;
+
+    @Override
+    public synchronized void collectFailedSpeculations() {
+        if (lastFailed != null) {
+            if (failedSpeculations == null) {
+                failedSpeculations = new HashSet<>(2);
+            }
+            failedSpeculations.add((SpeculationReason) lastFailed);
+            lastFailed = null;
+            speculations = null;
+        }
+    }
+
+    @Override
+    public synchronized boolean maySpeculate(SpeculationReason reason) {
+        if (failedSpeculations != null && failedSpeculations.contains(reason)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public JavaConstant speculate(SpeculationReason reason) {
+        assert maySpeculate(reason);
+
+        /*
+         * Objects referenced from nmethods are weak references. We need a strong reference to the
+         * reason objects that are embedded in nmethods, so we add them to the speculations
+         * collection.
+         */
+        if (speculations == null) {
+            synchronized (this) {
+                if (speculations == null) {
+                    speculations = new ConcurrentLinkedQueue<>();
+                }
+            }
+        }
+        speculations.add(reason);
+
+        return HotSpotObjectConstantImpl.forObject(reason);
+    }
+
+    @Override
+    public synchronized boolean hasSpeculations() {
+        return speculations != null && !speculations.isEmpty();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.Arrays;
+
+import jdk.vm.ci.code.stack.InspectedFrame;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class HotSpotStackFrameReference implements InspectedFrame {
+
+    private CompilerToVM compilerToVM;
+
+    // information used to find the stack frame
+    private long stackPointer;
+    private int frameNumber;
+
+    // information about the stack frame's contents
+    private int bci;
+    private HotSpotResolvedJavaMethod method;
+    private Object[] locals;
+    private boolean[] localIsVirtual;
+
+    public long getStackPointer() {
+        return stackPointer;
+    }
+
+    public int getFrameNumber() {
+        return frameNumber;
+    }
+
+    @Override
+    public Object getLocal(int index) {
+        return locals[index];
+    }
+
+    @Override
+    public boolean isVirtual(int index) {
+        return localIsVirtual == null ? false : localIsVirtual[index];
+    }
+
+    @Override
+    public void materializeVirtualObjects(boolean invalidateCode) {
+        compilerToVM.materializeVirtualObjects(this, invalidateCode);
+    }
+
+    @Override
+    public int getBytecodeIndex() {
+        return bci;
+    }
+
+    @Override
+    public ResolvedJavaMethod getMethod() {
+        return method;
+    }
+
+    @Override
+    public boolean isMethod(ResolvedJavaMethod otherMethod) {
+        return method.equals(otherMethod);
+    }
+
+    @Override
+    public boolean hasVirtualObjects() {
+        return localIsVirtual != null;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotStackFrameReference [stackPointer=" + stackPointer + ", frameNumber=" + frameNumber + ", bci=" + bci + ", method=" + getMethod() + ", locals=" + Arrays.toString(locals) +
+                        ", localIsVirtual=" + Arrays.toString(localIsVirtual) + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackIntrospection.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.stack.InspectedFrameVisitor;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class HotSpotStackIntrospection implements StackIntrospection {
+
+    protected final HotSpotJVMCIRuntimeProvider runtime;
+
+    public HotSpotStackIntrospection(HotSpotJVMCIRuntimeProvider runtime) {
+        this.runtime = runtime;
+    }
+
+    @Override
+    public <T> T iterateFrames(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip, InspectedFrameVisitor<T> visitor) {
+        CompilerToVM compilerToVM = runtime.getCompilerToVM();
+        HotSpotStackFrameReference current = compilerToVM.getNextStackFrame(null, initialMethods, initialSkip);
+        while (current != null) {
+            T result = visitor.visitFrame(current);
+            if (result != null) {
+                return result;
+            }
+            current = compilerToVM.getNextStackFrame(current, matchingMethods, 0);
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaField;
+import jdk.vm.ci.meta.JavaType;
+
+/**
+ * A implementation of {@link JavaField} for an unresolved field.
+ */
+class HotSpotUnresolvedField implements JavaField {
+
+    private final String name;
+    private final JavaType holder;
+    private final JavaType type;
+
+    HotSpotUnresolvedField(JavaType holder, String name, JavaType type) {
+        this.name = name;
+        this.type = type;
+        this.holder = holder;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public JavaType getType() {
+        return type;
+    }
+
+    public JavaType getDeclaringClass() {
+        return holder;
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || !(obj instanceof HotSpotUnresolvedField)) {
+            return false;
+        }
+        HotSpotUnresolvedField that = (HotSpotUnresolvedField) obj;
+        return this.holder.equals(that.holder) && this.name.equals(that.name) && this.type.equals(that.type);
+    }
+
+    /**
+     * Converts this compiler interface field to a string.
+     */
+    @Override
+    public String toString() {
+        return format("HotSpotField<%H.%n %t, unresolved>");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link JavaType} for unresolved HotSpot classes.
+ */
+final class HotSpotUnresolvedJavaType extends HotSpotJavaType {
+
+    private final HotSpotJVMCIRuntimeProvider runtime;
+
+    private HotSpotUnresolvedJavaType(String name, HotSpotJVMCIRuntimeProvider runtime) {
+        super(name);
+        assert name.charAt(0) == '[' || name.charAt(name.length() - 1) == ';' : name;
+        this.runtime = runtime;
+    }
+
+    /**
+     * Creates an unresolved type for a valid {@link JavaType#getName() type name}.
+     */
+    static HotSpotUnresolvedJavaType create(HotSpotJVMCIRuntimeProvider runtime, String name) {
+        return new HotSpotUnresolvedJavaType(name, runtime);
+    }
+
+    @Override
+    public JavaType getComponentType() {
+        assert getName().charAt(0) == '[' : "no array class" + getName();
+        return new HotSpotUnresolvedJavaType(getName().substring(1), runtime);
+    }
+
+    @Override
+    public JavaType getArrayClass() {
+        return new HotSpotUnresolvedJavaType('[' + getName(), runtime);
+    }
+
+    @Override
+    public JavaKind getJavaKind() {
+        return JavaKind.Object;
+    }
+
+    @Override
+    public int hashCode() {
+        return getName().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || !(obj instanceof HotSpotUnresolvedJavaType)) {
+            return false;
+        }
+        HotSpotUnresolvedJavaType that = (HotSpotUnresolvedJavaType) obj;
+        return this.getName().equals(that.getName());
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotType<" + getName() + ", unresolved>";
+    }
+
+    @Override
+    public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+        return (ResolvedJavaType) runtime.lookupType(getName(), (HotSpotResolvedObjectType) accessingClass, true);
+    }
+
+    /**
+     * Try to find a loaded version of this class.
+     *
+     * @param accessingClass
+     * @return the resolved class or null.
+     */
+    ResolvedJavaType reresolve(HotSpotResolvedObjectType accessingClass) {
+        JavaType type = runtime.lookupType(getName(), accessingClass, false);
+        if (type instanceof ResolvedJavaType) {
+            return (ResolvedJavaType) type;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import sun.misc.Unsafe;
+
+/**
+ * Used to access native configuration details.
+ */
+class HotSpotVMConfig extends HotSpotVMConfigAccess {
+
+    static HotSpotVMConfig config() {
+        return HotSpotJVMCIRuntime.runtime().getConfig();
+    }
+
+    private final String osArch = getHostArchitectureName();
+
+    @SuppressWarnings("try")
+    HotSpotVMConfig(HotSpotVMConfigStore store) {
+        super(store);
+    }
+
+    /**
+     * Gets the host architecture name for the purpose of finding the corresponding
+     * {@linkplain HotSpotJVMCIBackendFactory backend}.
+     */
+    String getHostArchitectureName() {
+        String arch = System.getProperty("os.arch");
+        if (arch.equals("x86_64")) {
+            arch = "amd64";
+        } else if (arch.equals("sparcv9")) {
+            arch = "sparc";
+        }
+        return arch;
+    }
+
+    private final Integer amd64RequiredInt = osArch.equals("amd64") ? null : 0;
+
+    // Compressed Oops related values.
+    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
+
+    final int prototypeMarkWordOffset = getFieldOffset("Klass::_prototype_header", Integer.class, "markOop");
+    final int subklassOffset = getFieldOffset("Klass::_subklass", Integer.class, "Klass*");
+    final int nextSiblingOffset = getFieldOffset("Klass::_next_sibling", Integer.class, "Klass*");
+    final int superCheckOffsetOffset = getFieldOffset("Klass::_super_check_offset", Integer.class, "juint");
+    final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*");
+
+    final int classMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "oop");
+
+    final int klassAccessFlagsOffset = getFieldOffset("Klass::_access_flags", Integer.class, "AccessFlags");
+    final int klassLayoutHelperOffset = getFieldOffset("Klass::_layout_helper", Integer.class, "jint");
+
+    final int klassLayoutHelperNeutralValue = getConstant("Klass::_lh_neutral_value", Integer.class);
+    final int klassLayoutHelperInstanceSlowPathBit = getConstant("Klass::_lh_instance_slow_path_bit", Integer.class);
+
+    final int arrayKlassComponentMirrorOffset = getFieldOffset("ArrayKlass::_component_mirror", Integer.class, "oop");
+
+    final int vtableEntrySize = getFieldValue("CompilerToVM::Data::sizeof_vtableEntry", Integer.class, "int");
+    final int vtableEntryMethodOffset = getFieldOffset("vtableEntry::_method", Integer.class, "Method*");
+
+    final int arrayU1LengthOffset = getFieldOffset("Array<int>::_length", Integer.class, "int");
+    final int arrayU1DataOffset = getFieldOffset("Array<u1>::_data", Integer.class);
+    final int arrayU2DataOffset = getFieldOffset("Array<u2>::_data", Integer.class);
+
+    final int instanceKlassSourceFileNameIndexOffset = getFieldOffset("InstanceKlass::_source_file_name_index", Integer.class, "u2");
+    final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
+    final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
+    final int instanceKlassFieldsOffset = getFieldOffset("InstanceKlass::_fields", Integer.class, "Array<u2>*");
+
+    final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
+    final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
+
+    final int fieldInfoAccessFlagsOffset = getConstant("FieldInfo::access_flags_offset", Integer.class);
+    final int fieldInfoNameIndexOffset = getConstant("FieldInfo::name_index_offset", Integer.class);
+    final int fieldInfoSignatureIndexOffset = getConstant("FieldInfo::signature_index_offset", Integer.class);
+    final int fieldInfoLowPackedOffset = getConstant("FieldInfo::low_packed_offset", Integer.class);
+    final int fieldInfoHighPackedOffset = getConstant("FieldInfo::high_packed_offset", Integer.class);
+    final int fieldInfoFieldSlots = getConstant("FieldInfo::field_slots", Integer.class);
+
+    final int fieldInfoTagSize = getConstant("FIELDINFO_TAG_SIZE", Integer.class);
+
+    final int jvmAccFieldInternal = getConstant("JVM_ACC_FIELD_INTERNAL", Integer.class);
+    final int jvmAccFieldStable = getConstant("JVM_ACC_FIELD_STABLE", Integer.class);
+    final int jvmAccFieldHasGenericSignature = getConstant("JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE", Integer.class);
+    final int jvmAccIsCloneable = getConstant("JVM_ACC_IS_CLONEABLE", Integer.class);
+
+    // These modifiers are not public in Modifier so we get them via vmStructs.
+    final int jvmAccSynthetic = getConstant("JVM_ACC_SYNTHETIC", Integer.class);
+    final int jvmAccAnnotation = getConstant("JVM_ACC_ANNOTATION", Integer.class);
+    final int jvmAccBridge = getConstant("JVM_ACC_BRIDGE", Integer.class);
+    final int jvmAccVarargs = getConstant("JVM_ACC_VARARGS", Integer.class);
+    final int jvmAccEnum = getConstant("JVM_ACC_ENUM", Integer.class);
+
+    final int runtimeCallStackSize = getConstant("frame::arg_reg_save_area_bytes", Integer.class, amd64RequiredInt);
+    final int markWordNoHashInPlace = getConstant("markOopDesc::no_hash_in_place", Integer.class);
+    final int markWordNoLockInPlace = getConstant("markOopDesc::no_lock_in_place", Integer.class);
+
+    long arrayPrototypeMarkWord() {
+        return markWordNoHashInPlace | markWordNoLockInPlace;
+    }
+
+    final int methodAccessFlagsOffset = getFieldOffset("Method::_access_flags", Integer.class, "AccessFlags");
+    final int methodConstMethodOffset = getFieldOffset("Method::_constMethod", Integer.class, "ConstMethod*");
+    final int methodIntrinsicIdOffset = getFieldOffset("Method::_intrinsic_id", Integer.class, "u1");
+    final int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, "u1");
+    final int methodVtableIndexOffset = getFieldOffset("Method::_vtable_index", Integer.class, "int");
+
+    final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class);
+    final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class);
+    final int methodFlagsDontInline = getConstant("Method::_dont_inline", Integer.class);
+    final int nonvirtualVtableIndex = getConstant("Method::nonvirtual_vtable_index", Integer.class);
+    final int invalidVtableIndex = getConstant("Method::invalid_vtable_index", Integer.class);
+
+    final int invocationEntryBci = getConstant("InvocationEntryBci", Integer.class);
+
+    final int extraStackEntries = getFieldValue("CompilerToVM::Data::Method_extra_stack_entries", Integer.class, "int");
+
+    final int constMethodConstantsOffset = getFieldOffset("ConstMethod::_constants", Integer.class, "ConstantPool*");
+    final int constMethodFlagsOffset = getFieldOffset("ConstMethod::_flags", Integer.class, "u2");
+    final int constMethodCodeSizeOffset = getFieldOffset("ConstMethod::_code_size", Integer.class, "u2");
+    final int constMethodNameIndexOffset = getFieldOffset("ConstMethod::_name_index", Integer.class, "u2");
+    final int constMethodSignatureIndexOffset = getFieldOffset("ConstMethod::_signature_index", Integer.class, "u2");
+    final int constMethodMaxStackOffset = getFieldOffset("ConstMethod::_max_stack", Integer.class, "u2");
+    final int methodMaxLocalsOffset = getFieldOffset("ConstMethod::_max_locals", Integer.class, "u2");
+
+    final int constMethodHasLineNumberTable = getConstant("ConstMethod::_has_linenumber_table", Integer.class);
+    final int constMethodHasLocalVariableTable = getConstant("ConstMethod::_has_localvariable_table", Integer.class);
+    final int constMethodHasExceptionTable = getConstant("ConstMethod::_has_exception_table", Integer.class);
+
+    final int exceptionTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_ExceptionTableElement", Integer.class, "int");
+    final int exceptionTableElementStartPcOffset = getFieldOffset("ExceptionTableElement::start_pc", Integer.class, "u2");
+    final int exceptionTableElementEndPcOffset = getFieldOffset("ExceptionTableElement::end_pc", Integer.class, "u2");
+    final int exceptionTableElementHandlerPcOffset = getFieldOffset("ExceptionTableElement::handler_pc", Integer.class, "u2");
+    final int exceptionTableElementCatchTypeIndexOffset = getFieldOffset("ExceptionTableElement::catch_type_index", Integer.class, "u2");
+
+    final int localVariableTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_LocalVariableTableElement", Integer.class, "int");
+    final int localVariableTableElementStartBciOffset = getFieldOffset("LocalVariableTableElement::start_bci", Integer.class, "u2");
+    final int localVariableTableElementLengthOffset = getFieldOffset("LocalVariableTableElement::length", Integer.class, "u2");
+    final int localVariableTableElementNameCpIndexOffset = getFieldOffset("LocalVariableTableElement::name_cp_index", Integer.class, "u2");
+    final int localVariableTableElementDescriptorCpIndexOffset = getFieldOffset("LocalVariableTableElement::descriptor_cp_index", Integer.class, "u2");
+    final int localVariableTableElementSlotOffset = getFieldOffset("LocalVariableTableElement::slot", Integer.class, "u2");
+
+    final int constantPoolSize = getFieldValue("CompilerToVM::Data::sizeof_ConstantPool", Integer.class, "int");
+    final int constantPoolTagsOffset = getFieldOffset("ConstantPool::_tags", Integer.class, "Array<u1>*");
+    final int constantPoolHolderOffset = getFieldOffset("ConstantPool::_pool_holder", Integer.class, "InstanceKlass*");
+    final int constantPoolLengthOffset = getFieldOffset("ConstantPool::_length", Integer.class, "int");
+
+    final int constantPoolCpCacheIndexTag = getConstant("ConstantPool::CPCACHE_INDEX_TAG", Integer.class);
+
+    final int jvmConstantUtf8 = getConstant("JVM_CONSTANT_Utf8", Integer.class);
+    final int jvmConstantInteger = getConstant("JVM_CONSTANT_Integer", Integer.class);
+    final int jvmConstantLong = getConstant("JVM_CONSTANT_Long", Integer.class);
+    final int jvmConstantFloat = getConstant("JVM_CONSTANT_Float", Integer.class);
+    final int jvmConstantDouble = getConstant("JVM_CONSTANT_Double", Integer.class);
+    final int jvmConstantClass = getConstant("JVM_CONSTANT_Class", Integer.class);
+    final int jvmConstantUnresolvedClass = getConstant("JVM_CONSTANT_UnresolvedClass", Integer.class);
+    final int jvmConstantUnresolvedClassInError = getConstant("JVM_CONSTANT_UnresolvedClassInError", Integer.class);
+    final int jvmConstantString = getConstant("JVM_CONSTANT_String", Integer.class);
+    final int jvmConstantFieldref = getConstant("JVM_CONSTANT_Fieldref", Integer.class);
+    final int jvmConstantMethodref = getConstant("JVM_CONSTANT_Methodref", Integer.class);
+    final int jvmConstantInterfaceMethodref = getConstant("JVM_CONSTANT_InterfaceMethodref", Integer.class);
+    final int jvmConstantNameAndType = getConstant("JVM_CONSTANT_NameAndType", Integer.class);
+    final int jvmConstantMethodHandle = getConstant("JVM_CONSTANT_MethodHandle", Integer.class);
+    final int jvmConstantMethodHandleInError = getConstant("JVM_CONSTANT_MethodHandleInError", Integer.class);
+    final int jvmConstantMethodType = getConstant("JVM_CONSTANT_MethodType", Integer.class);
+    final int jvmConstantMethodTypeInError = getConstant("JVM_CONSTANT_MethodTypeInError", Integer.class);
+    final int jvmConstantInvokeDynamic = getConstant("JVM_CONSTANT_InvokeDynamic", Integer.class);
+
+    final int jvmConstantExternalMax = getConstant("JVM_CONSTANT_ExternalMax", Integer.class);
+    final int jvmConstantInternalMin = getConstant("JVM_CONSTANT_InternalMin", Integer.class);
+    final int jvmConstantInternalMax = getConstant("JVM_CONSTANT_InternalMax", Integer.class);
+
+    final int heapWordSize = getConstant("HeapWordSize", Integer.class);
+
+    final int symbolPointerSize = getFieldValue("CompilerToVM::Data::sizeof_SymbolPointer", Integer.class, "int");
+
+    final long vmSymbolsSymbols = getFieldAddress("vmSymbols::_symbols[0]", "Symbol*");
+    final int vmSymbolsFirstSID = getConstant("vmSymbols::FIRST_SID", Integer.class);
+    final int vmSymbolsSIDLimit = getConstant("vmSymbols::SID_LIMIT", Integer.class);
+
+    final long symbolInit = getFieldValue("CompilerToVM::Data::symbol_init", Long.class);
+    final long symbolClinit = getFieldValue("CompilerToVM::Data::symbol_clinit", Long.class);
+
+    /**
+     * Returns the symbol in the {@code vmSymbols} table at position {@code index} as a
+     * {@link String}.
+     *
+     * @param index position in the symbol table
+     * @return the symbol at position id
+     */
+    String symbolAt(int index) {
+        HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
+        assert vmSymbolsFirstSID <= index && index < vmSymbolsSIDLimit : "index " + index + " is out of bounds";
+        assert symbolPointerSize == Unsafe.ADDRESS_SIZE : "the following address read is broken";
+        int offset = index * symbolPointerSize;
+        return runtime.getCompilerToVM().getSymbol(UNSAFE.getAddress(vmSymbolsSymbols + offset));
+    }
+
+    final int klassHasFinalizerFlag = getConstant("JVM_ACC_HAS_FINALIZER", Integer.class);
+
+    final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
+    final int klassVtableLengthOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_length_offset", Integer.class, "int");
+    final int universeBaseVtableSize = getFieldValue("CompilerToVM::Data::Universe_base_vtable_size", Integer.class, "int");
+
+    final int baseVtableLength() {
+        return universeBaseVtableSize / (vtableEntrySize / heapWordSize);
+    }
+
+    final int klassOffset = getFieldValue("java_lang_Class::_klass_offset", Integer.class, "int");
+
+    final int methodDataOffset = getFieldOffset("Method::_method_data", Integer.class, "MethodData*");
+    final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, "nmethod*");
+
+    final int methodDataSize = getFieldOffset("MethodData::_size", Integer.class, "int");
+    final int methodDataDataSize = getFieldOffset("MethodData::_data_size", Integer.class, "int");
+    final int methodDataOopDataOffset = getFieldOffset("MethodData::_data[0]", Integer.class, "intptr_t");
+    final int methodDataOopTrapHistoryOffset = getFieldOffset("MethodData::_trap_hist._array[0]", Integer.class, "u1");
+    final int methodDataIRSizeOffset = getFieldOffset("MethodData::_jvmci_ir_size", Integer.class, "int");
+
+    final int methodDataDecompiles = getFieldOffset("MethodData::_nof_decompiles", Integer.class, "uint");
+    final int methodDataOverflowRecompiles = getFieldOffset("MethodData::_nof_overflow_recompiles", Integer.class, "uint");
+    final int methodDataOverflowTraps = getFieldOffset("MethodData::_nof_overflow_traps", Integer.class, "uint");
+
+    final int nmethodCompLevelOffset = getFieldOffset("nmethod::_comp_level", Integer.class, "int");
+
+    final int compilationLevelNone = getConstant("CompLevel_none", Integer.class);
+    final int compilationLevelSimple = getConstant("CompLevel_simple", Integer.class);
+    final int compilationLevelLimitedProfile = getConstant("CompLevel_limited_profile", Integer.class);
+    final int compilationLevelFullProfile = getConstant("CompLevel_full_profile", Integer.class);
+    final int compilationLevelFullOptimization = getConstant("CompLevel_full_optimization", Integer.class);
+
+    final int compLevelAdjustmentNone = getConstant("JVMCIRuntime::none", Integer.class);
+    final int compLevelAdjustmentByHolder = getConstant("JVMCIRuntime::by_holder", Integer.class);
+    final int compLevelAdjustmentByFullSignature = getConstant("JVMCIRuntime::by_full_signature", Integer.class);
+
+    /**
+     * The DataLayout header size is the same as the cell size.
+     */
+    final int dataLayoutHeaderSize = getConstant("DataLayout::cell_size", Integer.class);
+    final int dataLayoutTagOffset = getFieldOffset("DataLayout::_header._struct._tag", Integer.class, "u1");
+    final int dataLayoutFlagsOffset = getFieldOffset("DataLayout::_header._struct._flags", Integer.class, "u1");
+    final int dataLayoutBCIOffset = getFieldOffset("DataLayout::_header._struct._bci", Integer.class, "u2");
+    final int dataLayoutCellSize = getConstant("DataLayout::cell_size", Integer.class);
+
+    final int dataLayoutNoTag = getConstant("DataLayout::no_tag", Integer.class);
+    final int dataLayoutBitDataTag = getConstant("DataLayout::bit_data_tag", Integer.class);
+    final int dataLayoutCounterDataTag = getConstant("DataLayout::counter_data_tag", Integer.class);
+    final int dataLayoutJumpDataTag = getConstant("DataLayout::jump_data_tag", Integer.class);
+    final int dataLayoutReceiverTypeDataTag = getConstant("DataLayout::receiver_type_data_tag", Integer.class);
+    final int dataLayoutVirtualCallDataTag = getConstant("DataLayout::virtual_call_data_tag", Integer.class);
+    final int dataLayoutRetDataTag = getConstant("DataLayout::ret_data_tag", Integer.class);
+    final int dataLayoutBranchDataTag = getConstant("DataLayout::branch_data_tag", Integer.class);
+    final int dataLayoutMultiBranchDataTag = getConstant("DataLayout::multi_branch_data_tag", Integer.class);
+    final int dataLayoutArgInfoDataTag = getConstant("DataLayout::arg_info_data_tag", Integer.class);
+    final int dataLayoutCallTypeDataTag = getConstant("DataLayout::call_type_data_tag", Integer.class);
+    final int dataLayoutVirtualCallTypeDataTag = getConstant("DataLayout::virtual_call_type_data_tag", Integer.class);
+    final int dataLayoutParametersTypeDataTag = getConstant("DataLayout::parameters_type_data_tag", Integer.class);
+    final int dataLayoutSpeculativeTrapDataTag = getConstant("DataLayout::speculative_trap_data_tag", Integer.class);
+
+    final int bciProfileWidth = getFlag("BciProfileWidth", Integer.class);
+    final int typeProfileWidth = getFlag("TypeProfileWidth", Integer.class);
+    final int methodProfileWidth = getFlag("MethodProfileWidth", Integer.class);
+
+    final int deoptReasonNone = getConstant("Deoptimization::Reason_none", Integer.class);
+    final int deoptReasonNullCheck = getConstant("Deoptimization::Reason_null_check", Integer.class);
+    final int deoptReasonRangeCheck = getConstant("Deoptimization::Reason_range_check", Integer.class);
+    final int deoptReasonClassCheck = getConstant("Deoptimization::Reason_class_check", Integer.class);
+    final int deoptReasonArrayCheck = getConstant("Deoptimization::Reason_array_check", Integer.class);
+    final int deoptReasonUnreached0 = getConstant("Deoptimization::Reason_unreached0", Integer.class);
+    final int deoptReasonTypeCheckInlining = getConstant("Deoptimization::Reason_type_checked_inlining", Integer.class);
+    final int deoptReasonOptimizedTypeCheck = getConstant("Deoptimization::Reason_optimized_type_check", Integer.class);
+    final int deoptReasonNotCompiledExceptionHandler = getConstant("Deoptimization::Reason_not_compiled_exception_handler", Integer.class);
+    final int deoptReasonUnresolved = getConstant("Deoptimization::Reason_unresolved", Integer.class);
+    final int deoptReasonJsrMismatch = getConstant("Deoptimization::Reason_jsr_mismatch", Integer.class);
+    final int deoptReasonDiv0Check = getConstant("Deoptimization::Reason_div0_check", Integer.class);
+    final int deoptReasonConstraint = getConstant("Deoptimization::Reason_constraint", Integer.class);
+    final int deoptReasonLoopLimitCheck = getConstant("Deoptimization::Reason_loop_limit_check", Integer.class);
+    final int deoptReasonAliasing = getConstant("Deoptimization::Reason_aliasing", Integer.class);
+    final int deoptReasonTransferToInterpreter = getConstant("Deoptimization::Reason_transfer_to_interpreter", Integer.class);
+    final int deoptReasonOSROffset = getConstant("Deoptimization::Reason_LIMIT", Integer.class);
+
+    final int deoptActionNone = getConstant("Deoptimization::Action_none", Integer.class);
+    final int deoptActionMaybeRecompile = getConstant("Deoptimization::Action_maybe_recompile", Integer.class);
+    final int deoptActionReinterpret = getConstant("Deoptimization::Action_reinterpret", Integer.class);
+    final int deoptActionMakeNotEntrant = getConstant("Deoptimization::Action_make_not_entrant", Integer.class);
+    final int deoptActionMakeNotCompilable = getConstant("Deoptimization::Action_make_not_compilable", Integer.class);
+
+    final int deoptimizationActionBits = getConstant("Deoptimization::_action_bits", Integer.class);
+    final int deoptimizationReasonBits = getConstant("Deoptimization::_reason_bits", Integer.class);
+    final int deoptimizationDebugIdBits = getConstant("Deoptimization::_debug_id_bits", Integer.class);
+    final int deoptimizationActionShift = getConstant("Deoptimization::_action_shift", Integer.class);
+    final int deoptimizationReasonShift = getConstant("Deoptimization::_reason_shift", Integer.class);
+    final int deoptimizationDebugIdShift = getConstant("Deoptimization::_debug_id_shift", Integer.class);
+
+    final int vmIntrinsicInvokeBasic = getConstant("vmIntrinsics::_invokeBasic", Integer.class);
+    final int vmIntrinsicLinkToVirtual = getConstant("vmIntrinsics::_linkToVirtual", Integer.class);
+    final int vmIntrinsicLinkToStatic = getConstant("vmIntrinsics::_linkToStatic", Integer.class);
+    final int vmIntrinsicLinkToSpecial = getConstant("vmIntrinsics::_linkToSpecial", Integer.class);
+    final int vmIntrinsicLinkToInterface = getConstant("vmIntrinsics::_linkToInterface", Integer.class);
+
+    final int codeInstallResultOk = getConstant("JVMCIEnv::ok", Integer.class);
+    final int codeInstallResultDependenciesFailed = getConstant("JVMCIEnv::dependencies_failed", Integer.class);
+    final int codeInstallResultDependenciesInvalid = getConstant("JVMCIEnv::dependencies_invalid", Integer.class);
+    final int codeInstallResultCacheFull = getConstant("JVMCIEnv::cache_full", Integer.class);
+    final int codeInstallResultCodeTooLarge = getConstant("JVMCIEnv::code_too_large", Integer.class);
+
+    String getCodeInstallResultDescription(int codeInstallResult) {
+        if (codeInstallResult == codeInstallResultOk) {
+            return "ok";
+        }
+        if (codeInstallResult == codeInstallResultDependenciesFailed) {
+            return "dependencies failed";
+        }
+        if (codeInstallResult == codeInstallResultDependenciesInvalid) {
+            return "dependencies invalid";
+        }
+        if (codeInstallResult == codeInstallResultCacheFull) {
+            return "code cache is full";
+        }
+        if (codeInstallResult == codeInstallResultCodeTooLarge) {
+            return "code is too large";
+        }
+        assert false : codeInstallResult;
+        return "unknown";
+    }
+
+    final int bitDataExceptionSeenFlag = getConstant("BitData::exception_seen_flag", Integer.class);
+    final int bitDataNullSeenFlag = getConstant("BitData::null_seen_flag", Integer.class);
+    final int methodDataCountOffset = getConstant("CounterData::count_off", Integer.class);
+    final int jumpDataTakenOffset = getConstant("JumpData::taken_off_set", Integer.class);
+    final int jumpDataDisplacementOffset = getConstant("JumpData::displacement_off_set", Integer.class);
+    final int receiverTypeDataNonprofiledCountOffset = getConstant("ReceiverTypeData::nonprofiled_count_off_set", Integer.class);
+    final int receiverTypeDataReceiverTypeRowCellCount = getConstant("ReceiverTypeData::receiver_type_row_cell_count", Integer.class);
+    final int receiverTypeDataReceiver0Offset = getConstant("ReceiverTypeData::receiver0_offset", Integer.class);
+    final int receiverTypeDataCount0Offset = getConstant("ReceiverTypeData::count0_offset", Integer.class);
+    final int branchDataNotTakenOffset = getConstant("BranchData::not_taken_off_set", Integer.class);
+    final int arrayDataArrayLenOffset = getConstant("ArrayData::array_len_off_set", Integer.class);
+    final int arrayDataArrayStartOffset = getConstant("ArrayData::array_start_off_set", Integer.class);
+    final int multiBranchDataPerCaseCellCount = getConstant("MultiBranchData::per_case_cell_count", Integer.class);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.common.JVMCIError;
+
+/**
+ * Access to VM configuration data.
+ */
+public class HotSpotVMConfigAccess {
+
+    /**
+     * Gets the available configuration data.
+     */
+    public HotSpotVMConfigStore getStore() {
+        return store;
+    }
+
+    /**
+     * Gets the address of a C++ symbol.
+     *
+     * @param name name of C++ symbol
+     * @param notPresent if non-null and the symbol is not present then this value is returned
+     * @return the address of the symbol
+     * @throws JVMCIError if the symbol is not present and {@code notPresent == null}
+     */
+    public long getAddress(String name, Long notPresent) {
+        Long entry = store.vmAddresses.get(name);
+        if (entry == null) {
+            if (notPresent != null) {
+                return notPresent;
+            }
+            throw new JVMCIError("expected VM symbol not found: " + name);
+        }
+        return entry;
+    }
+
+    /**
+     * Gets the address of a C++ symbol.
+     *
+     * @param name name of C++ symbol
+     * @return the address of the symbol
+     * @throws JVMCIError if the symbol is not present
+     */
+    public long getAddress(String name) {
+        return getAddress(name, null);
+    }
+
+    /**
+     * Gets the value of a C++ constant.
+     *
+     * @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"})
+     * @param type the boxed type to which the constant value will be converted
+     * @param notPresent if non-null and the constant is not present then this value is returned
+     * @return the constant value converted to {@code type}
+     * @throws JVMCIError if the constant is not present and {@code notPresent == null}
+     */
+    public <T> T getConstant(String name, Class<T> type, T notPresent) {
+        Long c = store.vmConstants.get(name);
+        if (c == null) {
+            if (notPresent != null) {
+                return notPresent;
+            }
+            throw new JVMCIError("expected VM constant not found: " + name);
+        }
+        return type.cast(convertValue(name, type, c, null));
+    }
+
+    /**
+     * Gets the value of a C++ constant.
+     *
+     * @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"})
+     * @param type the boxed type to which the constant value will be converted
+     * @return the constant value converted to {@code type}
+     * @throws JVMCIError if the constant is not present
+     */
+    public <T> T getConstant(String name, Class<T> type) {
+        return getConstant(name, type, null);
+    }
+
+    /**
+     * Gets the offset of a non-static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the offset value will be converted (must be
+     *            {@link Integer} or {@link Long})
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @return the offset in bytes of the requested field
+     * @throws JVMCIError if the field is static or not present and {@code notPresent} is null
+     */
+    public <T> T getFieldOffset(String name, Class<T> type, String cppType, T notPresent) {
+        assert type == Integer.class || type == Long.class;
+        VMField entry = getField(name, cppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.address != 0) {
+            throw new JVMCIError("cannot get offset of static field " + name);
+        }
+        return type.cast(convertValue(name, type, entry.offset, cppType));
+    }
+
+    /**
+     * Gets the offset of a non-static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the offset value will be converted (must be
+     *            {@link Integer} or {@link Long})
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @return the offset in bytes of the requested field
+     * @throws JVMCIError if the field is static or not present
+     */
+    public <T> T getFieldOffset(String name, Class<T> type, String cppType) {
+        return getFieldOffset(name, type, cppType, null);
+    }
+
+    /**
+     * Gets the offset of a non-static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the offset value will be converted (must be
+     *            {@link Integer} or {@link Long})
+     * @return the offset in bytes of the requested field
+     * @throws JVMCIError if the field is static or not present
+     */
+    public <T> T getFieldOffset(String name, Class<T> type) {
+        return getFieldOffset(name, type, null, null);
+    }
+
+    /**
+     * Gets the address of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @return the address of the requested field
+     * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
+     */
+    public long getFieldAddress(String name, String cppType, Long notPresent) {
+        VMField entry = getField(name, cppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.address == 0) {
+            throw new JVMCIError(name + " is not a static field");
+        }
+        return entry.address;
+    }
+
+    /**
+     * Gets the address of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @return the address of the requested field
+     * @throws JVMCIError if the field is not static or not present
+     */
+    public long getFieldAddress(String name, String cppType) {
+        return getFieldAddress(name, cppType, null);
+    }
+
+    /**
+     * Gets the value of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the constant value will be converted
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @return the value of the requested field
+     * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
+     */
+    public <T> T getFieldValue(String name, Class<T> type, String cppType, T notPresent) {
+        VMField entry = getField(name, cppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.value == null) {
+            throw new JVMCIError(name + " is not a static field");
+        }
+        return type.cast(convertValue(name, type, entry.value, cppType));
+    }
+
+    /**
+     * Gets the value of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the constant value will be converted
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @return the value of the requested field
+     * @throws JVMCIError if the field is not static or not present
+     */
+    public <T> T getFieldValue(String name, Class<T> type, String cppType) {
+        return getFieldValue(name, type, cppType, null);
+    }
+
+    /**
+     * Gets the value of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the constant value will be converted
+     * @return the value of the requested field
+     * @throws JVMCIError if the field is not static or not present
+     */
+    public <T> T getFieldValue(String name, Class<T> type) {
+        return getFieldValue(name, type, null, null);
+    }
+
+    /**
+     * Gets a C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @param required specifies if the field must be present
+     * @return the field
+     * @throws JVMCIError if the field is not present and {@code required == true}
+     */
+    private VMField getField(String name, String cppType, boolean required) {
+        VMField entry = store.vmFields.get(name);
+        if (entry == null) {
+            if (!required) {
+                return null;
+            }
+            throw new JVMCIError("expected VM field not found: " + name);
+        }
+
+        // Make sure the native type is still the type we expect.
+        if (cppType != null && !cppType.equals(entry.type)) {
+            throw new JVMCIError("expected type " + cppType + " but VM field " + name + " is of type " + entry.type);
+        }
+        return entry;
+    }
+
+    /**
+     * Gets a VM flag value.
+     *
+     * @param name name of the flag (e.g., {@code "CompileTheWorldStartAt"})
+     * @param type the boxed type to which the flag's value will be converted
+     * @return the flag's value converted to {@code type} or {@code notPresent} if the flag is not
+     *         present
+     * @throws JVMCIError if the flag is not present
+     */
+    public <T> T getFlag(String name, Class<T> type) {
+        return getFlag(name, type, null);
+    }
+
+    /**
+     * Gets a VM flag value.
+     *
+     * @param name name of the flag (e.g., {@code "CompileTheWorldStartAt"})
+     * @param type the boxed type to which the flag's value will be converted
+     * @param notPresent if non-null and the flag is not present then this value is returned
+     * @return the flag's value converted to {@code type} or {@code notPresent} if the flag is not
+     *         present
+     * @throws JVMCIError if the flag is not present and {@code notPresent == null}
+     */
+    public <T> T getFlag(String name, Class<T> type, T notPresent) {
+        VMFlag entry = store.vmFlags.get(name);
+        Object value;
+        String cppType;
+        if (entry == null) {
+            // Fall back to VM call
+            value = store.compilerToVm.getFlagValue(name);
+            if (value == store.compilerToVm) {
+                if (notPresent != null) {
+                    return notPresent;
+                }
+                throw new JVMCIError("expected VM flag not found: " + name);
+            } else {
+                cppType = null;
+            }
+        } else {
+            value = entry.value;
+            cppType = entry.type;
+        }
+        return type.cast(convertValue(name, type, value, cppType));
+    }
+
+    private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError {
+        if (toType == Boolean.class) {
+            if (value instanceof String) {
+                return Boolean.valueOf((String) value);
+            } else if (value instanceof Boolean) {
+                return value;
+            } else if (value instanceof Long) {
+                return ((long) value) != 0;
+            }
+        } else if (toType == Byte.class) {
+            if (value instanceof Long) {
+                return (byte) (long) value;
+            }
+        } else if (toType == Integer.class) {
+            if (value instanceof Integer) {
+                return value;
+            } else if (value instanceof Long) {
+                return (int) (long) value;
+            }
+        } else if (toType == String.class) {
+            if (value == null || value instanceof String) {
+                return value;
+            }
+        } else if (toType == Long.class) {
+            return value;
+        }
+
+        throw new JVMCIError("cannot convert " + name + " of type " + value.getClass().getSimpleName() + (cppType == null ? "" : " [" + cppType + "]") + " to " + toType.getSimpleName());
+    }
+
+    private final HotSpotVMConfigStore store;
+
+    public HotSpotVMConfigAccess(HotSpotVMConfigStore store) {
+        this.store = store;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.common.InitTimer.timer;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.vm.ci.common.InitTimer;
+
+/**
+ * Access to VM configuration data.
+ */
+public final class HotSpotVMConfigStore {
+
+    /**
+     * Gets the C++ symbols whose addresses are exposed by this object.
+     *
+     * @return an unmodifiable map from the symbol names to their addresses
+     */
+    public Map<String, Long> getAddresses() {
+        return Collections.unmodifiableMap(vmAddresses);
+    }
+
+    /**
+     * Gets the C++ constants exposed by this object.
+     *
+     * @return an unmodifiable map from the names of C++ constants to their values
+     */
+    public Map<String, Long> getConstants() {
+        return Collections.unmodifiableMap(vmConstants);
+    }
+
+    /**
+     * Gets the VM flags exposed by this object.
+     *
+     * @return an unmodifiable map from VM flag names to {@link VMFlag} objects
+     */
+    public Map<String, VMFlag> getFlags() {
+        return Collections.unmodifiableMap(vmFlags);
+    }
+
+    /**
+     * Gets the C++ fields exposed by this object.
+     *
+     * @return an unmodifiable map from VM field names to {@link VMField} objects
+     */
+    public Map<String, VMField> getFields() {
+        return Collections.unmodifiableMap(vmFields);
+    }
+
+    /**
+     * Gets the VM intrinsic descriptions exposed by this object.
+     */
+    public List<VMIntrinsicMethod> getIntrinsics() {
+        return Collections.unmodifiableList(vmIntrinsics);
+    }
+
+    final HashMap<String, VMField> vmFields;
+    final HashMap<String, Long> vmConstants;
+    final HashMap<String, Long> vmAddresses;
+    final HashMap<String, VMFlag> vmFlags;
+    final List<VMIntrinsicMethod> vmIntrinsics;
+    final CompilerToVM compilerToVm;
+
+    /**
+     * Reads the database of VM info. The return value encodes the info in a nested object array
+     * that is described by the pseudo Java object {@code info} below:
+     *
+     * <pre>
+     *     info = [
+     *         VMField[] vmFields,
+     *         [String name, Long value, ...] vmConstants,
+     *         [String name, Long value, ...] vmAddresses,
+     *         VMFlag[] vmFlags
+     *         VMIntrinsicMethod[] vmIntrinsics
+     *     ]
+     * </pre>
+     */
+    @SuppressWarnings("try")
+    HotSpotVMConfigStore(CompilerToVM compilerToVm) {
+        this.compilerToVm = compilerToVm;
+        Object[] data;
+        try (InitTimer t = timer("CompilerToVm readConfiguration")) {
+            data = compilerToVm.readConfiguration();
+        }
+        assert data.length == 5 : data.length;
+
+        // @formatter:off
+        VMField[] vmFieldsInfo    = (VMField[]) data[0];
+        Object[] vmConstantsInfo  = (Object[])  data[1];
+        Object[] vmAddressesInfo  = (Object[])  data[2];
+        VMFlag[] vmFlagsInfo      = (VMFlag[])  data[3];
+
+        vmFields     = new HashMap<>(vmFieldsInfo.length);
+        vmConstants  = new HashMap<>(vmConstantsInfo.length);
+        vmAddresses  = new HashMap<>(vmAddressesInfo.length);
+        vmFlags      = new HashMap<>(vmFlagsInfo.length);
+        vmIntrinsics = Arrays.asList((VMIntrinsicMethod[]) data[4]);
+        // @formatter:on
+
+        try (InitTimer t = timer("HotSpotVMConfigStore<init> fill maps")) {
+            for (VMField vmField : vmFieldsInfo) {
+                vmFields.put(vmField.name, vmField);
+            }
+
+            for (int i = 0; i < vmConstantsInfo.length / 2; i++) {
+                String name = (String) vmConstantsInfo[i * 2];
+                Long value = (Long) vmConstantsInfo[i * 2 + 1];
+                vmConstants.put(name, value);
+            }
+
+            for (int i = 0; i < vmAddressesInfo.length / 2; i++) {
+                String name = (String) vmAddressesInfo[i * 2];
+                Long value = (Long) vmAddressesInfo[i * 2 + 1];
+                vmAddresses.put(name, value);
+            }
+
+            for (VMFlag vmFlag : vmFlagsInfo) {
+                vmFlags.put(vmFlag.name, vmFlag);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.CompiledCode;
+import jdk.vm.ci.code.InstalledCode;
+
+/**
+ * Listener for responding to VM events.
+ */
+public interface HotSpotVMEventListener {
+
+    /**
+     * Notifies this client that the VM is shutting down.
+     */
+    default void notifyShutdown() {
+    }
+
+    /**
+     * Notify on successful install into the code cache.
+     *
+     * @param hotSpotCodeCacheProvider the code cache into which the code was installed
+     * @param installedCode the code that was installed
+     * @param compiledCode the compiled code from which {@code installedCode} was produced
+     */
+    default void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
+    }
+
+    /**
+     * Notify on completion of a bootstrap.
+     */
+    default void notifyBootstrapFinished() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * A tag interface indicating that this type is a wrapper around a HotSpot metaspace object that
+ * requires GC interaction to keep alive.
+ *
+ * It would preferable if this were the base class containing the pointer but that would require
+ * mixins since most of the wrapper types have complex supertype hierarchies.
+ */
+interface MetaspaceWrapperObject {
+
+    long getMetaspacePointer();
+
+    /**
+     * Check if this object is properly registered for metadata tracking. All classes which
+     * implement this interface must be registered with the
+     * {@link HotSpotJVMCIMetaAccessContext#add} unless they are kept alive through other means.
+     * Currently the only type which doesn't require explicit registration is
+     * {@link HotSpotResolvedObjectTypeImpl} since it's kept alive by references to the
+     * {@link Class}.
+     *
+     * @return true if this object is properly registered for meta data tracking.
+     */
+    default boolean isRegistered() {
+        return HotSpotJVMCIRuntime.runtime().metaAccessContext.isRegistered(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.vm.ci.hotspot;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation functions as an alias for the java.lang.invoke.Stable annotation within JVMCI
+ * code. It is specially recognized during class file parsing in the same way as that annotation.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@interface Stable {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SuppressFBWarnings.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+@interface SuppressFBWarnings {
+    /**
+     * The set of FindBugs
+     * <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+     * suppressed in annotated element. The value can be a bug category, kind or pattern.
+     */
+    String[] value();
+
+    /**
+     * Reason why the warning is suppressed.
+     */
+    String justification();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 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 jdk.vm.ci.hotspot;
+
+import java.lang.reflect.Field;
+
+import sun.misc.Unsafe;
+
+/**
+ * Package private access to the {@link Unsafe} capability.
+ */
+class UnsafeAccess {
+
+    static final Unsafe UNSAFE = initUnsafe();
+
+    private static Unsafe initUnsafe() {
+        try {
+            // Fast path when we are trusted.
+            return Unsafe.getUnsafe();
+        } catch (SecurityException se) {
+            // Slow path when we are not trusted.
+            try {
+                Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+                theUnsafe.setAccessible(true);
+                return (Unsafe) theUnsafe.get(Unsafe.class);
+            } catch (Exception e) {
+                throw new RuntimeException("exception while trying to get Unsafe", e);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMField.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * Describes a C++ field exposed via {@link HotSpotVMConfigAccess}.
+ */
+public final class VMField {
+
+    /**
+     * Fully qualified name of the represented field (e.g., "Klass::_name").
+     */
+    public final String name;
+
+    /**
+     * The represented field's type (e.g., "Symbol*"). This may be {@code null}.
+     */
+    public final String type;
+
+    /**
+     * If represented field is non-static, this is its offset within the containing structure.
+     */
+    public final long offset;
+
+    /**
+     * If represented field is static, this is its address. Otherwise, this field is 0.
+     */
+    public final long address;
+
+    /**
+     * Value of the field represented as a boxed long; only valid for non-oop static fields. This
+     * value is only captured once, during JVMCI initialization. If {@link #type} cannot be
+     * meaningfully (e.g., a struct) or safely (e.g., an oop) expressed as a boxed long, this is
+     * {@code null}.
+     */
+    public final Long value;
+
+    /**
+     * Determines if the represented field is static.
+     */
+    public boolean isStatic() {
+        return address != 0;
+    }
+
+    /**
+     * Creates a description of a non-static field.
+     */
+    public VMField(String name, String type, long offset) {
+        this.name = name;
+        this.type = type;
+        this.offset = offset;
+        this.address = 0;
+        this.value = null;
+    }
+
+    /**
+     * Creates a description of a static field.
+     */
+    public VMField(String name, String type, long address, Long value) {
+        this.name = name;
+        this.type = type;
+        this.offset = 0;
+        this.address = address;
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        String val = value == null ? "null" : String.format("0x%x", value);
+        return String.format("Field[name=%s, type=%s, offset=%d, address=0x%x, value=%s]", name, type, offset, address, val);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMFlag.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * Describes a VM flag exposed via {@link HotSpotVMConfigAccess}.
+ */
+public final class VMFlag {
+
+    /**
+     * The name of the flag.
+     */
+    public final String name;
+
+    /**
+     * The C++ type of the flag.
+     */
+    public final String type;
+
+    /**
+     * The flag's value.
+     */
+    public final Object value;
+
+    VMFlag(String name, String type, Object value) {
+        this.name = name;
+        this.type = type;
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Flag[type=%s, name=%s, value=%s]", type, name, value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.Signature;
+
+/**
+ * Describes a method for which the VM has an intrinsic implementation.
+ */
+public final class VMIntrinsicMethod {
+
+    /**
+     * The name of the class declaring the intrinsified method. The name is in
+     * <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.2.1">class
+     * file format</a> (e.g., {@code "java/lang/Thread"} instead of {@code "java.lang.Thread"}).
+     */
+    public final String declaringClass;
+
+    /**
+     * The name of the intrinsified method. This is not guaranteed to be a legal method name (e.g.,
+     * there is a HotSpot intrinsic with the name {@code "<compiledLambdaForm>"}).
+     */
+    public final String name;
+
+    /**
+     * The {@link Signature#toMethodDescriptor() descriptor} of the intrinsified method. This is not
+     * guaranteed to be a legal method descriptor (e.g., intrinsics for signature polymorphic
+     * methods have a descriptor of {@code "*"}).
+     */
+    public final String descriptor;
+
+    /**
+     * The unique VM identifier for the intrinsic.
+     */
+    public final int id;
+
+    VMIntrinsicMethod(String declaringClass, String name, String descriptor, int id) {
+        this.declaringClass = declaringClass;
+        this.name = name;
+        this.descriptor = descriptor;
+        this.id = id;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof VMIntrinsicMethod) {
+            VMIntrinsicMethod that = (VMIntrinsicMethod) obj;
+            if (that.id == this.id) {
+                assert that.name.equals(this.name) &&
+                                that.declaringClass.equals(this.declaringClass) &&
+                                that.descriptor.equals(this.descriptor);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return id;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("IntrinsicMethod[declaringClass=%s, name=%s, descriptor=%s, id=%d]", declaringClass, name, descriptor, id);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/overview.html	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+</head>
+<body>
+
+The <code>jdk.vm.ci.meta</code> project provides an API to the runtime data structures
+for various Java elements. Unlike standard Java reflection, it can model elements that are not yet loaded.
+It can also expose profiling information collected by the runtime system.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractJavaProfile.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * This object holds probability information for a set of items that were profiled at a specific
+ * BCI. The precision of the supplied values may vary, but a runtime that provides this information
+ * should be aware that it will be used to guide performance-critical decisions like speculative
+ * inlining, etc.
+ *
+ * @param <T> a subclass of AbstractProfiledItem
+ * @param <U> the class of the items that are profiled at the specific BCI and for which
+ *            probabilities are stored. E.g., a ResolvedJavaType or a ResolvedJavaMethod.
+ */
+public abstract class AbstractJavaProfile<T extends AbstractProfiledItem<U>, U> {
+
+    private final double notRecordedProbability;
+    private final T[] pitems;
+
+    /**
+     *
+     * @param notRecordedProbability
+     * @param pitems
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of the `pitems` array parameter")
+    public AbstractJavaProfile(double notRecordedProbability, T[] pitems) {
+        this.pitems = pitems;
+        assert !Double.isNaN(notRecordedProbability);
+        this.notRecordedProbability = notRecordedProbability;
+        assert isSorted();
+        assert totalProbablility() >= 0 && totalProbablility() <= 1.0001 : totalProbablility() + " " + this;
+    }
+
+    private double totalProbablility() {
+        double total = notRecordedProbability;
+        for (T item : pitems) {
+            total += item.probability;
+        }
+        return total;
+    }
+
+    /**
+     * Determines if an array of profiled items are sorted in descending order of their
+     * probabilities.
+     */
+    private boolean isSorted() {
+        for (int i = 1; i < pitems.length; i++) {
+            if (pitems[i - 1].getProbability() < pitems[i].getProbability()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the estimated probability of all types that could not be recorded due to profiling
+     * limitations.
+     *
+     * @return double value &ge; 0.0 and &le; 1.0
+     */
+    public double getNotRecordedProbability() {
+        return notRecordedProbability;
+    }
+
+    protected T[] getItems() {
+        return pitems;
+    }
+
+    /**
+     * Searches for an entry of a given resolved Java type.
+     *
+     * @param type the type for which an entry should be searched
+     * @return the entry or null if no entry for this type can be found
+     */
+    public T findEntry(ResolvedJavaType type) {
+        if (pitems != null) {
+            for (T pt : pitems) {
+                if (pt.getItem().equals(type)) {
+                    return pt;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(this.getClass().getName());
+        builder.append("[");
+        if (pitems != null) {
+            for (T pt : pitems) {
+                builder.append(pt.toString());
+                builder.append(", ");
+            }
+        }
+        builder.append(this.notRecordedProbability);
+        builder.append("]");
+        return builder.toString();
+    }
+
+    public boolean isIncluded(U item) {
+        if (this.getNotRecordedProbability() > 0.0) {
+            return true;
+        } else {
+            for (int i = 0; i < getItems().length; i++) {
+                T pitem = getItems()[i];
+                U curType = pitem.getItem();
+                if (curType == item) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof AbstractJavaProfile)) {
+            return false;
+        }
+        AbstractJavaProfile<?, ?> that = (AbstractJavaProfile<?, ?>) obj;
+        if (that.notRecordedProbability != notRecordedProbability) {
+            return false;
+        }
+        if (that.pitems.length != pitems.length) {
+            return false;
+        }
+        for (int i = 0; i < pitems.length; ++i) {
+            if (!pitems[i].equals(that.pitems[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return (int) Double.doubleToLongBits(notRecordedProbability) + pitems.length * 13;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractProfiledItem.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * A profiled type that has a probability. Profiled types are naturally sorted in descending order
+ * of their probabilities.
+ */
+public abstract class AbstractProfiledItem<T> implements Comparable<AbstractProfiledItem<?>> {
+
+    protected final T item;
+    protected final double probability;
+
+    public AbstractProfiledItem(T item, double probability) {
+        assert item != null;
+        assert probability >= 0.0D && probability <= 1.0D;
+        this.item = item;
+        this.probability = probability;
+    }
+
+    protected T getItem() {
+        return item;
+    }
+
+    /**
+     * Returns the estimated probability of {@link #getItem()}.
+     *
+     * @return double value &ge; 0.0 and &le; 1.0
+     */
+    public double getProbability() {
+        return probability;
+    }
+
+    /**
+     * Returns -1 if the {@linkplain #getProbability() probability} of this item is greater than
+     * {@code o}'s probability, 0 if there are equal otherwise 1.
+     */
+    @Override
+    public int compareTo(AbstractProfiledItem<?> o) {
+        // Need to swap the order of operands so that higher probabilities are sorted first
+        return Double.compare(o.getProbability(), getProbability());
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        long temp;
+        temp = Double.doubleToLongBits(probability);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        result = prime * result + item.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AbstractProfiledItem<?> other = (AbstractProfiledItem<?>) obj;
+        if (Double.doubleToLongBits(probability) != Double.doubleToLongBits(other.probability)) {
+            return false;
+        }
+        return item.equals(other.item);
+    }
+
+    @Override
+    public abstract String toString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AllocatableValue.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Common base class for values that are stored in some location that's managed by the register
+ * allocator (e.g. register, stack slot).
+ */
+public abstract class AllocatableValue extends Value implements JavaValue {
+
+    public static final AllocatableValue[] NONE = {};
+
+    public AllocatableValue(ValueKind<?> kind) {
+        super(kind);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,400 @@
+/*
+ * 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 jdk.vm.ci.meta;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Class for recording assumptions made during compilation.
+ */
+public final class Assumptions implements Iterable<Assumptions.Assumption> {
+
+    /**
+     * Abstract base class for assumptions. An assumption assumes a property of the runtime that may
+     * be invalidated by subsequent execution (e.g., that a class has no subclasses implementing
+     * {@link NoFinalizableSubclass Object.finalize()}).
+     */
+    public abstract static class Assumption {
+    }
+
+    /**
+     * A class for providing information that is only valid in association with a set of
+     * {@link Assumption}s. It is permissible for AssumptionResults to have no assumptions at all.
+     * For instance, if {@link ResolvedJavaType#isLeaf()} returns true for a type
+     * {@link ResolvedJavaType#findLeafConcreteSubtype()} can return an AssumptionResult with no
+     * assumptions since the leaf information is statically true.
+     *
+     * @param <T>
+     */
+    public static class AssumptionResult<T> {
+        Assumption[] assumptions;
+        final T result;
+
+        private static final Assumption[] EMPTY = new Assumption[0];
+
+        public AssumptionResult(T result, Assumption... assumptions) {
+            this.result = result;
+            this.assumptions = assumptions;
+        }
+
+        public AssumptionResult(T result) {
+            this(result, EMPTY);
+        }
+
+        public T getResult() {
+            return result;
+        }
+
+        public boolean isAssumptionFree() {
+            return assumptions.length == 0;
+        }
+
+        public void add(AssumptionResult<T> other) {
+            Assumption[] newAssumptions = Arrays.copyOf(this.assumptions, this.assumptions.length + other.assumptions.length);
+            System.arraycopy(other.assumptions, 0, newAssumptions, this.assumptions.length, other.assumptions.length);
+            this.assumptions = newAssumptions;
+        }
+
+        public boolean canRecordTo(Assumptions target) {
+            /*
+             * We can use the result if it is either assumption free, or if we have a valid
+             * Assumptions object where we can record assumptions.
+             */
+            return assumptions.length == 0 || target != null;
+        }
+
+        public void recordTo(Assumptions target) {
+            assert canRecordTo(target);
+
+            if (assumptions.length > 0) {
+                for (Assumption assumption : assumptions) {
+                    target.record(assumption);
+                }
+            }
+        }
+    }
+
+    /**
+     * An assumption that a given class has no subclasses implementing {@link Object#finalize()}).
+     */
+    public static final class NoFinalizableSubclass extends Assumption {
+
+        private ResolvedJavaType receiverType;
+
+        public NoFinalizableSubclass(ResolvedJavaType receiverType) {
+            this.receiverType = receiverType;
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 + receiverType.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof NoFinalizableSubclass) {
+                NoFinalizableSubclass other = (NoFinalizableSubclass) obj;
+                return other.receiverType.equals(receiverType);
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "NoFinalizableSubclass[receiverType=" + receiverType.toJavaName() + "]";
+        }
+
+    }
+
+    /**
+     * An assumption that a given abstract or interface type has one direct concrete subtype. There
+     * is no requirement that the subtype is a leaf type.
+     */
+    public static final class ConcreteSubtype extends Assumption {
+
+        /**
+         * Type the assumption is made about.
+         */
+        public final ResolvedJavaType context;
+
+        /**
+         * Assumed concrete sub-type of the context type.
+         */
+        public final ResolvedJavaType subtype;
+
+        public ConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) {
+            this.context = context;
+            this.subtype = subtype;
+            assert context.isAbstract();
+            assert subtype.isConcrete() || context.isInterface() : subtype.toString() + " : " + context.toString();
+            assert !subtype.isArray() || subtype.getElementalType().isFinalFlagSet() : subtype.toString() + " : " + context.toString();
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + context.hashCode();
+            result = prime * result + subtype.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ConcreteSubtype) {
+                ConcreteSubtype other = (ConcreteSubtype) obj;
+                return other.context.equals(context) && other.subtype.equals(subtype);
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "ConcreteSubtype[context=" + context.toJavaName() + ", subtype=" + subtype.toJavaName() + "]";
+        }
+    }
+
+    /**
+     * An assumption that a given type has no subtypes.
+     */
+    public static final class LeafType extends Assumption {
+
+        /**
+         * Type the assumption is made about.
+         */
+        public final ResolvedJavaType context;
+
+        public LeafType(ResolvedJavaType context) {
+            assert !context.isLeaf() : "assumption isn't required for leaf types";
+            this.context = context;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + context.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof LeafType) {
+                LeafType other = (LeafType) obj;
+                return other.context.equals(context);
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "LeafSubtype[context=" + context.toJavaName() + "]";
+        }
+    }
+
+    /**
+     * An assumption that a given virtual method has a given unique implementation.
+     */
+    public static final class ConcreteMethod extends Assumption {
+
+        /**
+         * A virtual (or interface) method whose unique implementation for the receiver type in
+         * {@link #context} is {@link #impl}.
+         */
+        public final ResolvedJavaMethod method;
+
+        /**
+         * A receiver type.
+         */
+        public final ResolvedJavaType context;
+
+        /**
+         * The unique implementation of {@link #method} for {@link #context}.
+         */
+        public final ResolvedJavaMethod impl;
+
+        public ConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) {
+            this.method = method;
+            this.context = context;
+            this.impl = impl;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + method.hashCode();
+            result = prime * result + context.hashCode();
+            result = prime * result + impl.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ConcreteMethod) {
+                ConcreteMethod other = (ConcreteMethod) obj;
+                return other.method.equals(method) && other.context.equals(context) && other.impl.equals(impl);
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "ConcreteMethod[method=" + method.format("%H.%n(%p)%r") + ", context=" + context.toJavaName() + ", impl=" + impl.format("%H.%n(%p)%r") + "]";
+        }
+    }
+
+    /**
+     * An assumption that a given call site's method handle did not change.
+     */
+    public static final class CallSiteTargetValue extends Assumption {
+
+        public final CallSite callSite;
+        public final MethodHandle methodHandle;
+
+        public CallSiteTargetValue(CallSite callSite, MethodHandle methodHandle) {
+            this.callSite = callSite;
+            this.methodHandle = methodHandle;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + callSite.hashCode();
+            result = prime * result + methodHandle.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof CallSiteTargetValue) {
+                CallSiteTargetValue other = (CallSiteTargetValue) obj;
+                return callSite.equals(other.callSite) && methodHandle.equals(other.methodHandle);
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "CallSiteTargetValue[callSite=" + callSite + ", methodHandle=" + methodHandle + "]";
+        }
+    }
+
+    private final Set<Assumption> assumptions = new HashSet<>();
+
+    /**
+     * Returns whether any assumptions have been registered.
+     *
+     * @return {@code true} if at least one assumption has been registered, {@code false} otherwise.
+     */
+    public boolean isEmpty() {
+        return assumptions.isEmpty();
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException("hashCode");
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof Assumptions) {
+            Assumptions that = (Assumptions) obj;
+            if (!this.assumptions.equals(that.assumptions)) {
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Iterator<Assumption> iterator() {
+        return assumptions.iterator();
+    }
+
+    /**
+     * Records an assumption that the specified type has no finalizable subclasses.
+     *
+     * @param receiverType the type that is assumed to have no finalizable subclasses
+     */
+    public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) {
+        record(new NoFinalizableSubclass(receiverType));
+    }
+
+    /**
+     * Records that {@code subtype} is the only concrete subtype in the class hierarchy below
+     * {@code context}.
+     *
+     * @param context the root of the subtree of the class hierarchy that this assumptions is about
+     * @param subtype the one concrete subtype
+     */
+    public void recordConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) {
+        record(new ConcreteSubtype(context, subtype));
+    }
+
+    /**
+     * Records that {@code impl} is the only possible concrete target for a virtual call to
+     * {@code method} with a receiver of type {@code context}.
+     *
+     * @param method a method that is the target of a virtual call
+     * @param context the receiver type of a call to {@code method}
+     * @param impl the concrete method that is the only possible target for the virtual call
+     */
+    public void recordConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) {
+        record(new ConcreteMethod(method, context, impl));
+    }
+
+    public void record(Assumption assumption) {
+        assumptions.add(assumption);
+    }
+
+    /**
+     * Gets a copy of the assumptions recorded in this object as an array.
+     */
+    public Assumption[] toArray() {
+        return assumptions.toArray(new Assumption[assumptions.size()]);
+    }
+
+    /**
+     * Copies assumptions recorded by another {@link Assumptions} object into this object.
+     */
+    public void record(Assumptions other) {
+        assert other != this;
+        assumptions.addAll(other.assumptions);
+    }
+
+    @Override
+    public String toString() {
+        return "Assumptions[" + assumptions + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Constant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a compile-time constant (boxed) value within the compiler.
+ */
+public interface Constant {
+
+    boolean isDefaultForKind();
+
+    String toValueString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantPool.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents the runtime representation of the constant pool that is used by the compiler when
+ * parsing bytecode. Provides methods to look up a constant pool entry without performing
+ * resolution. They are used during compilation.
+ */
+public interface ConstantPool {
+
+    /**
+     * Returns the number of entries the constant pool.
+     *
+     * @return number of entries in the constant pool
+     */
+    int length();
+
+    /**
+     * Ensures that the type referenced by the specified constant pool entry is loaded and
+     * initialized. This can be used to compile time resolve a type. It works for field, method, or
+     * type constant pool entries.
+     *
+     * @param cpi the index of the constant pool entry that references the type
+     * @param opcode the opcode of the instruction that references the type
+     */
+    void loadReferencedType(int cpi, int opcode);
+
+    /**
+     * Looks up a reference to a field. If {@code opcode} is non-negative, then resolution checks
+     * specific to the bytecode it denotes are performed if the field is already resolved. Checks
+     * for some bytecodes require the method that contains the bytecode to be specified. Should any
+     * of these checks fail, an unresolved field reference is returned.
+     *
+     * @param cpi the constant pool index
+     * @param opcode the opcode of the instruction for which the lookup is being performed or
+     *            {@code -1}
+     * @param method the method for which the lookup is being performed
+     * @return a reference to the field at {@code cpi} in this pool
+     * @throws ClassFormatError if the entry at {@code cpi} is not a field
+     */
+    JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode);
+
+    /**
+     * Looks up a reference to a method. If {@code opcode} is non-negative, then resolution checks
+     * specific to the bytecode it denotes are performed if the method is already resolved. Should
+     * any of these checks fail, an unresolved method reference is returned.
+     *
+     * @param cpi the constant pool index
+     * @param opcode the opcode of the instruction for which the lookup is being performed or
+     *            {@code -1}
+     * @return a reference to the method at {@code cpi} in this pool
+     * @throws ClassFormatError if the entry at {@code cpi} is not a method
+     */
+    JavaMethod lookupMethod(int cpi, int opcode);
+
+    /**
+     * Looks up a reference to a type. If {@code opcode} is non-negative, then resolution checks
+     * specific to the bytecode it denotes are performed if the type is already resolved. Should any
+     * of these checks fail, an unresolved type reference is returned.
+     *
+     * @param cpi the constant pool index
+     * @param opcode the opcode of the instruction for which the lookup is being performed or
+     *            {@code -1}
+     * @return a reference to the compiler interface type
+     */
+    JavaType lookupType(int cpi, int opcode);
+
+    /**
+     * Looks up an Utf8 string.
+     *
+     * @param cpi the constant pool index
+     * @return the Utf8 string at index {@code cpi} in this constant pool
+     */
+    String lookupUtf8(int cpi);
+
+    /**
+     * Looks up a method signature.
+     *
+     * @param cpi the constant pool index
+     * @return the method signature at index {@code cpi} in this constant pool
+     */
+    Signature lookupSignature(int cpi);
+
+    /**
+     * Looks up a constant at the specified index.
+     *
+     * @param cpi the constant pool index
+     * @return the {@code Constant} or {@code JavaType} instance representing the constant pool
+     *         entry
+     */
+    Object lookupConstant(int cpi);
+
+    /**
+     * Looks up the appendix at the specified index.
+     *
+     * @param cpi the constant pool index
+     * @param opcode the opcode of the instruction for which the lookup is being performed or
+     *            {@code -1}
+     * @return the appendix if it exists and is resolved or {@code null}
+     */
+    JavaConstant lookupAppendix(int cpi, int opcode);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.invoke.MethodHandle;
+
+/**
+ * Reflection operations on values represented as {@linkplain JavaConstant constants}. All methods
+ * in this interface require the VM to access the actual object encapsulated in
+ * {@link JavaKind#Object object} constants. This access is not always possible, depending on kind
+ * of VM and the state that the VM is in. Therefore, all methods can return {@code null} at any
+ * time, to indicate that the result is not available at this point. The caller is responsible to
+ * check for {@code null} results and handle them properly, e.g., not perform an optimization.
+ */
+public interface ConstantReflectionProvider {
+
+    /**
+     * Compares two constants for equality. The equality relationship is symmetric. Returns
+     * {@link Boolean#TRUE true} if the two constants represent the same run time value,
+     * {@link Boolean#FALSE false} if they are different. Returns {@code null} if the constants
+     * cannot be compared at this point.
+     */
+    Boolean constantEquals(Constant x, Constant y);
+
+    /**
+     * Returns the length of the array constant. Returns {@code null} if the constant is not an
+     * array, or if the array length is not available at this point.
+     */
+    Integer readArrayLength(JavaConstant array);
+
+    /**
+     * Reads a value from the given array at the given index. Returns {@code null} if the constant
+     * is not an array, if the index is out of bounds, or if the value is not available at this
+     * point.
+     */
+    JavaConstant readArrayElement(JavaConstant array, int index);
+
+    /**
+     * Gets the current value of this field for a given object, if available.
+     *
+     * There is no guarantee that the same value will be returned by this method for a field unless
+     * the field is considered to be constant by the runtime.
+     *
+     * @param receiver object from which this field's value is to be read. This value is ignored if
+     *            this field is static.
+     * @return the value of this field or {@code null} if the value is not available (e.g., because
+     *         the field holder is not yet initialized).
+     */
+    JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver);
+
+    /**
+     * Converts the given {@link JavaKind#isPrimitive() primitive} constant to a boxed
+     * {@link JavaKind#Object object} constant, according to the Java boxing rules. Returns
+     * {@code null} if the source is is not a primitive constant, or the boxed value is not
+     * available at this point.
+     */
+    JavaConstant boxPrimitive(JavaConstant source);
+
+    /**
+     * Converts the given {@link JavaKind#Object object} constant to a {@link JavaKind#isPrimitive()
+     * primitive} constant, according to the Java unboxing rules. Returns {@code null} if the source
+     * is is not an object constant that can be unboxed, or the unboxed value is not available at
+     * this point.
+     */
+    JavaConstant unboxPrimitive(JavaConstant source);
+
+    /**
+     * Gets a string as a {@link JavaConstant}.
+     */
+    JavaConstant forString(String value);
+
+    /**
+     * Returns the {@link ResolvedJavaType} for a {@link Class} object (or any other object regarded
+     * as a class by the VM) encapsulated in the given constant. Returns {@code null} if the
+     * constant does not encapsulate a class, or if the type is not available at this point.
+     */
+    ResolvedJavaType asJavaType(Constant constant);
+
+    /**
+     * Gets access to the internals of {@link MethodHandle}.
+     */
+    MethodHandleAccessProvider getMethodHandleAccess();
+
+    /**
+     * Gets raw memory access.
+     */
+    MemoryAccessProvider getMemoryAccessProvider();
+
+    /**
+     * Gets the runtime representation of the {@link Class} object of this type.
+     */
+    JavaConstant asJavaClass(ResolvedJavaType type);
+
+    /**
+     * Gets the runtime representation of the "hub" of this type--that is, the closest part of the
+     * type representation which is typically stored in the object header.
+     */
+    Constant asObjectHub(ResolvedJavaType type);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,110 @@
+/*
+ * 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 jdk.vm.ci.meta;
+
+/**
+ * An implementation of {@link ProfilingInfo} that can used in the absence of real profile
+ * information.
+ */
+public final class DefaultProfilingInfo implements ProfilingInfo {
+
+    private static final ProfilingInfo[] NO_PROFILING_INFO = new ProfilingInfo[]{new DefaultProfilingInfo(TriState.TRUE), new DefaultProfilingInfo(TriState.FALSE),
+                    new DefaultProfilingInfo(TriState.UNKNOWN)};
+
+    private final TriState exceptionSeen;
+
+    DefaultProfilingInfo(TriState exceptionSeen) {
+        this.exceptionSeen = exceptionSeen;
+    }
+
+    @Override
+    public int getCodeSize() {
+        return 0;
+    }
+
+    @Override
+    public JavaTypeProfile getTypeProfile(int bci) {
+        return null;
+    }
+
+    @Override
+    public JavaMethodProfile getMethodProfile(int bci) {
+        return null;
+    }
+
+    @Override
+    public double getBranchTakenProbability(int bci) {
+        return -1;
+    }
+
+    @Override
+    public double[] getSwitchProbabilities(int bci) {
+        return null;
+    }
+
+    @Override
+    public TriState getExceptionSeen(int bci) {
+        return exceptionSeen;
+    }
+
+    @Override
+    public TriState getNullSeen(int bci) {
+        return TriState.UNKNOWN;
+    }
+
+    @Override
+    public int getExecutionCount(int bci) {
+        return -1;
+    }
+
+    public static ProfilingInfo get(TriState exceptionSeen) {
+        return NO_PROFILING_INFO[exceptionSeen.ordinal()];
+    }
+
+    @Override
+    public int getDeoptimizationCount(DeoptimizationReason reason) {
+        return 0;
+    }
+
+    @Override
+    public boolean isMature() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultProfilingInfo<" + this.toString(null, "; ") + ">";
+    }
+
+    public void setMature() {
+        // Do nothing
+    }
+
+    public boolean setCompilerIRSize(Class<?> irType, int nodeCount) {
+        return false;
+    }
+
+    public int getCompilerIRSize(Class<?> irType) {
+        return -1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,70 @@
+/*
+ * 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 jdk.vm.ci.meta;
+
+/**
+ * Specifies the action that should be taken by the runtime in case a certain deoptimization is
+ * triggered.
+ */
+public enum DeoptimizationAction {
+    /**
+     * Do not invalidate the machine code. This is typically used when deoptimizing at a point where
+     * it's highly likely nothing will change the likelihood of the deoptimization happening again.
+     * For example, a compiled array allocation where the size is negative.
+     */
+    None(false),
+
+    /**
+     * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is
+     * triggered too often.
+     */
+    RecompileIfTooManyDeopts(true),
+
+    /**
+     * Invalidate the machine code and reset the profiling information.
+     */
+    InvalidateReprofile(true),
+
+    /**
+     * Invalidate the machine code and immediately schedule a recompilation. This is typically used
+     * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not
+     * required to determine that the deoptimization will not re-occur.
+     */
+    InvalidateRecompile(true),
+
+    /**
+     * Invalidate the machine code and stop compiling the outermost method of this compilation.
+     */
+    InvalidateStopCompiling(true);
+
+    private final boolean invalidatesCompilation;
+
+    DeoptimizationAction(boolean invalidatesCompilation) {
+        this.invalidatesCompilation = invalidatesCompilation;
+    }
+
+    public boolean doesInvalidateCompilation() {
+        return invalidatesCompilation;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationReason.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 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 jdk.vm.ci.meta;
+
+/**
+ * Enumeration of reasons for why a deoptimization is happening.
+ */
+public enum DeoptimizationReason {
+    None,
+    NullCheckException,
+    BoundsCheckException,
+    ClassCastException,
+    ArrayStoreException,
+    UnreachedCode,
+    TypeCheckedInliningViolated,
+    OptimizedTypeCheckViolated,
+    NotCompiledExceptionHandler,
+    Unresolved,
+    JavaSubroutineMismatch,
+    ArithmeticException,
+    RuntimeConstraint,
+    LoopLimitCheck,
+    Aliasing,
+    TransferToInterpreter,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2009, 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 jdk.vm.ci.meta;
+
+import java.util.Objects;
+
+/**
+ * Represents an exception handler within the bytecodes.
+ */
+public final class ExceptionHandler {
+
+    private final int startBCI;
+    private final int endBCI;
+    private final int handlerBCI;
+    private final int catchTypeCPI;
+    private final JavaType catchType;
+
+    /**
+     * Creates a new exception handler with the specified ranges.
+     *
+     * @param startBCI the start index of the protected range
+     * @param endBCI the end index of the protected range
+     * @param catchBCI the index of the handler
+     * @param catchTypeCPI the index of the throwable class in the constant pool
+     * @param catchType the type caught by this exception handler
+     */
+    public ExceptionHandler(int startBCI, int endBCI, int catchBCI, int catchTypeCPI, JavaType catchType) {
+        this.startBCI = startBCI;
+        this.endBCI = endBCI;
+        this.handlerBCI = catchBCI;
+        this.catchTypeCPI = catchTypeCPI;
+        this.catchType = catchType;
+    }
+
+    /**
+     * Returns the start bytecode index of the protected range of this handler.
+     */
+    public int getStartBCI() {
+        return startBCI;
+    }
+
+    /**
+     * Returns the end bytecode index of the protected range of this handler.
+     */
+    public int getEndBCI() {
+        return endBCI;
+    }
+
+    /**
+     * Returns the bytecode index of the handler block of this handler.
+     */
+    public int getHandlerBCI() {
+        return handlerBCI;
+    }
+
+    /**
+     * Returns the index into the constant pool representing the type of exception caught by this
+     * handler.
+     */
+    public int catchTypeCPI() {
+        return catchTypeCPI;
+    }
+
+    /**
+     * Checks whether this handler catches all exceptions.
+     *
+     * @return {@code true} if this handler catches all exceptions
+     */
+    public boolean isCatchAll() {
+        return catchTypeCPI == 0;
+    }
+
+    /**
+     * Returns the type of exception caught by this exception handler.
+     */
+    public JavaType getCatchType() {
+        return catchType;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ExceptionHandler)) {
+            return false;
+        }
+        ExceptionHandler that = (ExceptionHandler) obj;
+        if (this.startBCI != that.startBCI || this.endBCI != that.endBCI || this.handlerBCI != that.handlerBCI || this.catchTypeCPI != that.catchTypeCPI) {
+            return false;
+        }
+        return Objects.equals(this.catchType, that.catchType);
+    }
+
+    @Override
+    public String toString() {
+        return "ExceptionHandler<startBCI=" + startBCI + ", endBCI=" + endBCI + ", handlerBCI=" + handlerBCI + ", catchTypeCPI=" + catchTypeCPI + ", catchType=" + catchType + ">";
+    }
+
+    @Override
+    public int hashCode() {
+        return catchTypeCPI ^ endBCI ^ handlerBCI;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/InvokeTarget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents the resolved target of an invocation.
+ */
+public interface InvokeTarget {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a constant (boxed) value, such as an integer, floating point number, or object
+ * reference, within the compiler and across the compiler/runtime interface. Exports a set of
+ * {@code JavaConstant} instances that represent frequently used constant values, such as
+ * {@link #NULL_POINTER}.
+ */
+public interface JavaConstant extends Constant, JavaValue {
+    /*
+     * Using a larger cache for integers leads to only a slight increase in cache hit ratio which is
+     * not enough to justify the impact on startup time.
+     */
+    JavaConstant NULL_POINTER = new NullConstant();
+    PrimitiveConstant INT_MINUS_1 = new PrimitiveConstant(JavaKind.Int, -1);
+    PrimitiveConstant INT_0 = new PrimitiveConstant(JavaKind.Int, 0);
+    PrimitiveConstant INT_1 = new PrimitiveConstant(JavaKind.Int, 1);
+    PrimitiveConstant INT_2 = new PrimitiveConstant(JavaKind.Int, 2);
+    PrimitiveConstant LONG_0 = new PrimitiveConstant(JavaKind.Long, 0L);
+    PrimitiveConstant LONG_1 = new PrimitiveConstant(JavaKind.Long, 1L);
+    PrimitiveConstant FLOAT_0 = new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(0.0F));
+    PrimitiveConstant FLOAT_1 = new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(1.0F));
+    PrimitiveConstant DOUBLE_0 = new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(0.0D));
+    PrimitiveConstant DOUBLE_1 = new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(1.0D));
+    PrimitiveConstant TRUE = new PrimitiveConstant(JavaKind.Boolean, 1L);
+    PrimitiveConstant FALSE = new PrimitiveConstant(JavaKind.Boolean, 0L);
+
+    /**
+     * Returns the Java kind of this constant.
+     */
+    JavaKind getJavaKind();
+
+    /**
+     * Checks whether this constant is null.
+     *
+     * @return {@code true} if this constant is the null constant
+     */
+    boolean isNull();
+
+    static boolean isNull(Constant c) {
+        if (c instanceof JavaConstant) {
+            return ((JavaConstant) c).isNull();
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Checks whether this constant is non-null.
+     *
+     * @return {@code true} if this constant is a primitive, or an object constant that is not null
+     */
+    default boolean isNonNull() {
+        return !isNull();
+    }
+
+    /**
+     * Checks whether this constant is the default value for its kind (null, 0, 0.0, false).
+     *
+     * @return {@code true} if this constant is the default value for its kind
+     */
+    boolean isDefaultForKind();
+
+    /**
+     * Returns the value of this constant as a boxed Java value.
+     *
+     * @return the value of this constant
+     */
+    Object asBoxedPrimitive();
+
+    /**
+     * Returns the primitive int value this constant represents. The constant must have a
+     * {@link JavaKind#getStackKind()} of {@link JavaKind#Int}.
+     *
+     * @return the constant value
+     */
+    int asInt();
+
+    /**
+     * Returns the primitive boolean value this constant represents. The constant must have kind
+     * {@link JavaKind#Boolean}.
+     *
+     * @return the constant value
+     */
+    boolean asBoolean();
+
+    /**
+     * Returns the primitive long value this constant represents. The constant must have kind
+     * {@link JavaKind#Long}, a {@link JavaKind#getStackKind()} of {@link JavaKind#Int}.
+     *
+     * @return the constant value
+     */
+    long asLong();
+
+    /**
+     * Returns the primitive float value this constant represents. The constant must have kind
+     * {@link JavaKind#Float}.
+     *
+     * @return the constant value
+     */
+    float asFloat();
+
+    /**
+     * Returns the primitive double value this constant represents. The constant must have kind
+     * {@link JavaKind#Double}.
+     *
+     * @return the constant value
+     */
+    double asDouble();
+
+    default String toValueString() {
+        if (getJavaKind() == JavaKind.Illegal) {
+            return "illegal";
+        } else {
+            return getJavaKind().format(asBoxedPrimitive());
+        }
+    }
+
+    static String toString(JavaConstant constant) {
+        if (constant.getJavaKind() == JavaKind.Illegal) {
+            return "illegal";
+        } else {
+            return constant.getJavaKind().getJavaName() + "[" + constant.toValueString() + "]";
+        }
+    }
+
+    /**
+     * Creates a boxed double constant.
+     *
+     * @param d the double value to box
+     * @return a boxed copy of {@code value}
+     */
+    static PrimitiveConstant forDouble(double d) {
+        if (Double.compare(0.0D, d) == 0) {
+            return DOUBLE_0;
+        }
+        if (Double.compare(d, 1.0D) == 0) {
+            return DOUBLE_1;
+        }
+        return new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(d));
+    }
+
+    /**
+     * Creates a boxed float constant.
+     *
+     * @param f the float value to box
+     * @return a boxed copy of {@code value}
+     */
+    static PrimitiveConstant forFloat(float f) {
+        if (Float.compare(f, 0.0F) == 0) {
+            return FLOAT_0;
+        }
+        if (Float.compare(f, 1.0F) == 0) {
+            return FLOAT_1;
+        }
+        return new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(f));
+    }
+
+    /**
+     * Creates a boxed long constant.
+     *
+     * @param i the long value to box
+     * @return a boxed copy of {@code value}
+     */
+    static PrimitiveConstant forLong(long i) {
+        if (i == 0) {
+            return LONG_0;
+        } else if (i == 1) {
+            return LONG_1;
+        } else {
+            return new PrimitiveConstant(JavaKind.Long, i);
+        }
+    }
+
+    /**
+     * Creates a boxed integer constant.
+     *
+     * @param i the integer value to box
+     * @return a boxed copy of {@code value}
+     */
+    static PrimitiveConstant forInt(int i) {
+        switch (i) {
+            case -1:
+                return INT_MINUS_1;
+            case 0:
+                return INT_0;
+            case 1:
+                return INT_1;
+            case 2:
+                return INT_2;
+            default:
+                return new PrimitiveConstant(JavaKind.Int, i);
+        }
+    }
+
+    /**
+     * Creates a boxed byte constant.
+     *
+     * @param i the byte value to box
+     * @return a boxed copy of {@code value}
+     */
+    static PrimitiveConstant forByte(byte i) {
+        return new PrimitiveConstant(JavaKind.Byte, i);
+    }
+
+    /**
+     * Creates a boxed boolean constant.
+     *
+     * @param i the boolean value to box
+     * @return a boxed copy of {@code value}
+     */
+    static PrimitiveConstant forBoolean(boolean i) {
+        return i ? TRUE : FALSE;
+    }
+
+    /**
+     * Creates a boxed char constant.
+     *
+     * @param i the char value to box
+     * @return a boxed copy of {@code value}
+     */
+    static PrimitiveConstant forChar(char i) {
+        return new PrimitiveConstant(JavaKind.Char, i);
+    }
+
+    /**
+     * Creates a boxed short constant.
+     *
+     * @param i the short value to box
+     * @return a boxed copy of {@code value}
+     */
+    static PrimitiveConstant forShort(short i) {
+        return new PrimitiveConstant(JavaKind.Short, i);
+    }
+
+    /**
+     * Creates a {@link JavaConstant} from a primitive integer of a certain kind.
+     */
+    static PrimitiveConstant forIntegerKind(JavaKind kind, long i) {
+        switch (kind) {
+            case Boolean:
+                return forBoolean(i != 0);
+            case Byte:
+                return forByte((byte) i);
+            case Short:
+                return forShort((short) i);
+            case Char:
+                return forChar((char) i);
+            case Int:
+                return forInt((int) i);
+            case Long:
+                return forLong(i);
+            default:
+                throw new IllegalArgumentException("not an integer kind: " + kind);
+        }
+    }
+
+    /**
+     * Creates a {@link JavaConstant} from a primitive integer of a certain width.
+     */
+    static PrimitiveConstant forPrimitiveInt(int bits, long i) {
+        assert bits <= 64;
+        switch (bits) {
+            case 1:
+                return forBoolean(i != 0);
+            case 8:
+                return forByte((byte) i);
+            case 16:
+                return forShort((short) i);
+            case 32:
+                return forInt((int) i);
+            case 64:
+                return forLong(i);
+            default:
+                throw new IllegalArgumentException("unsupported integer width: " + bits);
+        }
+    }
+
+    /**
+     * Creates a boxed constant for the given boxed primitive value.
+     *
+     * @param value the Java boxed value
+     * @return the primitive constant holding the {@code value}
+     */
+    static PrimitiveConstant forBoxedPrimitive(Object value) {
+        if (value instanceof Boolean) {
+            return forBoolean((Boolean) value);
+        } else if (value instanceof Byte) {
+            return forByte((Byte) value);
+        } else if (value instanceof Character) {
+            return forChar((Character) value);
+        } else if (value instanceof Short) {
+            return forShort((Short) value);
+        } else if (value instanceof Integer) {
+            return forInt((Integer) value);
+        } else if (value instanceof Long) {
+            return forLong((Long) value);
+        } else if (value instanceof Float) {
+            return forFloat((Float) value);
+        } else if (value instanceof Double) {
+            return forDouble((Double) value);
+        } else {
+            return null;
+        }
+    }
+
+    static PrimitiveConstant forIllegal() {
+        return new PrimitiveConstant(JavaKind.Illegal, 0);
+    }
+
+    /**
+     * Returns a constant with the default value for the given kind.
+     */
+    static JavaConstant defaultForKind(JavaKind kind) {
+        switch (kind) {
+            case Boolean:
+                return FALSE;
+            case Byte:
+                return forByte((byte) 0);
+            case Char:
+                return forChar((char) 0);
+            case Short:
+                return forShort((short) 0);
+            case Int:
+                return INT_0;
+            case Double:
+                return DOUBLE_0;
+            case Float:
+                return FLOAT_0;
+            case Long:
+                return LONG_0;
+            case Object:
+                return NULL_POINTER;
+            default:
+                throw new IllegalArgumentException(kind.toString());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.util.IllegalFormatException;
+import java.util.UnknownFormatConversionException;
+
+/**
+ * Represents a reference to a Java field, either resolved or unresolved fields. Fields, like
+ * methods and types, are resolved through {@link ConstantPool constant pools}.
+ */
+public interface JavaField {
+
+    /**
+     * Returns the name of this field.
+     */
+    String getName();
+
+    /**
+     * Returns a {@link JavaType} object that identifies the declared type for this field.
+     */
+    JavaType getType();
+
+    /**
+     * Returns the kind of this field. This is the same as calling {@link #getType}.
+     * {@link JavaType#getJavaKind getJavaKind}.
+     */
+    default JavaKind getJavaKind() {
+        return getType().getJavaKind();
+    }
+
+    /**
+     * Returns the {@link JavaType} object representing the class or interface that declares this
+     * field.
+     */
+    JavaType getDeclaringClass();
+
+    /**
+     * Gets a string for this field formatted according to a given format specification. A format
+     * specification is composed of characters that are to be copied verbatim to the result and
+     * specifiers that denote an attribute of this field that is to be copied to the result. A
+     * specifier is a single character preceded by a '%' character. The accepted specifiers and the
+     * field attributes they denote are described below:
+     *
+     * <pre>
+     *     Specifier | Description                                          | Example(s)
+     *     ----------+------------------------------------------------------------------------------------------
+     *     'T'       | Qualified type                                       | "int" "java.lang.String"
+     *     't'       | Unqualified type                                     | "int" "String"
+     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
+     *     'h'       | Unqualified holder                                   | "Entry"
+     *     'n'       | Field name                                           | "age"
+     *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
+     *     '%'       | A '%' character                                      | "%"
+     * </pre>
+     *
+     * @param format a format specification
+     * @return the result of formatting this field according to {@code format}
+     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
+     */
+    default String format(String format) throws IllegalFormatException {
+        StringBuilder sb = new StringBuilder();
+        int index = 0;
+        JavaType type = getType();
+        while (index < format.length()) {
+            char ch = format.charAt(index++);
+            if (ch == '%') {
+                if (index >= format.length()) {
+                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a field format specification");
+                }
+                char specifier = format.charAt(index++);
+                switch (specifier) {
+                    case 'T':
+                    case 't': {
+                        sb.append(type.toJavaName(specifier == 'T'));
+                        break;
+                    }
+                    case 'H':
+                    case 'h': {
+                        sb.append(getDeclaringClass().toJavaName(specifier == 'H'));
+                        break;
+                    }
+                    case 'n': {
+                        sb.append(getName());
+                        break;
+                    }
+                    case 'f': {
+                        sb.append(!(this instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) this).isStatic() ? "static" : "instance");
+                        break;
+                    }
+                    case '%': {
+                        sb.append('%');
+                        break;
+                    }
+                    default: {
+                        throw new UnknownFormatConversionException(String.valueOf(specifier));
+                    }
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.reflect.Array;
+
+//JaCoCo Exclude
+
+/**
+ * Denotes the basic kinds of types in CRI, including the all the Java primitive types, for example,
+ * {@link JavaKind#Int} for {@code int} and {@link JavaKind#Object} for all object types. A kind has
+ * a single character short name, a Java name, and a set of flags further describing its behavior.
+ */
+public enum JavaKind {
+    /** The primitive boolean kind, represented as an int on the stack. */
+    Boolean('Z', "boolean", 1, true, java.lang.Boolean.TYPE, java.lang.Boolean.class),
+
+    /** The primitive byte kind, represented as an int on the stack. */
+    Byte('B', "byte", 1, true, java.lang.Byte.TYPE, java.lang.Byte.class),
+
+    /** The primitive short kind, represented as an int on the stack. */
+    Short('S', "short", 1, true, java.lang.Short.TYPE, java.lang.Short.class),
+
+    /** The primitive char kind, represented as an int on the stack. */
+    Char('C', "char", 1, true, java.lang.Character.TYPE, java.lang.Character.class),
+
+    /** The primitive int kind, represented as an int on the stack. */
+    Int('I', "int", 1, true, java.lang.Integer.TYPE, java.lang.Integer.class),
+
+    /** The primitive float kind. */
+    Float('F', "float", 1, false, java.lang.Float.TYPE, java.lang.Float.class),
+
+    /** The primitive long kind. */
+    Long('J', "long", 2, false, java.lang.Long.TYPE, java.lang.Long.class),
+
+    /** The primitive double kind. */
+    Double('D', "double", 2, false, java.lang.Double.TYPE, java.lang.Double.class),
+
+    /** The Object kind, also used for arrays. */
+    Object('A', "Object", 1, false, null, null),
+
+    /** The void kind. */
+    Void('V', "void", 0, false, java.lang.Void.TYPE, java.lang.Void.class),
+
+    /** The non-type. */
+    Illegal('-', "illegal", 0, false, null, null);
+
+    private final char typeChar;
+    private final String javaName;
+    private final boolean isStackInt;
+    private final Class<?> primitiveJavaClass;
+    private final Class<?> boxedJavaClass;
+    private final int slotCount;
+
+    JavaKind(char typeChar, String javaName, int slotCount, boolean isStackInt, Class<?> primitiveJavaClass, Class<?> boxedJavaClass) {
+        this.typeChar = typeChar;
+        this.javaName = javaName;
+        this.slotCount = slotCount;
+        this.isStackInt = isStackInt;
+        this.primitiveJavaClass = primitiveJavaClass;
+        this.boxedJavaClass = boxedJavaClass;
+        assert primitiveJavaClass == null || javaName.equals(primitiveJavaClass.getName());
+    }
+
+    /**
+     * Returns the number of stack slots occupied by this kind according to the Java bytecodes
+     * specification.
+     */
+    public int getSlotCount() {
+        return this.slotCount;
+    }
+
+    /**
+     * Returns whether this kind occupied two stack slots.
+     */
+    public boolean needsTwoSlots() {
+        return this.slotCount == 2;
+    }
+
+    /**
+     * Returns the name of the kind as a single upper case character. For the void and primitive
+     * kinds, this is the <i>FieldType</i> term in
+     * <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2-200">
+     * table 4.3-A</a> of the JVM Specification. For {@link #Object}, the character {@code 'A'} is
+     * returned and for {@link #Illegal}, {@code '-'} is returned.
+     */
+    public char getTypeChar() {
+        return typeChar;
+    }
+
+    /**
+     * Returns the name of this kind which will also be it Java programming language name if it is
+     * {@linkplain #isPrimitive() primitive} or {@code void}.
+     */
+    public String getJavaName() {
+        return javaName;
+    }
+
+    /**
+     * Checks whether this type is a Java primitive type.
+     *
+     * @return {@code true} if this is {@link #Boolean}, {@link #Byte}, {@link #Char},
+     *         {@link #Short}, {@link #Int}, {@link #Long}, {@link #Float}, {@link #Double}, or
+     *         {@link #Void}.
+     */
+    public boolean isPrimitive() {
+        return primitiveJavaClass != null;
+    }
+
+    /**
+     * Returns the kind that represents this kind when on the Java operand stack.
+     *
+     * @return the kind used on the operand stack
+     */
+    public JavaKind getStackKind() {
+        if (isStackInt) {
+            return Int;
+        }
+        return this;
+    }
+
+    /**
+     * Checks whether this type is a Java primitive type representing an integer number.
+     *
+     * @return {@code true} if the stack kind is {@link #Int} or {@link #Long}.
+     */
+    public boolean isNumericInteger() {
+        return isStackInt || this == JavaKind.Long;
+    }
+
+    /**
+     * Checks whether this type is a Java primitive type representing an unsigned number.
+     *
+     * @return {@code true} if the kind is {@link #Boolean} or {@link #Char}.
+     */
+    public boolean isUnsigned() {
+        return this == JavaKind.Boolean || this == JavaKind.Char;
+    }
+
+    /**
+     * Checks whether this type is a Java primitive type representing a floating point number.
+     *
+     * @return {@code true} if this is {@link #Float} or {@link #Double}.
+     */
+    public boolean isNumericFloat() {
+        return this == JavaKind.Float || this == JavaKind.Double;
+    }
+
+    /**
+     * Checks whether this represent an Object of some sort.
+     *
+     * @return {@code true} if this is {@link #Object}.
+     */
+    public boolean isObject() {
+        return this == JavaKind.Object;
+    }
+
+    /**
+     * Returns the kind corresponding to the Java type string.
+     *
+     * @param typeString the Java type string
+     * @return the kind
+     */
+    public static JavaKind fromTypeString(String typeString) {
+        assert typeString.length() > 0;
+        final char first = typeString.charAt(0);
+        if (first == '[' || first == 'L') {
+            return JavaKind.Object;
+        }
+        return JavaKind.fromPrimitiveOrVoidTypeChar(first);
+    }
+
+    /**
+     * Returns the kind of a word given the size of a word in bytes.
+     *
+     * @param wordSizeInBytes the size of a word in bytes
+     * @return the kind representing a word value
+     */
+    public static JavaKind fromWordSize(int wordSizeInBytes) {
+        if (wordSizeInBytes == 8) {
+            return JavaKind.Long;
+        } else {
+            assert wordSizeInBytes == 4 : "Unsupported word size!";
+            return JavaKind.Int;
+        }
+    }
+
+    /**
+     * Returns the kind from the character describing a primitive or void.
+     *
+     * @param ch the character for a void or primitive kind as returned by {@link #getTypeChar()}
+     * @return the kind
+     */
+    public static JavaKind fromPrimitiveOrVoidTypeChar(char ch) {
+        switch (ch) {
+            case 'Z':
+                return Boolean;
+            case 'C':
+                return Char;
+            case 'F':
+                return Float;
+            case 'D':
+                return Double;
+            case 'B':
+                return Byte;
+            case 'S':
+                return Short;
+            case 'I':
+                return Int;
+            case 'J':
+                return Long;
+            case 'V':
+                return Void;
+        }
+        throw new IllegalArgumentException("unknown primitive or void type character: " + ch);
+    }
+
+    /**
+     * Returns the Kind representing the given Java class.
+     *
+     * @param klass the class
+     * @return the kind
+     */
+    public static JavaKind fromJavaClass(Class<?> klass) {
+        if (klass == Boolean.primitiveJavaClass) {
+            return Boolean;
+        } else if (klass == Byte.primitiveJavaClass) {
+            return Byte;
+        } else if (klass == Short.primitiveJavaClass) {
+            return Short;
+        } else if (klass == Char.primitiveJavaClass) {
+            return Char;
+        } else if (klass == Int.primitiveJavaClass) {
+            return Int;
+        } else if (klass == Long.primitiveJavaClass) {
+            return Long;
+        } else if (klass == Float.primitiveJavaClass) {
+            return Float;
+        } else if (klass == Double.primitiveJavaClass) {
+            return Double;
+        } else if (klass == Void.primitiveJavaClass) {
+            return Void;
+        } else {
+            return Object;
+        }
+    }
+
+    /**
+     * Returns the Java class representing this kind.
+     *
+     * @return the Java class
+     */
+    public Class<?> toJavaClass() {
+        return primitiveJavaClass;
+    }
+
+    /**
+     * Returns the Java class for instances of boxed values of this kind.
+     *
+     * @return the Java class
+     */
+    public Class<?> toBoxedJavaClass() {
+        return boxedJavaClass;
+    }
+
+    /**
+     * Converts this value type to a string.
+     */
+    @Override
+    public String toString() {
+        return javaName;
+    }
+
+    /**
+     * Marker interface for types that should be {@linkplain JavaKind#format(Object) formatted} with
+     * their {@link Object#toString()} value. Calling {@link Object#toString()} on other objects
+     * poses a security risk because it can potentially call user code.
+     */
+    public interface FormatWithToString {
+    }
+
+    /**
+     * Classes for which invoking {@link Object#toString()} does not run user code.
+     */
+    private static boolean isToStringSafe(Class<?> c) {
+        return c == Boolean.class || c == Byte.class || c == Character.class || c == Short.class || c == Integer.class || c == Float.class || c == Long.class || c == Double.class;
+    }
+
+    /**
+     * Gets a formatted string for a given value of this kind.
+     *
+     * @param value a value of this kind
+     * @return a formatted string for {@code value} based on this kind
+     */
+    public String format(Object value) {
+        if (isPrimitive()) {
+            assert isToStringSafe(value.getClass());
+            return value.toString();
+        } else {
+            if (value == null) {
+                return "null";
+            } else {
+                if (value instanceof String) {
+                    String s = (String) value;
+                    if (s.length() > 50) {
+                        return "String:\"" + s.substring(0, 30) + "...\"";
+                    } else {
+                        return "String:\"" + s + '"';
+                    }
+                } else if (value instanceof JavaType) {
+                    return "JavaType:" + ((JavaType) value).toJavaName();
+                } else if (value instanceof Enum) {
+                    return MetaUtil.getSimpleName(value.getClass(), true) + ":" + ((Enum<?>) value).name();
+                } else if (value instanceof FormatWithToString) {
+                    return MetaUtil.getSimpleName(value.getClass(), true) + ":" + String.valueOf(value);
+                } else if (value instanceof Class<?>) {
+                    return "Class:" + ((Class<?>) value).getName();
+                } else if (isToStringSafe(value.getClass())) {
+                    return value.toString();
+                } else if (value.getClass().isArray()) {
+                    return formatArray(value);
+                } else {
+                    return MetaUtil.getSimpleName(value.getClass(), true) + "@" + System.identityHashCode(value);
+                }
+            }
+        }
+    }
+
+    private static final int MAX_FORMAT_ARRAY_LENGTH = 5;
+
+    private static String formatArray(Object array) {
+        Class<?> componentType = array.getClass().getComponentType();
+        assert componentType != null;
+        int arrayLength = Array.getLength(array);
+        StringBuilder buf = new StringBuilder(MetaUtil.getSimpleName(componentType, true)).append('[').append(arrayLength).append("]{");
+        int length = Math.min(MAX_FORMAT_ARRAY_LENGTH, arrayLength);
+        boolean primitive = componentType.isPrimitive();
+        for (int i = 0; i < length; i++) {
+            if (primitive) {
+                buf.append(Array.get(array, i));
+            } else {
+                Object o = ((Object[]) array)[i];
+                buf.append(JavaKind.Object.format(o));
+            }
+            if (i != length - 1) {
+                buf.append(", ");
+            }
+        }
+        if (arrayLength != length) {
+            buf.append(", ...");
+        }
+        return buf.append('}').toString();
+    }
+
+    /**
+     * Gets the minimum value that can be represented as a value of this kind.
+     *
+     * @return the minimum value represented as a {@code long}
+     */
+    public long getMinValue() {
+        switch (this) {
+            case Boolean:
+                return 0;
+            case Byte:
+                return java.lang.Byte.MIN_VALUE;
+            case Char:
+                return java.lang.Character.MIN_VALUE;
+            case Short:
+                return java.lang.Short.MIN_VALUE;
+            case Int:
+                return java.lang.Integer.MIN_VALUE;
+            case Long:
+                return java.lang.Long.MIN_VALUE;
+            case Float:
+                return java.lang.Float.floatToRawIntBits(java.lang.Float.MIN_VALUE);
+            case Double:
+                return java.lang.Double.doubleToRawLongBits(java.lang.Double.MIN_VALUE);
+            default:
+                throw new IllegalArgumentException("illegal call to minValue on " + this);
+        }
+    }
+
+    /**
+     * Gets the maximum value that can be represented as a value of this kind.
+     *
+     * @return the maximum value represented as a {@code long}
+     */
+    public long getMaxValue() {
+        switch (this) {
+            case Boolean:
+                return 1;
+            case Byte:
+                return java.lang.Byte.MAX_VALUE;
+            case Char:
+                return java.lang.Character.MAX_VALUE;
+            case Short:
+                return java.lang.Short.MAX_VALUE;
+            case Int:
+                return java.lang.Integer.MAX_VALUE;
+            case Long:
+                return java.lang.Long.MAX_VALUE;
+            case Float:
+                return java.lang.Float.floatToRawIntBits(java.lang.Float.MAX_VALUE);
+            case Double:
+                return java.lang.Double.doubleToRawLongBits(java.lang.Double.MAX_VALUE);
+            default:
+                throw new IllegalArgumentException("illegal call to maxValue on " + this);
+        }
+    }
+
+    /**
+     * Number of bytes that are necessary to represent a value of this kind.
+     *
+     * @return the number of bytes
+     */
+    public int getByteCount() {
+        if (this == Boolean) {
+            return 1;
+        } else {
+            return getBitCount() >> 3;
+        }
+    }
+
+    /**
+     * Number of bits that are necessary to represent a value of this kind.
+     *
+     * @return the number of bits
+     */
+    public int getBitCount() {
+        switch (this) {
+            case Boolean:
+                return 1;
+            case Byte:
+                return 8;
+            case Char:
+            case Short:
+                return 16;
+            case Float:
+                return 32;
+            case Int:
+                return 32;
+            case Double:
+                return 64;
+            case Long:
+                return 64;
+            default:
+                throw new IllegalArgumentException("illegal call to bits on " + this);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2009, 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 jdk.vm.ci.meta;
+
+import java.util.IllegalFormatException;
+import java.util.UnknownFormatConversionException;
+
+/**
+ * Represents a reference to a Java method, either resolved or unresolved. Methods, like fields and
+ * types, are resolved through {@link ConstantPool constant pools}.
+ */
+public interface JavaMethod {
+
+    /**
+     * Returns the name of this method.
+     */
+    String getName();
+
+    /**
+     * Returns the {@link JavaType} object representing the class or interface that declares this
+     * method.
+     */
+    JavaType getDeclaringClass();
+
+    /**
+     * Returns the signature of this method.
+     */
+    Signature getSignature();
+
+    /**
+     * Gets a string for this method formatted according to a given format specification. A format
+     * specification is composed of characters that are to be copied verbatim to the result and
+     * specifiers that denote an attribute of this method that is to be copied to the result. A
+     * specifier is a single character preceded by a '%' character. The accepted specifiers and the
+     * method attributes they denote are described below:
+     *
+     * <pre>
+     *     Specifier | Description                                          | Example(s)
+     *     ----------+------------------------------------------------------------------------------------------
+     *     'R'       | Qualified return type                                | "int" "java.lang.String"
+     *     'r'       | Unqualified return type                              | "int" "String"
+     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
+     *     'h'       | Unqualified holder                                   | "Entry"
+     *     'n'       | Method name                                          | "add"
+     *     'P'       | Qualified parameter types, separated by ', '         | "int, java.lang.String"
+     *     'p'       | Unqualified parameter types, separated by ', '       | "int, String"
+     *     'f'       | Indicator if method is unresolved, static or virtual | "unresolved" "static" "virtual"
+     *     '%'       | A '%' character                                      | "%"
+     * </pre>
+     *
+     * @param format a format specification
+     * @return the result of formatting this method according to {@code format}
+     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
+     */
+    default String format(String format) throws IllegalFormatException {
+        StringBuilder sb = new StringBuilder();
+        int index = 0;
+        Signature sig = null;
+        while (index < format.length()) {
+            char ch = format.charAt(index++);
+            if (ch == '%') {
+                if (index >= format.length()) {
+                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a method format specification");
+                }
+                char specifier = format.charAt(index++);
+                switch (specifier) {
+                    case 'R':
+                    case 'r': {
+                        if (sig == null) {
+                            sig = getSignature();
+                        }
+                        sb.append(sig.getReturnType(null).toJavaName(specifier == 'R'));
+                        break;
+                    }
+                    case 'H':
+                    case 'h': {
+                        sb.append(getDeclaringClass().toJavaName(specifier == 'H'));
+                        break;
+                    }
+                    case 'n': {
+                        sb.append(getName());
+                        break;
+                    }
+                    case 'P':
+                    case 'p': {
+                        if (sig == null) {
+                            sig = getSignature();
+                        }
+                        for (int i = 0; i < sig.getParameterCount(false); i++) {
+                            if (i != 0) {
+                                sb.append(", ");
+                            }
+                            sb.append(sig.getParameterType(i, null).toJavaName(specifier == 'P'));
+                        }
+                        break;
+                    }
+                    case 'f': {
+                        sb.append(!(this instanceof ResolvedJavaMethod) ? "unresolved" : ((ResolvedJavaMethod) this).isStatic() ? "static" : "virtual");
+                        break;
+                    }
+                    case '%': {
+                        sb.append('%');
+                        break;
+                    }
+                    default: {
+                        throw new UnknownFormatConversionException(String.valueOf(specifier));
+                    }
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod;
+
+/**
+ * This profile object represents the method profile at a specific BCI. The precision of the
+ * supplied values may vary, but a runtime that provides this information should be aware that it
+ * will be used to guide performance-critical decisions like speculative inlining, etc.
+ */
+public final class JavaMethodProfile extends AbstractJavaProfile<ProfiledMethod, ResolvedJavaMethod> {
+
+    public JavaMethodProfile(double notRecordedProbability, ProfiledMethod[] pitems) {
+        super(notRecordedProbability, pitems);
+    }
+
+    public ProfiledMethod[] getMethods() {
+        return super.getItems();
+    }
+
+    public static class ProfiledMethod extends AbstractProfiledItem<ResolvedJavaMethod> {
+
+        public ProfiledMethod(ResolvedJavaMethod method, double probability) {
+            super(method, probability);
+        }
+
+        /**
+         * Returns the type for this profile entry.
+         */
+        public ResolvedJavaMethod getMethod() {
+            return getItem();
+        }
+
+        @Override
+        public String toString() {
+            return "{" + item.getName() + ", " + probability + "}";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import static jdk.vm.ci.meta.MetaUtil.internalNameToJava;
+
+/**
+ * Represents a resolved or unresolved type. Types include primitives, objects, {@code void}, and
+ * arrays thereof.
+ */
+public interface JavaType {
+
+    /**
+     * Returns the name of this type in internal form. The following are examples of strings
+     * returned by this method:
+     *
+     * <pre>
+     *     "Ljava/lang/Object;"
+     *     "I"
+     *     "[[B"
+     * </pre>
+     */
+    String getName();
+
+    /**
+     * Returns an unqualified name of this type.
+     *
+     * <pre>
+     *     "Object"
+     *     "Integer"
+     * </pre>
+     */
+    default String getUnqualifiedName() {
+        String name = getName();
+        if (name.indexOf('/') != -1) {
+            name = name.substring(name.lastIndexOf('/') + 1);
+        }
+        if (name.endsWith(";")) {
+            name = name.substring(0, name.length() - 1);
+        }
+        return name;
+    }
+
+    /**
+     * Checks whether this type is an array class.
+     *
+     * @return {@code true} if this type is an array class
+     */
+    default boolean isArray() {
+        return getComponentType() != null;
+    }
+
+    /**
+     * For array types, gets the type of the components, or {@code null} if this is not an array
+     * type. This method is analogous to {@link Class#getComponentType()}.
+     */
+    JavaType getComponentType();
+
+    /**
+     * Gets the elemental type for this given type. The elemental type is the corresponding zero
+     * dimensional type of an array type. For example, the elemental type of {@code int[][][]} is
+     * {@code int}. A non-array type is its own elemental type.
+     */
+    default JavaType getElementalType() {
+        JavaType t = this;
+        while (t.getComponentType() != null) {
+            t = t.getComponentType();
+        }
+        return t;
+    }
+
+    /**
+     * Gets the array class type representing an array with elements of this type.
+     */
+    JavaType getArrayClass();
+
+    /**
+     * Gets the {@link JavaKind} of this type.
+     */
+    JavaKind getJavaKind();
+
+    /**
+     * Resolves this type to a {@link ResolvedJavaType}.
+     *
+     * @param accessingClass the context of resolution (must not be null)
+     * @return the resolved Java type
+     * @throws LinkageError if the resolution failed
+     * @throws NullPointerException if {@code accessingClass} is {@code null}
+     */
+    ResolvedJavaType resolve(ResolvedJavaType accessingClass);
+
+    /**
+     * Gets the Java programming language name for this type. The following are examples of strings
+     * returned by this method:
+     *
+     * <pre>
+     *      java.lang.Object
+     *      int
+     *      boolean[][]
+     * </pre>
+     *
+     * @return the Java name corresponding to this type
+     */
+    default String toJavaName() {
+        return internalNameToJava(getName(), true, false);
+    }
+
+    /**
+     * Gets the Java programming language name for this type. The following are examples of strings
+     * returned by this method:
+     *
+     * <pre>
+     *     qualified == true:
+     *         java.lang.Object
+     *         int
+     *         boolean[][]
+     *     qualified == false:
+     *         Object
+     *         int
+     *         boolean[][]
+     * </pre>
+     *
+     * @param qualified specifies if the package prefix of this type should be included in the
+     *            returned name
+     * @return the Java name corresponding to this type
+     */
+    default String toJavaName(boolean qualified) {
+        JavaKind kind = getJavaKind();
+        if (kind == JavaKind.Object) {
+            return internalNameToJava(getName(), qualified, false);
+        }
+        return getJavaKind().getJavaName();
+    }
+
+    /**
+     * Returns this type's name in the same format as {@link Class#getName()}.
+     */
+    default String toClassName() {
+        return internalNameToJava(getName(), true, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2011, 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 jdk.vm.ci.meta;
+
+import java.util.ArrayList;
+
+import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
+
+/**
+ * This profile object represents the type profile at a specific BCI. The precision of the supplied
+ * values may vary, but a runtime that provides this information should be aware that it will be
+ * used to guide performance-critical decisions like speculative inlining, etc.
+ */
+public final class JavaTypeProfile extends AbstractJavaProfile<ProfiledType, ResolvedJavaType> {
+
+    private static final ProfiledType[] EMPTY_ARRAY = new ProfiledType[0];
+
+    private final TriState nullSeen;
+
+    public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType[] pitems) {
+        super(notRecordedProbability, pitems);
+        this.nullSeen = nullSeen;
+    }
+
+    /**
+     * Returns whether a null value was at the type check.
+     */
+    public TriState getNullSeen() {
+        return nullSeen;
+    }
+
+    /**
+     * A list of types for which the runtime has recorded probability information. Note that this
+     * includes both positive and negative types where a positive type is a subtype of the checked
+     * type and a negative type is not.
+     */
+    public ProfiledType[] getTypes() {
+        return getItems();
+    }
+
+    public JavaTypeProfile restrict(JavaTypeProfile otherProfile) {
+        if (otherProfile.getNotRecordedProbability() > 0.0) {
+            // Not useful for restricting since there is an unknown set of types occurring.
+            return this;
+        }
+
+        if (this.getNotRecordedProbability() > 0.0) {
+            // We are unrestricted, so the other profile is always a better estimate.
+            return otherProfile;
+        }
+
+        ArrayList<ProfiledType> result = new ArrayList<>();
+        for (int i = 0; i < getItems().length; i++) {
+            ProfiledType ptype = getItems()[i];
+            ResolvedJavaType type = ptype.getItem();
+            if (otherProfile.isIncluded(type)) {
+                result.add(ptype);
+            }
+        }
+
+        TriState newNullSeen = (otherProfile.getNullSeen() == TriState.FALSE) ? TriState.FALSE : getNullSeen();
+        double newNotRecorded = getNotRecordedProbability();
+        return createAdjustedProfile(result, newNullSeen, newNotRecorded);
+    }
+
+    public JavaTypeProfile restrict(ResolvedJavaType declaredType, boolean nonNull) {
+        ArrayList<ProfiledType> result = new ArrayList<>();
+        for (int i = 0; i < getItems().length; i++) {
+            ProfiledType ptype = getItems()[i];
+            ResolvedJavaType type = ptype.getItem();
+            if (declaredType.isAssignableFrom(type)) {
+                result.add(ptype);
+            }
+        }
+
+        TriState newNullSeen = (nonNull) ? TriState.FALSE : getNullSeen();
+        double newNotRecorded = this.getNotRecordedProbability();
+        // Assume for the types not recorded, the incompatibility rate is the same.
+        if (getItems().length != 0) {
+            newNotRecorded *= ((double) result.size() / (double) getItems().length);
+        }
+        return createAdjustedProfile(result, newNullSeen, newNotRecorded);
+    }
+
+    private JavaTypeProfile createAdjustedProfile(ArrayList<ProfiledType> result, TriState newNullSeen, double newNotRecorded) {
+        if (result.size() != this.getItems().length || newNotRecorded != getNotRecordedProbability() || newNullSeen != getNullSeen()) {
+            if (result.size() == 0) {
+                return new JavaTypeProfile(newNullSeen, 1.0, EMPTY_ARRAY);
+            }
+            double factor;
+            if (result.size() == this.getItems().length) {
+                /* List of types did not change, no need to recompute probabilities. */
+                factor = 1.0;
+            } else {
+                double probabilitySum = 0.0;
+                for (int i = 0; i < result.size(); i++) {
+                    probabilitySum += result.get(i).getProbability();
+                }
+                probabilitySum += newNotRecorded;
+
+                factor = 1.0 / probabilitySum; // Normalize to 1.0
+                assert factor >= 1.0;
+            }
+            ProfiledType[] newResult = new ProfiledType[result.size()];
+            for (int i = 0; i < newResult.length; ++i) {
+                ProfiledType curType = result.get(i);
+                newResult[i] = new ProfiledType(curType.getItem(), Math.min(1.0, curType.getProbability() * factor));
+            }
+            double newNotRecordedTypeProbability = Math.min(1.0, newNotRecorded * factor);
+            return new JavaTypeProfile(newNullSeen, newNotRecordedTypeProbability, newResult);
+        }
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        return super.equals(other) && nullSeen.equals(((JavaTypeProfile) other).nullSeen);
+    }
+
+    @Override
+    public int hashCode() {
+        return nullSeen.hashCode() + super.hashCode();
+    }
+
+    public static class ProfiledType extends AbstractProfiledItem<ResolvedJavaType> {
+
+        public ProfiledType(ResolvedJavaType type, double probability) {
+            super(type, probability);
+            assert type.isArray() || type.isConcrete() : type;
+        }
+
+        /**
+         * Returns the type for this profile entry.
+         */
+        public ResolvedJavaType getType() {
+            return getItem();
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%.6f#%s", probability, item);
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder("JavaTypeProfile<nullSeen=").append(getNullSeen()).append(", types=[");
+        for (int j = 0; j < getTypes().length; j++) {
+            if (j != 0) {
+                buf.append(", ");
+            }
+            ProfiledType ptype = getTypes()[j];
+            buf.append(String.format("%.6f:%s", ptype.getProbability(), ptype.getType()));
+        }
+        return buf.append(String.format("], notRecorded:%.6f>", getNotRecordedProbability())).toString();
+    }
+
+    /**
+     * Returns {@code true} if all types seen at this location have been recorded in the profile.
+     */
+    public boolean allTypesRecorded() {
+        return this.getNotRecordedProbability() == 0.0;
+    }
+
+    /**
+     * Returns the single monormorphic type representing this profile or {@code null} if no such
+     * type exists.
+     */
+    public ResolvedJavaType asSingleType() {
+        if (allTypesRecorded() && this.getTypes().length == 1) {
+            return getTypes()[0].getType();
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaValue.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Marker interface for things that represent a Java value.
+ */
+public interface JavaValue {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LineNumberTable.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,75 @@
+/*
+ * 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 jdk.vm.ci.meta;
+
+/**
+ * Maps bytecode indexes to source line numbers.
+ *
+ * @see "https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.12"
+ */
+public class LineNumberTable {
+
+    private final int[] lineNumbers;
+    private final int[] bcis;
+
+    /**
+     *
+     * @param lineNumbers an array of source line numbers. This array is now owned by this object
+     *            and should not be mutated by the caller.
+     * @param bcis an array of bytecode indexes the same length at {@code lineNumbers} whose entries
+     *            are sorted in ascending order. This array is now owned by this object and must not
+     *            be mutated by the caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `lineNumbers` and `bcis`")
+    public LineNumberTable(int[] lineNumbers, int[] bcis) {
+        assert bcis.length == lineNumbers.length;
+        this.lineNumbers = lineNumbers;
+        this.bcis = bcis;
+    }
+
+    /**
+     * Gets a source line number for bytecode index {@code atBci}.
+     */
+    public int getLineNumber(int atBci) {
+        for (int i = 0; i < this.bcis.length - 1; i++) {
+            if (this.bcis[i] <= atBci && atBci < this.bcis[i + 1]) {
+                return lineNumbers[i];
+            }
+        }
+        return lineNumbers[lineNumbers.length - 1];
+    }
+
+    /**
+     * Gets a copy of the array of line numbers that was passed to this object's constructor.
+     */
+    public int[] getLineNumbers() {
+        return lineNumbers.clone();
+    }
+
+    /**
+     * Gets a copy of the array of bytecode indexes that was passed to this object's constructor.
+     */
+    public int[] getBcis() {
+        return bcis.clone();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Local.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,82 @@
+/*
+ * 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 jdk.vm.ci.meta;
+
+/**
+ * Describes the type and bytecode index range in which a local variable is live.
+ */
+public class Local {
+
+    private final String name;
+    private final int startBci;
+    private final int endBci;
+    private final int slot;
+    private final JavaType type;
+
+    public Local(String name, JavaType type, int startBci, int endBci, int slot) {
+        this.name = name;
+        this.startBci = startBci;
+        this.endBci = endBci;
+        this.slot = slot;
+        this.type = type;
+    }
+
+    public int getStartBCI() {
+        return startBci;
+    }
+
+    public int getEndBCI() {
+        return endBci;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public JavaType getType() {
+        return type;
+    }
+
+    public int getSlot() {
+        return slot;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof Local)) {
+            return false;
+        }
+        Local that = (Local) obj;
+        return this.name.equals(that.name) && this.startBci == that.startBci && this.endBci == that.endBci && this.slot == that.slot && this.type.equals(that.type);
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "LocalImpl<name=" + name + ", type=" + type + ", startBci=" + startBci + ", endBci=" + endBci + ", slot=" + slot + ">";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTable.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,88 @@
+/*
+ * 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 jdk.vm.ci.meta;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Describes the {@link Local}s for a Java method.
+ *
+ * @see "https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.13"
+ */
+public class LocalVariableTable {
+
+    private final Local[] locals;
+
+    /**
+     * Creates an object describing the {@link Local}s for a Java method.
+     *
+     * @param locals array of objects describing local variables. This array is now owned by this
+     *            object and must not be mutated by the caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `locals`")
+    public LocalVariableTable(Local[] locals) {
+        this.locals = locals;
+    }
+
+    /**
+     * Gets a description of a local variable that occupies the bytecode frame slot indexed by
+     * {@code slot} and is live at the bytecode index {@code bci}.
+     *
+     * @return a description of the requested local variable or null if no such variable matches
+     *         {@code slot} and {@code bci}
+     */
+    public Local getLocal(int slot, int bci) {
+        Local result = null;
+        for (Local local : locals) {
+            if (local.getSlot() == slot && local.getStartBCI() <= bci && local.getEndBCI() >= bci) {
+                if (result == null) {
+                    result = local;
+                } else {
+                    throw new IllegalStateException("Locals overlap!");
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Gets a copy of the array of {@link Local}s that was passed to this object's constructor.
+     */
+    public Local[] getLocals() {
+        return locals.clone();
+    }
+
+    /**
+     * Gets a description of all the local variables live at the bytecode index {@code bci}.
+     */
+    public Local[] getLocalsAt(int bci) {
+        List<Local> result = new ArrayList<>();
+        for (Local l : locals) {
+            if (l.getStartBCI() <= bci && bci <= l.getEndBCI()) {
+                result.add(l);
+            }
+        }
+        return result.toArray(new Local[result.size()]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MemoryAccessProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Provides memory access operations for the target VM.
+ */
+public interface MemoryAccessProvider {
+
+    /**
+     * Reads a primitive value using a base address and a displacement.
+     *
+     * @param kind the {@link JavaKind} of the returned {@link JavaConstant} object
+     * @param base the base address from which the value is read
+     * @param displacement the displacement within the object in bytes
+     * @param bits the number of bits to read from memory
+     * @return the read value encapsulated in a {@link JavaConstant} object of {@link JavaKind} kind
+     * @throws IllegalArgumentException if {@code kind} is {@link JavaKind#Void} or not
+     *             {@linkplain JavaKind#isPrimitive() primitive} kind or {@code bits} is not 8, 16,
+     *             32 or 64
+     */
+    JavaConstant readPrimitiveConstant(JavaKind kind, Constant base, long displacement, int bits) throws IllegalArgumentException;
+
+    /**
+     * Reads a Java {@link Object} value using a base address and a displacement.
+     *
+     * @param base the base address from which the value is read
+     * @param displacement the displacement within the object in bytes
+     * @return the read value encapsulated in a {@link Constant} object or {@code null} if the
+     *         address computed from {@code base} and {@code displacement} does not denote a
+     *         location holding an {@code Object} value
+     */
+    JavaConstant readObjectConstant(Constant base, long displacement);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Provides access to the metadata of a class typically provided in a class file.
+ */
+public interface MetaAccessProvider {
+
+    /**
+     * Returns the resolved Java type representing a given Java class.
+     *
+     * @param clazz the Java class object
+     * @return the resolved Java type object
+     */
+    ResolvedJavaType lookupJavaType(Class<?> clazz);
+
+    /**
+     * Returns the resolved Java types representing some given Java classes.
+     *
+     * @param classes the Java class objects
+     * @return the resolved Java type objects
+     */
+    default ResolvedJavaType[] lookupJavaTypes(Class<?>[] classes) {
+        ResolvedJavaType[] result = new ResolvedJavaType[classes.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = lookupJavaType(classes[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Provides the {@link ResolvedJavaMethod} for a {@link Method} or {@link Constructor} obtained
+     * via reflection.
+     */
+    ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod);
+
+    /**
+     * Provides the {@link ResolvedJavaField} for a {@link Field} obtained via reflection.
+     */
+    ResolvedJavaField lookupJavaField(Field reflectionField);
+
+    /**
+     * Returns the resolved Java type of the given {@link JavaConstant} object.
+     *
+     * @return {@code null} if {@code constant.isNull() || !constant.kind.isObject()}
+     */
+    ResolvedJavaType lookupJavaType(JavaConstant constant);
+
+    /**
+     * Returns the number of bytes occupied by this constant value or constant object.
+     *
+     * @param constant the constant whose bytes should be measured
+     * @return the number of bytes occupied by this constant
+     */
+    long getMemorySize(JavaConstant constant);
+
+    /**
+     * Parses a
+     * <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
+     * descriptor</a> into a {@link Signature}. The behavior of this method is undefined if the
+     * method descriptor is not well formed.
+     */
+    Signature parseMethodDescriptor(String methodDescriptor);
+
+    /**
+     * Encodes a deoptimization action and a deoptimization reason in an integer value.
+     *
+     * @param debugId an integer that can be used to track the origin of a deoptimization at
+     *            runtime. There is no guarantee that the runtime will use this value. The runtime
+     *            may even keep fewer than 32 bits.
+     *
+     * @return the encoded value as an integer
+     */
+    JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId);
+
+    DeoptimizationReason decodeDeoptReason(JavaConstant constant);
+
+    DeoptimizationAction decodeDeoptAction(JavaConstant constant);
+
+    int decodeDebugId(JavaConstant constant);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients.
+ */
+public class MetaUtil {
+
+    /**
+     * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for
+     * anonymous and local classes.
+     *
+     * @param clazz the class for which the simple name is being requested
+     * @param withEnclosingClass specifies if the returned name should be qualified with the name(s)
+     *            of the enclosing class/classes of {@code clazz} (if any). This option is ignored
+     *            if {@code clazz} denotes an anonymous or local class.
+     * @return the simple name
+     */
+    public static String getSimpleName(Class<?> clazz, boolean withEnclosingClass) {
+        String simpleName = null;
+        try {
+            simpleName = clazz.getSimpleName();
+        } catch (InternalError e) {
+        }
+        if (simpleName != null && simpleName.length() != 0) {
+            if (withEnclosingClass) {
+                String prefix = "";
+                Class<?> enclosingClass = clazz;
+                while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) {
+                    prefix = enclosingClass.getSimpleName() + "." + prefix;
+                }
+                return prefix + simpleName;
+            }
+            return simpleName;
+        }
+        // Must be an anonymous or local class
+        final String name = clazz.getName();
+        int index = name.lastIndexOf('.');
+        return name.substring(index + 1);
+    }
+
+    /**
+     * Converts a type name in internal form to an external form.
+     *
+     * @param name the internal name to convert
+     * @param qualified whether the returned name should be qualified with the package name
+     * @param classForNameCompatible specifies if the returned name for array types should be in
+     *            {@link Class#forName(String)} format (e.g., {@code "[Ljava.lang.Object;"},
+     *            {@code "[[I"}) or in Java source code format (e.g., {@code "java.lang.Object[]"},
+     *            {@code "int[][]"} ).
+     */
+    public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) {
+        switch (name.charAt(0)) {
+            case 'L': {
+                String result = name.substring(1, name.length() - 1).replace('/', '.');
+                if (!qualified) {
+                    final int lastDot = result.lastIndexOf('.');
+                    if (lastDot != -1) {
+                        result = result.substring(lastDot + 1);
+                    }
+                }
+                return result;
+            }
+            case '[':
+                return classForNameCompatible ? name.replace('/', '.') : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]";
+            default:
+                if (name.length() != 1) {
+                    throw new IllegalArgumentException("Illegal internal name: " + name);
+                }
+                return JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)).getJavaName();
+        }
+    }
+
+    /**
+     * Convenient shortcut for calling
+     * {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a
+     * {@link StringBuilder} instance and convert the result to a string.
+     */
+    public static String toLocation(ResolvedJavaMethod method, int bci) {
+        return appendLocation(new StringBuilder(), method, bci).toString();
+    }
+
+    /**
+     * Appends a string representation of a location specified by a given method and bci to a given
+     * {@link StringBuilder}. If a stack trace element with a non-null file name and non-negative
+     * line number is {@linkplain ResolvedJavaMethod#asStackTraceElement(int) available} for the
+     * given method, then the string returned is the {@link StackTraceElement#toString()} value of
+     * the stack trace element, suffixed by the bci location. For example:
+     *
+     * <pre>
+     *     java.lang.String.valueOf(String.java:2930) [bci: 12]
+     * </pre>
+     *
+     * Otherwise, the string returned is the value of applying {@link JavaMethod#format(String)}
+     * with the format string {@code "%H.%n(%p)"}, suffixed by the bci location. For example:
+     *
+     * <pre>
+     *     java.lang.String.valueOf(int) [bci: 12]
+     * </pre>
+     *
+     * @param sb
+     * @param method
+     * @param bci
+     */
+    public static StringBuilder appendLocation(StringBuilder sb, ResolvedJavaMethod method, int bci) {
+        if (method != null) {
+            StackTraceElement ste = method.asStackTraceElement(bci);
+            if (ste.getFileName() != null && ste.getLineNumber() > 0) {
+                sb.append(ste);
+            } else {
+                sb.append(method.format("%H.%n(%p)"));
+            }
+        } else {
+            sb.append("Null method");
+        }
+        return sb.append(" [bci: ").append(bci).append(']');
+    }
+
+    static void appendProfile(StringBuilder buf, AbstractJavaProfile<?, ?> profile, int bci, String type, String sep) {
+        if (profile != null) {
+            AbstractProfiledItem<?>[] pitems = profile.getItems();
+            if (pitems != null) {
+                buf.append(String.format("%s@%d:", type, bci));
+                for (int j = 0; j < pitems.length; j++) {
+                    AbstractProfiledItem<?> pitem = pitems[j];
+                    buf.append(String.format(" %.6f (%s)%s", pitem.getProbability(), pitem.getItem(), sep));
+                }
+                if (profile.getNotRecordedProbability() != 0) {
+                    buf.append(String.format(" %.6f <other %s>%s", profile.getNotRecordedProbability(), type, sep));
+                } else {
+                    buf.append(String.format(" <no other %s>%s", type, sep));
+                }
+            }
+        }
+    }
+
+    /**
+     * Converts a Java source-language class name into the internal form.
+     *
+     * @param className the class name
+     * @return the internal name form of the class name
+     */
+    public static String toInternalName(String className) {
+        if (className.startsWith("[")) {
+            /* Already in the correct array style. */
+            return className.replace('.', '/');
+        }
+
+        StringBuilder result = new StringBuilder();
+        String base = className;
+        while (base.endsWith("[]")) {
+            result.append("[");
+            base = base.substring(0, base.length() - 2);
+        }
+
+        switch (base) {
+            case "boolean":
+                result.append("Z");
+                break;
+            case "byte":
+                result.append("B");
+                break;
+            case "short":
+                result.append("S");
+                break;
+            case "char":
+                result.append("C");
+                break;
+            case "int":
+                result.append("I");
+                break;
+            case "float":
+                result.append("F");
+                break;
+            case "long":
+                result.append("J");
+                break;
+            case "double":
+                result.append("D");
+                break;
+            case "void":
+                result.append("V");
+                break;
+            default:
+                result.append("L").append(base.replace('.', '/')).append(";");
+                break;
+        }
+        return result.toString();
+    }
+
+    /**
+     * Gets a string representation of an object based soley on its class and its
+     * {@linkplain System#identityHashCode(Object) identity hash code}. This avoids and calls to
+     * virtual methods on the object such as {@link Object#hashCode()}.
+     */
+    public static String identityHashCodeString(Object obj) {
+        if (obj == null) {
+            return "null";
+        }
+        return obj.getClass().getName() + "@" + System.identityHashCode(obj);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.invoke.MethodHandle;
+
+/**
+ * Interface to access the internals of the {@link MethodHandle} implementation of the VM. An
+ * implementation of this interface is usually required to access non-public classes, methods, and
+ * fields of {@link MethodHandle}, i.e., data that is not standardized by the Java specification.
+ */
+public interface MethodHandleAccessProvider {
+
+    /**
+     * Identification for methods defined on the class {@link MethodHandle} that are processed by
+     * the {@link MethodHandleAccessProvider}.
+     */
+    enum IntrinsicMethod {
+        /** The method {@code MethodHandle.invokeBasic}. */
+        INVOKE_BASIC,
+        /** The method {@code MethodHandle.linkToStatic}. */
+        LINK_TO_STATIC,
+        /** The method {@code MethodHandle.linkToSpecial}. */
+        LINK_TO_SPECIAL,
+        /** The method {@code MethodHandle.linkToVirtual}. */
+        LINK_TO_VIRTUAL,
+        /** The method {@code MethodHandle.linkToInterface}. */
+        LINK_TO_INTERFACE
+    }
+
+    /**
+     * Returns the method handle method intrinsic identifier for the provided method, or
+     * {@code null} if the method is not an intrinsic processed by this interface.
+     *
+     * @throws NullPointerException if {@code method} is null
+     */
+    IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method);
+
+    /**
+     * Resolves the invocation target for an invocation of {@link IntrinsicMethod#INVOKE_BASIC
+     * MethodHandle.invokeBasic} with the given constant receiver {@link MethodHandle}. Returns
+     * {@code null} if the invocation target is not available at this time.
+     *
+     * The first invocations of a method handle can use an interpreter to lookup the actual invoked
+     * method; frequently executed method handles can use Java bytecode generation to avoid the
+     * interpreter overhead. If the parameter forceBytecodeGeneration is set to true, the VM should
+     * try to generate bytecodes before this method returns.
+     *
+     * @returns {@code null} if {@code methodHandle} is not a {@link MethodHandle} or the invocation
+     *          target is not available at this time
+     * @throws NullPointerException if {@code methodHandle} is null
+     */
+    ResolvedJavaMethod resolveInvokeBasicTarget(JavaConstant methodHandle, boolean forceBytecodeGeneration);
+
+    /**
+     * Resolves the invocation target for an invocation of a {@code MethodHandle.linkTo*} method
+     * with the given constant member name. The member name is the last parameter of the
+     * {@code linkTo*} method.
+     *
+     * @returns {@code null} if the invocation target is not available at this time
+     * @throws NullPointerException if {@code memberName} is null
+     * @throws IllegalArgumentException if {@code memberName} is not a
+     *             {@code java.lang.invoke.MemberName}
+     */
+    ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import static java.lang.reflect.Modifier.FINAL;
+import static java.lang.reflect.Modifier.PRIVATE;
+import static java.lang.reflect.Modifier.PROTECTED;
+import static java.lang.reflect.Modifier.PUBLIC;
+import static java.lang.reflect.Modifier.STATIC;
+import static java.lang.reflect.Modifier.TRANSIENT;
+import static java.lang.reflect.Modifier.VOLATILE;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * A Java element (i.e., a class, interface, field or method) that is described by a set of Java
+ * language {@linkplain #getModifiers() modifiers}.
+ */
+public interface ModifiersProvider {
+
+    /**
+     * Returns the modifiers for this element.
+     */
+    int getModifiers();
+
+    /**
+     * @see Modifier#isInterface(int)
+     */
+    default boolean isInterface() {
+        return Modifier.isInterface(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isSynchronized(int)
+     */
+    default boolean isSynchronized() {
+        return Modifier.isSynchronized(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isStatic(int)
+     */
+    default boolean isStatic() {
+        return Modifier.isStatic(getModifiers());
+    }
+
+    /**
+     * The setting of the final modifier bit for types is somewhat confusing, so don't export
+     * isFinal by default. Subclasses like {@link ResolvedJavaField} and {@link ResolvedJavaMethod}
+     * can export it as isFinal, but {@link ResolvedJavaType} can provide a more sensible equivalent
+     * like {@link ResolvedJavaType#isLeaf}.
+     *
+     * @see Modifier#isFinal(int)
+     */
+    default boolean isFinalFlagSet() {
+        return Modifier.isFinal(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isPublic(int)
+     */
+    default boolean isPublic() {
+        return Modifier.isPublic(getModifiers());
+    }
+
+    /**
+     * Determines if this element is neither {@linkplain #isPublic() public},
+     * {@linkplain #isProtected() protected} nor {@linkplain #isPrivate() private}.
+     */
+    default boolean isPackagePrivate() {
+        return ((PUBLIC | PROTECTED | PRIVATE) & getModifiers()) == 0;
+    }
+
+    /**
+     * @see Modifier#isPrivate(int)
+     */
+    default boolean isPrivate() {
+        return Modifier.isPrivate(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isProtected(int)
+     */
+    default boolean isProtected() {
+        return Modifier.isProtected(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isTransient(int)
+     */
+    default boolean isTransient() {
+        return Modifier.isTransient(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isStrict(int)
+     */
+    default boolean isStrict() {
+        return Modifier.isStrict(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isVolatile(int)
+     */
+    default boolean isVolatile() {
+        return Modifier.isVolatile(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isNative(int)
+     */
+    default boolean isNative() {
+        return Modifier.isNative(getModifiers());
+    }
+
+    /**
+     * @see Modifier#isAbstract(int)
+     */
+    default boolean isAbstract() {
+        return Modifier.isAbstract(getModifiers());
+    }
+
+    /**
+     * Checks that the method is concrete and not abstract.
+     *
+     * @return whether the method is a concrete method
+     */
+    default boolean isConcrete() {
+        return !isAbstract();
+    }
+
+    /**
+     * This is removed in JDK 9 and should not be used. It used to rely on use of reflection to read
+     * non-public values from {@link Modifier}. Such cross-module (i.e., {@code jdk.vm.ci} to
+     * {@code java.base}) reflection is disabled in 9 and will require a VM option such
+     * {@code --add-exports-private} to be enabled.
+     */
+    @Deprecated
+    static int jvmFieldModifiers() {
+        // Reflection replaced with hard coded values (which will not change in JDK 8).
+        final int accEnum = 0x4000;
+        final int accSynthethic = 0x1000;
+        return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | accEnum | accSynthethic;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/NullConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * The implementation type of the {@link JavaConstant#NULL_POINTER null constant}.
+ */
+final class NullConstant implements JavaConstant {
+
+    protected NullConstant() {
+    }
+
+    @Override
+    public JavaKind getJavaKind() {
+        return JavaKind.Object;
+    }
+
+    @Override
+    public boolean isNull() {
+        return true;
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return true;
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public int asInt() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public boolean asBoolean() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public long asLong() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public float asFloat() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public double asDouble() {
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public String toString() {
+        return JavaConstant.toString(this);
+    }
+
+    @Override
+    public String toValueString() {
+        return "null";
+    }
+
+    @Override
+    public int hashCode() {
+        return 13;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof NullConstant;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a platform-specific low-level type for values.
+ */
+public interface PlatformKind {
+
+    String name();
+
+    public interface Key {
+
+    }
+
+    class EnumKey<E extends Enum<E>> implements Key {
+        private final Enum<E> e;
+
+        public EnumKey(Enum<E> e) {
+            this.e = e;
+        }
+
+        @Override
+        public int hashCode() {
+            return e.ordinal();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == this) {
+                return true;
+            }
+            if (obj instanceof EnumKey) {
+                EnumKey<?> that = (EnumKey<?>) obj;
+                return this.e == that.e;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Gets a value associated with this object that can be used as a stable key in a map. The
+     * {@link Object#hashCode()} implementation of the returned value should be stable between VM
+     * executions.
+     */
+    Key getKey();
+
+    /**
+     * Get the size in bytes of this {@link PlatformKind}.
+     */
+    int getSizeInBytes();
+
+    /**
+     * Returns how many primitive values fit in this {@link PlatformKind}. For scalar types this is
+     * one, for SIMD types it may be higher.
+     */
+    int getVectorLength();
+
+    /**
+     * Gets a single type char that identifies this type for use in debug output.
+     */
+    char getTypeChar();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Represents a primitive constant value, such as an integer or floating point number, within the
+ * compiler and across the compiler/runtime interface.
+ */
+public class PrimitiveConstant implements JavaConstant, SerializableConstant {
+
+    private final JavaKind kind;
+
+    /**
+     * The boxed primitive value as a {@code long}. For {@code float} and {@code double} values,
+     * this value is the result of {@link Float#floatToRawIntBits(float)} and
+     * {@link Double#doubleToRawLongBits(double)} respectively.
+     */
+    private final long primitive;
+
+    protected PrimitiveConstant(JavaKind kind, long primitive) {
+        this.primitive = primitive;
+        this.kind = kind;
+
+        assert kind.isPrimitive() || kind == JavaKind.Illegal;
+    }
+
+    @Override
+    public JavaKind getJavaKind() {
+        return kind;
+    }
+
+    @Override
+    public boolean isNull() {
+        return false;
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return primitive == 0;
+    }
+
+    @Override
+    public boolean asBoolean() {
+        assert getJavaKind() == JavaKind.Boolean;
+        return primitive != 0L;
+    }
+
+    @Override
+    public int asInt() {
+        assert getJavaKind().getStackKind() == JavaKind.Int : getJavaKind().getStackKind();
+        return (int) primitive;
+    }
+
+    @Override
+    public long asLong() {
+        assert getJavaKind().isNumericInteger();
+        return primitive;
+    }
+
+    @Override
+    public float asFloat() {
+        assert getJavaKind() == JavaKind.Float;
+        return Float.intBitsToFloat((int) primitive);
+    }
+
+    @Override
+    public double asDouble() {
+        assert getJavaKind() == JavaKind.Double;
+        return Double.longBitsToDouble(primitive);
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        switch (getJavaKind()) {
+            case Byte:
+                return Byte.valueOf((byte) primitive);
+            case Boolean:
+                return Boolean.valueOf(asBoolean());
+            case Short:
+                return Short.valueOf((short) primitive);
+            case Char:
+                return Character.valueOf((char) primitive);
+            case Int:
+                return Integer.valueOf(asInt());
+            case Long:
+                return Long.valueOf(asLong());
+            case Float:
+                return Float.valueOf(asFloat());
+            case Double:
+                return Double.valueOf(asDouble());
+            default:
+                throw new IllegalArgumentException("unexpected kind " + getJavaKind());
+        }
+    }
+
+    @Override
+    public int getSerializedSize() {
+        return getJavaKind().getByteCount();
+    }
+
+    @Override
+    public void serialize(ByteBuffer buffer) {
+        switch (getJavaKind()) {
+            case Byte:
+            case Boolean:
+                buffer.put((byte) primitive);
+                break;
+            case Short:
+                buffer.putShort((short) primitive);
+                break;
+            case Char:
+                buffer.putChar((char) primitive);
+                break;
+            case Int:
+                buffer.putInt(asInt());
+                break;
+            case Long:
+                buffer.putLong(asLong());
+                break;
+            case Float:
+                buffer.putFloat(asFloat());
+                break;
+            case Double:
+                buffer.putDouble(asDouble());
+                break;
+            default:
+                throw new IllegalArgumentException("unexpected kind " + getJavaKind());
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return (int) (primitive ^ (primitive >>> 32)) * (getJavaKind().ordinal() + 31);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof PrimitiveConstant)) {
+            return false;
+        }
+        PrimitiveConstant other = (PrimitiveConstant) o;
+        return this.kind.equals(other.kind) && this.primitive == other.primitive;
+    }
+
+    @Override
+    public String toString() {
+        if (getJavaKind() == JavaKind.Illegal) {
+            return "illegal";
+        } else {
+            return getJavaKind().getJavaName() + "[" + asBoxedPrimitive() + "|0x" + Long.toHexString(primitive) + "]";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ProfilingInfo.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012, 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 jdk.vm.ci.meta;
+
+/**
+ * Provides access to the profiling information of one specific method. Every accessor method
+ * returns the information that is available at the time of invocation. If a method is invoked
+ * multiple times, it may return significantly different results for every invocation as the
+ * profiling information may be changed by other Java threads at any time.
+ */
+public interface ProfilingInfo {
+
+    /**
+     * Returns the length of the bytecodes associated with this profile.
+     */
+    int getCodeSize();
+
+    /**
+     * Returns an estimate of how often the branch at the given byte code was taken.
+     *
+     * @return The estimated probability, with 0.0 meaning never and 1.0 meaning always, or -1 if
+     *         this information is not available.
+     */
+    double getBranchTakenProbability(int bci);
+
+    /**
+     * Returns an estimate of how often the switch cases are taken at the given BCI. The default
+     * case is stored as the last entry.
+     *
+     * @return A double value that contains the estimated probabilities, with 0.0 meaning never and
+     *         1.0 meaning always, or -1 if this information is not available.
+     */
+    double[] getSwitchProbabilities(int bci);
+
+    /**
+     * Returns the TypeProfile for the given BCI.
+     *
+     * @return Returns a JavaTypeProfile object, or null if not available.
+     */
+    JavaTypeProfile getTypeProfile(int bci);
+
+    /**
+     * Returns the MethodProfile for the given BCI.
+     *
+     * @return Returns a JavaMethodProfile object, or null if not available.
+     */
+    JavaMethodProfile getMethodProfile(int bci);
+
+    /**
+     * Returns information if the given BCI did ever throw an exception.
+     *
+     * @return {@link TriState#TRUE} if the instruction has thrown an exception at least once,
+     *         {@link TriState#FALSE} if it never threw an exception, and {@link TriState#UNKNOWN}
+     *         if this information was not recorded.
+     */
+    TriState getExceptionSeen(int bci);
+
+    /**
+     * Returns information if null was ever seen for the given BCI. This information is collected
+     * for the aastore, checkcast and instanceof bytecodes.
+     *
+     * @return {@link TriState#TRUE} if null was seen for the instruction, {@link TriState#FALSE} if
+     *         null was NOT seen, and {@link TriState#UNKNOWN} if this information was not recorded.
+     */
+    TriState getNullSeen(int bci);
+
+    /**
+     * Returns an estimate how often the current BCI was executed. Avoid comparing execution counts
+     * to each other, as the returned value highly depends on the time of invocation.
+     *
+     * @return the estimated execution count or -1 if not available.
+     */
+    int getExecutionCount(int bci);
+
+    /**
+     * Returns how frequently a method was deoptimized for the given deoptimization reason. This
+     * only indicates how often the method did fall back to the interpreter for the execution and
+     * does not indicate how often it was recompiled.
+     *
+     * @param reason the reason for which the number of deoptimizations should be queried
+     * @return the number of times the compiled method deoptimized for the given reason.
+     */
+    int getDeoptimizationCount(DeoptimizationReason reason);
+
+    /**
+     * Records the size of the compiler intermediate representation (IR) associated with this
+     * method.
+     *
+     * @param irType the IR type for which the size is being recorded
+     * @param irSize the IR size to be recorded. The unit depends on the IR.
+     * @return whether recording this information for {@code irType} is supported
+     */
+    boolean setCompilerIRSize(Class<?> irType, int irSize);
+
+    /**
+     * Gets the size of the compiler intermediate representation (IR) associated with this method
+     * last recorded by {@link #setCompilerIRSize(Class, int)}.
+     *
+     * @param irType the IR type for which the size is being requested
+     * @return the requested IR size or -1 if it is unavailable for {@code irType}
+     */
+    int getCompilerIRSize(Class<?> irType);
+
+    /**
+     * Returns true if the profiling information can be assumed as sufficiently accurate.
+     *
+     * @return true if the profiling information was recorded often enough mature enough, false
+     *         otherwise.
+     */
+    boolean isMature();
+
+    /**
+     * Force data to be treated as mature if possible.
+     */
+    void setMature();
+
+    /**
+     * Formats this profiling information to a string.
+     *
+     * @param method an optional method that augments the profile string returned
+     * @param sep the separator to use for each separate profile record
+     */
+    default String toString(ResolvedJavaMethod method, String sep) {
+        StringBuilder buf = new StringBuilder(100);
+        if (method != null) {
+            buf.append(String.format("canBeStaticallyBound: %b%s", method.canBeStaticallyBound(), sep));
+        }
+        for (int i = 0; i < getCodeSize(); i++) {
+            if (getExecutionCount(i) != -1) {
+                buf.append(String.format("executionCount@%d: %d%s", i, getExecutionCount(i), sep));
+            }
+
+            if (getBranchTakenProbability(i) != -1) {
+                buf.append(String.format("branchProbability@%d: %.6f%s", i, getBranchTakenProbability(i), sep));
+            }
+
+            double[] switchProbabilities = getSwitchProbabilities(i);
+            if (switchProbabilities != null) {
+                buf.append(String.format("switchProbabilities@%d:", i));
+                for (int j = 0; j < switchProbabilities.length; j++) {
+                    buf.append(String.format(" %.6f", switchProbabilities[j]));
+                }
+                buf.append(sep);
+            }
+
+            if (getExceptionSeen(i) != TriState.UNKNOWN) {
+                buf.append(String.format("exceptionSeen@%d: %s%s", i, getExceptionSeen(i).name(), sep));
+            }
+
+            if (getNullSeen(i) != TriState.UNKNOWN) {
+                buf.append(String.format("nullSeen@%d: %s%s", i, getNullSeen(i).name(), sep));
+            }
+
+            JavaTypeProfile typeProfile = getTypeProfile(i);
+            MetaUtil.appendProfile(buf, typeProfile, i, "types", sep);
+
+            JavaMethodProfile methodProfile = getMethodProfile(i);
+            MetaUtil.appendProfile(buf, methodProfile, i, "methods", sep);
+        }
+
+        boolean firstDeoptReason = true;
+        for (DeoptimizationReason reason : DeoptimizationReason.values()) {
+            int count = getDeoptimizationCount(reason);
+            if (count > 0) {
+                if (firstDeoptReason) {
+                    buf.append("deoptimization history").append(sep);
+                    firstDeoptReason = false;
+                }
+                buf.append(String.format(" %s: %d%s", reason.name(), count, sep));
+            }
+        }
+        if (buf.length() == 0) {
+            return "";
+        }
+        String s = buf.toString();
+        return s.substring(0, s.length() - sep.length());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/RawConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+public class RawConstant extends PrimitiveConstant {
+
+    public RawConstant(long rawValue) {
+        super(JavaKind.Int, rawValue);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Modifier;
+
+/**
+ * Represents a reference to a resolved Java field. Fields, like methods and types, are resolved
+ * through {@link ConstantPool constant pools}.
+ */
+public interface ResolvedJavaField extends JavaField, ModifiersProvider, AnnotatedElement {
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Only the {@linkplain Modifier#fieldModifiers() field flags} specified in the JVM
+     * specification will be included in the returned mask.
+     */
+    int getModifiers();
+
+    default boolean isFinal() {
+        return ModifiersProvider.super.isFinalFlagSet();
+    }
+
+    /**
+     * Determines if this field was injected by the VM. Such a field, for example, is not derived
+     * from a class file.
+     */
+    boolean isInternal();
+
+    /**
+     * Determines if this field is a synthetic field as defined by the Java Language Specification.
+     */
+    boolean isSynthetic();
+
+    /**
+     * Returns the {@link ResolvedJavaType} object representing the class or interface that declares
+     * this field.
+     */
+    ResolvedJavaType getDeclaringClass();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+
+/**
+ * Represents a resolved Java method. Methods, like fields and types, are resolved through
+ * {@link ConstantPool constant pools}.
+ */
+public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersProvider, AnnotatedElement {
+
+    /**
+     * Returns the bytecode of this method, if the method has code. The returned byte array does not
+     * contain breakpoints or non-Java bytecodes. This may return null if the
+     * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}.
+     *
+     * The contained constant pool indices may not be the ones found in the original class file but
+     * they can be used with the JVMCI API (e.g. methods in {@link ConstantPool}).
+     *
+     * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the
+     *         code is not ready.
+     */
+    byte[] getCode();
+
+    /**
+     * Returns the size of the bytecode of this method, if the method has code. This is equivalent
+     * to {@link #getCode()}. {@code length} if the method has code.
+     *
+     * @return the size of the bytecode in bytes, or 0 if no bytecode is available
+     */
+    int getCodeSize();
+
+    /**
+     * Returns the {@link ResolvedJavaType} object representing the class or interface that declares
+     * this method.
+     */
+    ResolvedJavaType getDeclaringClass();
+
+    /**
+     * Returns the maximum number of locals used in this method's bytecodes.
+     */
+    int getMaxLocals();
+
+    /**
+     * Returns the maximum number of stack slots used in this method's bytecodes.
+     */
+    int getMaxStackSize();
+
+    default boolean isFinal() {
+        return ModifiersProvider.super.isFinalFlagSet();
+    }
+
+    /**
+     * Determines if this method is a synthetic method as defined by the Java Language
+     * Specification.
+     */
+    boolean isSynthetic();
+
+    /**
+     * Checks that the method is a
+     * <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">varargs</a>
+     * method.
+     *
+     * @return whether the method is a varargs method
+     */
+    boolean isVarArgs();
+
+    /**
+     * Checks that the method is a
+     * <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">bridge</a>
+     * method.
+     *
+     * @return whether the method is a bridge method
+     */
+    boolean isBridge();
+
+    /**
+     * Returns {@code true} if this method is a default method; returns {@code false} otherwise.
+     *
+     * A default method is a public non-abstract instance method, that is, a non-static method with
+     * a body, declared in an interface type.
+     *
+     * @return true if and only if this method is a default method as defined by the Java Language
+     *         Specification.
+     */
+    boolean isDefault();
+
+    /**
+     * Checks whether this method is a class initializer.
+     *
+     * @return {@code true} if the method is a class initializer
+     */
+    boolean isClassInitializer();
+
+    /**
+     * Checks whether this method is a constructor.
+     *
+     * @return {@code true} if the method is a constructor
+     */
+    boolean isConstructor();
+
+    /**
+     * Checks whether this method can be statically bound (usually, that means it is final or
+     * private or static, but not abstract, or the declaring class is final).
+     *
+     * @return {@code true} if this method can be statically bound
+     */
+    boolean canBeStaticallyBound();
+
+    /**
+     * Returns the list of exception handlers for this method.
+     */
+    ExceptionHandler[] getExceptionHandlers();
+
+    /**
+     * Returns a stack trace element for this method and a given bytecode index.
+     */
+    StackTraceElement asStackTraceElement(int bci);
+
+    /**
+     * Returns an object that provides access to the profiling information recorded for this method.
+     */
+    default ProfilingInfo getProfilingInfo() {
+        return getProfilingInfo(true, true);
+    }
+
+    /**
+     * Returns an object that provides access to the profiling information recorded for this method.
+     *
+     * @param includeNormal if true,
+     *            {@linkplain ProfilingInfo#getDeoptimizationCount(DeoptimizationReason)
+     *            deoptimization counts} will include deoptimization that happened during execution
+     *            of standard non-osr methods.
+     * @param includeOSR if true,
+     *            {@linkplain ProfilingInfo#getDeoptimizationCount(DeoptimizationReason)
+     *            deoptimization counts} will include deoptimization that happened during execution
+     *            of on-stack-replacement methods.
+     */
+    ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR);
+
+    /**
+     * Invalidates the profiling information and restarts profiling upon the next invocation.
+     */
+    void reprofile();
+
+    /**
+     * Returns the constant pool of this method.
+     */
+    ConstantPool getConstantPool();
+
+    /**
+     * A {@code Parameter} provides information about method parameters.
+     */
+    class Parameter implements AnnotatedElement {
+        private final String name;
+        private final ResolvedJavaMethod method;
+        private final int modifiers;
+        private final int index;
+
+        /**
+         * Constructor for {@code Parameter}.
+         *
+         * @param name the name of the parameter or {@code null} if there is no
+         *            {@literal MethodParameters} class file attribute providing a non-empty name
+         *            for the parameter
+         * @param modifiers the modifier flags for the parameter
+         * @param method the method which defines this parameter
+         * @param index the index of the parameter
+         */
+        public Parameter(String name,
+                        int modifiers,
+                        ResolvedJavaMethod method,
+                        int index) {
+            assert name == null || !name.isEmpty();
+            this.name = name;
+            this.modifiers = modifiers;
+            this.method = method;
+            this.index = index;
+        }
+
+        /**
+         * Gets the name of the parameter. If the parameter's name is {@linkplain #isNamePresent()
+         * present}, then this method returns the name provided by the class file. Otherwise, this
+         * method synthesizes a name of the form argN, where N is the index of the parameter in the
+         * descriptor of the method which declares the parameter.
+         *
+         * @return the name of the parameter, either provided by the class file or synthesized if
+         *         the class file does not provide a name
+         */
+        public String getName() {
+            if (name == null) {
+                return "arg" + index;
+            } else {
+                return name;
+            }
+        }
+
+        /**
+         * Gets the method declaring the parameter.
+         */
+        public ResolvedJavaMethod getDeclaringMethod() {
+            return method;
+        }
+
+        /**
+         * Get the modifier flags for the parameter.
+         */
+        public int getModifiers() {
+            return modifiers;
+        }
+
+        /**
+         * Gets the kind of the parameter.
+         */
+        public JavaKind getKind() {
+            return method.getSignature().getParameterKind(index);
+        }
+
+        /**
+         * Gets the formal type of the parameter.
+         */
+        public Type getParameterizedType() {
+            return method.getGenericParameterTypes()[index];
+        }
+
+        /**
+         * Gets the type of the parameter.
+         */
+        public JavaType getType() {
+            return method.getSignature().getParameterType(index, method.getDeclaringClass());
+        }
+
+        /**
+         * Determines if the parameter has a name according to a {@literal MethodParameters} class
+         * file attribute.
+         *
+         * @return true if and only if the parameter has a name according to the class file.
+         */
+        public boolean isNamePresent() {
+            return name != null;
+        }
+
+        /**
+         * Determines if the parameter represents a variable argument list.
+         */
+        public boolean isVarArgs() {
+            return method.isVarArgs() && index == method.getSignature().getParameterCount(false) - 1;
+        }
+
+        public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+            return method.getParameterAnnotations(annotationClass)[index];
+        }
+
+        public Annotation[] getAnnotations() {
+            return method.getParameterAnnotations()[index];
+        }
+
+        public Annotation[] getDeclaredAnnotations() {
+            return getAnnotations();
+        }
+
+        @Override
+        public String toString() {
+            Type type = getParameterizedType();
+            String typename = type.getTypeName();
+            if (isVarArgs()) {
+                typename = typename.replaceFirst("\\[\\]$", "...");
+            }
+
+            final StringBuilder sb = new StringBuilder(Modifier.toString(getModifiers()));
+            if (sb.length() != 0) {
+                sb.append(' ');
+            }
+            return sb.append(typename).append(' ').append(getName()).toString();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Parameter) {
+                Parameter other = (Parameter) obj;
+                return (other.method.equals(method) && other.index == index);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return method.hashCode() ^ index;
+        }
+    }
+
+    /**
+     * Returns an array of {@code Parameter} objects that represent all the parameters to this
+     * method. Returns an array of length 0 if this method has no parameters. Returns {@code null}
+     * if the parameter information is unavailable.
+     */
+    default Parameter[] getParameters() {
+        return null;
+    }
+
+    /**
+     * Returns an array of arrays that represent the annotations on the formal parameters, in
+     * declaration order, of this method.
+     *
+     * @see Method#getParameterAnnotations()
+     */
+    Annotation[][] getParameterAnnotations();
+
+    /**
+     * Returns an array of {@link Type} objects that represent the formal parameter types, in
+     * declaration order, of this method.
+     *
+     * @see Method#getGenericParameterTypes()
+     */
+    Type[] getGenericParameterTypes();
+
+    /**
+     * Returns {@code true} if this method is not excluded from inlining and has associated Java
+     * bytecodes (@see {@link ResolvedJavaMethod#hasBytecodes()}).
+     */
+    boolean canBeInlined();
+
+    /**
+     * Determines if this method is targeted by a VM directive (e.g.,
+     * {@code -XX:CompileCommand=dontinline,<pattern>}) or VM recognized annotation (e.g.,
+     * {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
+     */
+    boolean hasNeverInlineDirective();
+
+    /**
+     * Returns {@code true} if the inlining of this method should be forced.
+     */
+    boolean shouldBeInlined();
+
+    /**
+     * Returns the LineNumberTable of this method or null if this method does not have a line
+     * numbers table.
+     */
+    LineNumberTable getLineNumberTable();
+
+    /**
+     * Returns the local variable table of this method or null if this method does not have a local
+     * variable table.
+     */
+    LocalVariableTable getLocalVariableTable();
+
+    /**
+     * Gets the encoding of (that is, a constant representing the value of) this method.
+     *
+     * @return a constant representing a reference to this method
+     */
+    Constant getEncoding();
+
+    /**
+     * Checks if this method is present in the virtual table for subtypes of the specified
+     * {@linkplain ResolvedJavaType type}.
+     *
+     * @return true is this method is present in the virtual table for subtypes of this type.
+     */
+    boolean isInVirtualMethodTable(ResolvedJavaType resolved);
+
+    /**
+     * Gets the annotation of a particular type for a formal parameter of this method.
+     *
+     * @param annotationClass the Class object corresponding to the annotation type
+     * @param parameterIndex the index of a formal parameter of {@code method}
+     * @return the annotation of type {@code annotationClass} for the formal parameter present, else
+     *         null
+     * @throws IndexOutOfBoundsException if {@code parameterIndex} does not denote a formal
+     *             parameter
+     */
+    default <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex) {
+        if (parameterIndex >= 0) {
+            Annotation[][] parameterAnnotations = getParameterAnnotations();
+            for (Annotation a : parameterAnnotations[parameterIndex]) {
+                if (a.annotationType() == annotationClass) {
+                    return annotationClass.cast(a);
+                }
+            }
+        }
+        return null;
+    }
+
+    default JavaType[] toParameterTypes() {
+        JavaType receiver = isStatic() || isConstructor() ? null : getDeclaringClass();
+        return getSignature().toParameterTypes(receiver);
+    }
+
+    /**
+     * Gets the annotations of a particular type for the formal parameters of this method.
+     *
+     * @param annotationClass the Class object corresponding to the annotation type
+     * @return the annotation of type {@code annotationClass} (if any) for each formal parameter
+     *         present
+     */
+    @SuppressWarnings("unchecked")
+    default <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass) {
+        Annotation[][] parameterAnnotations = getParameterAnnotations();
+        T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length);
+        for (int i = 0; i < parameterAnnotations.length; i++) {
+            for (Annotation a : parameterAnnotations[i]) {
+                if (a.annotationType() == annotationClass) {
+                    result[i] = annotationClass.cast(a);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Checks whether the method has bytecodes associated with it. Methods without bytecodes are
+     * either abstract or native methods.
+     *
+     * @return whether the definition of this method is Java bytecodes
+     */
+    default boolean hasBytecodes() {
+        return isConcrete() && !isNative();
+    }
+
+    /**
+     * Checks whether the method has a receiver parameter - i.e., whether it is not static.
+     *
+     * @return whether the method has a receiver parameter
+     */
+    default boolean hasReceiver() {
+        return !isStatic();
+    }
+
+    /**
+     * Determines if this method is {@link java.lang.Object#Object()}.
+     */
+    default boolean isJavaLangObjectInit() {
+        return getDeclaringClass().isJavaLangObject() && getName().equals("<init>");
+    }
+
+    SpeculationLog getSpeculationLog();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.lang.reflect.AnnotatedElement;
+
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+
+/**
+ * Represents a resolved Java type. Types include primitives, objects, {@code void}, and arrays
+ * thereof. Types, like fields and methods, are resolved through {@link ConstantPool constant pools}
+ * .
+ */
+public interface ResolvedJavaType extends JavaType, ModifiersProvider, AnnotatedElement {
+    /**
+     * Checks whether this type has a finalizer method.
+     *
+     * @return {@code true} if this class has a finalizer
+     */
+    boolean hasFinalizer();
+
+    /**
+     * Checks whether this type has any finalizable subclasses so far. Any decisions based on this
+     * information require the registration of a dependency, since this information may change.
+     *
+     * @return {@code true} if this class has any subclasses with finalizers
+     */
+    AssumptionResult<Boolean> hasFinalizableSubclass();
+
+    /**
+     * Checks whether this type is an interface.
+     *
+     * @return {@code true} if this type is an interface
+     */
+    boolean isInterface();
+
+    /**
+     * Checks whether this type is an instance class.
+     *
+     * @return {@code true} if this type is an instance class
+     */
+    boolean isInstanceClass();
+
+    /**
+     * Checks whether this type is primitive.
+     *
+     * @return {@code true} if this type is primitive
+     */
+    boolean isPrimitive();
+
+    /*
+     * The setting of the final bit for types is a bit confusing since arrays are marked as final.
+     * This method provides a semantically equivalent test that appropriate for types.
+     */
+    default boolean isLeaf() {
+        return getElementalType().isFinalFlagSet();
+    }
+
+    /**
+     * Checks whether this type is initialized. If a type is initialized it implies that it was
+     * {@link #isLinked() linked} and that the static initializer has run.
+     *
+     * @return {@code true} if this type is initialized
+     */
+    boolean isInitialized();
+
+    /**
+     * Initializes this type.
+     */
+    void initialize();
+
+    /**
+     * Checks whether this type is linked and verified. When a type is linked the static initializer
+     * has not necessarily run. An {@link #isInitialized() initialized} type is always linked.
+     *
+     * @return {@code true} if this type is linked
+     */
+    boolean isLinked();
+
+    /**
+     * Determines if this type is either the same as, or is a superclass or superinterface of, the
+     * type represented by the specified parameter. This method is identical to
+     * {@link Class#isAssignableFrom(Class)} in terms of the value return for this type.
+     */
+    boolean isAssignableFrom(ResolvedJavaType other);
+
+    /**
+     * Returns true if this type is exactly the type {@link java.lang.Object}.
+     */
+    default boolean isJavaLangObject() {
+        // Removed assertion due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=434442
+        return getSuperclass() == null && !isInterface() && getJavaKind() == JavaKind.Object;
+    }
+
+    /**
+     * Checks whether the specified object is an instance of this type.
+     *
+     * @param obj the object to test
+     * @return {@code true} if the object is an instance of this type
+     */
+    boolean isInstance(JavaConstant obj);
+
+    /**
+     * Gets the super class of this type. If this type represents either the {@code Object} class,
+     * an interface, a primitive type, or void, then null is returned. If this object represents an
+     * array class then the type object representing the {@code Object} class is returned.
+     */
+    ResolvedJavaType getSuperclass();
+
+    /**
+     * Gets the interfaces implemented or extended by this type. This method is analogous to
+     * {@link Class#getInterfaces()} and as such, only returns the interfaces directly implemented
+     * or extended by this type.
+     */
+    ResolvedJavaType[] getInterfaces();
+
+    /**
+     * Gets the single implementor of this type. Calling this method on a non-interface type causes
+     * an exception.
+     * <p>
+     * If the compiler uses the result of this method for its compilation, the usage must be guarded
+     * because the verifier can not guarantee that the assigned type really implements this
+     * interface. Additionally, class loading can invalidate the result of this method.
+     *
+     * @return {@code null} if there is no implementor, the implementor if there is only one, or
+     *         {@code this} if there are more than one.
+     */
+    ResolvedJavaType getSingleImplementor();
+
+    /**
+     * Walks the class hierarchy upwards and returns the least common class that is a superclass of
+     * both the current and the given type.
+     *
+     * @return the least common type that is a super type of both the current and the given type, or
+     *         {@code null} if primitive types are involved.
+     */
+    ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType);
+
+    /**
+     * Attempts to get a leaf concrete subclass of this type.
+     * <p>
+     * For an {@linkplain #isArray() array} type A, the leaf concrete subclass is A if the
+     * {@linkplain #getElementalType() elemental} type of A is final (which includes primitive
+     * types). Otherwise {@code null} is returned for A.
+     * <p>
+     * For a non-array type T, the result is the leaf concrete type in the current hierarchy of T.
+     * <p>
+     * A runtime may decide not to manage or walk a large hierarchy and so the result is
+     * conservative. That is, a non-null result is guaranteed to be the leaf concrete class in T's
+     * hierarchy <b>at the current point in time</b> but a null result does not necessarily imply
+     * that there is no leaf concrete class in T's hierarchy.
+     * <p>
+     * If the compiler uses the result of this method for its compilation, it must register the
+     * {@link AssumptionResult} in its {@link Assumptions} because dynamic class loading can
+     * invalidate the result of this method.
+     *
+     * @return an {@link AssumptionResult} containing the leaf concrete subclass for this type as
+     *         described above
+     */
+    AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype();
+
+    ResolvedJavaType getComponentType();
+
+    default ResolvedJavaType getElementalType() {
+        ResolvedJavaType t = this;
+        while (t.isArray()) {
+            t = t.getComponentType();
+        }
+        return t;
+    }
+
+    ResolvedJavaType getArrayClass();
+
+    /**
+     * Resolves the method implementation for virtual dispatches on objects of this dynamic type.
+     * This resolution process only searches "up" the class hierarchy of this type. A broader search
+     * that also walks "down" the hierarchy is implemented by
+     * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}. For interface types it returns null
+     * since no concrete object can be an interface.
+     *
+     * @param method the method to select the implementation of
+     * @param callerType the caller or context type used to perform access checks
+     * @return the method that would be selected at runtime (might be abstract) or {@code null} if
+     *         it can not be resolved
+     */
+    ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType);
+
+    /**
+     * A convenience wrapper for {@link #resolveMethod(ResolvedJavaMethod, ResolvedJavaType)} that
+     * only returns non-abstract methods.
+     *
+     * @param method the method to select the implementation of
+     * @param callerType the caller or context type used to perform access checks
+     * @return the concrete method that would be selected at runtime, or {@code null} if there is no
+     *         concrete implementation of {@code method} in this type or any of its superclasses
+     */
+    default ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
+        ResolvedJavaMethod resolvedMethod = resolveMethod(method, callerType);
+        if (resolvedMethod == null || resolvedMethod.isAbstract()) {
+            return null;
+        }
+        return resolvedMethod;
+    }
+
+    /**
+     * Given a {@link ResolvedJavaMethod} A, returns a concrete {@link ResolvedJavaMethod} B that is
+     * the only possible unique target for a virtual call on A(). Returns {@code null} if either no
+     * such concrete method or more than one such method exists. Returns the method A if A is a
+     * concrete method that is not overridden.
+     * <p>
+     * If the compiler uses the result of this method for its compilation, it must register an
+     * assumption because dynamic class loading can invalidate the result of this method.
+     *
+     * @param method the method A for which a unique concrete target is searched
+     * @return the unique concrete target or {@code null} if no such target exists or assumptions
+     *         are not supported by this runtime
+     */
+    AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method);
+
+    /**
+     * Returns the instance fields of this class, including
+     * {@linkplain ResolvedJavaField#isInternal() internal} fields. A zero-length array is returned
+     * for array and primitive types. The order of fields returned by this method is stable. That
+     * is, for a single JVM execution the same order is returned each time this method is called. It
+     * is also the "natural" order, which means that the JVM would expect the fields in this order
+     * if no specific order is given.
+     *
+     * @param includeSuperclasses if true, then instance fields for the complete hierarchy of this
+     *            type are included in the result
+     * @return an array of instance fields
+     */
+    ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses);
+
+    /**
+     * Returns the static fields of this class, including {@linkplain ResolvedJavaField#isInternal()
+     * internal} fields. A zero-length array is returned for array and primitive types. The order of
+     * fields returned by this method is stable. That is, for a single JVM execution the same order
+     * is returned each time this method is called.
+     */
+    ResolvedJavaField[] getStaticFields();
+
+    /**
+     * Returns the instance field of this class (or one of its super classes) at the given offset,
+     * or {@code null} if there is no such field.
+     *
+     * @param offset the offset of the field to look for
+     * @return the field with the given offset, or {@code null} if there is no such field.
+     */
+    ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedKind);
+
+    /**
+     * Returns name of source file of this type.
+     */
+    String getSourceFileName();
+
+    /**
+     * Returns {@code true} if the type is a local type.
+     */
+    boolean isLocal();
+
+    /**
+     * Returns {@code true} if the type is a member type.
+     */
+    boolean isMember();
+
+    /**
+     * Returns the enclosing type of this type, if it exists, or {@code null}.
+     */
+    ResolvedJavaType getEnclosingType();
+
+    /**
+     * Returns an array reflecting all the constructors declared by this type. This method is
+     * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors.
+     */
+    ResolvedJavaMethod[] getDeclaredConstructors();
+
+    /**
+     * Returns an array reflecting all the methods declared by this type. This method is similar to
+     * {@link Class#getDeclaredMethods()} in terms of returned methods.
+     */
+    ResolvedJavaMethod[] getDeclaredMethods();
+
+    /**
+     * Returns the {@code <clinit>} method for this class if there is one.
+     */
+    ResolvedJavaMethod getClassInitializer();
+
+    default ResolvedJavaMethod findMethod(String name, Signature signature) {
+        for (ResolvedJavaMethod method : getDeclaredMethods()) {
+            if (method.getName().equals(name) && method.getSignature().equals(signature)) {
+                return method;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns true if this type is {@link Cloneable} and can be safely cloned by creating a normal
+     * Java allocation and populating it from the fields returned by
+     * {@link #getInstanceFields(boolean)}. Some types may require special handling by the platform
+     * so they would to go through the normal {@link Object#clone} path.
+     */
+    boolean isCloneableWithAllocation();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Represents a compile-time constant that can be converted to a byte array.
+ */
+public interface SerializableConstant extends Constant {
+
+    /**
+     * Return the size in bytes of the serialized representation of this constant.
+     */
+    int getSerializedSize();
+
+    /**
+     * Serialize the constant into the ByteBuffer. There must be at least
+     * {@link #getSerializedSize()} bytes available capacity in the buffer.
+     */
+    void serialize(ByteBuffer buffer);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Signature.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a method signature provided by the runtime.
+ *
+ * @see <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">Method
+ *      Descriptors</a>
+ */
+public interface Signature {
+
+    /**
+     * Returns the number of parameters in this signature, adding 1 for a receiver if requested.
+     *
+     * @param receiver true if 1 is to be added to the result for a receiver
+     * @return the number of parameters; + 1 iff {@code receiver == true}
+     */
+    int getParameterCount(boolean receiver);
+
+    /**
+     * Gets the parameter type at the specified position.
+     *
+     * @param index the index into the parameters, with {@code 0} indicating the first parameter
+     * @param accessingClass the context of the type lookup. If non-null, its class loader is used
+     *            for resolving the type. If {@code null}, then the type returned is either
+     *            unresolved or a resolved type whose resolution is context free (e.g., a primitive
+     *            type or a type in a java.* package).
+     * @return the {@code index}'th parameter type
+     * @throws LinkageError if {@code accessingClass != null} and resolution fails
+     *
+     */
+    JavaType getParameterType(int index, ResolvedJavaType accessingClass);
+
+    /**
+     * Gets the parameter kind at the specified position. This is the same as calling
+     * {@link #getParameterType}. {@link JavaType#getJavaKind getJavaKind}.
+     *
+     * @param index the index into the parameters, with {@code 0} indicating the first parameter
+     * @return the kind of the parameter at the specified position
+     */
+    default JavaKind getParameterKind(int index) {
+        return getParameterType(index, null).getJavaKind();
+    }
+
+    /**
+     * Gets the return type of this signature.
+     *
+     * @param accessingClass the context of the type lookup. If non-null, its class loader is used
+     *            for resolving the type. If {@code null}, then the type returned is either
+     *            unresolved or a resolved type whose resolution is context free (e.g., a primitive
+     *            type or a type in a java.* package).
+     * @return the return type
+     * @throws LinkageError if {@code accessingClass != null} and resolution fails
+     */
+    JavaType getReturnType(ResolvedJavaType accessingClass);
+
+    /**
+     * Gets the return kind of this signature. This is the same as calling {@link #getReturnType}.
+     * {@link JavaType#getJavaKind getJavaKind}.
+     */
+    default JavaKind getReturnKind() {
+        return getReturnType(null).getJavaKind();
+    }
+
+    /**
+     * Gets the
+     * <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
+     * descriptor</a> corresponding to this signature. For example:
+     *
+     * <pre>
+     * (ILjava/lang/String;D)V
+     * </pre>
+     *
+     * @return the signature as a string
+     */
+    default String toMethodDescriptor() {
+        StringBuilder sb = new StringBuilder("(");
+        for (int i = 0; i < getParameterCount(false); ++i) {
+            sb.append(getParameterType(i, null).getName());
+        }
+        sb.append(')').append(getReturnType(null).getName());
+        return sb.toString();
+    }
+
+    default JavaType[] toParameterTypes(JavaType receiverType) {
+        int args = getParameterCount(false);
+        JavaType[] result;
+        int i = 0;
+        if (receiverType != null) {
+            result = new JavaType[args + 1];
+            result[0] = receiverType;
+            i = 1;
+        } else {
+            result = new JavaType[args];
+        }
+        for (int j = 0; j < args; j++) {
+            result[i + j] = getParameterType(j, null);
+        }
+        return result;
+    }
+
+    default JavaKind[] toParameterKinds(boolean receiver) {
+        int args = getParameterCount(false);
+        JavaKind[] result;
+        int i = 0;
+        if (receiver) {
+            result = new JavaKind[args + 1];
+            result[0] = JavaKind.Object;
+            i = 1;
+        } else {
+            result = new JavaKind[args];
+        }
+        for (int j = 0; j < args; j++) {
+            result[i + j] = getParameterKind(j);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Manages unique deoptimization reasons. Reasons are embedded in compiled code and can be
+ * invalidated at run time. Subsequent compilations then should not speculate again on such
+ * invalidated reasons to avoid repeated deoptimization.
+ *
+ * All methods of this interface are called by the compiler. There is no need for API to register
+ * failed speculations during deoptimization, since every VM has different needs there.
+ */
+public interface SpeculationLog {
+
+    /**
+     * Marker interface for speculation objects that can be added to the speculation log.
+     */
+    public interface SpeculationReason {
+    }
+
+    /**
+     * Must be called before compilation, i.e., before a compiler calls {@link #maySpeculate}.
+     */
+    void collectFailedSpeculations();
+
+    /**
+     * If this method returns true, the compiler is allowed to {@link #speculate} with the given
+     * reason.
+     */
+    boolean maySpeculate(SpeculationReason reason);
+
+    /**
+     * Registers a speculation that was performed by the compiler.
+     *
+     * @return A compiler constant encapsulating the provided reason. It is usually passed as an
+     *         argument to the deoptimization function.
+     */
+    JavaConstant speculate(SpeculationReason reason);
+
+    /**
+     * Returns if this log has speculations.
+     *
+     * @return true if there are speculations, false otherwise
+     */
+    boolean hasSpeculations();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SuppressFBWarnings.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+@interface SuppressFBWarnings {
+    /**
+     * The set of FindBugs
+     * <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+     * suppressed in annotated element. The value can be a bug category, kind or pattern.
+     */
+    String[] value();
+
+    /**
+     * Reason why the warning is suppressed.
+     */
+    String justification();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/TriState.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a logic value that can be either {@link #TRUE}, {@link #FALSE}, or {@link #UNKNOWN}.
+ */
+public enum TriState {
+    TRUE,
+    FALSE,
+    UNKNOWN;
+
+    public static TriState get(boolean value) {
+        return value ? TRUE : FALSE;
+    }
+
+    /**
+     * This is optimistic about {@link #UNKNOWN} (it prefers known values over {@link #UNKNOWN}) and
+     * pesimistic about known (it perfers {@link #TRUE} over {@link #FALSE}).
+     */
+    public static TriState merge(TriState a, TriState b) {
+        if (a == TRUE || b == TRUE) {
+            return TRUE;
+        }
+        if (a == FALSE || b == FALSE) {
+            return FALSE;
+        }
+        assert a == UNKNOWN && b == UNKNOWN;
+        return UNKNOWN;
+    }
+
+    public boolean isTrue() {
+        return this == TRUE;
+    }
+
+    public boolean isFalse() {
+        return this == FALSE;
+    }
+
+    public boolean isUnknown() {
+        return this == UNKNOWN;
+    }
+
+    public boolean isKnown() {
+        return this != UNKNOWN;
+    }
+
+    public boolean toBoolean() {
+        if (isTrue()) {
+            return true;
+        } else if (isFalse()) {
+            return false;
+        } else {
+            throw new IllegalStateException("Cannot convert to boolean, TriState is in an unknown state");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/VMConstant.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents a constant that needs to be patched at runtime by the VM.
+ */
+public interface VMConstant extends Constant {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Value.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Abstract base class for values.
+ */
+public abstract class Value {
+
+    public static final Value[] NO_VALUES = new Value[0];
+
+    public static final AllocatableValue ILLEGAL = new IllegalValue();
+
+    private static final class IllegalValue extends AllocatableValue {
+        private IllegalValue() {
+            super(ValueKind.Illegal);
+        }
+
+        @Override
+        public String toString() {
+            return "-";
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            // Due to de-serialization this object may exist multiple times. So we compare classes
+            // instead of the individual objects. (This anonymous class has always the same meaning)
+            return other instanceof IllegalValue;
+        }
+    }
+
+    private final ValueKind<?> valueKind;
+
+    /**
+     * Initializes a new value of the specified kind.
+     *
+     * @param valueKind the kind
+     */
+    protected Value(ValueKind<?> valueKind) {
+        this.valueKind = valueKind;
+    }
+
+    /**
+     * Returns a String representation of the kind, which should be the end of all
+     * {@link #toString()} implementation of subclasses.
+     */
+    protected final String getKindSuffix() {
+        return "|" + valueKind.getKindSuffix();
+    }
+
+    public final ValueKind<?> getValueKind() {
+        return valueKind;
+    }
+
+    public final <K extends ValueKind<K>> K getValueKind(Class<K> cls) {
+        return cls.cast(valueKind);
+    }
+
+    /**
+     * Returns the platform specific kind used to store this value.
+     */
+    public final PlatformKind getPlatformKind() {
+        return valueKind.getPlatformKind();
+    }
+
+    @Override
+    public int hashCode() {
+        return 41 + valueKind.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Value) {
+            Value that = (Value) obj;
+            return valueKind.equals(that.valueKind);
+        }
+        return false;
+    }
+
+    /**
+     * Checks if this value is identical to {@code other}.
+     *
+     * Warning: Use with caution! Usually equivalence {@link #equals(Object)} is sufficient and
+     * should be used.
+     */
+    public final boolean identityEquals(Value other) {
+        return this == other;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ValueKind.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Represents the type of {@link Value values}. This class can be extended by compilers to track
+ * additional information about values.
+ */
+public abstract class ValueKind<K extends ValueKind<K>> {
+
+    private enum IllegalKind implements PlatformKind {
+        ILLEGAL;
+
+        private final EnumKey<IllegalKind> key = new EnumKey<>(this);
+
+        public Key getKey() {
+            return key;
+        }
+
+        public int getSizeInBytes() {
+            return 0;
+        }
+
+        public int getVectorLength() {
+            return 0;
+        }
+
+        public char getTypeChar() {
+            return '-';
+        }
+    }
+
+    private static class IllegalValueKind extends ValueKind<IllegalValueKind> {
+
+        IllegalValueKind() {
+            super(IllegalKind.ILLEGAL);
+        }
+
+        @Override
+        public IllegalValueKind changeType(PlatformKind newPlatformKind) {
+            return this;
+        }
+
+        @Override
+        public String toString() {
+            return "ILLEGAL";
+        }
+    }
+
+    /**
+     * The non-type.
+     */
+    public static final ValueKind<?> Illegal = new IllegalValueKind();
+
+    private final PlatformKind platformKind;
+
+    public ValueKind(PlatformKind platformKind) {
+        this.platformKind = platformKind;
+    }
+
+    public final PlatformKind getPlatformKind() {
+        return platformKind;
+    }
+
+    /**
+     * Create a new {@link ValueKind} with a different {@link PlatformKind}. Subclasses must
+     * override this to preserve the additional information added by the compiler.
+     */
+    public abstract K changeType(PlatformKind newPlatformKind);
+
+    /**
+     * Returns a String representation of the kind, which will be included at the end of
+     * {@link Value#toString()} implementation. Defaults to {@link #toString()} but can be
+     * overridden to provide something more specific.
+     */
+    public String getKindSuffix() {
+        return toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/package-info.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009, 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 that defines the interface between a runtime and a Java application that wants to access
+ * meta information. The runtime provides an implementation of the
+ * {@link jdk.vm.ci.meta.MetaAccessProvider} interface.
+ */
+package jdk.vm.ci.meta;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile ConstantTest.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit jdk.vm.ci.runtime.test.ConstantTest
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.JavaConstant;
+
+public class ConstantTest extends FieldUniverse {
+
+    @Test
+    public void testNegativeZero() {
+        Assert.assertTrue("Constant for 0.0f must be different from -0.0f", JavaConstant.FLOAT_0 != JavaConstant.forFloat(-0.0F));
+        Assert.assertTrue("Constant for 0.0d must be different from -0.0d", JavaConstant.DOUBLE_0 != JavaConstant.forDouble(-0.0d));
+    }
+
+    @Test
+    public void testNullIsNull() {
+        Assert.assertTrue(JavaConstant.NULL_POINTER.isNull());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime.test;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.vm.ci.meta.ResolvedJavaField;
+
+/**
+ * Context for field related tests.
+ */
+public class FieldUniverse extends TypeUniverse {
+
+    public static final Map<Field, ResolvedJavaField> fields = new HashMap<>();
+
+    {
+        for (Class<?> c : classes) {
+            for (Field f : c.getDeclaredFields()) {
+                ResolvedJavaField field = metaAccess.lookupJavaField(f);
+                fields.put(f, field);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime.test;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Context for method related tests.
+ */
+public class MethodUniverse extends TypeUniverse {
+
+    public static final Map<Method, ResolvedJavaMethod> methods = new HashMap<>();
+    public static final Map<Constructor<?>, ResolvedJavaMethod> constructors = new HashMap<>();
+
+    {
+        for (Class<?> c : classes) {
+            for (Method m : c.getDeclaredMethods()) {
+                ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
+                methods.put(m, method);
+            }
+            for (Constructor<?> m : c.getDeclaredConstructors()) {
+                constructors.put(m, metaAccess.lookupJavaMethod(m));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,90 @@
+/*
+ * 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 jdk.vm.ci.runtime.test;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+import jdk.vm.ci.runtime.JVMCI;
+
+class NameAndSignature {
+
+    public static final MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+
+    final String name;
+    final Class<?> returnType;
+    final Class<?>[] parameterTypes;
+
+    NameAndSignature(Method m) {
+        this.name = m.getName();
+        this.returnType = m.getReturnType();
+        this.parameterTypes = m.getParameterTypes();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof NameAndSignature) {
+            NameAndSignature s = (NameAndSignature) obj;
+            return s.returnType == returnType && name.equals(s.name) && Arrays.equals(s.parameterTypes, parameterTypes);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(name + "(");
+        String sep = "";
+        for (Class<?> p : parameterTypes) {
+            sb.append(sep);
+            sep = ", ";
+            sb.append(p.getName());
+        }
+        return sb.append(')').append(returnType.getName()).toString();
+    }
+
+    public boolean signatureEquals(ResolvedJavaMethod m) {
+        Signature s = m.getSignature();
+        ResolvedJavaType declaringClass = m.getDeclaringClass();
+        if (!s.getReturnType(declaringClass).resolve(declaringClass).equals(metaAccess.lookupJavaType(returnType))) {
+            return false;
+        }
+        if (s.getParameterCount(false) != parameterTypes.length) {
+            return false;
+        }
+        for (int i = 0; i < parameterTypes.length; i++) {
+            if (!s.getParameterType(i, declaringClass).resolve(declaringClass).equals(metaAccess.lookupJavaType(parameterTypes[i]))) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,176 @@
+/*
+ * 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 jdk.vm.ci.runtime.test;
+
+import static org.junit.Assume.assumeTrue;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import javax.tools.ToolProvider;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests that {@link ResolvedJavaMethod}s are safe in the context of class redefinition being used
+ * to redefine the method to which they refer.
+ */
+public class RedefineClassTest extends TypeUniverse {
+
+    static class Foo {
+        public static Object getName() {
+            return "foo";
+        }
+    }
+
+    @Test
+    public void test() throws Throwable {
+
+        Method fooMethod = Foo.class.getDeclaredMethod("getName");
+
+        ResolvedJavaMethod foo1 = metaAccess.lookupJavaMethod(fooMethod);
+        ResolvedJavaMethod foo2 = metaAccess.lookupJavaMethod(fooMethod);
+
+        String foo1Code = Arrays.toString(foo1.getCode());
+        String foo2Code = Arrays.toString(foo2.getCode());
+
+        Assert.assertEquals("foo", Foo.getName());
+
+        redefineFoo();
+        System.gc();
+
+        // Make sure the transformation happened
+        Assert.assertEquals("bar", Foo.getName());
+
+        Assert.assertEquals(foo1Code, Arrays.toString(foo1.getCode()));
+        Assert.assertEquals(foo2Code, Arrays.toString(foo1.getCode()));
+    }
+
+    /**
+     * Adds the class file bytes for a given class to a JAR stream.
+     */
+    static void add(JarOutputStream jar, Class<?> c) throws IOException {
+        String name = c.getName();
+        String classAsPath = name.replace('.', '/') + ".class";
+        jar.putNextEntry(new JarEntry(classAsPath));
+
+        InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath);
+
+        int nRead;
+        byte[] buf = new byte[1024];
+        while ((nRead = stream.read(buf, 0, buf.length)) != -1) {
+            jar.write(buf, 0, nRead);
+        }
+
+        jar.closeEntry();
+    }
+
+    protected void redefineFoo() throws Exception {
+        Manifest manifest = new Manifest();
+        manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
+        Attributes mainAttrs = manifest.getMainAttributes();
+        mainAttrs.putValue("Agent-Class", FooAgent.class.getName());
+        mainAttrs.putValue("Can-Redefine-Classes", "true");
+        mainAttrs.putValue("Can-Retransform-Classes", "true");
+
+        Path jar = Files.createTempFile("myagent", ".jar");
+        try {
+            JarOutputStream jarStream = new JarOutputStream(new FileOutputStream(jar.toFile()), manifest);
+            add(jarStream, FooAgent.class);
+            add(jarStream, FooTransformer.class);
+            jarStream.close();
+
+            loadAgent(jar);
+        } finally {
+            Files.deleteIfExists(jar);
+        }
+    }
+
+    public static void loadAgent(Path agent) throws Exception {
+        String vmName = ManagementFactory.getRuntimeMXBean().getName();
+        int p = vmName.indexOf('@');
+        assumeTrue("VM name not in <pid>@<host> format: " + vmName, p != -1);
+        String pid = vmName.substring(0, p);
+        ClassLoader cl = ToolProvider.getSystemToolClassLoader();
+        Class<?> c = Class.forName("com.sun.tools.attach.VirtualMachine", true, cl);
+        Method attach = c.getDeclaredMethod("attach", String.class);
+        Method loadAgent = c.getDeclaredMethod("loadAgent", String.class, String.class);
+        Method detach = c.getDeclaredMethod("detach");
+        Object vm = attach.invoke(null, pid);
+        loadAgent.invoke(vm, agent.toString(), "");
+        detach.invoke(vm);
+    }
+
+    public static class FooAgent {
+
+        public static void agentmain(@SuppressWarnings("unused") String args, Instrumentation inst) throws Exception {
+            if (inst.isRedefineClassesSupported() && inst.isRetransformClassesSupported()) {
+                inst.addTransformer(new FooTransformer(), true);
+                Class<?>[] allClasses = inst.getAllLoadedClasses();
+                for (int i = 0; i < allClasses.length; i++) {
+                    Class<?> c = allClasses[i];
+                    if (c == Foo.class) {
+                        inst.retransformClasses(new Class<?>[]{c});
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * This transformer replaces the first instance of the constant "foo" in the class file for
+     * {@link Foo} with "bar".
+     */
+    static class FooTransformer implements ClassFileTransformer {
+
+        @Override
+        public byte[] transform(ClassLoader cl, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+            if (Foo.class.equals(classBeingRedefined)) {
+                String cf = new String(classfileBuffer);
+                int i = cf.indexOf("foo");
+                Assert.assertTrue("cannot find \"foo\" constant in " + Foo.class.getSimpleName() + "'s class file", i > 0);
+                classfileBuffer[i] = 'b';
+                classfileBuffer[i + 1] = 'a';
+                classfileBuffer[i + 2] = 'r';
+            }
+            return classfileBuffer;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
+
+import org.junit.Test;
+
+public class ResolvedJavaTypeResolveConcreteMethodTest {
+    public final MetaAccessProvider metaAccess;
+
+    public ResolvedJavaTypeResolveConcreteMethodTest() {
+        metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+    }
+
+    protected abstract static class A {
+        @SuppressWarnings("unused")
+        private void priv() {
+        }
+
+        public void v1() {
+        }
+
+        public void v2() {
+        }
+
+        public abstract void abs();
+    }
+
+    protected static class B extends A implements I {
+        public void i() {
+        }
+
+        @Override
+        public void v2() {
+        }
+
+        @Override
+        public void abs() {
+
+        }
+    }
+
+    protected static class C extends B {
+        public void d() {
+        }
+    }
+
+    protected abstract static class D extends A {
+
+    }
+
+    protected static class E extends D {
+        @Override
+        public void abs() {
+        }
+    }
+
+    protected interface I {
+        void i();
+
+        default void d() {
+        }
+    }
+
+    @Test
+    public void testDefaultMethod() {
+        ResolvedJavaType i = getType(I.class);
+        ResolvedJavaType b = getType(B.class);
+        ResolvedJavaType c = getType(C.class);
+        ResolvedJavaMethod di = getMethod(i, "d");
+        ResolvedJavaMethod dc = getMethod(c, "d");
+
+        assertEquals(null, i.resolveConcreteMethod(di, c));
+        assertEquals(di, b.resolveConcreteMethod(di, c));
+        assertEquals(dc, c.resolveConcreteMethod(di, c));
+    }
+
+    @Test
+    public void testPrivateMethod() {
+        ResolvedJavaType a = getType(A.class);
+        ResolvedJavaType b = getType(B.class);
+        ResolvedJavaType c = getType(C.class);
+        ResolvedJavaMethod priv = getMethod(a, "priv");
+
+        assertNull(a.resolveConcreteMethod(priv, c));
+        assertNull(b.resolveConcreteMethod(priv, c));
+    }
+
+    @Test
+    public void testAbstractMethod() {
+        ResolvedJavaType a = getType(A.class);
+        ResolvedJavaType b = getType(B.class);
+        ResolvedJavaType c = getType(C.class);
+        ResolvedJavaType d = getType(D.class);
+        ResolvedJavaType e = getType(E.class);
+        ResolvedJavaMethod absa = getMethod(a, "abs");
+        ResolvedJavaMethod absb = getMethod(b, "abs");
+        ResolvedJavaMethod abse = getMethod(e, "abs");
+
+        assertNull(a.resolveConcreteMethod(absa, c));
+        assertNull(d.resolveConcreteMethod(absa, c));
+
+        assertEquals(absb, b.resolveConcreteMethod(absa, c));
+        assertEquals(absb, b.resolveConcreteMethod(absb, c));
+        assertEquals(absb, c.resolveConcreteMethod(absa, c));
+        assertEquals(absb, c.resolveConcreteMethod(absb, c));
+        assertEquals(abse, e.resolveConcreteMethod(absa, c));
+        assertNull(e.resolveConcreteMethod(absb, c));
+        assertEquals(abse, e.resolveConcreteMethod(abse, c));
+    }
+
+    @Test
+    public void testVirtualMethod() {
+        ResolvedJavaType a = getType(A.class);
+        ResolvedJavaType b = getType(B.class);
+        ResolvedJavaType c = getType(C.class);
+        ResolvedJavaMethod v1a = getMethod(a, "v1");
+        ResolvedJavaMethod v2a = getMethod(a, "v2");
+        ResolvedJavaMethod v2b = getMethod(b, "v2");
+
+        assertEquals(v1a, a.resolveConcreteMethod(v1a, c));
+        assertEquals(v1a, b.resolveConcreteMethod(v1a, c));
+        assertEquals(v1a, c.resolveConcreteMethod(v1a, c));
+        assertEquals(v2a, a.resolveConcreteMethod(v2a, c));
+        assertEquals(v2b, b.resolveConcreteMethod(v2a, c));
+        assertEquals(v2b, b.resolveConcreteMethod(v2b, c));
+        assertEquals(v2b, c.resolveConcreteMethod(v2a, c));
+        assertEquals(v2b, c.resolveConcreteMethod(v2b, c));
+
+    }
+
+    static ResolvedJavaMethod getMethod(ResolvedJavaType type, String methodName) {
+        for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+            if (method.getName().equals(methodName)) {
+                return method;
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+
+    protected ResolvedJavaType getType(Class<?> clazz) {
+        ResolvedJavaType type = metaAccess.lookupJavaType(clazz);
+        type.initialize();
+        return type;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
+
+import org.junit.Test;
+
+public class ResolvedJavaTypeResolveMethodTest {
+    public final MetaAccessProvider metaAccess;
+
+    public ResolvedJavaTypeResolveMethodTest() {
+        metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+    }
+
+    protected abstract static class A {
+        @SuppressWarnings("unused")
+        private void priv() {
+        }
+
+        public void v1() {
+        }
+
+        public void v2() {
+        }
+
+        public abstract void abs();
+    }
+
+    protected static class B extends A implements I {
+        public void i() {
+        }
+
+        @Override
+        public void v2() {
+        }
+
+        @Override
+        public void abs() {
+
+        }
+    }
+
+    protected static class C extends B {
+        public void d() {
+        }
+    }
+
+    protected abstract static class D extends A {
+
+    }
+
+    protected static class E extends D {
+        @Override
+        public void abs() {
+        }
+    }
+
+    protected interface I {
+        void i();
+
+        default void d() {
+        }
+    }
+
+    @Test
+    public void testDefaultMethod() {
+        ResolvedJavaType i = getType(I.class);
+        ResolvedJavaType b = getType(B.class);
+        ResolvedJavaType c = getType(C.class);
+        ResolvedJavaMethod di = getMethod(i, "d");
+        ResolvedJavaMethod dc = getMethod(c, "d");
+
+        assertEquals(null, i.resolveMethod(di, c));
+        assertEquals(di, b.resolveMethod(di, c));
+        assertEquals(dc, c.resolveMethod(di, c));
+    }
+
+    @Test
+    public void testPrivateMethod() {
+        ResolvedJavaType a = getType(A.class);
+        ResolvedJavaType b = getType(B.class);
+        ResolvedJavaType c = getType(C.class);
+        ResolvedJavaMethod priv = getMethod(a, "priv");
+
+        assertNull(a.resolveMethod(priv, c));
+        assertNull(b.resolveMethod(priv, c));
+    }
+
+    @Test
+    public void testAbstractMethod() {
+        ResolvedJavaType a = getType(A.class);
+        ResolvedJavaType b = getType(B.class);
+        ResolvedJavaType c = getType(C.class);
+        ResolvedJavaType d = getType(D.class);
+        ResolvedJavaType e = getType(E.class);
+        ResolvedJavaMethod absa = getMethod(a, "abs");
+        ResolvedJavaMethod absb = getMethod(b, "abs");
+        ResolvedJavaMethod abse = getMethod(e, "abs");
+
+        assertEquals(absa, a.resolveMethod(absa, c));
+        assertEquals(absa, d.resolveMethod(absa, c));
+
+        assertEquals(absb, b.resolveMethod(absa, c));
+        assertEquals(absb, b.resolveMethod(absb, c));
+        assertEquals(absb, c.resolveMethod(absa, c));
+        assertEquals(absb, c.resolveMethod(absb, c));
+        assertEquals(abse, e.resolveMethod(absa, c));
+        assertNull(e.resolveMethod(absb, c));
+        assertEquals(abse, e.resolveMethod(abse, c));
+    }
+
+    @Test
+    public void testVirtualMethod() {
+        ResolvedJavaType a = getType(A.class);
+        ResolvedJavaType b = getType(B.class);
+        ResolvedJavaType c = getType(C.class);
+        ResolvedJavaMethod v1a = getMethod(a, "v1");
+        ResolvedJavaMethod v2a = getMethod(a, "v2");
+        ResolvedJavaMethod v2b = getMethod(b, "v2");
+
+        assertEquals(v1a, a.resolveMethod(v1a, c));
+        assertEquals(v1a, b.resolveMethod(v1a, c));
+        assertEquals(v1a, c.resolveMethod(v1a, c));
+        assertEquals(v2a, a.resolveMethod(v2a, c));
+        assertEquals(v2b, b.resolveMethod(v2a, c));
+        assertEquals(v2b, b.resolveMethod(v2b, c));
+        assertEquals(v2b, c.resolveMethod(v2a, c));
+        assertEquals(v2b, c.resolveMethod(v2b, c));
+
+    }
+
+    static ResolvedJavaMethod getMethod(ResolvedJavaType type, String methodName) {
+        for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+            if (method.getName().equals(methodName)) {
+                return method;
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+
+    protected ResolvedJavaType getType(Class<?> clazz) {
+        ResolvedJavaType type = metaAccess.lookupJavaType(clazz);
+        type.initialize();
+        return type;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Array;
+import java.util.List;
+
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link ConstantReflectionProvider}. It assumes an implementation of the interface that
+ * actually returns non-null results for access operations that are possible, i.e., the tests will
+ * fail for an implementation that spuriously returns null (which is allowed by the specification).
+ */
+public class TestConstantReflectionProvider extends TypeUniverse {
+
+    @Test
+    public void constantEqualsTest() {
+        for (ConstantValue c1 : constants()) {
+            for (ConstantValue c2 : constants()) {
+                // test symmetry
+                assertEquals(constantReflection.constantEquals(c1.value, c2.value), constantReflection.constantEquals(c2.value, c1.value));
+                if (c1.value.getJavaKind() != JavaKind.Object && c2.value.getJavaKind() != JavaKind.Object) {
+                    assertEquals(c1.value.equals(c2.value), constantReflection.constantEquals(c2.value, c1.value));
+                }
+            }
+        }
+    }
+
+    @Test
+    public void readArrayLengthTest() {
+        for (ConstantValue cv : constants()) {
+            JavaConstant c = cv.value;
+            Integer actual = constantReflection.readArrayLength(c);
+            if (c.getJavaKind() != JavaKind.Object || c.isNull() || !cv.boxed.getClass().isArray()) {
+                assertNull(actual);
+            } else {
+                assertNotNull(actual);
+                int actualInt = actual;
+                assertEquals(Array.getLength(cv.boxed), actualInt);
+            }
+        }
+    }
+
+    static class PrimitiveConstants {
+        static final long LONG_CONST = 42;
+        static final int INT_CONST = 66;
+        static final byte BYTE_CONST = 123;
+        static final boolean BOOL_CONST = true;
+    }
+
+    static class BoxedConstants {
+        static final Long LONG_CONST = 42L;
+        static final Integer INT_CONST = 66;
+        static final Byte BYTE_CONST = 123;
+        static final Boolean BOOL_CONST = true;
+    }
+
+    @Test
+    public void boxTest() {
+        for (ConstantValue cv : constants()) {
+            JavaConstant c = cv.value;
+            JavaConstant boxed = constantReflection.boxPrimitive(c);
+            if (boxed != null && c.getJavaKind().isPrimitive()) {
+                assertTrue(boxed.getJavaKind().isObject());
+                assertFalse(boxed.isNull());
+            }
+        }
+
+        List<ConstantValue> primitiveConstants = readConstants(PrimitiveConstants.class);
+        List<ConstantValue> boxedConstants = readConstants(BoxedConstants.class);
+        for (int i = 0; i < primitiveConstants.size(); i++) {
+            ConstantValue prim = primitiveConstants.get(i);
+            ConstantValue box = boxedConstants.get(i);
+            assertEquals(box.value, constantReflection.boxPrimitive(prim.value));
+        }
+
+        assertNull(constantReflection.boxPrimitive(JavaConstant.NULL_POINTER));
+    }
+
+    @Test
+    public void unboxTest() {
+        for (ConstantValue cv : constants()) {
+            JavaConstant c = cv.value;
+            JavaConstant unboxed = c.isNull() ? null : constantReflection.unboxPrimitive(c);
+            if (unboxed != null) {
+                assertFalse(unboxed.getJavaKind().isObject());
+            }
+        }
+        List<ConstantValue> primitiveConstants = readConstants(PrimitiveConstants.class);
+        List<ConstantValue> boxedConstants = readConstants(BoxedConstants.class);
+        for (int i = 0; i < primitiveConstants.size(); i++) {
+            ConstantValue prim = primitiveConstants.get(i);
+            ConstantValue box = boxedConstants.get(i);
+            assert prim.getSimpleName().equals(box.getSimpleName());
+            assertEquals(prim.value, constantReflection.unboxPrimitive(box.value));
+        }
+
+        assertNull(constantReflection.unboxPrimitive(JavaConstant.NULL_POINTER));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile TestJavaField.java FieldUniverse.java TypeUniverse.java
+ * @run junit jdk.vm.ci.runtime.test.TestJavaField
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+import jdk.vm.ci.meta.JavaField;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link JavaField}.
+ */
+public class TestJavaField extends FieldUniverse {
+
+    @Test
+    public void getNameTest() {
+        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+            String expected = e.getKey().getName();
+            String actual = e.getValue().getName();
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void getTypeTest() {
+        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+            // Must resolve types first as a resolved types != unresolved types
+            ResolvedJavaField rf = e.getValue();
+            JavaType expected = metaAccess.lookupJavaType(e.getKey().getType()).resolve(rf.getDeclaringClass());
+            JavaType actual = rf.getType().resolve(rf.getDeclaringClass());
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void getJavaKindTest() {
+        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+            JavaKind expected = metaAccess.lookupJavaType(e.getKey().getType()).getJavaKind();
+            JavaKind actual = e.getValue().getJavaKind();
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void getDeclaringClassTest() {
+        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+            Class<?> expected = e.getKey().getDeclaringClass();
+            ResolvedJavaType actual = e.getValue().getDeclaringClass();
+            assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile TestJavaMethod.java MethodUniverse.java TypeUniverse.java TestMetaAccessProvider.java NameAndSignature.java
+ * @run junit jdk.vm.ci.runtime.test.TestJavaMethod
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link JavaMethod}.
+ */
+public class TestJavaMethod extends MethodUniverse {
+
+    @Test
+    public void getNameTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            String expected = e.getKey().getName();
+            String actual = e.getValue().getName();
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void getDeclaringClassTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            Class<?> expected = e.getKey().getDeclaringClass();
+            ResolvedJavaType actual = e.getValue().getDeclaringClass();
+            assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+        }
+    }
+
+    @Test
+    public void getSignatureTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            assertTrue(new NameAndSignature(e.getKey()).signatureEquals(e.getValue()));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile TestJavaType.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit jdk.vm.ci.runtime.test.TestJavaType
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.assertEquals;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link JavaType}.
+ */
+public class TestJavaType extends TypeUniverse {
+
+    public TestJavaType() {
+    }
+
+    @Test
+    public void getJavaKindTest() {
+        for (Class<?> c : classes) {
+            JavaType type = metaAccess.lookupJavaType(c);
+            JavaKind expected = JavaKind.fromJavaClass(c);
+            JavaKind actual = type.getJavaKind();
+            assertEquals(expected, actual);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile TestMetaAccessProvider.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit jdk.vm.ci.runtime.test.TestMetaAccessProvider
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static jdk.vm.ci.meta.MetaUtil.toInternalName;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link MetaAccessProvider}.
+ */
+public class TestMetaAccessProvider extends TypeUniverse {
+
+    @Test
+    public void lookupJavaTypeTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            assertNotNull(c.toString(), type);
+            assertEquals(c.toString(), type.getName(), toInternalName(c.getName()));
+            assertEquals(c.toString(), type.getName(), toInternalName(type.toJavaName()));
+            assertEquals(c.toString(), c.getName(), type.toClassName());
+            if (!type.isArray()) {
+                assertEquals(c.toString(), c.getName(), type.toJavaName());
+            }
+        }
+    }
+
+    @Test
+    public void lookupJavaMethodTest() {
+        for (Class<?> c : classes) {
+            for (Method reflect : c.getDeclaredMethods()) {
+                ResolvedJavaMethod method = metaAccess.lookupJavaMethod(reflect);
+                assertNotNull(method);
+                assertTrue(method.getDeclaringClass().equals(metaAccess.lookupJavaType(reflect.getDeclaringClass())));
+            }
+        }
+    }
+
+    @Test
+    public void lookupJavaFieldTest() {
+        for (Class<?> c : classes) {
+            for (Field reflect : c.getDeclaredFields()) {
+                ResolvedJavaField field = metaAccess.lookupJavaField(reflect);
+                assertNotNull(field);
+                assertTrue(field.getDeclaringClass().equals(metaAccess.lookupJavaType(reflect.getDeclaringClass())));
+            }
+        }
+    }
+
+    @Test
+    public void lookupJavaTypeConstantTest() {
+        for (ConstantValue cv : constants()) {
+            JavaConstant c = cv.value;
+            if (c.getJavaKind() == JavaKind.Object && !c.isNull()) {
+                Object o = cv.boxed;
+                ResolvedJavaType type = metaAccess.lookupJavaType(c);
+                assertNotNull(type);
+                assertTrue(type.equals(metaAccess.lookupJavaType(o.getClass())));
+            } else {
+                assertEquals(metaAccess.lookupJavaType(c), null);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile TestResolvedJavaField.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit jdk.vm.ci.runtime.test.TestResolvedJavaField
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Tests for {@link ResolvedJavaField}.
+ */
+public class TestResolvedJavaField extends FieldUniverse {
+
+    public TestResolvedJavaField() {
+    }
+
+    @Test
+    public void getModifiersTest() {
+        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+            int expected = e.getKey().getModifiers();
+            int actual = e.getValue().getModifiers();
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void isSyntheticTest() {
+        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+            boolean expected = e.getKey().isSynthetic();
+            boolean actual = e.getValue().isSynthetic();
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void getAnnotationsTest() {
+        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+            Annotation[] expected = e.getKey().getAnnotations();
+            Annotation[] actual = e.getValue().getAnnotations();
+            assertArrayEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void getAnnotationTest() {
+        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
+            for (Annotation expected : e.getKey().getAnnotations()) {
+                if (expected != null) {
+                    Annotation actual = e.getValue().getAnnotation(expected.annotationType());
+                    assertEquals(expected, actual);
+                }
+            }
+        }
+    }
+
+    private Method findTestMethod(Method apiMethod) {
+        String testName = apiMethod.getName() + "Test";
+        for (Method m : getClass().getDeclaredMethods()) {
+            if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    // @formatter:off
+    private static final String[] untestedApiMethods = {
+        "getDeclaringClass",
+        "isInternal",
+        "isFinal"
+    };
+    // @formatter:on
+
+    /**
+     * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
+     * for them or are added to {@link #untestedApiMethods}.
+     */
+    @Test
+    public void testCoverage() {
+        Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
+        for (Method m : ResolvedJavaField.class.getDeclaredMethods()) {
+            if (m.isSynthetic()) {
+                continue;
+            }
+            if (findTestMethod(m) == null) {
+                assertTrue("test missing for " + m, known.contains(m.getName()));
+            } else {
+                assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile TestResolvedJavaMethod.java MethodUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit jdk.vm.ci.runtime.test.TestResolvedJavaMethod
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.ExceptionHandler;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaMethod.Parameter;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Tests for {@link ResolvedJavaMethod}.
+ */
+public class TestResolvedJavaMethod extends MethodUniverse {
+
+    public TestResolvedJavaMethod() {
+    }
+
+    /**
+     * @see ResolvedJavaMethod#getCode()
+     */
+    @Test
+    public void getCodeTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            byte[] code = m.getCode();
+            if (code == null) {
+                assertTrue(m.getCodeSize() == 0);
+            } else {
+                if (m.isAbstract()) {
+                    assertTrue(code.length == 0);
+                } else if (!m.isNative()) {
+                    assertTrue(code.length > 0);
+                }
+            }
+        }
+    }
+
+    /**
+     * @see ResolvedJavaMethod#getCodeSize()
+     */
+    @Test
+    public void getCodeSizeTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            int codeSize = m.getCodeSize();
+            if (m.isAbstract()) {
+                assertTrue(codeSize == 0);
+            } else if (!m.isNative()) {
+                assertTrue(codeSize > 0);
+            }
+        }
+    }
+
+    @Test
+    public void getModifiersTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            int expected = e.getKey().getModifiers();
+            int actual = m.getModifiers();
+            assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            int expected = e.getKey().getModifiers();
+            int actual = m.getModifiers();
+            assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
+        }
+    }
+
+    /**
+     * @see ResolvedJavaMethod#isClassInitializer()
+     */
+    @Test
+    public void isClassInitializerTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            // Class initializers are hidden from reflection
+            ResolvedJavaMethod m = e.getValue();
+            assertFalse(m.isClassInitializer());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertFalse(m.isClassInitializer());
+        }
+    }
+
+    @Test
+    public void isConstructorTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertFalse(m.isConstructor());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertTrue(m.isConstructor());
+        }
+    }
+
+    @Test
+    public void isSyntheticTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
+        }
+    }
+
+    @Test
+    public void isBridgeTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isBridge(), m.isBridge());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(false, m.isBridge());
+        }
+    }
+
+    @Test
+    public void isVarArgsTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
+        }
+    }
+
+    @Test
+    public void isSynchronizedTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
+        }
+    }
+
+    @Test
+    public void canBeStaticallyBoundTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey()));
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey()));
+        }
+    }
+
+    private static boolean canBeStaticallyBound(Member method) {
+        int modifiers = method.getModifiers();
+        return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(method.getDeclaringClass().getModifiers())) &&
+                        !Modifier.isAbstract(modifiers);
+    }
+
+    private static String methodWithExceptionHandlers(String p1, Object o2) {
+        try {
+            return p1.substring(100) + o2.toString();
+        } catch (IndexOutOfBoundsException e) {
+            e.printStackTrace();
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+        } catch (RuntimeException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Test
+    public void getExceptionHandlersTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithExceptionHandlers", String.class, Object.class));
+        ExceptionHandler[] handlers = method.getExceptionHandlers();
+        assertNotNull(handlers);
+        assertEquals(handlers.length, 3);
+        handlers[0].getCatchType().equals(metaAccess.lookupJavaType(IndexOutOfBoundsException.class));
+        handlers[1].getCatchType().equals(metaAccess.lookupJavaType(NullPointerException.class));
+        handlers[2].getCatchType().equals(metaAccess.lookupJavaType(RuntimeException.class));
+    }
+
+    private static String nullPointerExceptionOnFirstLine(Object o, String ignored) {
+        return o.toString() + ignored;
+    }
+
+    @Test
+    public void asStackTraceElementTest() throws NoSuchMethodException {
+        try {
+            nullPointerExceptionOnFirstLine(null, "ignored");
+            Assert.fail("should not reach here");
+        } catch (NullPointerException e) {
+            StackTraceElement expected = e.getStackTrace()[0];
+            ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+            StackTraceElement actual = method.asStackTraceElement(0);
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void getConstantPoolTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            ConstantPool cp = m.getConstantPool();
+            assertTrue(cp.length() > 0);
+        }
+    }
+
+    @Test
+    public void getParametersTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            java.lang.reflect.Parameter[] expected = e.getKey().getParameters();
+            Parameter[] actual = e.getValue().getParameters();
+            assertEquals(actual.length, expected.length);
+            for (int i = 0; i < actual.length; i++) {
+                java.lang.reflect.Parameter exp = expected[i];
+                Parameter act = actual[i];
+                assertEquals(exp.getName(), act.getName());
+                assertEquals(exp.isNamePresent(), act.isNamePresent());
+                assertEquals(exp.getModifiers(), act.getModifiers());
+                assertArrayEquals(exp.getAnnotations(), act.getAnnotations());
+                assertEquals(exp.getType().getName(), act.getType().toClassName());
+                assertEquals(exp.getParameterizedType(), act.getParameterizedType());
+                assertEquals(metaAccess.lookupJavaMethod(exp.getDeclaringExecutable()), act.getDeclaringMethod());
+            }
+        }
+    }
+
+    @Test(timeout = 1000L)
+    public void getAnnotationTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationTest"));
+        Test annotation = method.getAnnotation(Test.class);
+        assertNotNull(annotation);
+        assertEquals(1000L, annotation.timeout());
+    }
+
+    @Test(timeout = 1000L)
+    public void getAnnotationsTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationsTest"));
+        Annotation[] annotations = method.getAnnotations();
+        assertNotNull(annotations);
+        assertEquals(1, annotations.length);
+        assertEquals(1000L, ((Test) annotations[0]).timeout());
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.PARAMETER)
+    @interface NonNull {
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.PARAMETER)
+    @interface Special {
+    }
+
+    private static native void methodWithAnnotatedParameters(@NonNull HashMap<String, String> p1, @Special @NonNull Class<? extends Annotation> p2);
+
+    @Test
+    public void getParameterAnnotationsTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+        Annotation[][] annotations = method.getParameterAnnotations();
+        assertEquals(2, annotations.length);
+        assertEquals(1, annotations[0].length);
+        assertEquals(NonNull.class, annotations[0][0].annotationType());
+        assertEquals(2, annotations[1].length);
+        assertEquals(Special.class, annotations[1][0].annotationType());
+        assertEquals(NonNull.class, annotations[1][1].annotationType());
+    }
+
+    @Test
+    public void getGenericParameterTypesTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+        Type[] genericParameterTypes = method.getGenericParameterTypes();
+        assertEquals(2, genericParameterTypes.length);
+        assertEquals("java.util.HashMap<java.lang.String, java.lang.String>", genericParameterTypes[0].toString());
+        assertEquals("java.lang.Class<? extends java.lang.annotation.Annotation>", genericParameterTypes[1].toString());
+    }
+
+    @Test
+    public void getMaxLocalsTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method1 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+        ResolvedJavaMethod method2 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+        assertEquals(0, method1.getMaxLocals());
+        assertEquals(2, method2.getMaxLocals());
+
+    }
+
+    @Test
+    public void getMaxStackSizeTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method1 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+        ResolvedJavaMethod method2 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+        assertEquals(0, method1.getMaxStackSize());
+        // some versions of javac produce bytecode with a stacksize of 2 for this method
+        // JSR 292 also sometimes need one more stack slot
+        int method2StackSize = method2.getMaxStackSize();
+        assertTrue(2 <= method2StackSize && method2StackSize <= 4);
+    }
+
+    @Test
+    public void isDefaultTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isDefault(), m.isDefault());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertFalse(m.isDefault());
+        }
+    }
+
+    @Test
+    public void hasReceiverTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertTrue(m.hasReceiver() != Modifier.isStatic(e.getKey().getModifiers()));
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertTrue(m.hasReceiver());
+        }
+    }
+
+    @Test
+    public void hasBytecodesTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertTrue(m.hasBytecodes() == (m.isConcrete() && !m.isNative()));
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertTrue(m.hasBytecodes());
+        }
+    }
+
+    @Test
+    public void isJavaLangObjectInitTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Object.class.getConstructor());
+        assertTrue(method.isJavaLangObjectInit());
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertFalse(m.isJavaLangObjectInit());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            Constructor<?> key = e.getKey();
+            if (key.getDeclaringClass() == Object.class && key.getParameters().length == 0) {
+                assertTrue(m.isJavaLangObjectInit());
+            } else {
+                assertFalse(m.isJavaLangObjectInit());
+            }
+        }
+    }
+
+    /**
+     * All public non-final methods should be available in the vtable.
+     */
+    @Test
+    public void testVirtualMethodTableAccess() {
+        for (Class<?> c : classes) {
+            if (c.isPrimitive() || c.isInterface()) {
+                continue;
+            }
+            ResolvedJavaType receiverType = metaAccess.lookupJavaType(c);
+            for (Method m : c.getMethods()) {
+                ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
+                if (!method.isStatic() && !method.isFinal() && !method.getDeclaringClass().isLeaf() && !method.getDeclaringClass().isInterface()) {
+                    assertTrue(method + " not available in " + receiverType, method.isInVirtualMethodTable(receiverType));
+                }
+            }
+        }
+    }
+
+    private Method findTestMethod(Method apiMethod) {
+        String testName = apiMethod.getName() + "Test";
+        for (Method m : getClass().getDeclaredMethods()) {
+            if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    // @formatter:off
+    private static final String[] untestedApiMethods = {
+        "newInstance",
+        "getDeclaringClass",
+        "getEncoding",
+        "getProfilingInfo",
+        "reprofile",
+        "getCompilerStorage",
+        "hasNeverInlineDirective",
+        "canBeInlined",
+        "shouldBeInlined",
+        "getLineNumberTable",
+        "getLocalVariableTable",
+        "isInVirtualMethodTable",
+        "toParameterTypes",
+        "getParameterAnnotation",
+        "getSpeculationLog",
+        "isFinal",
+        "$jacocoInit"
+    };
+    // @formatter:on
+
+    /**
+     * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
+     * for them or are added to {@link #untestedApiMethods}.
+     */
+    @Test
+    public void testCoverage() {
+        Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
+        for (Method m : ResolvedJavaMethod.class.getDeclaredMethods()) {
+            if (Modifier.isStatic(m.getModifiers())) {
+                continue;
+            }
+            if (findTestMethod(m) == null) {
+                assertTrue("test missing for " + m, known.contains(m.getName()));
+            } else {
+                assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,922 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile TestResolvedJavaType.java TypeUniverse.java TestMetaAccessProvider.java
+ * @run junit jdk.vm.ci.runtime.test.TestResolvedJavaType
+ */
+
+package jdk.vm.ci.runtime.test;
+
+import static java.lang.reflect.Modifier.isAbstract;
+import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isPrivate;
+import static java.lang.reflect.Modifier.isProtected;
+import static java.lang.reflect.Modifier.isPublic;
+import static java.lang.reflect.Modifier.isStatic;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import sun.reflect.ConstantPool;
+
+/**
+ * Tests for {@link ResolvedJavaType}.
+ */
+public class TestResolvedJavaType extends TypeUniverse {
+
+    public TestResolvedJavaType() {
+    }
+
+    @Test
+    public void findInstanceFieldWithOffsetTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            Set<Field> reflectionFields = getInstanceFields(c, true);
+            for (Field f : reflectionFields) {
+                ResolvedJavaField rf = lookupField(type.getInstanceFields(true), f);
+                assertNotNull(rf);
+                long offset = isStatic(f.getModifiers()) ? unsafe.staticFieldOffset(f) : unsafe.objectFieldOffset(f);
+                ResolvedJavaField result = type.findInstanceFieldWithOffset(offset, rf.getJavaKind());
+                assertNotNull(result);
+                assertTrue(fieldsEqual(f, result));
+            }
+        }
+    }
+
+    @Test
+    public void isInterfaceTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            boolean expected = c.isInterface();
+            boolean actual = type.isInterface();
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void isInstanceClassTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            boolean expected = !c.isArray() && !c.isPrimitive() && !c.isInterface();
+            boolean actual = type.isInstanceClass();
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void isArrayTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            boolean expected = c.isArray();
+            boolean actual = type.isArray();
+            assertEquals(expected, actual);
+        }
+    }
+
+    @Test
+    public void getModifiersTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            int mask = Modifier.classModifiers() & ~Modifier.STATIC;
+            int expected = c.getModifiers() & mask;
+            int actual = type.getModifiers() & mask;
+            Class<?> elementalType = c;
+            while (elementalType.isArray()) {
+                elementalType = elementalType.getComponentType();
+            }
+            if (elementalType.isMemberClass()) {
+                // member class get their modifiers from the inner-class attribute in the JVM and
+                // from the classfile header in jvmci
+                expected &= ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
+                actual &= ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
+            }
+            assertEquals(String.format("%s: 0x%x != 0x%x", type, expected, actual), expected, actual);
+        }
+    }
+
+    @Test
+    public void isAssignableFromTest() {
+        Class<?>[] all = classes.toArray(new Class<?>[classes.size()]);
+        for (int i = 0; i < all.length; i++) {
+            Class<?> c1 = all[i];
+            for (int j = i; j < all.length; j++) {
+                Class<?> c2 = all[j];
+                ResolvedJavaType t1 = metaAccess.lookupJavaType(c1);
+                ResolvedJavaType t2 = metaAccess.lookupJavaType(c2);
+                boolean expected = c1.isAssignableFrom(c2);
+                boolean actual = t1.isAssignableFrom(t2);
+                assertEquals(expected, actual);
+                if (expected && t1 != t2) {
+                    assertFalse(t2.isAssignableFrom(t1));
+                }
+            }
+        }
+    }
+
+    @Test
+    public void isInstanceTest() {
+        for (ConstantValue cv : constants()) {
+            JavaConstant c = cv.value;
+            if (c.getJavaKind() == JavaKind.Object && !c.isNull()) {
+                ResolvedJavaType cType = metaAccess.lookupJavaType(c);
+                for (ResolvedJavaType t : javaTypes) {
+                    if (t.isAssignableFrom(cType)) {
+                        assertTrue(t.isInstance(c));
+                    } else {
+                        assertFalse(t.isInstance(c));
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    public void getSuperclassTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            Class<?> expected = c.getSuperclass();
+            ResolvedJavaType actual = type.getSuperclass();
+            if (expected == null) {
+                assertTrue(actual == null);
+            } else {
+                assertNotNull(actual);
+                assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+            }
+        }
+    }
+
+    @Test
+    public void getInterfacesTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            Class<?>[] expected = c.getInterfaces();
+            ResolvedJavaType[] actual = type.getInterfaces();
+            assertEquals(expected.length, actual.length);
+            for (int i = 0; i < expected.length; i++) {
+                assertTrue(actual[i].equals(metaAccess.lookupJavaType(expected[i])));
+            }
+        }
+    }
+
+    public Class<?> getSupertype(Class<?> c) {
+        assert !c.isPrimitive();
+        if (c.isArray()) {
+            Class<?> componentType = c.getComponentType();
+            if (componentType.isPrimitive() || componentType == Object.class) {
+                return Object.class;
+            }
+            return getArrayClass(getSupertype(componentType));
+        }
+        if (c.isInterface()) {
+            return Object.class;
+        }
+        return c.getSuperclass();
+    }
+
+    public Class<?> findLeastCommonAncestor(Class<?> c1Initial, Class<?> c2Initial) {
+        if (c1Initial.isPrimitive() || c2Initial.isPrimitive()) {
+            return null;
+        } else {
+            Class<?> c1 = c1Initial;
+            Class<?> c2 = c2Initial;
+            while (true) {
+                if (c1.isAssignableFrom(c2)) {
+                    return c1;
+                }
+                if (c2.isAssignableFrom(c1)) {
+                    return c2;
+                }
+                c1 = getSupertype(c1);
+                c2 = getSupertype(c2);
+            }
+        }
+    }
+
+    @Test
+    public void findLeastCommonAncestorTest() {
+        Class<?>[] all = classes.toArray(new Class<?>[classes.size()]);
+        for (int i = 0; i < all.length; i++) {
+            Class<?> c1 = all[i];
+            for (int j = i; j < all.length; j++) {
+                Class<?> c2 = all[j];
+                ResolvedJavaType t1 = metaAccess.lookupJavaType(c1);
+                ResolvedJavaType t2 = metaAccess.lookupJavaType(c2);
+                Class<?> expected = findLeastCommonAncestor(c1, c2);
+                ResolvedJavaType actual = t1.findLeastCommonAncestor(t2);
+                if (expected == null) {
+                    assertTrue(actual == null);
+                } else {
+                    assertNotNull(actual);
+                    assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+                }
+            }
+        }
+    }
+
+    private static class Base {
+    }
+
+    abstract static class Abstract1 extends Base {
+    }
+
+    interface Interface1 {
+    }
+
+    static class Concrete1 extends Abstract1 {
+    }
+
+    static class Concrete2 extends Abstract1 implements Interface1 {
+    }
+
+    static class Concrete3 extends Concrete2 {
+    }
+
+    static final class Final1 extends Abstract1 {
+    }
+
+    abstract static class Abstract4 extends Concrete3 {
+    }
+
+    void checkConcreteSubtype(ResolvedJavaType type, ResolvedJavaType expected) {
+        AssumptionResult<ResolvedJavaType> leafConcreteSubtype = type.findLeafConcreteSubtype();
+        if (leafConcreteSubtype == null) {
+            // findLeafConcreteSubtype() is conservative
+        } else {
+            if (expected == null) {
+                assertNull(leafConcreteSubtype);
+            } else {
+                assertTrue(leafConcreteSubtype.getResult().equals(expected));
+            }
+            assertTrue(!type.isLeaf() || leafConcreteSubtype.isAssumptionFree());
+        }
+
+        if (!type.isArray()) {
+            ResolvedJavaType arrayType = type.getArrayClass();
+            AssumptionResult<ResolvedJavaType> arraySubtype = arrayType.findLeafConcreteSubtype();
+            if (arraySubtype != null) {
+                assertEquals(arraySubtype.getResult(), arrayType);
+            } else {
+                // findLeafConcreteSubtype() method is conservative
+            }
+        }
+    }
+
+    @Test
+    public void findLeafConcreteSubtypeTest() {
+        ResolvedJavaType base = metaAccess.lookupJavaType(Base.class);
+        checkConcreteSubtype(base, base);
+
+        ResolvedJavaType a1 = metaAccess.lookupJavaType(Abstract1.class);
+        ResolvedJavaType c1 = metaAccess.lookupJavaType(Concrete1.class);
+
+        checkConcreteSubtype(base, null);
+        checkConcreteSubtype(a1, c1);
+        checkConcreteSubtype(c1, c1);
+
+        ResolvedJavaType i1 = metaAccess.lookupJavaType(Interface1.class);
+        ResolvedJavaType c2 = metaAccess.lookupJavaType(Concrete2.class);
+
+        checkConcreteSubtype(base, null);
+        checkConcreteSubtype(a1, null);
+        checkConcreteSubtype(c1, c1);
+        checkConcreteSubtype(i1, c2);
+        checkConcreteSubtype(c2, c2);
+
+        ResolvedJavaType c3 = metaAccess.lookupJavaType(Concrete3.class);
+        checkConcreteSubtype(c2, null);
+        checkConcreteSubtype(c3, c3);
+
+        ResolvedJavaType a4 = metaAccess.lookupJavaType(Abstract4.class);
+        checkConcreteSubtype(c3, null);
+        checkConcreteSubtype(a4, null);
+
+        ResolvedJavaType a1a = metaAccess.lookupJavaType(Abstract1[].class);
+        checkConcreteSubtype(a1a, null);
+        ResolvedJavaType i1a = metaAccess.lookupJavaType(Interface1[].class);
+        checkConcreteSubtype(i1a, null);
+        ResolvedJavaType c1a = metaAccess.lookupJavaType(Concrete1[].class);
+        checkConcreteSubtype(c1a, c1a);
+        ResolvedJavaType f1a = metaAccess.lookupJavaType(Final1[].class);
+        checkConcreteSubtype(f1a, f1a);
+
+        ResolvedJavaType obja = metaAccess.lookupJavaType(Object[].class);
+        checkConcreteSubtype(obja, null);
+
+        ResolvedJavaType inta = metaAccess.lookupJavaType(int[].class);
+        checkConcreteSubtype(inta, inta);
+    }
+
+    interface NoImplementor {
+    }
+
+    interface SingleImplementorInterface {
+    }
+
+    static class SingleConcreteImplementor implements SingleImplementorInterface {
+    }
+
+    interface SingleAbstractImplementorInterface {
+    }
+
+    abstract static class SingleAbstractImplementor implements SingleAbstractImplementorInterface {
+    }
+
+    interface MultiImplementorInterface {
+    }
+
+    static class ConcreteImplementor1 implements MultiImplementorInterface {
+    }
+
+    static class ConcreteImplementor2 implements MultiImplementorInterface {
+    }
+
+    interface MultipleAbstractImplementorInterface {
+    }
+
+    abstract static class MultiAbstractImplementor1 implements MultipleAbstractImplementorInterface {
+    }
+
+    abstract static class MultiAbstractImplementor2 implements MultipleAbstractImplementorInterface {
+    }
+
+    interface SingleAbstractImplementorInterface2 {
+    }
+
+    interface ExtendedSingleImplementorInterface {
+    }
+
+    abstract static class SingleAbstractImplementor2 implements SingleAbstractImplementorInterface2 {
+    }
+
+    static class ConcreteTransitiveImplementor1 extends SingleAbstractImplementor2 implements ExtendedSingleImplementorInterface {
+    }
+
+    static class ConcreteTransitiveImplementor2 extends SingleAbstractImplementor2 implements ExtendedSingleImplementorInterface {
+    }
+
+    @Test
+    public void getSingleImplementorTest() {
+        ResolvedJavaType iNi = metaAccess.lookupJavaType(NoImplementor.class);
+        assertNull(iNi.getSingleImplementor());
+
+        ResolvedJavaType iSi = metaAccess.lookupJavaType(SingleImplementorInterface.class);
+        ResolvedJavaType cSi = metaAccess.lookupJavaType(SingleConcreteImplementor.class);
+        assertEquals(cSi, iSi.getSingleImplementor());
+
+        ResolvedJavaType iSai = metaAccess.lookupJavaType(SingleAbstractImplementorInterface.class);
+        ResolvedJavaType aSai = metaAccess.lookupJavaType(SingleAbstractImplementor.class);
+        assertEquals(aSai, iSai.getSingleImplementor());
+
+        ResolvedJavaType iMi = metaAccess.lookupJavaType(MultiImplementorInterface.class);
+        metaAccess.lookupJavaType(ConcreteImplementor1.class);
+        metaAccess.lookupJavaType(ConcreteImplementor2.class);
+        assertEquals(iMi, iMi.getSingleImplementor());
+
+        ResolvedJavaType iMai = metaAccess.lookupJavaType(MultipleAbstractImplementorInterface.class);
+        metaAccess.lookupJavaType(MultiAbstractImplementor1.class);
+        metaAccess.lookupJavaType(MultiAbstractImplementor2.class);
+        assertEquals(iMai, iMai.getSingleImplementor());
+
+        ResolvedJavaType iSai2 = metaAccess.lookupJavaType(SingleAbstractImplementorInterface2.class);
+        ResolvedJavaType aSai2 = metaAccess.lookupJavaType(SingleAbstractImplementor2.class);
+        metaAccess.lookupJavaType(ConcreteTransitiveImplementor1.class);
+        metaAccess.lookupJavaType(ConcreteTransitiveImplementor2.class);
+        assertEquals(aSai2, iSai2.getSingleImplementor());
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void getSingleImplementorTestClassReceiver() {
+        ResolvedJavaType base = metaAccess.lookupJavaType(Base.class);
+        base.getSingleImplementor();
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void getSingleImplementorTestPrimitiveReceiver() {
+        ResolvedJavaType primitive = metaAccess.lookupJavaType(int.class);
+        primitive.getSingleImplementor();
+    }
+
+    @Test
+    public void getComponentTypeTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            Class<?> expected = c.getComponentType();
+            ResolvedJavaType actual = type.getComponentType();
+            if (expected == null) {
+                assertNull(actual);
+            } else {
+                assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+            }
+        }
+    }
+
+    @Test
+    public void getArrayClassTest() {
+        for (Class<?> c : classes) {
+            if (c != void.class) {
+                ResolvedJavaType type = metaAccess.lookupJavaType(c);
+                Class<?> expected = getArrayClass(c);
+                ResolvedJavaType actual = type.getArrayClass();
+                assertTrue(actual.equals(metaAccess.lookupJavaType(expected)));
+            }
+        }
+    }
+
+    static class Declarations {
+
+        final Method implementation;
+        final Set<Method> declarations;
+
+        Declarations(Method impl) {
+            this.implementation = impl;
+            declarations = new HashSet<>();
+        }
+    }
+
+    /**
+     * See <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.4.5">Method
+     * overriding</a>.
+     */
+    static boolean isOverriderOf(Method impl, Method m) {
+        if (!isPrivate(m.getModifiers()) && !isFinal(m.getModifiers())) {
+            if (m.getName().equals(impl.getName())) {
+                if (m.getReturnType() == impl.getReturnType()) {
+                    if (Arrays.equals(m.getParameterTypes(), impl.getParameterTypes())) {
+                        if (isPublic(m.getModifiers()) || isProtected(m.getModifiers())) {
+                            // m is public or protected
+                            return isPublic(impl.getModifiers()) || isProtected(impl.getModifiers());
+                        } else {
+                            // m is package-private
+                            return impl.getDeclaringClass().getPackage() == m.getDeclaringClass().getPackage();
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    static final Map<Class<?>, VTable> vtables = new HashMap<>();
+
+    static class VTable {
+
+        final Map<NameAndSignature, Method> methods = new HashMap<>();
+    }
+
+    static synchronized VTable getVTable(Class<?> c) {
+        VTable vtable = vtables.get(c);
+        if (vtable == null) {
+            vtable = new VTable();
+            if (c != Object.class) {
+                VTable superVtable = getVTable(c.getSuperclass());
+                vtable.methods.putAll(superVtable.methods);
+            }
+            for (Method m : c.getDeclaredMethods()) {
+                if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) {
+                    if (isAbstract(m.getModifiers())) {
+                        // A subclass makes a concrete method in a superclass abstract
+                        vtable.methods.remove(new NameAndSignature(m));
+                    } else {
+                        vtable.methods.put(new NameAndSignature(m), m);
+                    }
+                }
+            }
+            vtables.put(c, vtable);
+        }
+        return vtable;
+    }
+
+    static Set<Method> findDeclarations(Method impl, Class<?> c) {
+        Set<Method> declarations = new HashSet<>();
+        NameAndSignature implSig = new NameAndSignature(impl);
+        if (c != null) {
+            for (Method m : c.getDeclaredMethods()) {
+                if (new NameAndSignature(m).equals(implSig)) {
+                    declarations.add(m);
+                    break;
+                }
+            }
+            if (!c.isInterface()) {
+                declarations.addAll(findDeclarations(impl, c.getSuperclass()));
+            }
+            for (Class<?> i : c.getInterfaces()) {
+                declarations.addAll(findDeclarations(impl, i));
+            }
+        }
+        return declarations;
+    }
+
+    @Test
+    public void resolveMethodTest() {
+        ResolvedJavaType context = metaAccess.lookupJavaType(TestResolvedJavaType.class);
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            if (c.isInterface()) {
+                for (Method m : c.getDeclaredMethods()) {
+                    ResolvedJavaMethod resolved = metaAccess.lookupJavaMethod(m);
+                    ResolvedJavaMethod impl = type.resolveMethod(resolved, context);
+                    assertEquals(m.toString(), null, impl);
+                }
+            } else if (c.isPrimitive()) {
+                assertEquals("No methods expected", c.getDeclaredMethods().length, 0);
+            } else {
+                VTable vtable = getVTable(c);
+                for (Method impl : vtable.methods.values()) {
+                    Set<Method> decls = findDeclarations(impl, c);
+                    for (Method decl : decls) {
+                        ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl);
+                        if (m.isPublic()) {
+                            ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl);
+                            assertEquals(m.toString(), i, type.resolveMethod(m, context));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    public void resolveConcreteMethodTest() {
+        ResolvedJavaType context = metaAccess.lookupJavaType(TestResolvedJavaType.class);
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            if (c.isInterface()) {
+                for (Method m : c.getDeclaredMethods()) {
+                    ResolvedJavaMethod resolved = metaAccess.lookupJavaMethod(m);
+                    ResolvedJavaMethod impl = type.resolveConcreteMethod(resolved, context);
+                    assertEquals(m.toString(), null, impl);
+                }
+            } else if (c.isPrimitive()) {
+                assertEquals("No methods expected", c.getDeclaredMethods().length, 0);
+            } else {
+                VTable vtable = getVTable(c);
+                for (Method impl : vtable.methods.values()) {
+                    Set<Method> decls = findDeclarations(impl, c);
+                    for (Method decl : decls) {
+                        ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl);
+                        if (m.isPublic()) {
+                            ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl);
+                            assertEquals(i, type.resolveConcreteMethod(m, context));
+                        }
+                    }
+                }
+                for (Method m : c.getDeclaredMethods()) {
+                    ResolvedJavaMethod impl = type.resolveConcreteMethod(metaAccess.lookupJavaMethod(m), context);
+                    ResolvedJavaMethod expected = isAbstract(m.getModifiers()) ? null : impl;
+                    assertEquals(type + " " + m.toString(), expected, impl);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void findUniqueConcreteMethodTest() throws NoSuchMethodException {
+        ResolvedJavaMethod thisMethod = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("findUniqueConcreteMethodTest"));
+        ResolvedJavaMethod ucm = metaAccess.lookupJavaType(getClass()).findUniqueConcreteMethod(thisMethod).getResult();
+        assertEquals(thisMethod, ucm);
+    }
+
+    public static Set<Field> getInstanceFields(Class<?> c, boolean includeSuperclasses) {
+        if (c.isArray() || c.isPrimitive() || c.isInterface()) {
+            return Collections.emptySet();
+        }
+        Set<Field> result = new HashSet<>();
+        for (Field f : c.getDeclaredFields()) {
+            if (!Modifier.isStatic(f.getModifiers())) {
+                result.add(f);
+            }
+        }
+        if (includeSuperclasses && c != Object.class) {
+            result.addAll(getInstanceFields(c.getSuperclass(), true));
+        }
+        return result;
+    }
+
+    public static Set<Field> getStaticFields(Class<?> c) {
+        Set<Field> result = new HashSet<>();
+        for (Field f : c.getDeclaredFields()) {
+            if (Modifier.isStatic(f.getModifiers())) {
+                result.add(f);
+            }
+        }
+        return result;
+    }
+
+    public boolean fieldsEqual(Field f, ResolvedJavaField rjf) {
+        return rjf.getDeclaringClass().equals(metaAccess.lookupJavaType(f.getDeclaringClass())) && rjf.getName().equals(f.getName()) &&
+                        rjf.getType().resolve(rjf.getDeclaringClass()).equals(metaAccess.lookupJavaType(f.getType()));
+    }
+
+    public ResolvedJavaField lookupField(ResolvedJavaField[] fields, Field key) {
+        for (ResolvedJavaField rf : fields) {
+            if (fieldsEqual(key, rf)) {
+                return rf;
+            }
+        }
+        return null;
+    }
+
+    public Field lookupField(Set<Field> fields, ResolvedJavaField key) {
+        for (Field f : fields) {
+            if (fieldsEqual(f, key)) {
+                return f;
+            }
+        }
+        return null;
+    }
+
+    private static boolean isHiddenFromReflection(ResolvedJavaField f) {
+        if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(Throwable.class)) && f.getName().equals("backtrace")) {
+            return true;
+        }
+        if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(ConstantPool.class)) && f.getName().equals("constantPoolOop")) {
+            return true;
+        }
+        if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(Class.class)) && f.getName().equals("classLoader")) {
+            return true;
+        }
+        return false;
+    }
+
+    @Test
+    public void getInstanceFieldsTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            for (boolean includeSuperclasses : new boolean[]{true, false}) {
+                Set<Field> expected = getInstanceFields(c, includeSuperclasses);
+                ResolvedJavaField[] actual = type.getInstanceFields(includeSuperclasses);
+                for (Field f : expected) {
+                    assertNotNull(lookupField(actual, f));
+                }
+                for (ResolvedJavaField rf : actual) {
+                    if (!isHiddenFromReflection(rf)) {
+                        assertEquals(rf.toString(), lookupField(expected, rf) != null, !rf.isInternal());
+                    }
+                }
+
+                // Test stability of getInstanceFields
+                ResolvedJavaField[] actual2 = type.getInstanceFields(includeSuperclasses);
+                assertArrayEquals(actual, actual2);
+            }
+        }
+    }
+
+    @Test
+    public void getStaticFieldsTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            Set<Field> expected = getStaticFields(c);
+            ResolvedJavaField[] actual = type.getStaticFields();
+            for (Field f : expected) {
+                assertNotNull(lookupField(actual, f));
+            }
+            for (ResolvedJavaField rf : actual) {
+                if (!isHiddenFromReflection(rf)) {
+                    assertEquals(lookupField(expected, rf) != null, !rf.isInternal());
+                }
+            }
+
+            // Test stability of getStaticFields
+            ResolvedJavaField[] actual2 = type.getStaticFields();
+            assertArrayEquals(actual, actual2);
+        }
+    }
+
+    @Test
+    public void getDeclaredMethodsTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            Method[] raw = c.getDeclaredMethods();
+            Set<ResolvedJavaMethod> expected = new HashSet<>();
+            for (Method m : raw) {
+                ResolvedJavaMethod resolvedMethod = metaAccess.lookupJavaMethod(m);
+                assertNotNull(resolvedMethod);
+                expected.add(resolvedMethod);
+            }
+            Set<ResolvedJavaMethod> actual = new HashSet<>(Arrays.asList(type.getDeclaredMethods()));
+            assertEquals(expected, actual);
+        }
+    }
+
+    static class A {
+        static String name = "foo";
+    }
+
+    static class B extends A {
+    }
+
+    static class C {
+    }
+
+    static class D {
+        void foo() {
+            // use of assertions causes the class to have a <clinit>
+            assert getClass() != null;
+        }
+    }
+
+    static class SubD extends D {
+
+    }
+
+    @Test
+    public void getClassInitializerTest() {
+        assertNotNull(metaAccess.lookupJavaType(A.class).getClassInitializer());
+        assertNotNull(metaAccess.lookupJavaType(D.class).getClassInitializer());
+        assertNull(metaAccess.lookupJavaType(B.class).getClassInitializer());
+        assertNull(metaAccess.lookupJavaType(C.class).getClassInitializer());
+        assertNull(metaAccess.lookupJavaType(int.class).getClassInitializer());
+        assertNull(metaAccess.lookupJavaType(void.class).getClassInitializer());
+    }
+
+    @Test
+    public void getAnnotationsTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            assertArrayEquals(c.getAnnotations(), type.getAnnotations());
+        }
+    }
+
+    @Test
+    public void getAnnotationTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            for (Annotation a : c.getAnnotations()) {
+                assertEquals(a, type.getAnnotation(a.annotationType()));
+            }
+        }
+    }
+
+    @Test
+    public void memberClassesTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            assertEquals(c.isLocalClass(), type.isLocal());
+            assertEquals(c.isMemberClass(), type.isMember());
+            Class<?> enclc = c.getEnclosingClass();
+            ResolvedJavaType enclt = type.getEnclosingType();
+            assertFalse(enclc == null ^ enclt == null);
+            if (enclc != null) {
+                assertEquals(enclt, metaAccess.lookupJavaType(enclc));
+            }
+        }
+    }
+
+    @Test
+    public void isLeafTest() {
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            ResolvedJavaType arrayType = c != void.class ? metaAccess.lookupJavaType(getArrayClass(c)) : null;
+            if (c.isPrimitive()) {
+                assertTrue(type.isLeaf());
+                assertTrue(arrayType == null || arrayType.isLeaf());
+            } else {
+                assertTrue(c.toString(), type.isLeaf() == arrayType.isLeaf());
+                if (!c.isArray()) {
+                    assertTrue(c.toString(), type.isLeaf() == Modifier.isFinal(c.getModifiers()));
+                }
+            }
+        }
+    }
+
+    static class TrivialCloneable implements Cloneable {
+        @Override
+        protected Object clone() {
+            return new TrivialCloneable();
+        }
+    }
+
+    @Test
+    public void isCloneableWithAllocationTest() {
+        ResolvedJavaType cloneable = metaAccess.lookupJavaType(Cloneable.class);
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            if (type.isCloneableWithAllocation()) {
+                // Only Cloneable types should be allocation cloneable
+                assertTrue(c.toString(), cloneable.isAssignableFrom(type));
+            }
+        }
+        /*
+         * We can't know for sure which types should be allocation cloneable on a particular
+         * platform but assume that at least totally trivial objects should be.
+         */
+        ResolvedJavaType trivialCloneable = metaAccess.lookupJavaType(TrivialCloneable.class);
+        assertTrue(trivialCloneable.toString(), trivialCloneable.isCloneableWithAllocation());
+    }
+
+    @Test
+    public void findMethodTest() {
+        try {
+            ResolvedJavaMethod findFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("()V"));
+            ResolvedJavaMethod expectedFoo = metaAccess.lookupJavaMethod(D.class.getDeclaredMethod("foo"));
+            assertEquals(expectedFoo, findFoo);
+
+            ResolvedJavaMethod wrongReturnTypeFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("()I"));
+            assertNull(wrongReturnTypeFoo);
+
+            ResolvedJavaMethod wrongArgumentsFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("(I)V"));
+            assertNull(wrongArgumentsFoo);
+
+            ResolvedJavaMethod wrongNameFoo = metaAccess.lookupJavaType(D.class).findMethod("bar", metaAccess.parseMethodDescriptor("()V"));
+            assertNull(wrongNameFoo);
+
+            ResolvedJavaMethod wrongClassFoo = metaAccess.lookupJavaType(SubD.class).findMethod("foo", metaAccess.parseMethodDescriptor("()V"));
+            assertNull(wrongClassFoo);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private Method findTestMethod(Method apiMethod) {
+        String testName = apiMethod.getName() + "Test";
+        for (Method m : getClass().getDeclaredMethods()) {
+            if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    // @formatter:off
+    private static final String[] untestedApiMethods = {
+        "initialize",
+        "isPrimitive",
+        "newArray",
+        "getDeclaredConstructors",
+        "isInitialized",
+        "isLinked",
+        "getJavaClass",
+        "getObjectHub",
+        "hasFinalizableSubclass",
+        "hasFinalizer",
+        "getSourceFileName",
+        "isLocal",
+        "isJavaLangObject",
+        "isMember",
+        "getElementalType",
+        "getEnclosingType",
+        "$jacocoInit"
+    };
+    // @formatter:on
+
+    /**
+     * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
+     * for them or are added to {@link #untestedApiMethods}.
+     */
+    @Test
+    public void testCoverage() {
+        Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
+        for (Method m : ResolvedJavaType.class.getDeclaredMethods()) {
+            if (findTestMethod(m) == null) {
+                assertTrue("test missing for " + m, known.contains(m.getName()));
+            } else {
+                assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime.test;
+
+import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isStatic;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.AbstractCollection;
+import java.util.AbstractList;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
+import sun.misc.Unsafe;
+
+/**
+ * Context for type related tests.
+ */
+public class TypeUniverse {
+
+    public static final Unsafe unsafe;
+    public static final double JAVA_VERSION = Double.valueOf(System.getProperty("java.specification.version"));
+
+    public static final MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+    public static final ConstantReflectionProvider constantReflection = JVMCI.getRuntime().getHostJVMCIBackend().getConstantReflection();
+    public static final Collection<Class<?>> classes = new HashSet<>();
+    public static final Set<ResolvedJavaType> javaTypes;
+    public static final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
+
+    private static List<ConstantValue> constants;
+
+    public class InnerClass {
+
+    }
+
+    public static class InnerStaticClass {
+
+    }
+
+    public static final class InnerStaticFinalClass {
+
+    }
+
+    private class PrivateInnerClass {
+
+    }
+
+    protected class ProtectedInnerClass {
+
+    }
+
+    static {
+        Unsafe theUnsafe = null;
+        try {
+            theUnsafe = Unsafe.getUnsafe();
+        } catch (Exception e) {
+            try {
+                Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+                theUnsafeField.setAccessible(true);
+                theUnsafe = (Unsafe) theUnsafeField.get(null);
+            } catch (Exception e1) {
+                throw (InternalError) new InternalError("unable to initialize unsafe").initCause(e1);
+            }
+        }
+        unsafe = theUnsafe;
+
+        Class<?>[] initialClasses = {void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, boolean[].class,
+                        byte[].class, short[].class, char[].class, int[].class, float[].class, long[].class, double[].class, Object[].class, Class[].class, List[].class, boolean[][].class,
+                        byte[][].class, short[][].class, char[][].class, int[][].class, float[][].class, long[][].class, double[][].class, Object[][].class, Class[][].class, List[][].class,
+                        ClassLoader.class, String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class,
+                        HashMap.class, LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class, InnerClass.class,
+                        InnerStaticClass.class, InnerStaticFinalClass.class, PrivateInnerClass.class, ProtectedInnerClass.class};
+        for (Class<?> c : initialClasses) {
+            addClass(c);
+        }
+
+        javaTypes = Collections.unmodifiableSet(classes.stream().map(c -> metaAccess.lookupJavaType(c)).collect(Collectors.toSet()));
+    }
+
+    static class ConstantsUniverse {
+        static final Object[] ARRAYS = classes.stream().map(c -> c != void.class && !c.isArray() ? Array.newInstance(c, 42) : null).filter(o -> o != null).collect(Collectors.toList()).toArray();
+        static final Object CONST1 = new ArrayList<>();
+        static final Object CONST2 = new ArrayList<>();
+        static final Object CONST3 = new IdentityHashMap<>();
+        static final Object CONST4 = new LinkedHashMap<>();
+        static final Object CONST5 = new TreeMap<>();
+        static final Object CONST6 = new ArrayDeque<>();
+        static final Object CONST7 = new LinkedList<>();
+        static final Object CONST8 = "a string";
+        static final Object CONST9 = 42;
+        static final Object CONST10 = String.class;
+        static final Object CONST11 = String[].class;
+    }
+
+    public static List<ConstantValue> constants() {
+        if (constants == null) {
+            List<ConstantValue> res = readConstants(JavaConstant.class);
+            res.addAll(readConstants(ConstantsUniverse.class));
+            constants = res;
+        }
+        return constants;
+    }
+
+    public static class ConstantValue {
+        public final String name;
+        public final JavaConstant value;
+        public final Object boxed;
+
+        public ConstantValue(String name, JavaConstant value, Object boxed) {
+            this.name = name;
+            this.value = value;
+            this.boxed = boxed;
+        }
+
+        @Override
+        public String toString() {
+            return name + "=" + value;
+        }
+
+        public String getSimpleName() {
+            return name.substring(name.lastIndexOf('.') + 1);
+        }
+    }
+
+    /**
+     * Reads the value of all {@code static final} fields from a given class into an array of
+     * {@link ConstantValue}s.
+     */
+    public static List<ConstantValue> readConstants(Class<?> fromClass) {
+        try {
+            List<ConstantValue> res = new ArrayList<>();
+            for (Field field : fromClass.getDeclaredFields()) {
+                if (isStatic(field.getModifiers()) && isFinal(field.getModifiers())) {
+                    ResolvedJavaField javaField = metaAccess.lookupJavaField(field);
+                    Object boxed = field.get(null);
+                    if (boxed instanceof JavaConstant) {
+                        res.add(new ConstantValue(javaField.format("%H.%n"), (JavaConstant) boxed, boxed));
+                    } else {
+                        JavaConstant value = constantReflection.readFieldValue(javaField, null);
+                        if (value != null) {
+                            res.add(new ConstantValue(javaField.format("%H.%n"), value, boxed));
+                            if (boxed instanceof Object[]) {
+                                Object[] arr = (Object[]) boxed;
+                                for (int i = 0; i < arr.length; i++) {
+                                    JavaConstant element = constantReflection.readArrayElement(value, i);
+                                    if (element != null) {
+                                        res.add(new ConstantValue(javaField.format("%H.%n[" + i + "]"), element, arr[i]));
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return res;
+        } catch (Exception e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    public synchronized Class<?> getArrayClass(Class<?> componentType) {
+        Class<?> arrayClass = arrayClasses.get(componentType);
+        if (arrayClass == null) {
+            arrayClass = Array.newInstance(componentType, 0).getClass();
+            arrayClasses.put(componentType, arrayClass);
+        }
+        return arrayClass;
+    }
+
+    public static int dimensions(Class<?> c) {
+        if (c.getComponentType() != null) {
+            return 1 + dimensions(c.getComponentType());
+        }
+        return 0;
+    }
+
+    private static void addClass(Class<?> c) {
+        if (classes.add(c)) {
+            if (c.getSuperclass() != null) {
+                addClass(c.getSuperclass());
+            }
+            for (Class<?> sc : c.getInterfaces()) {
+                addClass(sc);
+            }
+            for (Class<?> dc : c.getDeclaredClasses()) {
+                addClass(dc);
+            }
+            for (Method m : c.getDeclaredMethods()) {
+                addClass(m.getReturnType());
+                for (Class<?> p : m.getParameterTypes()) {
+                    addClass(p);
+                }
+            }
+
+            if (c != void.class && dimensions(c) < 2) {
+                Class<?> arrayClass = Array.newInstance(c, 0).getClass();
+                arrayClasses.put(c, arrayClass);
+                addClass(arrayClass);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime;
+
+import java.util.Formatter;
+
+public class JVMCI {
+
+    private static final JVMCIRuntime runtime;
+
+    private static native JVMCIRuntime initializeRuntime();
+
+    public static void initialize() {
+        // force static initializer
+    }
+
+    /**
+     * Gets the singleton {@link JVMCIRuntime} instance available to the application.
+     *
+     * @throws UnsupportedOperationException if JVMCI is not supported
+     */
+    public static JVMCIRuntime getRuntime() {
+        if (runtime == null) {
+            String javaHome = System.getProperty("java.home");
+            String vmName = System.getProperty("java.vm.name");
+            Formatter errorMessage = new Formatter();
+            errorMessage.format("The VM does not support the JVMCI API.%n");
+            errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
+            errorMessage.format("Currently used VM configuration is: %s", vmName);
+            throw new UnsupportedOperationException(errorMessage.toString());
+        }
+        return runtime;
+    }
+
+    static {
+        JVMCIRuntime rt = null;
+        try {
+            rt = initializeRuntime();
+        } catch (UnsatisfiedLinkError e) {
+        }
+        runtime = rt;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime;
+
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
+
+/**
+ * A JVMCI backend encapsulates the capabilities needed by a Java based compiler for compiling and
+ * installing code for a single compute unit within a JVM. In a JVM with support for heterogeneous
+ * computing, more than one backend may be exposed.
+ */
+public class JVMCIBackend {
+
+    private final MetaAccessProvider metaAccess;
+    private final CodeCacheProvider codeCache;
+    private final ConstantReflectionProvider constantReflection;
+    private final StackIntrospection stackIntrospection;
+
+    public JVMCIBackend(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, StackIntrospection stackIntrospection) {
+        this.metaAccess = metaAccess;
+        this.codeCache = codeCache;
+        this.constantReflection = constantReflection;
+        this.stackIntrospection = stackIntrospection;
+    }
+
+    public MetaAccessProvider getMetaAccess() {
+        return metaAccess;
+    }
+
+    public CodeCacheProvider getCodeCache() {
+        return codeCache;
+    }
+
+    public ConstantReflectionProvider getConstantReflection() {
+        return constantReflection;
+    }
+
+    public TargetDescription getTarget() {
+        return codeCache.getTarget();
+    }
+
+    public StackIntrospection getStackIntrospection() {
+        return stackIntrospection;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompiler.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime;
+
+import jdk.vm.ci.code.CompilationRequest;
+import jdk.vm.ci.code.CompilationRequestResult;
+
+public interface JVMCICompiler {
+    int INVOCATION_ENTRY_BCI = -1;
+
+    /**
+     * Services a compilation request. This object should compile the method to machine code and
+     * install it in the code cache if the compilation is successful.
+     */
+    CompilationRequestResult compileMethod(CompilationRequest request);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompilerFactory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime;
+
+import java.io.PrintStream;
+
+/**
+ * Factory for creating JVMCI compilers.
+ */
+public interface JVMCICompilerFactory {
+
+    /**
+     * Get the name of this compiler. The name is used by JVMCI to determine which factory to use.
+     */
+    String getCompilerName();
+
+    /**
+     * Notifies this object that it has been selected to {@linkplain #createCompiler(JVMCIRuntime)
+     * create} a compiler and it should now perform any heavy weight initialization that it deferred
+     * during construction.
+     */
+    default void onSelection() {
+    }
+
+    /**
+     * Create a new instance of a {@link JVMCICompiler}.
+     */
+    JVMCICompiler createCompiler(JVMCIRuntime runtime);
+
+    /**
+     * Prints a description of the properties used to configure this compiler.
+     *
+     * @param out where to print the message
+     */
+    default void printProperties(PrintStream out) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime;
+
+import jdk.vm.ci.code.Architecture;
+
+/**
+ * Interface for accessing the {@link JVMCI} APIs supported by the runtime.
+ */
+public interface JVMCIRuntime {
+
+    /**
+     * Gets the default system compiler.
+     */
+    JVMCICompiler getCompiler();
+
+    /**
+     * Gets the host JVMCI backend.
+     */
+    JVMCIBackend getHostJVMCIBackend();
+
+    /**
+     * Gets the backend for a given architecture.
+     *
+     * @param arch a specific architecture class
+     */
+    <T extends Architecture> JVMCIBackend getJVMCIBackend(Class<T> arch);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.services/.checkstyle_checks.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+    Checkstyle-Configuration: Checks
+    Description: none
+-->
+<module name="Checker">
+  <property name="severity" value="error"/>
+  <module name="TreeWalker">
+    <property name="tabWidth" value="4"/>
+    <module name="FileContentsHolder"/>
+    <module name="JavadocStyle">
+      <property name="checkHtml" value="false"/>
+    </module>
+    <module name="LocalFinalVariableName"/>
+    <module name="LocalVariableName"/>
+    <module name="MemberName">
+      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
+    </module>
+    <module name="MethodName"/>
+    <module name="PackageName"/>
+    <module name="ParameterName"/>
+    <module name="TypeName">
+      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
+    </module>
+    <module name="RedundantImport"/>
+    <module name="LineLength">
+      <property name="max" value="250"/>
+    </module>
+    <module name="MethodParamPad"/>
+    <module name="NoWhitespaceAfter">
+      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
+    </module>
+    <module name="AvoidStarImport">
+       <property name="allowClassImports" value="false"/>
+       <property name="allowStaticMemberImports" value="false"/>
+    </module>
+    <module name="NoWhitespaceBefore">
+      <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+    </module>
+    <module name="ParenPad"/>
+    <module name="TypecastParenPad">
+      <property name="tokens" value="RPAREN,TYPECAST"/>
+    </module>
+    <module name="WhitespaceAfter"/>
+    <module name="WhitespaceAround">
+      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
+    </module>
+    <module name="RedundantModifier"/>
+    <module name="AvoidNestedBlocks">
+      <property name="allowInSwitchCase" value="true"/>
+    </module>
+    <module name="EmptyBlock">
+      <property name="option" value="text"/>
+      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
+    </module>
+    <module name="LeftCurly"/>
+    <module name="NeedBraces"/>
+    <module name="RightCurly"/>
+    <module name="EmptyStatement"/>
+    <module name="HiddenField">
+      <property name="severity" value="ignore"/>
+      <property name="ignoreConstructorParameter" value="true"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="FinalClass"/>
+    <module name="HideUtilityClassConstructor">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ArrayTypeStyle"/>
+    <module name="UpperEll"/>
+    <module name="FallThrough"/>
+    <module name="FinalLocalVariable">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="MultipleVariableDeclarations"/>
+    <module name="StringLiteralEquality">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="SuperFinalize"/>
+    <module name="UnnecessaryParentheses">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="Indentation">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="StaticVariableName">
+      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="EmptyForInitializerPad"/>
+    <module name="EmptyForIteratorPad"/>
+    <module name="ModifierOrder"/>
+    <module name="DefaultComesLast"/>
+    <module name="InnerAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ModifiedControlVariable"/>
+    <module name="MutableException">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ParameterAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
+      <property name="format" value="\s$"/>
+      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
+      <property name="format" value=" ,"/>
+      <property name="message" value="illegal space before a comma"/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="[^\x00-\x7F]"/>
+      <property name="message" value="Only use ASCII characters."/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
+      <property name="message" value="Don't use old synchronized collection classes"/>
+    </module>
+  </module>
+  <module name="RegexpHeader">
+    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
+    <property name="fileExtensions" value="java"/>
+  </module>
+  <module name="FileTabCharacter">
+    <property name="severity" value="error"/>
+    <property name="fileExtensions" value="java"/>
+  </module>
+  <module name="NewlineAtEndOfFile">
+    <property name="lineSeparator" value="lf"/>
+  </module>
+  <module name="Translation"/>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+    <property name="checkFormat" value="ConstantNameCheck"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+    <property name="checkFormat" value="MethodName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+    <property name="checkFormat" value="ParameterAssignment"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+    <property name="checkFormat" value="FinalLocalVariable"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop"/>
+    <property name="onCommentFormat" value="Checkstyle: resume"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+    <property name="checkFormat" value="InnerAssignment"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+    <property name="checkFormat" value="MemberName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+  </module>
+  <module name="RegexpMultiline">
+    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
+    <property name="format" value="\r\n"/>
+    <property name="message" value="illegal Windows line ending"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+    <property name="checkFormat" value=".*Header"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
+    <property name="checkFormat" value="LineLength"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: start generated"/>
+    <property name="onCommentFormat" value="CheckStyle: stop generated"/>
+    <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
+  </module>
+</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIClassLoaderFactory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.services;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+
+import sun.misc.VM;
+
+/**
+ * Utility called from the VM to create and register a separate class loader for loading JVMCI
+ * classes (i.e., those in found in lib/jvmci/*.jar) as well as those available on the class path in
+ * the {@code "jvmci.class.path.append"} system property.
+ */
+class JVMCIClassLoaderFactory {
+
+    /**
+     * Copy of the {@code UseJVMCIClassLoader} VM option. Set by the VM before the static
+     * initializer is called.
+     */
+    private static boolean useJVMCIClassLoader;
+
+    /**
+     * Registers the JVMCI class loader in the VM.
+     */
+    private static native void init(ClassLoader loader);
+
+    static {
+        init(useJVMCIClassLoader ? newClassLoader() : null);
+    }
+
+    /**
+     * Creates a new class loader for loading JVMCI classes.
+     */
+    private static ClassLoader newClassLoader() {
+        URL[] urls = getJVMCIJarsUrls();
+        ClassLoader parent = null;
+        return URLClassLoader.newInstance(urls, parent);
+    }
+
+    /**
+     * Gets the URLs for lib/jvmci/*.jar.
+     */
+    private static URL[] getJVMCIJarsUrls() {
+        File javaHome = new File(VM.getSavedProperty("java.home"));
+        File lib = new File(javaHome, "lib");
+        File jvmci = new File(lib, "jvmci");
+        if (!jvmci.isDirectory()) {
+            throw new InternalError(jvmci + " does not exist or is not a directory");
+        }
+
+        List<URL> urls = new ArrayList<>();
+        for (String fileName : jvmci.list()) {
+            if (fileName.endsWith(".jar")) {
+                File file = new File(jvmci, fileName);
+                if (file.isDirectory()) {
+                    continue;
+                }
+                try {
+                    urls.add(file.toURI().toURL());
+                } catch (MalformedURLException e) {
+                    throw new InternalError(e);
+                }
+            }
+        }
+
+        String append = VM.getSavedProperty("jvmci.class.path.append");
+        if (append != null) {
+            for (String entry : append.split(File.pathSeparator)) {
+                File file = new File(entry);
+                try {
+                    urls.add(file.toURI().toURL());
+                } catch (MalformedURLException e) {
+                    throw new InternalError(e);
+                }
+            }
+        }
+
+        return urls.toArray(new URL[urls.size()]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIPermission.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.services;
+
+import java.security.BasicPermission;
+
+/**
+ * This class represents the permission to access JVMCI services.
+ */
+public class JVMCIPermission extends BasicPermission {
+
+    private static final long serialVersionUID = 6346818963934448226L;
+
+    public JVMCIPermission() {
+        super("jvmci");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.services;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Service-provider class for the runtime to locate providers of JVMCI services where the latter are
+ * not in packages exported by the JVMCI module. As part of instantiating
+ * {@link JVMCIServiceLocator}, all JVMCI packages will be {@linkplain Services#exportJVMCITo(Class)
+ * exported} to the module defining the class of the instantiated object.
+ *
+ * While the {@link #getProvider(Class)} method can be used directly, it's usually easier to use
+ * {@link #getProviders(Class)}.
+ */
+public abstract class JVMCIServiceLocator {
+
+    private static Void checkPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new JVMCIPermission());
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unused")
+    private JVMCIServiceLocator(Void ignore) {
+    }
+
+    /**
+     * Creates a capability for accessing JVMCI. Once successfully instantiated, JVMCI exports all
+     * its packages to the module defining the type of this object.
+     *
+     * @throws SecurityException if a security manager has been installed and it denies
+     *             {@link JVMCIPermission}
+     */
+    protected JVMCIServiceLocator() {
+        this(checkPermission());
+        Services.exportJVMCITo(getClass());
+    }
+
+    /**
+     * Gets the provider of the service defined by {@code service} or {@code null} if this object
+     * does not have a provider for {@code service}.
+     */
+    public abstract <S> S getProvider(Class<S> service);
+
+    /**
+     * Gets the providers of the service defined by {@code service} by querying the
+     * {@link JVMCIServiceLocator} providers obtained by {@link Services#load(Class)}.
+     */
+    public static <S> List<S> getProviders(Class<S> service) {
+        List<S> providers = new ArrayList<>();
+        for (JVMCIServiceLocator access : Services.load(JVMCIServiceLocator.class)) {
+            S provider = access.getProvider(service);
+            if (provider != null) {
+                providers.add(provider);
+            }
+        }
+        return providers;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.services;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import sun.reflect.Reflection;
+
+/**
+ * An mechanism for accessing service providers via JVMCI. These providers are loaded via a JVMCI
+ * class loader that is hidden from application code. Hence the {@link SecurityManager} checks in
+ * {@link #load(Class)} and {@link #loadSingle(Class, boolean)}.
+ */
+public final class Services {
+
+    private Services() {
+    }
+
+    private static boolean jvmciEnabled = true;
+
+    private static final ClassValue<List<?>> cache = new ClassValue<List<?>>() {
+        @Override
+        protected List<?> computeValue(Class<?> type) {
+            List<Object> impls = new ArrayList<>();
+            if (jvmciEnabled) {
+                try {
+                    for (Object impl : ServiceLoader.load(type, getJVMCIClassLoader())) {
+                        impls.add(impl);
+                    }
+                } catch (InternalError e) {
+                    if (e.getMessage().equals("JVMCI is not enabled")) {
+                        jvmciEnabled = false;
+                    } else {
+                        throw e;
+                    }
+                }
+            }
+            return impls;
+        }
+    };
+
+    /**
+     * Performs any required security checks and dynamic reconfiguration to allow the module of a
+     * given class to access the classes in the JVMCI module.
+     *
+     * Note: This API exists to provide backwards compatibility for JVMCI clients compiled against a
+     * JDK release earlier than 9.
+     *
+     * @param requestor a class requesting access to the JVMCI module for its module
+     * @throws SecurityException if a security manager is present and it denies
+     *             {@link JVMCIPermission}
+     */
+    public static void exportJVMCITo(Class<?> requestor) {
+        // There are no modules in JVMCI-8.
+    }
+
+    /**
+     * Gets an {@link Iterable} of the JVMCI providers available for a given service.
+     *
+     * @throws SecurityException if a security manager is present and it denies <tt>
+     *             {@link RuntimePermission}("jvmci")</tt>
+     */
+    @SuppressWarnings("unchecked")
+    public static <S> Iterable<S> load(Class<S> service) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new JVMCIPermission());
+        }
+        try {
+            return (Iterable<S>) cache.get(service);
+        } catch (UnsatisfiedLinkError e) {
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * Gets the JVMCI provider for a given service for which at most one provider must be available.
+     *
+     * @param service the service whose provider is being requested
+     * @param required specifies if an {@link InternalError} should be thrown if no provider of
+     *            {@code service} is available
+     * @throws SecurityException if a security manager is present and it denies <tt>
+     *             {@link RuntimePermission}("jvmci")</tt>
+     */
+    @SuppressWarnings({"unchecked"})
+    public static <S> S loadSingle(Class<S> service, boolean required) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new JVMCIPermission());
+        }
+        Iterable<S> providers;
+        try {
+            providers = (Iterable<S>) cache.get(service);
+        } catch (UnsatisfiedLinkError e) {
+            providers = Collections.emptyList();
+        }
+
+        S singleProvider = null;
+        for (S provider : providers) {
+            if (singleProvider != null) {
+                throw new InternalError(String.format("Multiple %s providers found: %s, %s", service.getName(), singleProvider.getClass().getName(), provider.getClass().getName()));
+            }
+            singleProvider = provider;
+        }
+        if (singleProvider == null && required) {
+            String javaHome = System.getProperty("java.home");
+            String vmName = System.getProperty("java.vm.name");
+            Formatter errorMessage = new Formatter();
+            errorMessage.format("The VM does not expose required service %s.%n", service.getName());
+            errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
+            errorMessage.format("Currently used VM configuration is: %s", vmName);
+            throw new UnsupportedOperationException(errorMessage.toString());
+        }
+        return singleProvider;
+    }
+
+    static {
+        Reflection.registerMethodsToFilter(Services.class, "getJVMCIClassLoader");
+        Reflection.registerFieldsToFilter(Services.class, "cache");
+    }
+
+    /**
+     * Gets the JVMCI class loader.
+     *
+     * @throws InternalError with the {@linkplain Throwable#getMessage() message}
+     *             {@code "JVMCI is not enabled"} iff JVMCI is not enabled
+     */
+    private static native ClassLoader getJVMCIClassLoader();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.sparc;
+
+import static java.nio.ByteOrder.BIG_ENDIAN;
+import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD;
+import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
+import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
+
+import java.util.Set;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterArray;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.PlatformKind;
+
+/**
+ * Represents the SPARC architecture.
+ */
+public class SPARC extends Architecture {
+
+    public static final RegisterCategory CPU = new RegisterCategory("CPU");
+    public static final RegisterCategory FPUs = new RegisterCategory("FPUs");
+    public static final RegisterCategory FPUd = new RegisterCategory("FPUd");
+    public static final RegisterCategory FPUq = new RegisterCategory("FPUq");
+
+    // General purpose registers
+    public static final Register g0 = new Register(0, 0, "g0", CPU);
+    public static final Register g1 = new Register(1, 1, "g1", CPU);
+    public static final Register g2 = new Register(2, 2, "g2", CPU);
+    public static final Register g3 = new Register(3, 3, "g3", CPU);
+    public static final Register g4 = new Register(4, 4, "g4", CPU);
+    public static final Register g5 = new Register(5, 5, "g5", CPU);
+    public static final Register g6 = new Register(6, 6, "g6", CPU);
+    public static final Register g7 = new Register(7, 7, "g7", CPU);
+
+    public static final Register o0 = new Register(8, 8, "o0", CPU);
+    public static final Register o1 = new Register(9, 9, "o1", CPU);
+    public static final Register o2 = new Register(10, 10, "o2", CPU);
+    public static final Register o3 = new Register(11, 11, "o3", CPU);
+    public static final Register o4 = new Register(12, 12, "o4", CPU);
+    public static final Register o5 = new Register(13, 13, "o5", CPU);
+    public static final Register o6 = new Register(14, 14, "o6", CPU);
+    public static final Register o7 = new Register(15, 15, "o7", CPU);
+
+    public static final Register l0 = new Register(16, 16, "l0", CPU);
+    public static final Register l1 = new Register(17, 17, "l1", CPU);
+    public static final Register l2 = new Register(18, 18, "l2", CPU);
+    public static final Register l3 = new Register(19, 19, "l3", CPU);
+    public static final Register l4 = new Register(20, 20, "l4", CPU);
+    public static final Register l5 = new Register(21, 21, "l5", CPU);
+    public static final Register l6 = new Register(22, 22, "l6", CPU);
+    public static final Register l7 = new Register(23, 23, "l7", CPU);
+
+    public static final Register i0 = new Register(24, 24, "i0", CPU);
+    public static final Register i1 = new Register(25, 25, "i1", CPU);
+    public static final Register i2 = new Register(26, 26, "i2", CPU);
+    public static final Register i3 = new Register(27, 27, "i3", CPU);
+    public static final Register i4 = new Register(28, 28, "i4", CPU);
+    public static final Register i5 = new Register(29, 29, "i5", CPU);
+    public static final Register i6 = new Register(30, 30, "i6", CPU);
+    public static final Register i7 = new Register(31, 31, "i7", CPU);
+
+    public static final Register sp = o6;
+    public static final Register fp = i6;
+
+    // Floating point registers
+    public static final Register f0 = new Register(32, 0, "f0", FPUs);
+    public static final Register f1 = new Register(33, 1, "f1", FPUs);
+    public static final Register f2 = new Register(34, 2, "f2", FPUs);
+    public static final Register f3 = new Register(35, 3, "f3", FPUs);
+    public static final Register f4 = new Register(36, 4, "f4", FPUs);
+    public static final Register f5 = new Register(37, 5, "f5", FPUs);
+    public static final Register f6 = new Register(38, 6, "f6", FPUs);
+    public static final Register f7 = new Register(39, 7, "f7", FPUs);
+
+    public static final Register f8 = new Register(40, 8, "f8", FPUs);
+    public static final Register f9 = new Register(41, 9, "f9", FPUs);
+    public static final Register f10 = new Register(42, 10, "f10", FPUs);
+    public static final Register f11 = new Register(43, 11, "f11", FPUs);
+    public static final Register f12 = new Register(44, 12, "f12", FPUs);
+    public static final Register f13 = new Register(45, 13, "f13", FPUs);
+    public static final Register f14 = new Register(46, 14, "f14", FPUs);
+    public static final Register f15 = new Register(47, 15, "f15", FPUs);
+
+    public static final Register f16 = new Register(48, 16, "f16", FPUs);
+    public static final Register f17 = new Register(49, 17, "f17", FPUs);
+    public static final Register f18 = new Register(50, 18, "f18", FPUs);
+    public static final Register f19 = new Register(51, 19, "f19", FPUs);
+    public static final Register f20 = new Register(52, 20, "f20", FPUs);
+    public static final Register f21 = new Register(53, 21, "f21", FPUs);
+    public static final Register f22 = new Register(54, 22, "f22", FPUs);
+    public static final Register f23 = new Register(55, 23, "f23", FPUs);
+
+    public static final Register f24 = new Register(56, 24, "f24", FPUs);
+    public static final Register f25 = new Register(57, 25, "f25", FPUs);
+    public static final Register f26 = new Register(58, 26, "f26", FPUs);
+    public static final Register f27 = new Register(59, 27, "f27", FPUs);
+    public static final Register f28 = new Register(60, 28, "f28", FPUs);
+    public static final Register f29 = new Register(61, 29, "f29", FPUs);
+    public static final Register f30 = new Register(62, 30, "f30", FPUs);
+    public static final Register f31 = new Register(63, 31, "f31", FPUs);
+
+    // Double precision registers
+    public static final Register d0 = new Register(64, getDoubleEncoding(0), "d0", FPUd);
+    public static final Register d2 = new Register(65, getDoubleEncoding(2), "d2", FPUd);
+    public static final Register d4 = new Register(66, getDoubleEncoding(4), "d4", FPUd);
+    public static final Register d6 = new Register(67, getDoubleEncoding(6), "d6", FPUd);
+    public static final Register d8 = new Register(68, getDoubleEncoding(8), "d8", FPUd);
+    public static final Register d10 = new Register(69, getDoubleEncoding(10), "d10", FPUd);
+    public static final Register d12 = new Register(70, getDoubleEncoding(12), "d12", FPUd);
+    public static final Register d14 = new Register(71, getDoubleEncoding(14), "d14", FPUd);
+
+    public static final Register d16 = new Register(72, getDoubleEncoding(16), "d16", FPUd);
+    public static final Register d18 = new Register(73, getDoubleEncoding(18), "d18", FPUd);
+    public static final Register d20 = new Register(74, getDoubleEncoding(20), "d20", FPUd);
+    public static final Register d22 = new Register(75, getDoubleEncoding(22), "d22", FPUd);
+    public static final Register d24 = new Register(76, getDoubleEncoding(24), "d24", FPUd);
+    public static final Register d26 = new Register(77, getDoubleEncoding(26), "d26", FPUd);
+    public static final Register d28 = new Register(78, getDoubleEncoding(28), "d28", FPUd);
+    public static final Register d30 = new Register(79, getDoubleEncoding(28), "d28", FPUd);
+
+    public static final Register d32 = new Register(80, getDoubleEncoding(32), "d32", FPUd);
+    public static final Register d34 = new Register(81, getDoubleEncoding(34), "d34", FPUd);
+    public static final Register d36 = new Register(82, getDoubleEncoding(36), "d36", FPUd);
+    public static final Register d38 = new Register(83, getDoubleEncoding(38), "d38", FPUd);
+    public static final Register d40 = new Register(84, getDoubleEncoding(40), "d40", FPUd);
+    public static final Register d42 = new Register(85, getDoubleEncoding(42), "d42", FPUd);
+    public static final Register d44 = new Register(86, getDoubleEncoding(44), "d44", FPUd);
+    public static final Register d46 = new Register(87, getDoubleEncoding(46), "d46", FPUd);
+
+    public static final Register d48 = new Register(88, getDoubleEncoding(48), "d48", FPUd);
+    public static final Register d50 = new Register(89, getDoubleEncoding(50), "d50", FPUd);
+    public static final Register d52 = new Register(90, getDoubleEncoding(52), "d52", FPUd);
+    public static final Register d54 = new Register(91, getDoubleEncoding(54), "d54", FPUd);
+    public static final Register d56 = new Register(92, getDoubleEncoding(56), "d56", FPUd);
+    public static final Register d58 = new Register(93, getDoubleEncoding(58), "d58", FPUd);
+    public static final Register d60 = new Register(94, getDoubleEncoding(60), "d60", FPUd);
+    public static final Register d62 = new Register(95, getDoubleEncoding(62), "d62", FPUd);
+
+    // Quad precision registers
+    public static final Register q0 = new Register(96, getQuadncoding(0), "q0", FPUq);
+    public static final Register q4 = new Register(97, getQuadncoding(4), "q4", FPUq);
+    public static final Register q8 = new Register(98, getQuadncoding(8), "q8", FPUq);
+    public static final Register q12 = new Register(99, getQuadncoding(12), "q12", FPUq);
+    public static final Register q16 = new Register(100, getQuadncoding(16), "q16", FPUq);
+    public static final Register q20 = new Register(101, getQuadncoding(20), "q20", FPUq);
+    public static final Register q24 = new Register(102, getQuadncoding(24), "q24", FPUq);
+    public static final Register q28 = new Register(103, getQuadncoding(28), "q28", FPUq);
+
+    public static final Register q32 = new Register(104, getQuadncoding(32), "q32", FPUq);
+    public static final Register q36 = new Register(105, getQuadncoding(36), "q36", FPUq);
+    public static final Register q40 = new Register(106, getQuadncoding(40), "q40", FPUq);
+    public static final Register q44 = new Register(107, getQuadncoding(44), "q44", FPUq);
+    public static final Register q48 = new Register(108, getQuadncoding(48), "q48", FPUq);
+    public static final Register q52 = new Register(109, getQuadncoding(52), "q52", FPUq);
+    public static final Register q56 = new Register(110, getQuadncoding(56), "q56", FPUq);
+    public static final Register q60 = new Register(111, getQuadncoding(60), "q60", FPUq);
+
+    // @formatter:off
+    public static final RegisterArray cpuRegisters = new RegisterArray(
+        g0,  g1,  g2,  g3,  g4,  g5,  g6,  g7,
+        o0,  o1,  o2,  o3,  o4,  o5,  o6,  o7,
+        l0,  l1,  l2,  l3,  l4,  l5,  l6,  l7,
+        i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7
+    );
+
+    public static final RegisterArray fpusRegisters = new RegisterArray(
+        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15,
+        f16, f17, f18, f19, f20, f21, f22, f23,
+        f24, f25, f26, f27, f28, f29, f30, f31
+    );
+
+    public static final RegisterArray fpudRegisters = new RegisterArray(
+        d0, d2, d4, d6, d8,  d10, d12, d14,
+        d16, d18, d20, d22, d24, d26, d28, d30,
+        d32, d34, d36, d38, d40, d42, d44, d46,
+        d48, d50, d52, d54, d56, d58, d60, d62
+    );
+
+    public static final RegisterArray fpuqRegisters = new RegisterArray(
+        q0, q4, q8, q12,
+        q16, q20, q24, q28,
+        q32, q36, q40, q44,
+        q48, q52, q56, q60
+    );
+
+    public static final RegisterArray allRegisters = new RegisterArray(
+        g0,  g1,  g2,  g3,  g4,  g5,  g6,  g7,
+        o0,  o1,  o2,  o3,  o4,  o5,  o6,  o7,
+        l0,  l1,  l2,  l3,  l4,  l5,  l6,  l7,
+        i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7,
+
+        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15,
+        f16, f17, f18, f19, f20, f21, f22, f23,
+        f24, f25, f26, f27, f28, f29, f30, f31,
+
+        d0, d2, d4, d6, d8,  d10, d12, d14,
+        d16, d18, d20, d22, d24, d26, d28, d30,
+        d32, d34, d36, d38, d40, d42, d44, d46,
+        d48, d50, d52, d54, d56, d58, d60, d62,
+
+        q0, q4, q8, q12,
+        q16, q20, q24, q28,
+        q32, q36, q40, q44,
+        q48, q52, q56, q60
+    );
+    // @formatter:on
+
+    /**
+     * Stack bias for stack and frame pointer loads.
+     */
+    public static final int STACK_BIAS = 0x7ff;
+
+    /**
+     * Size to keep free for flushing the register-window to stack.
+     */
+    public static final int REGISTER_SAFE_AREA_SIZE = 128;
+
+    public final Set<CPUFeature> features;
+
+    public SPARC(Set<CPUFeature> features) {
+        super("SPARC", SPARCKind.XWORD, BIG_ENDIAN, false, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8);
+        this.features = features;
+    }
+
+    @Override
+    public RegisterArray getAvailableValueRegisters() {
+        return allRegisters;
+    }
+
+    @Override
+    public boolean canStoreValue(RegisterCategory category, PlatformKind kind) {
+        SPARCKind sparcKind = (SPARCKind) kind;
+        switch (sparcKind) {
+            case BYTE:
+            case HWORD:
+            case WORD:
+            case XWORD:
+                return CPU.equals(category);
+            case SINGLE:
+            case V32_BYTE:
+            case V32_HWORD:
+                return FPUs.equals(category);
+            case DOUBLE:
+            case V64_BYTE:
+            case V64_HWORD:
+            case V64_WORD:
+            case V64_SINGLE:
+                return FPUd.equals(category);
+            case QUAD:
+                return FPUq.equals(category);
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public PlatformKind getLargestStorableKind(RegisterCategory category) {
+        if (category.equals(CPU)) {
+            return SPARCKind.XWORD;
+        } else if (category.equals(FPUd)) {
+            return SPARCKind.DOUBLE;
+        } else if (category.equals(FPUs)) {
+            return SPARCKind.SINGLE;
+        } else if (category.equals(FPUq)) {
+            return SPARCKind.QUAD;
+        } else {
+            throw new IllegalArgumentException("Unknown register category: " + category);
+        }
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(JavaKind javaKind) {
+        switch (javaKind) {
+            case Boolean:
+            case Byte:
+                return SPARCKind.BYTE;
+            case Short:
+            case Char:
+                return SPARCKind.HWORD;
+            case Int:
+                return SPARCKind.WORD;
+            case Long:
+            case Object:
+                return SPARCKind.XWORD;
+            case Float:
+                return SPARCKind.SINGLE;
+            case Double:
+                return SPARCKind.DOUBLE;
+            default:
+                throw new IllegalArgumentException("Unknown JavaKind: " + javaKind);
+        }
+    }
+
+    private static int getDoubleEncoding(int reg) {
+        assert reg < 64 && ((reg & 1) == 0);
+        return (reg & 0x1e) | ((reg & 0x20) >> 5);
+    }
+
+    private static int getQuadncoding(int reg) {
+        assert reg < 64 && ((reg & 1) == 0);
+        return (reg & 0x1c) | ((reg & 0x20) >> 5);
+    }
+
+    public Set<CPUFeature> getFeatures() {
+        return features;
+    }
+
+    public boolean hasFeature(CPUFeature feature) {
+        return features.contains(feature);
+    }
+
+    public enum CPUFeature {
+        VIS1,
+        VIS2,
+        VIS3,
+        CBCOND,
+        V8,
+        HARDWARE_MUL32,
+        HARDWARE_DIV32,
+        HARDWARE_FSMULD,
+        HARDWARE_POPC,
+        V9,
+        SUN4V,
+        BLK_INIT_INSTRUCTIONS,
+        FMAF,
+        FMAU,
+        SPARC64_FAMILY,
+        M_FAMILY,
+        T_FAMILY,
+        T1_MODEL,
+        SPARC5,
+        AES,
+        SHA1,
+        SHA256,
+        SHA512
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.sparc;
+
+import jdk.vm.ci.meta.PlatformKind;
+
+public enum SPARCKind implements PlatformKind {
+    BYTE(1),
+    HWORD(2),
+    WORD(4),
+    XWORD(8),
+    SINGLE(4),
+    DOUBLE(8),
+    QUAD(16),
+
+    V32_BYTE(4, BYTE),
+    V32_HWORD(4, HWORD),
+
+    V64_BYTE(8, BYTE),
+    V64_HWORD(8, HWORD),
+    V64_WORD(8, WORD),
+    V64_SINGLE(8, SINGLE);
+
+    private final int size;
+    private final int vectorLength;
+
+    private final SPARCKind scalar;
+    private final EnumKey<SPARCKind> key = new EnumKey<>(this);
+
+    SPARCKind(int size) {
+        this.size = size;
+        this.scalar = this;
+        this.vectorLength = 1;
+    }
+
+    SPARCKind(int size, SPARCKind scalar) {
+        this.size = size;
+        this.scalar = scalar;
+
+        assert size % scalar.size == 0;
+        this.vectorLength = size / scalar.size;
+    }
+
+    public SPARCKind getScalar() {
+        return scalar;
+    }
+
+    public int getSizeInBytes() {
+        return size;
+    }
+
+    public int getSizeInBits() {
+        return getSizeInBytes() * 8;
+    }
+
+    public int getVectorLength() {
+        return vectorLength;
+    }
+
+    public Key getKey() {
+        return key;
+    }
+
+    public boolean isInteger() {
+        switch (this) {
+            case BYTE:
+            case HWORD:
+            case WORD:
+            case XWORD:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public boolean isFloat() {
+        return !isInteger();
+    }
+
+    public char getTypeChar() {
+        switch (this) {
+            case BYTE:
+                return 'b';
+            case HWORD:
+                return 'h';
+            case WORD:
+                return 'w';
+            case XWORD:
+                return 'd';
+            case SINGLE:
+                return 'S';
+            case DOUBLE:
+            case V64_BYTE:
+            case V64_HWORD:
+            case V64_WORD:
+                return 'D';
+            default:
+                return '-';
+        }
+    }
+}
--- a/make/Makefile	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/Makefile	Mon Feb 06 17:18:57 2017 +0100
@@ -63,6 +63,10 @@
 
 # Default is build both product fastdebug and create export area
 
+
+# Directory for shared code (e.g. jvmci.jar)
+SHARED_DIR=$(OUTPUTDIR)/shared
+
 # Allow to build HotSpot in local directory from sources specified by GAMMADIR.
 # After make/defs.make GAMMADIR is defined.
 ifdef GAMMADIR
@@ -164,6 +168,7 @@
 C1_DIR      =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1
 C2_DIR      =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2
 CORE_DIR    =$(OUTPUTDIR)/$(VM_PLATFORM)_core
+JVMCI_DIR   =$(OUTPUTDIR)/$(VM_PLATFORM)_jvmci
 MINIMAL1_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1
 ZERO_DIR    =$(OUTPUTDIR)/$(VM_PLATFORM)_zero
 SHARK_DIR   =$(OUTPUTDIR)/$(VM_PLATFORM)_shark
@@ -201,7 +206,7 @@
 	$(QUIETLY) chmod +x $@
 
 # Build compiler1 (client) rule, different for platforms
-generic_build1: $(HOTSPOT_SCRIPT)
+generic_build1: $(HOTSPOT_SCRIPT) buildshared
 	$(MKDIR) -p $(OUTPUTDIR)
 ifeq ($(OSNAME),windows)
   ifeq ($(ARCH_DATA_MODEL), 32)
@@ -216,17 +221,13 @@
 	@$(ECHO) "No compiler1 ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)"
   endif
 else
-  ifeq ($(ARCH_DATA_MODEL), 32)
 	$(CD) $(OUTPUTDIR); \
 	    $(MAKE) -f $(ABS_OS_MAKEFILE) \
 		      $(MAKE_ARGS) $(VM_TARGET)
-  else
-	@$(ECHO) "No compiler1 ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)"
-  endif
 endif
 
 # Build compiler2 (server) rule, different for platforms
-generic_build2: $(HOTSPOT_SCRIPT)
+generic_build2: $(HOTSPOT_SCRIPT) buildshared
 	$(MKDIR) -p $(OUTPUTDIR)
 ifeq ($(OSNAME),windows)
 	$(CD) $(OUTPUTDIR); \
@@ -289,6 +290,18 @@
 	@$(ECHO) "Error: trying to build a minimal target but JVM_VARIANT_MINIMAL1 is not true."
 endif
 
+generic_buildjvmci: $(HOTSPOT_SCRIPT) buildshared
+	$(MKDIR) -p $(OUTPUTDIR)
+	$(CD) $(OUTPUTDIR); \
+		$(MAKE) -f $(ABS_OS_MAKEFILE) \
+			$(MAKE_ARGS) $(VM_TARGET) 
+
+cleanshared:
+	$(call jvmci-make,clean)
+
+buildshared:
+	$(call jvmci-make,export)
+
 # Export file rule
 generic_export: $(EXPORT_LIST)
 
@@ -316,6 +329,7 @@
 C1_BUILD_DIR      =$(C1_DIR)/$(BUILD_FLAVOR)
 C2_BUILD_DIR      =$(C2_DIR)/$(BUILD_FLAVOR)
 CORE_BUILD_DIR    =$(CORE_DIR)/$(BUILD_FLAVOR)
+JVMCI_BUILD_DIR   =$(JVMCI_DIR)/$(BUILD_FLAVOR)
 MINIMAL1_BUILD_DIR=$(MINIMAL1_DIR)/$(BUILD_FLAVOR)
 ZERO_BUILD_DIR    =$(ZERO_DIR)/$(BUILD_FLAVOR)
 SHARK_BUILD_DIR   =$(SHARK_DIR)/$(BUILD_FLAVOR)
@@ -368,6 +382,55 @@
 	$(install-dir)
 $(EXPORT_SERVER_DIR)/%.dSYM:       		$(C2_BUILD_DIR)/%.dSYM
 	$(install-dir)
+
+# JVMCI
+# Common
+$(EXPORT_SERVER_DIR)/%.diz:       		$(JVMCI_BUILD_DIR)/%.diz
+	$(install-file)
+$(EXPORT_LIB_DIR)/%.jar:			$(JVMCI_BUILD_DIR)/../generated/%.jar
+	$(install-file)
+$(EXPORT_INCLUDE_DIR)/%:			$(JVMCI_BUILD_DIR)/../generated/jvmtifiles/%
+	$(install-file)
+# Windows
+$(EXPORT_SERVER_DIR)/%.dll:			$(JVMCI_BUILD_DIR)/%.dll
+	$(install-file)
+$(EXPORT_SERVER_DIR)/%.pdb:			$(JVMCI_BUILD_DIR)/%.pdb
+	$(install-file)
+$(EXPORT_SERVER_DIR)/%.map:			$(JVMCI_BUILD_DIR)/%.map
+	$(install-file)
+$(EXPORT_LIB_DIR)/%.lib:			$(JVMCI_BUILD_DIR)/%.lib
+	$(install-file)
+$(EXPORT_JRE_BIN_DIR)/%.diz:			$(JVMCI_BUILD_DIR)/%.diz
+	$(install-file)
+$(EXPORT_JRE_BIN_DIR)/%.dll:			$(JVMCI_BUILD_DIR)/%.dll
+	$(install-file)
+$(EXPORT_JRE_BIN_DIR)/%.pdb:			$(JVMCI_BUILD_DIR)/%.pdb
+	$(install-file)
+$(EXPORT_JRE_BIN_DIR)/%.map:			$(JVMCI_BUILD_DIR)/%.map
+	$(install-file)
+# Unix
+$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(JVMCI_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
+	$(install-file)
+$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(JVMCI_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
+	$(install-file)
+$(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX):    $(JVMCI_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
+	$(install-file)
+$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: 	$(JVMCI_BUILD_DIR)/%.debuginfo
+	$(install-file)
+$(EXPORT_SERVER_DIR)/%.debuginfo:       	$(JVMCI_BUILD_DIR)/%.debuginfo
+	$(install-file)
+$(EXPORT_SERVER_DIR)/64/%.debuginfo:    	$(JVMCI_BUILD_DIR)/%.debuginfo
+	$(install-file)
+$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: 		$(JVMCI_BUILD_DIR)/%.diz
+	$(install-file)
+$(EXPORT_SERVER_DIR)/64/%.diz:    		$(JVMCI_BUILD_DIR)/%.diz
+	$(install-file)
+# MacOS X
+$(EXPORT_JRE_LIB_ARCH_DIR)/%.dSYM: 		$(JVMCI_BUILD_DIR)/%.dSYM
+	$(install-dir)
+$(EXPORT_SERVER_DIR)/%.dSYM:       		$(JVMCI_BUILD_DIR)/%.dSYM
+	$(install-dir)
+
 endif
 
 # Client (C1)
@@ -542,6 +605,21 @@
 	$(install-dir)
 endif
 
+$(EXPORT_JRE_LIB_DIR)/%.jar: $(SHARED_DIR)/%.jar
+	$(install-file)
+
+$(EXPORT_JRE_LIB_EXT_DIR)/%.jar: $(SHARED_DIR)/%.jar
+	$(install-file)
+
+$(EXPORT_JRE_LIB_JVMCI_DIR)/%.jar: $(SHARED_DIR)/%.jar
+	$(install-file)
+
+$(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/%: $(SHARED_DIR)/jvmci.services/%
+	$(install-file)
+
+$(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/%: $(SHARED_DIR)/jvmci.options/%
+	$(install-file)
+
 $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/code/%
 	$(install-file)
 
@@ -578,11 +656,13 @@
 #
 # Clean rules
 #
-clobber clean: clean_build clean_export clean_jdk
+clobber clean: clean_build clean_export clean_jdk cleanshared
 clean_build:
+	$(RM) -r $(SHARED_DIR)
 	$(RM) -r $(C1_DIR)
 	$(RM) -r $(C2_DIR)
 	$(RM) -r $(CORE_DIR)
+	$(RM) -r $(JVMCI_DIR)
 	$(RM) -r $(ZERO_DIR)
 	$(RM) -r $(SHARK_DIR)
 	$(RM) -r $(MINIMAL1_DIR)
@@ -846,6 +926,8 @@
 
 jvmgshark: warn_jvmg_deprecated debugshark
 
+jvmgjvmci: warn_jvmg_deprecated debugjvmci
+
 # JPRT rule to build this workspace
 include $(GAMMADIR)/make/jprt.gmk
 
--- a/make/aix/makefiles/defs.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/aix/makefiles/defs.make	Mon Feb 06 17:18:57 2017 +0100
@@ -192,9 +192,9 @@
 #    EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo
 #  endif
 #endif
-EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
-EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
-EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
+EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server$(COMPILER_DIR_SUFFIX)
+EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client$(COMPILER_DIR_SUFFIX)
+EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal$(COMPILER_DIR_SUFFIX)
 
 ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK) $(JVM_VARIANT_CORE)), true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
--- a/make/bsd/Makefile	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/Makefile	Mon Feb 06 17:18:57 2017 +0100
@@ -192,6 +192,7 @@
 SUBDIRS_ZERO      = $(addprefix $(OSNAME)_$(VARIANTARCH)_zero/,$(TARGETS))
 SUBDIRS_SHARK     = $(addprefix $(OSNAME)_$(VARIANTARCH)_shark/,$(TARGETS))
 SUBDIRS_MINIMAL1  = $(addprefix $(OSNAME)_$(BUILDARCH)_minimal1/,$(TARGETS))
+SUBDIRS_JVMCI     = $(addprefix $(OSNAME)_$(BUILDARCH)_jvmci/,$(TARGETS))
 
 TARGETS_C2        = $(TARGETS)
 TARGETS_C1        = $(addsuffix 1,$(TARGETS))
@@ -200,6 +201,7 @@
 TARGETS_ZERO      = $(addsuffix zero,$(TARGETS))
 TARGETS_SHARK     = $(addsuffix shark,$(TARGETS))
 TARGETS_MINIMAL1  = $(addsuffix minimal1,$(TARGETS))
+TARGETS_JVMCI     = $(addsuffix jvmci,$(TARGETS))
 
 BUILDTREE_MAKE    = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make
 BUILDTREE_VARS    = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) LIBRARY_SUFFIX=$(LIBRARY_SUFFIX)
@@ -219,6 +221,7 @@
 	@echo "  $(TARGETS_ZERO)"
 	@echo "  $(TARGETS_SHARK)"
 	@echo "  $(TARGETS_MINIMAL1)"
+	@echo "  $(TARGETS_JVMCI)"
 
 checks: check_os_version check_j2se_version
 
@@ -281,6 +284,10 @@
 	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
 	$(BUILDTREE) VARIANT=minimal1
 
+$(SUBDIRS_JVMCI): $(BUILDTREE_MAKE)
+	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+	$(BUILDTREE) VARIANT=jvmci
+
 platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
 	$(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@
 
@@ -328,6 +335,12 @@
 	cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
+$(TARGETS_JVMCI):  $(SUBDIRS_JVMCI)
+	cd $(OSNAME)_$(BUILDARCH)_jvmci/$(patsubst %jvmci,%,$@) && $(MAKE) $(MFLAGS)
+ifdef INSTALL
+	cd $(OSNAME)_$(BUILDARCH)_jvmci/$(patsubst %jvmci,%,$@) && $(MAKE) $(MFLAGS) install
+endif
+
 # Just build the tree, and nothing else:
 tree:      $(SUBDIRS_C2)
 tree1:     $(SUBDIRS_C1)
@@ -335,6 +348,7 @@
 treezero:  $(SUBDIRS_ZERO)
 treeshark: $(SUBDIRS_SHARK)
 treeminimal1: $(SUBDIRS_MINIMAL1)
+treejvmci: $(SUBDIRS_JVMCI)
 
 # Doc target.  This is the same for all build options.
 #     Hence create a docs directory beside ...$(ARCH)_[...]
@@ -386,9 +400,9 @@
 
 #-------------------------------------------------------------------------------
 
-.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO) $(TARGETS_SHARK) $(TARGETS_MINIMAL1)
-.PHONY: tree tree1 treecore treezero treeshark
-.PHONY: all compiler1 compiler2 core zero shark
-.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
+.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO) $(TARGETS_SHARK) $(TARGETS_MINIMAL1) $(TARGETS_JVMCI)
+.PHONY: tree tree1 treecore treezero treeshark treejvmci
+.PHONY: all compiler1 compiler2 core zero shark jvmci
+.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs clean_jvmci
 .PHONY: checks check_os_version check_j2se_version
 .PHONY: $(HS_ALT_MAKE)/$(OSNAME)/Makefile.make
--- a/make/bsd/makefiles/buildtree.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/buildtree.make	Mon Feb 06 17:18:57 2017 +0100
@@ -242,7 +242,7 @@
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
 	echo; \
 	echo "Src_Dirs_I = \\"; \
 	echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \
@@ -258,7 +258,7 @@
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
 	    echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \
 	[ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \
--- a/make/bsd/makefiles/compiler1.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/compiler1.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = client
 
 CFLAGS += -DCOMPILER1
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = client-nojvmci
+endif
\ No newline at end of file
--- a/make/bsd/makefiles/compiler2.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/compiler2.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = server
 
 CFLAGS += -DCOMPILER2
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = server-nojvmci
+endif
\ No newline at end of file
--- a/make/bsd/makefiles/defs.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/defs.make	Mon Feb 06 17:18:57 2017 +0100
@@ -280,9 +280,9 @@
   endif
 endif
 
-EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
-EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
-EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
+EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server$(COMPILER_DIR_SUFFIX)
+EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client$(COMPILER_DIR_SUFFIX)
+EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal$(COMPILER_DIR_SUFFIX)
 
 ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
--- a/make/bsd/makefiles/gcc.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/gcc.make	Mon Feb 06 17:18:57 2017 +0100
@@ -149,7 +149,8 @@
     PCH_FLAG/sharedRuntimeTrig.o = $(PCH_FLAG/NO_PCH)
     PCH_FLAG/sharedRuntimeTrans.o = $(PCH_FLAG/NO_PCH)
     PCH_FLAG/unsafe.o = $(PCH_FLAG/NO_PCH)
-  
+    PCH_FLAG/jvmciCompilerToVM.o = $(PCH_FLAG/NO_PCH)
+
   endif
 else # ($(USE_CLANG), true)
   # check for precompiled headers support
@@ -314,10 +315,21 @@
 
 # Work around some compiler bugs.
 ifeq ($(USE_CLANG), true)
+  # Clang 4.2
   ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1)
     OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
     OPT_CFLAGS/unsafe.o += -O1
   endif
+  # Clang 5.0
+  ifeq ($(shell expr $(CC_VER_MAJOR) = 5 \& \( $(CC_VER_MINOR) = 0 \| $(CC_VER_MINOR) = 1 \) ), 1)
+    OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
+    OPT_CFLAGS/unsafe.o += -O1
+  endif
+  # Clang 6.x
+  ifeq ($(shell expr $(CC_VER_MAJOR) = 6), 1)
+    OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
+    OPT_CFLAGS/unsafe.o += -O1
+  endif
 else
   # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
   ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
@@ -325,6 +337,14 @@
   endif
 endif
 
+# We want to use libc++ on Clang 5.0
+ifeq ($(USE_CLANG), true)
+  # Clang 5.0
+  ifeq ($(shell expr $(CC_VER_MAJOR) = 5 \& \( $(CC_VER_MINOR) = 0 \| $(CC_VER_MINOR) = 1 \) ), 1)
+    CFLAGS += -stdlib=libc++
+  endif
+endif
+
 # Flags for generating make dependency flags.
 DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
 ifeq ($(USE_CLANG),)
@@ -365,6 +385,11 @@
 # statically link libstdc++.so, work with gcc but ignored by g++
 STATIC_STDCXX = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
 
+# Ensure use libstdc++ on clang, not libc++
+ifeq ($(USE_CLANG), true)
+  LFLAGS += -stdlib=libstdc++
+endif
+
 ifeq ($(USE_CLANG),)
   # statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x.
   ifneq ("${CC_VER_MAJOR}", "2")
--- a/make/bsd/makefiles/jsig.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/jsig.make	Mon Feb 06 17:18:57 2017 +0100
@@ -91,13 +91,13 @@
 install_jsig: $(LIBJSIG)
 	@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
 ifeq ($(OS_VENDOR), Darwin)
-	$(QUIETLY) test -d $(LIBJSIG_DEBUGINFO) && \
+	$(QUIETLY) test ! -d $(LIBJSIG_DEBUGINFO) || \
 	    cp -f -r $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO)
 else
 	$(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \
 	    cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO)
 endif
-	$(QUIETLY) test -f $(LIBJSIG_DIZ) && \
+	$(QUIETLY) test ! -f $(LIBJSIG_DIZ) || \
 	    cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ)
 	$(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/bsd/makefiles/jvmci.make	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2008, 2010 Red Hat, Inc.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+# Sets make macros for making JVMCI version of VM
+
+TYPE = JVMCI
+
+VM_SUBDIR = jvmci
+
+# To make a non-tiered JVMCI build, remove the -DCOMPILER1 below and
+# in vm.make remove COMPILER1_PATHS from Src_Dirs/JVMCI and add
+# COMPILER1_SPECIFIC_FILES to Src_Files_EXCLUDE/JVMCI
+CFLAGS += -DCOMPILERJVMCI -DJVMCI -DCOMPILER1
--- a/make/bsd/makefiles/saproc.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/saproc.make	Mon Feb 06 17:18:57 2017 +0100
@@ -72,6 +72,9 @@
     #objc compiler blows up on -march=i586, perhaps it should not be included in the macosx intel 32-bit C++ compiles?
     SAARCH = $(subst -march=i586,,$(ARCHFLAG))
 
+    ifeq ($(SDKPATH),)
+      SDKPATH = $(shell xcrun --show-sdk-path)
+    endif
     # This is needed to locate JavaNativeFoundation.framework
     # JDK 8 doesn't have SYSROOT_CFLAGS, so we'll cobble it together here
     SA_SYSROOT_FLAGS=
@@ -164,14 +167,14 @@
 install_saproc: $(BUILDLIBSAPROC)
 	@echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"
 ifeq ($(OS_VENDOR), Darwin)
-	$(QUIETLY) test -d $(LIBSAPROC_DEBUGINFO) && \
-	    cp -f -r $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO)
+	$(QUIETLY) test ! -d $(LIBSAPROC_DEBUGINFO) || \
+	    $(CP) -f -r $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO)
 else
-	$(QUIETLY) test -f $(LIBSAPROC_DEBUGINFO) && \
-	    cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO)
+	$(QUIETLY) test ! -f $(LIBSAPROC_DEBUGINFO) || \
+	    $(CP) -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO)
 endif
-	$(QUIETLY) test -f $(LIBSAPROC_DIZ) && \
-	    cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ)
-	$(QUIETLY) cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"
+	$(QUIETLY) test ! -f $(LIBSAPROC_DIZ) || \
+	    $(CP) -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ)
+	$(QUIETLY) $(CP) -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"
 
 .PHONY: install_saproc
--- a/make/bsd/makefiles/tiered.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/tiered.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = server
 
 CFLAGS += -DCOMPILER2 -DCOMPILER1
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = server-nojvmci
+endif
--- a/make/bsd/makefiles/vm.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/bsd/makefiles/vm.make	Mon Feb 06 17:18:57 2017 +0100
@@ -137,7 +137,7 @@
 # By default, link the *.o into the library, not the executable.
 LINK_INTO$(LINK_INTO) = LIBJVM
 
-JDK_LIBDIR = $(JAVA_HOME)/jre/lib/$(LIBARCH)
+JDK_LIBDIR = $(JAVA_HOME)/jre/lib
 
 #----------------------------------------------------------------------
 # jvm_db & dtrace
@@ -163,7 +163,7 @@
   LIBJVM_DIZ         = lib$(JVM).diz
 endif
 
-SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt
+SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt jvmci
 
 SOURCE_PATHS=\
   $(shell find $(HS_COMMON_SRC)/share/vm/* -type d \! \
@@ -193,13 +193,17 @@
 
 SHARK_PATHS := $(GAMMADIR)/src/share/vm/shark
 
+JVMCI_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/jvmci)
+JVMCI_PATHS += $(HS_COMMON_SRC)/share/vm/jvmci
+
 # Include dirs per type.
 Src_Dirs/CORE      := $(CORE_PATHS)
-Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS)
-Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS)
-Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS)
+Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS) $(JVMCI_PATHS)
+Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS) $(JVMCI_PATHS)
+Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS) $(JVMCI_PATHS)
 Src_Dirs/ZERO      := $(CORE_PATHS)
 Src_Dirs/SHARK     := $(CORE_PATHS) $(SHARK_PATHS)
+Src_Dirs/JVMCI     := $(CORE_PATHS) $(COMPILER1_PATHS) $(JVMCI_PATHS)
 Src_Dirs := $(Src_Dirs/$(TYPE))
 
 COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\*
@@ -207,16 +211,25 @@
 SHARK_SPECIFIC_FILES     := shark
 ZERO_SPECIFIC_FILES      := zero
 
+ifneq ($(INCLUDE_JVMCI), true)
+  JVMCI_SPECIFIC_FILES   := jvmci\*
+else
+  JVMCI_SPECIFIC_FILES   :=
+  Src_Dirs_I += $(HS_COMMON_SRC)/../mxbuild/jvmci/jdk.vm.ci.hotspot/src_gen/hotspot
+  Src_Dirs_I += $(MX_ALT_OUTPUT_ROOT)/jvmci/jvmci/jdk.vm.ci.hotspot/src_gen/hotspot
+endif
+
 # Always exclude these.
 Src_Files_EXCLUDE += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/JVMCI     := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
 
@@ -374,13 +387,13 @@
 install_jvm: $(LIBJVM)
 	@echo "Copying $(LIBJVM) to $(DEST_JVM)"
 ifeq ($(OS_VENDOR), Darwin)
-	$(QUIETLY) test -d $(LIBJVM_DEBUGINFO) && \
+	$(QUIETLY) test ! -d $(LIBJVM_DEBUGINFO) || \
 	    cp -f -r $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO)
 else
 	$(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \
 	    cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO)
 endif
-	$(QUIETLY) test -f $(LIBJVM_DIZ) && \
+	$(QUIETLY) test ! -f $(LIBJVM_DIZ) || \
 	    cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ)
 	$(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done"
 
--- a/make/defs.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/defs.make	Mon Feb 06 17:18:57 2017 +0100
@@ -113,6 +113,11 @@
   endif
 endif
 
+# If we build a no-jvmci-version, we suffix the compiler dir with -nojvmci
+ifeq ($(COMPILER_DIR_SUFFIX)$(subst false,,$(INCLUDE_JVMCI)),)
+	COMPILER_DIR_SUFFIX=-nojvmci
+endif
+
 # hotspot version definitions
 include $(GAMMADIR)/make/hotspot_version
 
@@ -349,6 +354,9 @@
 EXPORT_JRE_DIR = $(EXPORT_PATH)/jre
 EXPORT_JRE_BIN_DIR = $(EXPORT_JRE_DIR)/bin
 EXPORT_JRE_LIB_DIR = $(EXPORT_JRE_DIR)/lib
+EXPORT_JRE_LIB_EXT_DIR = $(EXPORT_JRE_LIB_DIR)/ext
+EXPORT_JRE_LIB_JVMCI_DIR = $(EXPORT_JRE_LIB_DIR)/jvmci
+EXPORT_JRE_LIB_JVMCI_SERVICES_DIR = $(EXPORT_JRE_LIB_JVMCI_DIR)/services
 EXPORT_JRE_LIB_ARCH_DIR = $(EXPORT_JRE_LIB_DIR)/$(LIBARCH)
 
 # non-universal macosx builds need to appear universal
--- a/make/excludeSrc.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/excludeSrc.make	Mon Feb 06 17:18:57 2017 +0100
@@ -127,6 +127,11 @@
 	 memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp
 endif
 
+ifeq ($(INCLUDE_JVMCI), false)
+      CXXFLAGS += -DINCLUDE_JVMCI=0
+      CFLAGS += -DINCLUDE_JVMCI=0
+endif
+
 -include $(HS_ALT_MAKE)/excludeSrc.make
 
 .PHONY: $(HS_ALT_MAKE)/excludeSrc.make
--- a/make/linux/Makefile	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/Makefile	Mon Feb 06 17:18:57 2017 +0100
@@ -199,6 +199,7 @@
 SUBDIRS_ZERO      = $(addprefix $(OSNAME)_$(VARIANTARCH)_zero/,$(TARGETS))
 SUBDIRS_SHARK     = $(addprefix $(OSNAME)_$(VARIANTARCH)_shark/,$(TARGETS))
 SUBDIRS_MINIMAL1  = $(addprefix $(OSNAME)_$(BUILDARCH)_minimal1/,$(TARGETS))
+SUBDIRS_JVMCI     = $(addprefix $(OSNAME)_$(BUILDARCH)_jvmci/,$(TARGETS))
 
 TARGETS_C2        = $(TARGETS)
 TARGETS_C1        = $(addsuffix 1,$(TARGETS))
@@ -207,6 +208,7 @@
 TARGETS_ZERO      = $(addsuffix zero,$(TARGETS))
 TARGETS_SHARK     = $(addsuffix shark,$(TARGETS))
 TARGETS_MINIMAL1 =  $(addsuffix minimal1,$(TARGETS))
+TARGETS_JVMCI     = $(addsuffix jvmci,$(TARGETS))
 
 BUILDTREE_MAKE    = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make
 BUILDTREE_VARS    = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH)
@@ -226,6 +228,7 @@
 	@echo "  $(TARGETS_ZERO)"
 	@echo "  $(TARGETS_SHARK)"
 	@echo "  $(TARGETS_MINIMAL1)"
+	@echo "  $(TARGETS_JVMCI)"
 
 checks: check_os_version check_j2se_version
 
@@ -287,6 +290,9 @@
 	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
 	$(BUILDTREE) VARIANT=minimal1
 
+$(SUBDIRS_JVMCI): $(BUILDTREE_MAKE)
+	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+	$(BUILDTREE) VARIANT=jvmci
 
 platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
 	$(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@
@@ -335,6 +341,12 @@
 	cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
+$(TARGETS_JVMCI):  $(SUBDIRS_JVMCI)
+	cd $(OSNAME)_$(BUILDARCH)_jvmci/$(patsubst %jvmci,%,$@) && $(MAKE) $(MFLAGS)
+ifdef INSTALL
+	cd $(OSNAME)_$(BUILDARCH)_jvmci/$(patsubst %jvmci,%,$@) && $(MAKE) $(MFLAGS) install
+endif
+
 # Just build the tree, and nothing else:
 tree:      $(SUBDIRS_C2)
 tree1:     $(SUBDIRS_C1)
@@ -342,6 +354,7 @@
 treezero:  $(SUBDIRS_ZERO)
 treeshark: $(SUBDIRS_SHARK)
 treeminimal1: $(SUBDIRS_MINIMAL1)
+treejvmci: $(SUBDIRS_JVMCI)
 
 # Doc target.  This is the same for all build options.
 #     Hence create a docs directory beside ...$(ARCH)_[...]
@@ -379,10 +392,10 @@
 clean_docs:
 	rm -rf $(SUBDIR_DOCS)
 
-clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark clean_minimal1:
+clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark clean_jvmci clean_minimal1:
 	rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@)
 
-clean:  clean_compiler2 clean_compiler1 clean_core clean_zero clean_shark clean_minimal1 clean_docs
+clean:  clean_compiler2 clean_compiler1 clean_core clean_zero clean_shark clean_minimal1 clean_jvmci clean_docs
 
 include $(GAMMADIR)/make/cscope.make
 
@@ -393,9 +406,9 @@
 
 #-------------------------------------------------------------------------------
 
-.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO) $(TARGETS_SHARK) $(TARGETS_MINIMAL1)
-.PHONY: tree tree1 treecore treezero treeshark
-.PHONY: all compiler1 compiler2 core zero shark
-.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
+.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO) $(TARGETS_SHARK) $(TARGETS_MINIMAL1) $(TARGETS_JVMCI)
+.PHONY: tree tree1 treecore treezero treeshark treejvmci
+.PHONY: all compiler1 compiler2 core zero shark jvmci
+.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs clean_jvmci
 .PHONY: checks check_os_version check_j2se_version
 .PHONY: $(HS_ALT_MAKE)/$(OSNAME)/Makefile.make
--- a/make/linux/makefiles/buildtree.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/makefiles/buildtree.make	Mon Feb 06 17:18:57 2017 +0100
@@ -241,7 +241,7 @@
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
 	echo; \
 	echo "Src_Dirs_I = \\"; \
 	echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \
@@ -256,8 +256,7 @@
 	echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
-	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
 	    echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \
 	[ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \
--- a/make/linux/makefiles/compiler1.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/makefiles/compiler1.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = client
 
 CFLAGS += -DCOMPILER1
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = client-nojvmci
+endif
\ No newline at end of file
--- a/make/linux/makefiles/compiler2.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/makefiles/compiler2.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = server
 
 CFLAGS += -DCOMPILER2
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = server-nojvmci
+endif
\ No newline at end of file
--- a/make/linux/makefiles/defs.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/makefiles/defs.make	Mon Feb 06 17:18:57 2017 +0100
@@ -245,9 +245,9 @@
     EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo
   endif
 endif
-EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
-EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
-EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
+EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server$(COMPILER_DIR_SUFFIX)
+EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client$(COMPILER_DIR_SUFFIX)
+EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal$(COMPILER_DIR_SUFFIX)
 
 ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK) $(JVM_VARIANT_CORE)), true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
--- a/make/linux/makefiles/gcc.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/makefiles/gcc.make	Mon Feb 06 17:18:57 2017 +0100
@@ -205,6 +205,7 @@
   WARNINGS_ARE_ERRORS += -Wno-switch -Wno-tautological-constant-out-of-range-compare -Wno-tautological-compare
   WARNINGS_ARE_ERRORS += -Wno-delete-non-virtual-dtor -Wno-deprecated -Wno-format -Wno-dynamic-class-memaccess
   WARNINGS_ARE_ERRORS += -Wno-return-type -Wno-empty-body
+  WARNINGS_ARE_ERRORS += -Wno-undefined-bool-conversion
 endif
 
 WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function -Wunused-value
@@ -215,6 +216,11 @@
   ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
     WARNING_FLAGS += -Wconversion
   endif
+  # Since GCC 6 gnu++98 is not the default language anymore and the compiler is more aggressive
+  ifeq "$(shell expr \( $(CC_VER_MAJOR) \>= 6 \))" "1"
+    CFLAGS += -std=gnu++98 -fno-delete-null-pointer-checks -fno-lifetime-dse
+    WARNINGS_ARE_ERRORS += -Wno-deprecated-declarations
+  endif
 endif
 
 CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
@@ -397,3 +403,5 @@
 endif
 
 -include $(HS_ALT_MAKE)/linux/makefiles/gcc.make
+
+.PHONY: $(HS_ALT_MAKE)/linux/makefiles/gcc.make
--- a/make/linux/makefiles/jsig.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/makefiles/jsig.make	Mon Feb 06 17:18:57 2017 +0100
@@ -74,9 +74,9 @@
 
 install_jsig: $(LIBJSIG)
 	@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
-	$(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \
+	$(QUIETLY) test ! -f $(LIBJSIG_DEBUGINFO) || \
 	    cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO)
-	$(QUIETLY) test -f $(LIBJSIG_DIZ) && \
+	$(QUIETLY) test ! -f $(LIBJSIG_DIZ) || \
 	    cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ)
 	$(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/linux/makefiles/jvmci.make	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2008, 2010 Red Hat, Inc.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+# Sets make macros for making JVMCI version of VM
+
+TYPE = JVMCI
+
+VM_SUBDIR = jvmci
+
+# To make a non-tiered JVMCI build, remove the -DCOMPILER1 below and
+# in vm.make remove COMPILER1_PATHS from Src_Dirs/JVMCI and add
+# COMPILER1_SPECIFIC_FILES to Src_Files_EXCLUDE/JVMCI
+CFLAGS += -DCOMPILERJVMCI -DJVMCI -DCOMPILER1
--- a/make/linux/makefiles/tiered.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/makefiles/tiered.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = server
 
 CFLAGS += -DCOMPILER2 -DCOMPILER1
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = server-nojvmci
+endif
\ No newline at end of file
--- a/make/linux/makefiles/vm.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/linux/makefiles/vm.make	Mon Feb 06 17:18:57 2017 +0100
@@ -148,7 +148,7 @@
 LIBJVM_DEBUGINFO   = lib$(JVM).debuginfo
 LIBJVM_DIZ         = lib$(JVM).diz
 
-SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt
+SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt jvmci
 
 SOURCE_PATHS=\
   $(shell find $(HS_COMMON_SRC)/share/vm/* -type d \! \
@@ -178,13 +178,17 @@
 
 SHARK_PATHS := $(GAMMADIR)/src/share/vm/shark
 
+JVMCI_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/jvmci)
+JVMCI_PATHS += $(HS_COMMON_SRC)/share/vm/jvmci
+
 # Include dirs per type.
 Src_Dirs/CORE      := $(CORE_PATHS)
-Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS)
-Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS)
-Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS)
+Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS) $(JVMCI_PATHS)
+Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS) $(JVMCI_PATHS)
+Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS) $(JVMCI_PATHS)
 Src_Dirs/ZERO      := $(CORE_PATHS)
 Src_Dirs/SHARK     := $(CORE_PATHS) $(SHARK_PATHS)
+Src_Dirs/JVMCI     := $(CORE_PATHS) $(COMPILER1_PATHS) $(JVMCI_PATHS)
 Src_Dirs := $(Src_Dirs/$(TYPE))
 
 COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\*
@@ -192,16 +196,25 @@
 SHARK_SPECIFIC_FILES     := shark
 ZERO_SPECIFIC_FILES      := zero
 
+ifneq ($(INCLUDE_JVMCI), true)
+  JVMCI_SPECIFIC_FILES   := jvmci\* 
+else
+  JVMCI_SPECIFIC_FILES   :=
+  Src_Dirs_I += $(HS_COMMON_SRC)/../mxbuild/jvmci/jdk.vm.ci.hotspot/src_gen/hotspot
+  Src_Dirs_I += $(MX_ALT_OUTPUT_ROOT)/jvmci/jvmci/jdk.vm.ci.hotspot/src_gen/hotspot
+endif
+
 # Always exclude these.
 Src_Files_EXCLUDE += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/JVMCI     := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
 
@@ -380,9 +393,9 @@
 
 install_jvm: $(LIBJVM)
 	@echo "Copying $(LIBJVM) to $(DEST_JVM)"
-	$(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \
+	$(QUIETLY) test ! -f $(LIBJVM_DEBUGINFO) || \
 	    cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO)
-	$(QUIETLY) test -f $(LIBJVM_DIZ) && \
+	$(QUIETLY) test ! -f $(LIBJVM_DIZ) || \
 	    cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ)
 	$(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done"
 
--- a/make/solaris/Makefile	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/solaris/Makefile	Mon Feb 06 17:18:57 2017 +0100
@@ -149,11 +149,13 @@
 SUBDIRS_C2        = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS))
 SUBDIRS_TIERED    = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS))
 SUBDIRS_CORE      = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS))
+SUBDIRS_JVMCI     = $(addprefix $(OSNAME)_$(BUILDARCH)_jvmci/,$(TARGETS))
 
 TARGETS_C2        = $(TARGETS)
 TARGETS_C1        = $(addsuffix 1,$(TARGETS))
 TARGETS_TIERED    = $(addsuffix tiered,$(TARGETS))
 TARGETS_CORE      = $(addsuffix core,$(TARGETS))
+TARGETS_JVMCI     = $(addsuffix jvmci,$(TARGETS))
 
 BUILDTREE_MAKE    = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make
 BUILDTREE_VARS    = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH)
@@ -171,6 +173,7 @@
 	@echo "  $(TARGETS_C2)"
 	@echo "  $(TARGETS_C1)"
 	@echo "  $(TARGETS_CORE)"
+	@echo "  $(TARGETS_JVMCI)"
 
 checks: check_os_version check_j2se_version
 
@@ -220,6 +223,10 @@
 	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
 	$(BUILDTREE) VARIANT=core
 
+$(SUBDIRS_JVMCI): $(BUILDTREE_MAKE)
+	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+	$(BUILDTREE) VARIANT=jvmci
+
 # Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME
 
 $(TARGETS_C2):  $(SUBDIRS_C2)
@@ -246,10 +253,17 @@
 	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
+$(TARGETS_JVMCI):  $(SUBDIRS_JVMCI)
+	cd $(OSNAME)_$(BUILDARCH)_jvmci/$(patsubst %jvmci,%,$@) && $(MAKE) $(MFLAGS)
+ifdef INSTALL
+	cd $(OSNAME)_$(BUILDARCH)_jvmci/$(patsubst %jvmci,%,$@) && $(MAKE) $(MFLAGS) install
+endif
+
 # Just build the tree, and nothing else:
 tree:      $(SUBDIRS_C2)
 tree1:     $(SUBDIRS_C1)
 treecore:  $(SUBDIRS_CORE)
+treejvmci: $(SUBDIRS_JVMCI)
 
 # Doc target.  This is the same for all build options.
 #     Hence create a docs directory beside ...$(ARCH)_[...]
@@ -279,17 +293,17 @@
 clean_docs:
 	rm -rf $(SUBDIR_DOCS)
 
-clean_compiler1 clean_compiler2 clean_core:
+clean_compiler1 clean_compiler2 clean_core clean_jvmci:
 	rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@)
 
-clean:  clean_compiler2 clean_compiler1 clean_core clean_docs
+clean:  clean_compiler2 clean_compiler1 clean_core clean_docs clean_jvmci
 
 include $(GAMMADIR)/make/cscope.make
 
 #-------------------------------------------------------------------------------
 
 .PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE)
-.PHONY: tree tree1 treecore
-.PHONY: all compiler1 compiler2 core
-.PHONY: clean clean_compiler1 clean_compiler2 clean_core docs clean_docs
+.PHONY: tree tree1 treecore treejvmci
+.PHONY: all compiler1 compiler2 core jvmci
+.PHONY: clean clean_compiler1 clean_compiler2 clean_core docs clean_docs clean_jvmci
 .PHONY: checks check_os_version check_j2se_version
--- a/make/solaris/makefiles/buildtree.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/solaris/makefiles/buildtree.make	Mon Feb 06 17:18:57 2017 +0100
@@ -229,7 +229,7 @@
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
 	echo; \
 	echo "Src_Dirs_I = \\"; \
 	echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \
@@ -244,8 +244,7 @@
 	echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(ARCH)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
-	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
 	    echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \
 	[ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \
--- a/make/solaris/makefiles/compiler1.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/solaris/makefiles/compiler1.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = client
 
 CFLAGS += -DCOMPILER1
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = client-nojvmci
+endif
--- a/make/solaris/makefiles/compiler2.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/solaris/makefiles/compiler2.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = server
 
 CFLAGS += -DCOMPILER2
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = server-nojvmci
+endif
--- a/make/solaris/makefiles/defs.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/solaris/makefiles/defs.make	Mon Feb 06 17:18:57 2017 +0100
@@ -233,8 +233,8 @@
   endif
 endif
 
-EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
-EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
+EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server$(COMPILER_DIR_SUFFIX)
+EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client$(COMPILER_DIR_SUFFIX)
 
 ifeq ($(JVM_VARIANT_SERVER),true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
--- a/make/solaris/makefiles/jsig.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/solaris/makefiles/jsig.make	Mon Feb 06 17:18:57 2017 +0100
@@ -70,9 +70,9 @@
 
 install_jsig: $(LIBJSIG)
 	@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
-	$(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \
+	$(QUIETLY) test ! -f $(LIBJSIG_DEBUGINFO) || \
 	    cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO)
-	$(QUIETLY) test -f $(LIBJSIG_DIZ) && \
+	$(QUIETLY) test ! -f $(LIBJSIG_DIZ) || \
 	    cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ)
 	$(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/solaris/makefiles/jvmci.make	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2008, 2010 Red Hat, Inc.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+# Sets make macros for making JVMCI version of VM
+
+TYPE = JVMCI
+
+VM_SUBDIR = jvmci
+
+# To make a non-tiered JVMCI build, remove the -DCOMPILER1 below and
+# in vm.make remove COMPILER1_PATHS from Src_Dirs/JVMCI and add
+# COMPILER1_SPECIFIC_FILES to Src_Files_EXCLUDE/JVMCI
+CFLAGS += -DCOMPILERJVMCI -DJVMCI -DCOMPILER1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/solaris/makefiles/mapfile-vers-JVMCI	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,30 @@
+#
+
+#
+# Copyright (c) 2006, 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.
+#  
+#
+
+# Define public interface.
+SUNWprivate_1.1 {
+        global:
+};
--- a/make/solaris/makefiles/tiered.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/solaris/makefiles/tiered.make	Mon Feb 06 17:18:57 2017 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = server
 
 CFLAGS += -DCOMPILER2 -DCOMPILER1
+
+ifeq ($(INCLUDE_JVMCI), false)
+  VM_SUBDIR = server-nojvmci
+endif
--- a/make/solaris/makefiles/vm.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/solaris/makefiles/vm.make	Mon Feb 06 17:18:57 2017 +0100
@@ -161,7 +161,7 @@
 LIBJVM_DEBUGINFO   = lib$(JVM).debuginfo
 LIBJVM_DIZ         = lib$(JVM).diz
 
-SPECIAL_PATHS:=adlc c1 dist gc_implementation opto shark libadt
+SPECIAL_PATHS:=adlc c1 dist gc_implementation opto shark libadt jvmci
 
 SOURCE_PATHS=\
   $(shell find $(HS_COMMON_SRC)/share/vm/* -type d \! \
@@ -189,13 +189,17 @@
 COMPILER2_PATHS += $(HS_COMMON_SRC)/share/vm/libadt
 COMPILER2_PATHS +=  $(GENERATED)/adfiles
 
+JVMCI_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/jvmci)
+JVMCI_PATHS += $(HS_COMMON_SRC)/share/vm/jvmci
+
 # Include dirs per type.
 Src_Dirs/CORE      := $(CORE_PATHS)
-Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS)
-Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS)
-Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS)
+Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS) $(JVMCI_PATHS)
+Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS) $(JVMCI_PATHS)
+Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS) $(JVMCI_PATHS)
 Src_Dirs/ZERO      := $(CORE_PATHS)
-Src_Dirs/SHARK     := $(CORE_PATHS)
+Src_Dirs/SHARK     := $(CORE_PATHS) $(SHARK_PATHS)
+Src_Dirs/JVMCI     := $(CORE_PATHS) $(COMPILER1_PATHS) $(JVMCI_PATHS)
 Src_Dirs := $(Src_Dirs/$(TYPE))
 
 COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\*
@@ -203,16 +207,25 @@
 SHARK_SPECIFIC_FILES     := shark
 ZERO_SPECIFIC_FILES      := zero
 
+ifneq ($(INCLUDE_JVMCI), true)
+  JVMCI_SPECIFIC_FILES   := jvmci\* 
+else
+  JVMCI_SPECIFIC_FILES   :=
+  Src_Dirs_I += $(HS_COMMON_SRC)/../mxbuild/jvmci/jdk.vm.ci.hotspot/src_gen/hotspot
+  Src_Dirs_I += $(MX_ALT_OUTPUT_ROOT)/jvmci/jvmci/jdk.vm.ci.hotspot/src_gen/hotspot
+endif
+
 # Always exclude these.
 Src_Files_EXCLUDE += dtrace jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(JVMCI_SPECIFIC_FILES)
+Src_Files_EXCLUDE/JVMCI     := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
 
@@ -324,9 +337,9 @@
 
 install_jvm: $(LIBJVM)
 	@echo "Copying $(LIBJVM) to $(DEST_JVM)"
-	$(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \
+	$(QUIETLY) test ! -f $(LIBJVM_DEBUGINFO) || \
 	    cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO)
-	$(QUIETLY) test -f $(LIBJVM_DIZ) && \
+	$(QUIETLY) test ! -f $(LIBJVM_DIZ) || \
 	    cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ)
 	$(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done"
 
--- a/make/windows/build.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/windows/build.make	Mon Feb 06 17:18:57 2017 +0100
@@ -110,6 +110,8 @@
 !endif
 !elseif "$(Variant)" == "tiered"
 VARIANT_TEXT=Tiered
+!elseif "$(Variant)" == "jvmci"
+VARIANT_TEXT=JVMCI
 !endif
 
 #########################################################################
@@ -306,9 +308,9 @@
 checks: checkVariant checkWorkSpace checkSA
 
 checkVariant:
-	@ if "$(Variant)"=="" echo Need to specify "Variant=[tiered|compiler2|compiler1|core]" && false
-	@ if "$(Variant)" NEQ "tiered" if "$(Variant)" NEQ "compiler2" if "$(Variant)" NEQ "compiler1" if "$(Variant)" NEQ "core" \
-          echo Need to specify "Variant=[tiered|compiler2|compiler1|core]" && false
+	@ if "$(Variant)"=="" echo Need to specify "Variant=[jvmci|tiered|compiler2|compiler1|core]" && false
+	@ if "$(Variant)" NEQ "jvmci" if "$(Variant)" NEQ "tiered" if "$(Variant)" NEQ "compiler2" if "$(Variant)" NEQ "compiler1" if "$(Variant)" NEQ "core" \
+          echo Need to specify "Variant=[jvmci|tiered|compiler2|compiler1|core]" && false
 
 checkWorkSpace:
 	@ if "$(WorkSpace)"=="" echo Need to specify "WorkSpace=..." && false
--- a/make/windows/build_vm_def.sh	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/windows/build_vm_def.sh	Mon Feb 06 17:18:57 2017 +0100
@@ -52,6 +52,7 @@
 CAT="$MKS_HOME/cat.exe"
 RM="$MKS_HOME/rm.exe"
 DUMPBIN="link.exe /dump"
+export VS_UNICODE_OUTPUT= 
 
 if [ "$1" = "-nosa" ]; then
     echo EXPORTS > vm.def
--- a/make/windows/create.bat	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/windows/create.bat	Mon Feb 06 17:18:57 2017 +0100
@@ -37,10 +37,14 @@
 REM that "grep" be accessible on the PATH. An MKS install does this.
 REM 
 
-cl 2>NUL >NUL
-if %errorlevel% == 0 goto nexttest
-echo Make sure cl.exe is in your PATH before running this script.
-goto end
+
+
+REM (cwirth) does not return a proper error code, so build fails all the time
+REM
+REM cl 2>NUL >NUL
+REM if %errorlevel% == 0 goto nexttest
+REM echo Make sure cl.exe is in your PATH before running this script.
+REM goto end
 
 :nexttest
 grep -V 2>NUL >NUL
@@ -155,7 +159,7 @@
 
 REM This is now safe to do.
 :copyfiles
-for /D %%i in (compiler1, compiler2, tiered ) do (
+for /D %%i in (jvmci, compiler1, compiler2, tiered) do (
 if NOT EXIST %HotSpotBuildSpace%\%%i\generated mkdir %HotSpotBuildSpace%\%%i\generated
 copy %HotSpotWorkSpace%\make\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\generated > NUL
 )
@@ -163,7 +167,7 @@
 REM force regneration of ProjectFile
 if exist %ProjectFile% del %ProjectFile%
 
-for /D %%i in (compiler1, compiler2, tiered ) do (
+for /D %%i in (jvmci, compiler1, compiler2, tiered) do (
 echo -- %%i --
 echo # Generated file!                                                        >    %HotSpotBuildSpace%\%%i\local.make
 echo # Changing a variable below and then deleting %ProjectFile% will cause  >>    %HotSpotBuildSpace%\%%i\local.make
--- a/make/windows/makefiles/projectcreator.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/windows/makefiles/projectcreator.make	Mon Feb 06 17:18:57 2017 +0100
@@ -56,6 +56,8 @@
         -relativeInclude src\os\windows\vm \
         -relativeInclude src\os_cpu\windows_$(Platform_arch)\vm \
         -relativeInclude src\cpu\$(Platform_arch)\vm \
+        -relativeInclude mxbuild\jvmci\jdk.vm.ci.hotspot\src_gen\hotspot \
+        -relativeInclude $(MX_ALT_OUTPUT_ROOT)\jvmci\jvmci\jdk.vm.ci.hotspot\src_gen\hotspot \
         -absoluteInclude $(HOTSPOTBUILDSPACE)/%f/generated \
         -relativeSrcInclude src \
         -absoluteSrcInclude $(HOTSPOTBUILDSPACE) \
@@ -109,7 +111,8 @@
         -jdkTargetRoot $(HOTSPOTJDKDIST) \
         -define ALIGN_STACK_FRAMES \
         -define VM_LITTLE_ENDIAN \
-        -prelink  "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b	set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME)	set JAVA_HOME=$(HOTSPOTJDKDIST)	$(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(BUILD_VM_DEF_FLAG) $(LD_VER)" \
+        -prelink  "" "Generating vm.def..." "cd %o	set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME)	set JAVA_HOME=$(HOTSPOTJDKDIST)	$(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(BUILD_VM_DEF_FLAG) $(LD_VER)" \
+        -postbuild "" "Building hotspot.exe..." "cd %o	set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME)	nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \
         -ignoreFile jsig.c \
         -ignoreFile jvmtiEnvRecommended.cpp \
         -ignoreFile jvmtiEnvStub.cpp \
@@ -148,6 +151,12 @@
  -ignorePath_TARGET tiered \
  -ignorePath_TARGET c1_
 
+ProjectCreatorIDEOptionsIgnoreJVMCI=\
+ -ignorePath_TARGET src/share/vm/jvmci \
+ -ignorePath_TARGET mxbuild/jvmci/jdk.vm.ci.hotspot/src_gen/hotspot \
+ -ignorePath_TARGET $(MX_ALT_OUTPUT_ROOT)/jvmci/jdk.vm.ci.hotspot/src_gen/hotspot \
+ -ignorePath_TARGET vm/jvmci
+
 ProjectCreatorIDEOptionsIgnoreCompiler2=\
  -ignorePath_TARGET compiler2 \
  -ignorePath_TARGET tiered \
@@ -168,14 +177,26 @@
 ##################################################
 ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
  -define_compiler1 COMPILER1 \
-$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1)
+ -define_compiler1 JVMCI \
+ $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1)
+
+##################################################
+# JVMCI compiler specific options
+##################################################
+ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
+ -define_jvmci COMPILER1 \
+ -define_jvmci COMPILERJVMCI \
+ -define_jvmci JVMCI \
+ $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=jvmci)
 
 ##################################################
 # Server(C2) compiler specific options
 ##################################################
 #NOTE! This list must be kept in sync with GENERATED_NAMES in adlc.make.
 ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
+ -define_compiler2 COMPILER1 \
  -define_compiler2 COMPILER2 \
+ -define_compiler2 JVMCI \
  -additionalFile_compiler2 $(Platform_arch_model).ad \
  -additionalFile_compiler2 ad_$(Platform_arch_model).cpp \
  -additionalFile_compiler2 ad_$(Platform_arch_model).hpp \
@@ -187,8 +208,7 @@
  -additionalFile_compiler2 ad_$(Platform_arch_model)_peephole.cpp \
  -additionalFile_compiler2 ad_$(Platform_arch_model)_pipeline.cpp \
  -additionalFile_compiler2 adGlobals_$(Platform_arch_model).hpp \
- -additionalFile_compiler2 dfa_$(Platform_arch_model).cpp \
- $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=compiler2)
+ -additionalFile_compiler2 dfa_$(Platform_arch_model).cpp
 
 # Add in the jvmti (JSR-163) options
 # NOTE: do not pull in jvmtiEnvRecommended.cpp.  This file is generated
--- a/make/windows/makefiles/vm.make	Mon Dec 05 13:09:39 2016 -0800
+++ b/make/windows/makefiles/vm.make	Mon Feb 06 17:18:57 2017 +0100
@@ -48,6 +48,10 @@
 CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" /D "COMPILER2"
 !endif
 
+!if "$(Variant)" == "jvmci"
+CXX_FLAGS=$(CXX_FLAGS) /D "JVMCI" /D "COMPILERJVMCI" /D "COMPILER1"
+!endif
+
 !if "$(BUILDARCH)" == "i486"
 HOTSPOT_LIB_ARCH=i386
 !else
@@ -142,6 +146,7 @@
 VM_PATH=$(VM_PATH);../generated/jvmtifiles
 VM_PATH=$(VM_PATH);../generated/tracefiles
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/c1
+VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/jvmci
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/compiler
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/code
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/interpreter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/windows/projectfiles/jvmci/Makefile	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+!include ../local.make
+
+!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/windows/projectfiles/jvmci/vm.def	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,7 @@
+;
+; This .DEF file is a placeholder for one which is automatically
+; generated during the build process. See
+; make\windows\build_vm_def.sh and
+; make\windows\makefiles\projectcreator.make (esp. the "-prelink"
+; options).
+;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/windows/projectfiles/jvmci/vm.dsw	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "vm"=.\vm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx.jvmci/.project	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>mx.jvmci</name>
+	<comment></comment>
+	<projects>
+		<project>mx</project>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.python.pydev.pythonNature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx.jvmci/.pydevproject	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?>
+
+<pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/mx.jvmci</path>
+</pydev_pathproperty>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/mxtool2</path>
+</pydev_pathproperty>
+
+</pydev_project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx.jvmci/eclipse-settings/org.eclipse.jdt.core.prefs	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx.jvmci/mx_jvmci.py	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1541 @@
+#
+# ----------------------------------------------------------------------------------------------------
+#
+# Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+# ----------------------------------------------------------------------------------------------------
+
+import os, stat, errno, sys, shutil, zipfile, tarfile, tempfile, re, time, datetime, platform, subprocess, socket
+from os.path import join, exists, basename
+from argparse import ArgumentParser, REMAINDER
+import xml.dom.minidom
+import json, textwrap
+from collections import OrderedDict
+
+import mx
+import mx_unittest
+from mx_unittest import unittest
+from mx_gate import Task
+import mx_gate
+
+_suite = mx.suite('jvmci')
+
+JVMCI_VERSION = 8
+
+""" The VMs that can be built and run along with an optional description. Only VMs with a
+    description are listed in the dialogue for setting the default VM (see get_vm()). """
+_vmChoices = {
+    'server' : 'Normal compilation is performed with a tiered system (C1 + C2 or Graal) and Graal is available for hosted compilation.',
+    'client' : None,  # VM compilation with client compiler, hosted compilation with Graal
+    'original' : None,  # default VM copied from bootstrap JDK
+}
+
+_jvmciModes = {
+    'hosted' : ['-XX:+UnlockExperimentalVMOptions', '-XX:+EnableJVMCI'],
+    'jit' : ['-XX:+UnlockExperimentalVMOptions', '-XX:+EnableJVMCI', '-XX:+UseJVMCICompiler'],
+    'disabled' : ['-XX:+UnlockExperimentalVMOptions', '-XX:-EnableJVMCI']
+}
+
+# Aliases for legacy VM names
+_vmAliases = {
+    'jvmci' : 'server',
+    'graal' : 'server',
+    'server-nograal' : 'server-nojvmci',
+    'client-nograal' : 'client-nograal',
+}
+
+_JVMCI_JDK_TAG = 'jvmci'
+
+""" The VM that will be run by the 'vm' command and built by default by the 'build' command.
+    It can be temporarily set by using a VM context manager object in a 'with' statement. """
+_vm = 'server'
+
+class JVMCIMode:
+    def __init__(self, jvmciMode):
+        self.jvmciMode = jvmciMode
+        self.vmArgs = _jvmciModes[jvmciMode]
+
+    def __enter__(self):
+        global _jvmciMode
+        self.previousMode = _jvmciMode
+        _jvmciMode = self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        global _jvmciMode
+        _jvmciMode = self.previousMode
+
+""" The JVMCI mode that will be used by the 'vm' command. This can be set with the global '-M' option.
+    It can also be temporarily set using the JVMCIMode context manager object in a 'with' statement.
+    Defaults to 'hosted'. """
+_jvmciMode = JVMCIMode('hosted')
+
+""" The VM builds that will be run by the 'vm' command - default is first in list """
+_vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized']
+
+""" The VM build that will be run by the 'vm' command.
+    This can be set via the global '--vmbuild' option.
+    It can also be temporarily set by using of a VM context manager object in a 'with' statement. """
+_vmbuild = _vmbuildChoices[0]
+
+""" The current working directory to switch to before running the VM. """
+_vm_cwd = None
+
+""" The base directory in which the JDKs cloned from $JAVA_HOME exist. """
+_installed_jdks = None
+
+""" Prefix for running the VM. """
+_vm_prefix = None
+
+_make_eclipse_launch = False
+
+_minVersion = mx.VersionSpec('1.8.0_111')
+
+# max version (first _unsupported_ version)
+_untilVersion = mx.VersionSpec('1.9')
+
+class JDKDeployedDist(object):
+    def __init__(self, name):
+        self._name = name
+
+    def dist(self):
+        return mx.distribution(self._name)
+
+    def deploy(self, jdkDir):
+        mx.nyi('deploy', self)
+
+    def post_parse_cmd_line(self):
+        def _install(d):
+            _installDistInJdks(self)
+        self.dist().add_update_listener(_install)
+
+class JarJDKDeployedDist(JDKDeployedDist):
+    def __init__(self, name):
+        JDKDeployedDist.__init__(self, name)
+
+    def targetDir(self):
+        mx.nyi('targetDir', self)
+
+    def _copyToJdk(self, jdkDir, target):
+        targetDir = join(jdkDir, target)
+        dist = self.dist()
+        mx.logv('Deploying {} to {}'.format(dist.name, targetDir))
+        copyToJdk(dist.path, targetDir)
+        if exists(dist.sourcesPath):
+            copyToJdk(dist.sourcesPath, targetDir)
+
+    def deploy(self, jdkDir):
+        self._copyToJdk(jdkDir, self.targetDir())
+
+class ExtJDKDeployedDist(JarJDKDeployedDist):
+    def __init__(self, name):
+        JarJDKDeployedDist.__init__(self, name)
+
+    def targetDir(self):
+        return join('jre', 'lib', 'ext')
+
+class LibJDKDeployedDist(JarJDKDeployedDist):
+    def __init__(self, name):
+        JarJDKDeployedDist.__init__(self, name)
+
+    def targetDir(self):
+        return join('jre', 'lib')
+
+class JvmciJDKDeployedDist(JarJDKDeployedDist):
+    def __init__(self, name):
+        JarJDKDeployedDist.__init__(self, name)
+
+    def targetDir(self):
+        return join('jre', 'lib', 'jvmci')
+
+def _exe(l):
+    return mx.exe_suffix(l)
+
+def _lib(l):
+    return mx.add_lib_suffix(mx.add_lib_prefix(l))
+
+def _lib_dbg(l):
+    return mx.add_debug_lib_suffix(mx.add_lib_prefix(l))
+
+class HotSpotVMJDKDeployedDist(JDKDeployedDist):
+    def dist(self):
+        name = mx.instantiatedDistributionName(self._name, dict(vm=get_vm(), vmbuild=_vmbuild), context=self._name)
+        return mx.distribution(name)
+
+    def deploy(self, jdkDir):
+        vmbuild = _vmbuildFromJdkDir(jdkDir)
+        if vmbuild != _vmbuild:
+            return
+        _hs_deploy_map = {
+            'jvmti.h' : 'include',
+            'sa-jdi.jar' : 'lib',
+            _lib('jvm') : join(relativeVmLibDirInJdk(), get_vm()),
+            _lib_dbg('jvm') : join(relativeVmLibDirInJdk(), get_vm()),
+            _lib('saproc') : relativeVmLibDirInJdk(),
+            _lib_dbg('saproc') : relativeVmLibDirInJdk(),
+            _lib('jsig') : relativeVmLibDirInJdk(),
+            _lib_dbg('jsig') : relativeVmLibDirInJdk(),
+        }
+        dist = self.dist()
+        with tarfile.open(dist.path, 'r') as tar:
+            for m in tar.getmembers():
+                if m.name in _hs_deploy_map:
+                    targetDir = join(jdkDir, _hs_deploy_map[m.name])
+                    mx.logv('Deploying {} from {} to {}'.format(m.name, dist.name, targetDir))
+                    tar.extract(m, targetDir)
+
+"""
+List of distributions that are deployed into a JDK by mx.
+"""
+jdkDeployedDists = [
+    LibJDKDeployedDist('JVMCI_SERVICES'),
+    JvmciJDKDeployedDist('JVMCI_API'),
+    JvmciJDKDeployedDist('JVMCI_HOTSPOT'),
+    HotSpotVMJDKDeployedDist('JVM_<vmbuild>_<vm>'),
+]
+
+JDK_UNIX_PERMISSIONS_DIR = 0755
+JDK_UNIX_PERMISSIONS_FILE = 0644
+JDK_UNIX_PERMISSIONS_EXEC = 0755
+
+def isVMSupported(vm):
+    if 'client' == vm and len(platform.mac_ver()[0]) != 0:
+        # Client VM not supported: java launcher on Mac OS X translates '-client' to '-server'
+        return False
+    return True
+
+def get_vm_cwd():
+    """
+    Get the current working directory to switch to before running the VM.
+    """
+    return _vm_cwd
+
+def get_installed_jdks():
+    """
+    Get the base directory in which the JDKs cloned from $JAVA_HOME exist.
+    """
+    return _installed_jdks
+
+def get_vm_prefix(asList=True):
+    """
+    Get the prefix for running the VM ("/usr/bin/gdb --args").
+    """
+    if asList:
+        return _vm_prefix.split() if _vm_prefix is not None else []
+    return _vm_prefix
+
+def get_vm_choices():
+    """
+    Get the names of available VMs.
+    """
+    return _vmChoices.viewkeys()
+
+def dealiased_vm(vm):
+    """
+    If 'vm' is an alias, returns the aliased name otherwise returns 'vm'.
+    """
+    if vm and vm in _vmAliases:
+        if vm == 'jvmci' or vm == 'graal':
+            mx.log('"--vm ' + vm + '" is deprecated, using "--vm server -Mjit" instead')
+            global _jvmciMode
+            _jvmciMode = JVMCIMode('jit')
+        return _vmAliases[vm]
+    return vm
+
+def get_jvmci_mode():
+    return _jvmciMode.jvmciMode
+
+def get_jvmci_mode_args():
+    return _jvmciMode.vmArgs
+
+def get_vm():
+    """
+    Gets the configured VM.
+    """
+    return _vm
+
+"""
+A context manager that can be used with the 'with' statement to set the VM
+used by all VM executions within the scope of the 'with' statement. For example:
+
+    with VM('server'):
+        dacapo(['pmd'])
+"""
+class VM:
+    def __init__(self, vm=None, build=None):
+        assert build is None or build in _vmbuildChoices
+        self.build = build if build else _vmbuild
+        if vm == 'jvmci':
+            mx.log('WARNING: jvmci VM is deprecated, using server VM with -Mjit instead')
+            self.vm = 'server'
+            self.jvmciMode = JVMCIMode('jit')
+        else:
+            assert vm is None or vm in _vmChoices.keys()
+            self.vm = vm if vm else _vm
+            self.jvmciMode = None
+
+    def __enter__(self):
+        global _vm, _vmbuild
+        self.previousVm = _vm
+        self.previousBuild = _vmbuild
+        mx.reInstantiateDistribution('JVM_<vmbuild>_<vm>', dict(vm=self.previousVm, vmbuild=self.previousBuild), dict(vm=self.vm, vmbuild=self.build))
+        _vm = self.vm
+        _vmbuild = self.build
+        if self.jvmciMode is not None:
+            self.jvmciMode.__enter__()
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        global _vm, _vmbuild
+        mx.reInstantiateDistribution('JVM_<vmbuild>_<vm>', dict(vm=self.vm, vmbuild=self.build), dict(vm=self.previousVm, vmbuild=self.previousBuild))
+        _vm = self.previousVm
+        _vmbuild = self.previousBuild
+        if self.jvmciMode is not None:
+            self.jvmciMode.__exit__(exc_type, exc_value, traceback)
+
+def chmodRecursive(dirname, chmodFlagsDir):
+    if mx.get_os() == 'windows':
+        return
+
+    def _chmodDir(chmodFlags, dirname, fnames):
+        os.chmod(dirname, chmodFlagsDir)
+
+    os.path.walk(dirname, _chmodDir, chmodFlagsDir)
+
+def export(args):
+    """create archives of builds split by vmbuild and vm"""
+
+    parser = ArgumentParser(prog='mx export')
+    args = parser.parse_args(args)
+
+    # collect data about export
+    infos = dict()
+    infos['timestamp'] = time.time()
+
+    hgcfg = mx.HgConfig()
+    hgcfg.check()
+    infos['revision'] = hgcfg.tip('.') + ('+' if hgcfg.isDirty('.') else '')
+    # TODO: infos['repository']
+
+    infos['jdkversion'] = str(get_jvmci_bootstrap_jdk().version)
+
+    infos['architecture'] = mx.get_arch()
+    infos['platform'] = mx.get_os()
+
+    if mx.get_os != 'windows':
+        pass
+        # infos['ccompiler']
+        # infos['linker']
+
+    infos['hostname'] = socket.gethostname()
+
+    def _writeJson(suffix, properties):
+        d = infos.copy()
+        for k, v in properties.iteritems():
+            assert not d.has_key(k)
+            d[k] = v
+
+        jsonFileName = 'export-' + suffix + '.json'
+        with open(jsonFileName, 'w') as f:
+            print >> f, json.dumps(d)
+        return jsonFileName
+
+
+    def _genFileName(archivetype, middle):
+        idPrefix = infos['revision'] + '_'
+        idSuffix = '.tar.gz'
+        return join(_suite.dir, "graalvm_" + archivetype + "_" + idPrefix + middle + idSuffix)
+
+    def _genFileArchPlatformName(archivetype, middle):
+        return _genFileName(archivetype, infos['platform'] + '_' + infos['architecture'] + '_' + middle)
+
+
+    # archive different build types of hotspot
+    for vmBuild in _vmbuildChoices:
+        jdkDir = join(_jdksDir(), vmBuild)
+        if not exists(jdkDir):
+            mx.logv("skipping " + vmBuild)
+            continue
+
+        tarName = _genFileArchPlatformName('basejdk', vmBuild)
+        mx.logv("creating basejdk " + tarName)
+        vmSet = set()
+        with tarfile.open(tarName, 'w:gz') as tar:
+            for root, _, files in os.walk(jdkDir):
+                if basename(root) in _vmChoices.keys():
+                    # TODO: add some assert to check path assumption
+                    vmSet.add(root)
+                    continue
+
+                for f in files:
+                    name = join(root, f)
+                    # print name
+                    tar.add(name, name)
+
+            n = _writeJson("basejdk-" + vmBuild, {'vmbuild' : vmBuild})
+            tar.add(n, n)
+
+        # create a separate archive for each VM
+        for vm in vmSet:
+            bVm = basename(vm)
+            vmTarName = _genFileArchPlatformName('vm', vmBuild + '_' + bVm)
+            mx.logv("creating vm " + vmTarName)
+
+            debugFiles = set()
+            with tarfile.open(vmTarName, 'w:gz') as tar:
+                for root, _, files in os.walk(vm):
+                    for f in files:
+                        # TODO: mac, windows, solaris?
+                        if any(map(f.endswith, [".debuginfo"])):
+                            debugFiles.add(f)
+                        else:
+                            name = join(root, f)
+                            # print name
+                            tar.add(name, name)
+
+                n = _writeJson("vm-" + vmBuild + "-" + bVm, {'vmbuild' : vmBuild, 'vm' : bVm})
+                tar.add(n, n)
+
+            if len(debugFiles) > 0:
+                debugTarName = _genFileArchPlatformName('debugfilesvm', vmBuild + '_' + bVm)
+                mx.logv("creating debugfilesvm " + debugTarName)
+                with tarfile.open(debugTarName, 'w:gz') as tar:
+                    for f in debugFiles:
+                        name = join(root, f)
+                        # print name
+                        tar.add(name, name)
+
+                    n = _writeJson("debugfilesvm-" + vmBuild + "-" + bVm, {'vmbuild' : vmBuild, 'vm' : bVm})
+                    tar.add(n, n)
+
+    # jvmci directory
+    jvmciDirTarName = _genFileName('classfiles', 'javac')
+    mx.logv("creating jvmci " + jvmciDirTarName)
+    with tarfile.open(jvmciDirTarName, 'w:gz') as tar:
+        for root, _, files in os.walk("jvmci"):
+            for f in [f for f in files if not f.endswith('.java')]:
+                name = join(root, f)
+                # print name
+                tar.add(name, name)
+
+        n = _writeJson("jvmci", {'javacompiler' : 'javac'})
+        tar.add(n, n)
+
+def relativeVmLibDirInJdk():
+    mxos = mx.get_os()
+    if mxos == 'darwin':
+        return join('jre', 'lib')
+    if mxos == 'windows' or mxos == 'cygwin':
+        return join('jre', 'bin')
+    return join('jre', 'lib', mx.get_arch())
+
+def vmLibDirInJdk(jdkDir):
+    """
+    Gets the directory within a JDK where the server and client
+    sub-directories are located.
+    """
+    return join(jdkDir, relativeVmLibDirInJdk())
+
+def getVmJliLibDirs(jdkDir):
+    """
+    Get the directories within a JDK where the jli library designates to.
+    """
+    mxos = mx.get_os()
+    if mxos == 'darwin':
+        return [join(jdkDir, 'jre', 'lib', 'jli')]
+    if mxos == 'windows' or mxos == 'cygwin':
+        return [join(jdkDir, 'jre', 'bin'), join(jdkDir, 'bin')]
+    return [join(jdkDir, 'jre', 'lib', mx.get_arch(), 'jli'), join(jdkDir, 'lib', mx.get_arch(), 'jli')]
+
+def getVmCfgInJdk(jdkDir, jvmCfgFile='jvm.cfg'):
+    """
+    Get the jvm.cfg file.
+    """
+    mxos = mx.get_os()
+    if mxos == "windows" or mxos == "cygwin":
+        return join(jdkDir, 'jre', 'lib', mx.get_arch(), jvmCfgFile)
+    return join(vmLibDirInJdk(jdkDir), jvmCfgFile)
+
+def _jdksDir():
+    return os.path.abspath(join(_installed_jdks if _installed_jdks else _suite.dir, 'jdk' + str(get_jvmci_bootstrap_jdk().version)))
+
+def _handle_missing_VM(bld, vm=None):
+    if not vm:
+        vm = get_vm()
+    mx.log('The ' + bld + ' ' + vm + ' VM has not been created')
+    if mx.is_interactive():
+        if mx.ask_yes_no('Build it now', 'y'):
+            with VM(vm, bld):
+                build([])
+            return
+    mx.abort('You need to run "mx --vm=' + vm + ' --vmbuild=' + bld + ' build" to build the selected VM')
+
+def check_VM_exists(vm, jdkDir, build=None):
+    if not build:
+        build = _vmbuild
+    jvmCfg = getVmCfgInJdk(jdkDir)
+    found = False
+    with open(jvmCfg) as f:
+        for line in f:
+            if line.strip() == '-' + vm + ' KNOWN':
+                found = True
+                break
+    if not found:
+        _handle_missing_VM(build, vm)
+
+def get_jvmci_jdk_dir(build=None, vmToCheck=None, create=False, deployDists=True):
+    """
+    Gets the path of the JVMCI JDK corresponding to 'build' (or '_vmbuild'), creating it
+    first if it does not exist and 'create' is True. If the JDK was created or
+    'deployDists' is True, then the JDK deployable distributions are deployed into
+    the JDK.
+    """
+    if not build:
+        build = _vmbuild
+    jdkDir = join(_jdksDir(), build)
+    if create:
+        srcJdk = get_jvmci_bootstrap_jdk().home
+        if not exists(jdkDir):
+            mx.log('Creating ' + jdkDir + ' from ' + srcJdk)
+            shutil.copytree(srcJdk, jdkDir)
+
+            # Make a copy of the default VM so that this JDK can be
+            # reliably used as the bootstrap for a HotSpot build.
+            jvmCfg = getVmCfgInJdk(jdkDir)
+            if not exists(jvmCfg):
+                mx.abort(jvmCfg + ' does not exist')
+
+            jvmCfgLines = []
+            with open(jvmCfg) as f:
+                jvmCfgLines = f.readlines()
+
+            jvmCfgLines += ['-original KNOWN\n']
+
+            defaultVM = 'server'
+            chmodRecursive(jdkDir, JDK_UNIX_PERMISSIONS_DIR)
+            shutil.move(join(vmLibDirInJdk(jdkDir), defaultVM), join(vmLibDirInJdk(jdkDir), 'original'))
+
+            if mx.get_os() != 'windows':
+                os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS_FILE)
+            with open(jvmCfg, 'w') as fp:
+                for line in jvmCfgLines:
+                    fp.write(line)
+
+            # Install a copy of the disassembler library
+            try:
+                hsdis_args = []
+                syntax = mx.get_env('HSDIS_SYNTAX')
+                if syntax:
+                    hsdis_args = [syntax]
+                hsdis(hsdis_args, copyToDir=vmLibDirInJdk(jdkDir))
+            except SystemExit:
+                pass
+    else:
+        if not exists(jdkDir):
+            if _installed_jdks:
+                mx.log("The selected JDK directory does not (yet) exist: " + jdkDir)
+            _handle_missing_VM(build, vmToCheck)
+
+    if deployDists:
+        for jdkDist in jdkDeployedDists:
+            dist = jdkDist.dist()
+            if exists(dist.path):
+                _installDistInJdks(jdkDist)
+
+        # patch 'release' file (append jvmci revision)
+        releaseFile = join(jdkDir, 'release')
+        if exists(releaseFile):
+            releaseFileLines = []
+            with open(releaseFile) as f:
+                for line in f:
+                    releaseFileLines.append(line)
+
+            if mx.get_os() != 'windows':
+                os.chmod(releaseFile, JDK_UNIX_PERMISSIONS_FILE)
+            with open(releaseFile, 'w') as fp:
+                for line in releaseFileLines:
+                    timmedLine = line.strip()
+                    if timmedLine.startswith('SOURCE="') and timmedLine.endswith('"'):
+                        try:
+                            versions = OrderedDict()
+                            for p in timmedLine[len('SOURCE="'):-len('"')].split(' '):
+                                if p:
+                                    idx = p.index(':')
+                                    versions[p[:idx]] = p[idx+1:]
+                            if _suite.vc:
+                                versions['jvmci'] = _suite.vc.parent(_suite.dir)[:12]
+                            else:
+                                versions['jvmci'] = "unknown"
+                            if 'hotspot' in versions:
+                                del versions['hotspot']
+                            fp.write('SOURCE=" ' + ' '.join((k + ":" + v for k, v in versions.iteritems())) + '"' + os.linesep)
+                            mx.logv("Updating " + releaseFile)
+                        except BaseException as e:
+                            mx.warn("Exception " + str(e) + " while updating release file")
+                            fp.write(line)
+                    else:
+                        fp.write(line)
+
+    if vmToCheck is not None:
+        jvmCfg = getVmCfgInJdk(jdkDir)
+        found = False
+        with open(jvmCfg) as f:
+            for line in f:
+                if line.strip() == '-' + vmToCheck + ' KNOWN':
+                    found = True
+                    break
+        if not found:
+            _handle_missing_VM(build, vmToCheck)
+
+    return jdkDir
+
+def copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE):
+    name = os.path.basename(src)
+    mx.ensure_dir_exists(dst)
+    dstLib = join(dst, name)
+    if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true':
+        # Using symlinks is much faster than copying but may
+        # cause issues if the lib is being updated while
+        # the VM is running.
+        if not os.path.islink(dstLib) or not os.path.realpath(dstLib) == src:
+            if exists(dstLib):
+                os.remove(dstLib)
+            os.symlink(src, dstLib)
+    else:
+        # do a copy and then a move to get atomic updating (on Unix)
+        fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dst)
+        shutil.copyfile(src, tmp)
+        os.close(fd)
+        shutil.move(tmp, dstLib)
+        os.chmod(dstLib, permissions)
+
+def _installDistInJdks(deployableDist):
+    """
+    Installs the jar(s) for a given Distribution into all existing JVMCI JDKs
+    """
+    jdks = _jdksDir()
+    if exists(jdks):
+        for e in os.listdir(jdks):
+            jdkDir = join(jdks, e)
+            deployableDist.deploy(jdkDir)
+
+def _vmbuildFromJdkDir(jdkDir):
+    """
+    Determines the VM build corresponding to 'jdkDir'.
+    """
+    jdksDir = _jdksDir()
+    assert jdkDir.startswith(jdksDir)
+    vmbuild = os.path.relpath(jdkDir, jdksDir)
+    assert vmbuild in _vmbuildChoices, 'The vmbuild derived from ' + jdkDir + ' is unknown: ' + vmbuild
+    return vmbuild
+
+def _getJdkDeployedJars(jdkDir):
+    """
+    Gets jar paths for all deployed distributions in the context of
+    a given JDK directory.
+    """
+    jars = []
+    for dist in jdkDeployedDists:
+        if not isinstance(dist, JarJDKDeployedDist):
+            continue
+        jar = basename(dist.dist().path)
+        jars.append(join(dist.targetDir(), jar))
+    return jars
+
+# run a command in the windows SDK Debug Shell
+def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
+    if respondTo is None:
+        respondTo = {}
+    newLine = os.linesep
+    startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE'
+    endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE'
+
+    winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\')
+
+    if not exists(mx._cygpathW2U(winSDK)):
+        mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist")
+
+    winSDKSetEnv = mx._cygpathW2U(join(winSDK, 'Bin', 'SetEnv.cmd'))
+    if not exists(winSDKSetEnv):
+        mx.abort("Invalid Windows SDK path (" + winSDK + ") : could not find Bin/SetEnv.cmd (you can use the WIN_SDK environment variable to specify an other path)")
+
+    wincmd = 'cmd.exe /E:ON /V:ON /K "' + mx._cygpathU2W(winSDKSetEnv) + '"'
+    p = subprocess.Popen(wincmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    stdout = p.stdout
+    stdin = p.stdin
+    if logFile:
+        log = open(logFile, 'w')
+    ret = False
+
+    def _writeProcess(s):
+        stdin.write(s + newLine)
+
+    _writeProcess("echo " + startToken)
+    while True:
+        # encoding may be None on windows plattforms
+        if sys.stdout.encoding is None:
+            encoding = 'utf-8'
+        else:
+            encoding = sys.stdout.encoding
+
+        line = stdout.readline().decode(encoding)
+        if logFile:
+            log.write(line.encode('utf-8'))
+        line = line.strip()
+        mx.log(line)
+        if line == startToken:
+            _writeProcess('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken)
+        for regex in respondTo.keys():
+            match = regex.search(line)
+            if match:
+                _writeProcess(respondTo[regex])
+        if findInOutput:
+            match = findInOutput.search(line)
+            if match:
+                ret = True
+        if line == endToken:
+            if not findInOutput:
+                _writeProcess('echo ERRXXX%errorlevel%')
+            else:
+                break
+        if line.startswith('ERRXXX'):
+            if line == 'ERRXXX0':
+                ret = True
+            break
+    _writeProcess("exit")
+    if logFile:
+        log.close()
+    return ret
+
+def jdkhome(vm=None):
+    """return the JDK directory selected for the 'vm' command"""
+    return get_jvmci_jdk_dir(deployDists=False)
+
+def print_jdkhome(args, vm=None):
+    """print the JDK directory selected for the 'vm' command"""
+    print jdkhome(vm)
+
+def buildvars(args):
+    """describe the variables that can be set by the -D option to the 'mx build' commmand"""
+
+    buildVars = {
+        'ALT_BOOTDIR' : 'The location of the bootstrap JDK installation (default: ' + get_jvmci_bootstrap_jdk().home + ')',
+        'ALT_OUTPUTDIR' : 'Build directory',
+        'HOTSPOT_BUILD_JOBS' : 'Number of CPUs used by make (default: ' + str(mx.cpu_count()) + ')',
+        'INSTALL' : 'Install the built VM into the JDK? (default: y)',
+        'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)',
+    }
+
+    mx.log('HotSpot build variables that can be set by the -D option to "mx build":')
+    mx.log('')
+    for n in sorted(buildVars.iterkeys()):
+        mx.log(n)
+        mx.log(textwrap.fill(buildVars[n], initial_indent='    ', subsequent_indent='    ', width=200))
+
+    mx.log('')
+    mx.log('Note that these variables can be given persistent values in the file ' + join(_suite.mxDir, 'env') + ' (see \'mx about\').')
+
+def _hotspotReplaceResultsVar(m):
+    var = m.group(1)
+    if var == 'os':
+        return _hotspotOs(mx.get_os())
+    if var == 'nojvmci':
+        if get_vm().endswith('nojvmci'):
+            return '-nojvmci'
+        return ''
+    if var == 'buildname':
+        return _hotspotGetVariant()
+    if var == 'vmbuild':
+        return _vmbuild
+    return mx._replaceResultsVar(m)
+
+class HotSpotProject(mx.NativeProject):
+    def __init__(self, suite, name, deps, workingSets, results, output, **args):
+        mx.NativeProject.__init__(self, suite, name, "", [], deps, workingSets, results, output, join(suite.dir, "src")) # TODO...
+
+    def getOutput(self, replaceVar=_hotspotReplaceResultsVar):
+        return mx.NativeProject.getOutput(self, replaceVar=replaceVar)
+
+    def getResults(self, replaceVar=_hotspotReplaceResultsVar):
+        return mx.NativeProject.getResults(self, replaceVar=replaceVar)
+
+    def getBuildTask(self, args):
+        return HotSpotBuildTask(self, args, _vmbuild, get_vm())
+
+def _hotspotOs(mx_os):
+    if mx_os == 'darwin':
+        return 'bsd'
+    return mx_os
+
+def _hotspotGetVariant(vm=None):
+    if not vm:
+        vm = get_vm()
+    variant = {'client': 'compiler1', 'server': 'compiler2', 'client-nojvmci': 'compiler1', 'server-nojvmci': 'compiler2'}.get(vm, vm)
+    return variant
+
+"""
+Represents a JDK HotSpot version derived from a build tag such as "jdk8u66-b16".
+"""
+class JDKHotSpotVersion:
+    def __init__(self, javaCompliance, update, build):
+        self.javaCompliance = javaCompliance
+        self.update = update
+        self.build = build
+
+    @staticmethod
+    def parse_tag(tag):
+        m = re.match(r'jdk8u(\d+)-b(\d+)', tag)
+        assert m, 'unrecognized jdk8 build tag: ' + tag
+        return JDKHotSpotVersion(mx.JavaCompliance('8'), m.group(1), m.group(2))
+
+    def __str__(self):
+        return '{}_{}_{}'.format(self.javaCompliance.value, self.update, self.build)
+
+    def __cmp__(self, other):
+        assert isinstance(other, JDKHotSpotVersion), 'cannot compare a JDKHotSpotVersion object with ' + type(other)
+        return cmp(str(self), str(other))
+
+def get_jvmci_hotspot_version():
+    """
+    Gets the upstream HotSpot version JVMCI is based on.
+    """
+    vc = mx.VC.get_vc(_suite.dir, abortOnError=False)
+    assert vc, 'expected jvmci-8 to be version controlled'
+    assert isinstance(vc, mx.HgConfig), 'expected jvmci-8 VC to be Mercurial, not ' + vc.proper_name
+    lines = vc.hg_command(_suite.dir, ['log', '-r', 'keyword("Added tag jdk8u")', '--template', '{desc}\\n'], quiet=True).strip().split('\n')
+    assert lines, 'no hg commits found that match "Added tag jdk8u..."'
+    versions = [line.split()[2] for line in lines]
+    return JDKHotSpotVersion.parse_tag(sorted(versions)[-1])
+
+def get_jdk_hotspot_version(tag=mx.DEFAULT_JDK_TAG):
+    """
+    Gets the HotSpot version in the JDK selected by `tag`.
+    """
+    jdk = mx.get_jdk(tag=tag)
+    output = subprocess.check_output([jdk.java, '-version'], stderr=subprocess.STDOUT)
+    m = re.search(r'Java\(TM\) SE Runtime Environment \(build 1.8.0_(\d+)-b(\d+)\)', output)
+    return JDKHotSpotVersion(jdk.javaCompliance, m.group(1), m.group(2))
+
+class HotSpotBuildTask(mx.NativeBuildTask):
+    def __init__(self, project, args, vmbuild, vm):
+        mx.NativeBuildTask.__init__(self, args, project)
+        self.vm = vm
+        self.vmbuild = vmbuild
+
+    def __str__(self):
+        return 'Building HotSpot[{}, {}]'.format(self.vmbuild, self.vm)
+
+    def build(self):
+        isWindows = platform.system() == 'Windows' or "CYGWIN" in platform.system()
+
+        if self.vm.startswith('server'):
+            buildSuffix = ''
+        else:
+            assert self.vm.startswith('client'), self.vm
+            buildSuffix = '1'
+
+        if isWindows:
+            t_compilelogfile = mx._cygpathU2W(os.path.join(_suite.dir, "jvmciCompile.log"))
+            mksHome = mx.get_env('MKS_HOME', 'C:\\cygwin\\bin')
+
+            variant = _hotspotGetVariant(self.vm)
+            project_config = variant + '_' + self.vmbuild
+            jvmciHome = mx._cygpathU2W(_suite.dir)
+            _runInDebugShell('msbuild ' + jvmciHome + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', jvmciHome)
+            winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set JAVA_HOME=' + mx._cygpathU2W(get_jvmci_bootstrap_jdk().home) + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + jvmciHome + r'\make\windows"& call create.bat ' + jvmciHome
+            print winCompileCmd
+            winCompileSuccess = re.compile(r"^Writing \.vcxproj file:")
+            if not _runInDebugShell(winCompileCmd, jvmciHome, t_compilelogfile, winCompileSuccess):
+                mx.abort('Error executing create command')
+            winBuildCmd = 'msbuild ' + jvmciHome + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64'
+            if not _runInDebugShell(winBuildCmd, jvmciHome, t_compilelogfile):
+                mx.abort('Error building project')
+        else:
+            def filterXusage(line):
+                if not 'Xusage.txt' in line:
+                    sys.stderr.write(line + os.linesep)
+            cpus = self.parallelism
+            makeDir = join(_suite.dir, 'make')
+            runCmd = [mx.gmake_cmd(), '-C', makeDir]
+
+            env = os.environ.copy()
+
+            # These must be passed as environment variables
+            env.setdefault('LANG', 'C')
+            #env['JAVA_HOME'] = jdk
+
+            def setMakeVar(name, default, env=None):
+                """Sets a make variable on the command line to the value
+                   of the variable in 'env' with the same name if defined
+                   and 'env' is not None otherwise to 'default'
+                """
+                runCmd.append(name + '=' + (env.get(name, default) if env else default))
+
+            if self.args.D:
+                for nv in self.args.D:
+                    name, value = nv.split('=', 1)
+                    setMakeVar(name.strip(), value)
+
+            setMakeVar('ARCH_DATA_MODEL', '64', env=env)
+            setMakeVar('HOTSPOT_BUILD_JOBS', str(cpus), env=env)
+            setMakeVar('ALT_BOOTDIR', get_jvmci_bootstrap_jdk().home, env=env)
+            # setMakeVar("EXPORT_PATH", jdk)
+            if mx.get_os() == 'linux' and platform.processor() == 'sparc64':
+                # SPARC/Linux
+                setMakeVar('INCLUDE_TRACE', 'false', env=env)
+                setMakeVar('DISABLE_COMMERCIAL_FEATURES', 'true', env=env)
+
+            setMakeVar('MAKE_VERBOSE', 'y' if mx._opts.verbose else '')
+            if self.vm.endswith('nojvmci'):
+                setMakeVar('INCLUDE_JVMCI', 'false')
+                setMakeVar('ALT_OUTPUTDIR', join(_suite.dir, 'build-nojvmci', _hotspotOs(mx.get_os())), env=env)
+            else:
+                version = _suite.release_version()
+                setMakeVar('USER_RELEASE_SUFFIX', 'jvmci-' + version)
+                setMakeVar('INCLUDE_JVMCI', 'true')
+            # setMakeVar('INSTALL', 'y', env=env)
+            if mx.get_os() == 'darwin' and platform.mac_ver()[0] != '':
+                # Force use of clang on MacOS
+                setMakeVar('USE_CLANG', 'true')
+                setMakeVar('COMPILER_WARNINGS_FATAL', 'false')
+
+            if mx.get_os() == 'solaris':
+                # If using sparcWorks, setup flags to avoid make complaining about CC version
+                cCompilerVersion = subprocess.Popen('CC -V', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stderr.readlines()[0]
+                if cCompilerVersion.startswith('CC: Sun C++'):
+                    compilerRev = cCompilerVersion.split(' ')[3]
+                    setMakeVar('ENFORCE_COMPILER_REV', compilerRev, env=env)
+                    setMakeVar('ENFORCE_CC_COMPILER_REV', compilerRev, env=env)
+                    if self.vmbuild == 'jvmg':
+                        # We want ALL the symbols when debugging on Solaris
+                        setMakeVar('STRIP_POLICY', 'no_strip')
+            # This removes the need to unzip the *.diz files before debugging in gdb
+            setMakeVar('ZIP_DEBUGINFO_FILES', '0', env=env)
+
+            if buildSuffix == "1":
+                setMakeVar("BUILD_CLIENT_ONLY", "true")
+
+            # Clear this variable as having it set can cause very confusing build problems
+            env.pop('CLASSPATH', None)
+
+            # Issue an env prefix that can be used to run the make on the command line
+            if not mx._opts.verbose:
+                mx.log('--------------- make command line ----------------------')
+
+            envPrefix = ' '.join([key + '=' + env[key] for key in env.iterkeys() if not os.environ.has_key(key) or env[key] != os.environ[key]])
+            if len(envPrefix):
+                mx.log('env ' + envPrefix + ' \\')
+
+            runCmd.append(self.vmbuild + buildSuffix)
+            runCmd.append("docs")
+            # runCmd.append("export_" + build)
+
+            if not mx._opts.verbose:
+                mx.log(' '.join(runCmd))
+                mx.log('--------------------------------------------------------')
+            mx.run(runCmd, err=filterXusage, env=env)
+        self._newestOutput = None
+
+    def needsBuild(self, newestInput):
+        # Skip super (NativeBuildTask) because it always returns true
+        (superNeeds, superReason) = mx.ProjectBuildTask.needsBuild(self, newestInput)
+        if superNeeds:
+            return (superNeeds, superReason)
+        newestOutput = self.newestOutput()
+        for d in ['src', 'make', join('jvmci', 'jdk.vm.ci.hotspot', 'src_gen', 'hotspot')]:  # TODO should this be replaced by a dependency to the project?
+            for root, dirnames, files in os.walk(join(_suite.dir, d)):
+                # ignore src/share/tools
+                if root == join(_suite.dir, 'src', 'share'):
+                    dirnames.remove('tools')
+                for f in (join(root, name) for name in files):
+                    ts = mx.TimeStampFile(f)
+                    if newestOutput:
+                        if not newestOutput.exists():
+                            return (True, '{} does not exist'.format(newestOutput))
+                        if ts.isNewerThan(newestOutput):
+                            return (True, '{} is newer than {}'.format(ts, newestOutput))
+        return (False, None)
+
+    def buildForbidden(self):
+        if mx.NativeBuildTask.buildForbidden(self):
+            return True
+        if self.vm == 'original':
+            if self.vmbuild != 'product':
+                mx.log('only product build of original VM exists')
+            return True
+        if not isVMSupported(self.vm):
+            mx.log('The ' + self.vm + ' VM is not supported on this platform - skipping')
+            return True
+        return False
+
+    def clean(self, forBuild=False):
+        if forBuild:  # Let make handle incremental builds
+            return
+        def handleRemoveReadonly(func, path, exc):
+            excvalue = exc[1]
+            if mx.get_os() == 'windows' and func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
+                os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)  # 0777
+                func(path)
+            else:
+                raise
+
+        def rmIfExists(name):
+            if os.path.isdir(name):
+                shutil.rmtree(name, ignore_errors=False, onerror=handleRemoveReadonly)
+            elif os.path.isfile(name):
+                os.unlink(name)
+        nojvmci_outputdir = join(_suite.dir, 'build-nojvmci', _hotspotOs(mx.get_os()))
+        makeFiles = join(_suite.dir, 'make')
+        if mx._opts.verbose:
+            outCapture = None
+        else:
+            def _consume(s):
+                pass
+            outCapture = _consume
+        mx.run([mx.gmake_cmd(), 'ARCH_DATA_MODEL=64', 'ALT_BOOTDIR=' + get_jvmci_bootstrap_jdk().home, 'clean'], out=outCapture, cwd=makeFiles)
+        mx.run([mx.gmake_cmd(), 'ARCH_DATA_MODEL=64', 'ALT_BOOTDIR=' + get_jvmci_bootstrap_jdk().home, 'ALT_OUTPUTDIR=' + nojvmci_outputdir, 'clean'], out=outCapture, cwd=makeFiles)
+        rmIfExists(_jdksDir())
+        self._newestOutput = None
+
+def build(args, vm=None):
+    """build the VM binary
+
+    The global '--vm' and '--vmbuild' options select which VM type and build target to build."""
+
+    # Override to fail quickly if extra arguments are given
+    # at the end of the command line. This allows for a more
+    # helpful error message.
+    class AP(ArgumentParser):
+        def __init__(self):
+            ArgumentParser.__init__(self, prog='mx build')
+        def parse_args(self, args):
+            result = ArgumentParser.parse_args(self, args)
+            if len(result.remainder) != 0:
+                firstBuildTarget = result.remainder[0]
+                mx.abort('To specify the ' + firstBuildTarget + ' VM build target, you need to use the global "--vmbuild" option. For example:\n' +
+                         '    mx --vmbuild=' + firstBuildTarget + ' build')
+            return result
+
+    # Call mx.build to compile the Java sources
+    parser = AP()
+    parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value')
+
+    # initialize jdk
+    get_jvmci_jdk_dir(create=True)
+
+    mx.build(['--source', '1.7'] + args, parser=parser)
+
+mx_gate.add_jacoco_includes(['jdk.vm.ci.*'])
+
+def run_vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None):
+    """run a Java program by executing the java executable in a JVMCI JDK"""
+    jdkTag = mx.get_jdk_option().tag
+    if jdkTag and jdkTag != _JVMCI_JDK_TAG:
+        mx.abort('The "--jdk" option must have the tag "' + _JVMCI_JDK_TAG + '" when running a command requiring a JVMCI VM')
+    jdk = get_jvmci_jdk(vmbuild=vmbuild)
+    return jdk.run_java(args, vm=vm, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
+
+def _unittest_config_participant(config):
+    vmArgs, mainClass, mainClassArgs = config
+    if isJVMCIEnabled(get_vm()):
+        # Remove entries from class path that are in JVMCI loaded jars
+        cpIndex, cp = mx.find_classpath_arg(vmArgs)
+        if cp:
+            excluded = set()
+            for jdkDist in jdkDeployedDists:
+                dist = jdkDist.dist()
+                excluded.update([d.output_dir() for d in dist.archived_deps() if d.isJavaProject()])
+                excluded.add(dist.path)
+            cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded])
+            vmArgs[cpIndex] = cp
+
+        # Run the VM in a mode where application/test classes can
+        # access JVMCI loaded classes.
+        vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs
+        return (vmArgs, mainClass, mainClassArgs)
+    return config
+
+def _unittest_vm_launcher(vmArgs, mainClass, mainClassArgs):
+    run_vm(vmArgs + [mainClass] + mainClassArgs)
+
+mx_unittest.add_config_participant(_unittest_config_participant)
+
+def shortunittest(args):
+    """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'"""
+
+    args = ['--whitelist', 'test/whitelist_shortunittest.txt'] + args
+    mx_unittest.unittest(args)
+
+def buildvms(args):
+    """build one or more VMs in various configurations"""
+
+    vmsDefault = ','.join(_vmChoices.keys())
+    vmbuildsDefault = ','.join(_vmbuildChoices)
+
+    parser = ArgumentParser(prog='mx buildvms')
+    parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='<args>', default=vmsDefault)
+    parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='<args>', default=vmbuildsDefault)
+    parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build')
+    parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file')
+
+    args = parser.parse_args(args)
+    vms = args.vms.split(',')
+    builds = args.builds.split(',')
+
+    allStart = time.time()
+    for vm in vms:
+        if not isVMSupported(vm):
+            mx.log('The ' + vm + ' VM is not supported on this platform - skipping')
+            continue
+
+        for vmbuild in builds:
+            if vm == 'original' and vmbuild != 'product':
+                continue
+            if not args.console:
+                logFile = join(vm + '-' + vmbuild + '.log')
+                log = open(join(_suite.dir, logFile), 'wb')
+                start = time.time()
+                mx.log('BEGIN: ' + vm + '-' + vmbuild + '\t(see: ' + logFile + ')')
+                verbose = ['-v'] if mx._opts.verbose else []
+                # Run as subprocess so that output can be directed to a file
+                cmd = [sys.executable, '-u', mx.__file__] + verbose + ['--vm=' + vm, '--vmbuild=' + vmbuild, 'build']
+                mx.logv("executing command: " + str(cmd))
+                subprocess.check_call(cmd, cwd=_suite.dir, stdout=log, stderr=subprocess.STDOUT)
+                duration = datetime.timedelta(seconds=time.time() - start)
+                mx.log('END:   ' + vm + '-' + vmbuild + '\t[' + str(duration) + ']')
+            else:
+                with VM(vm, vmbuild):
+                    build([])
+            if not args.no_check:
+                vmargs = ['-version']
+                run_vm(vmargs, vm=vm, vmbuild=vmbuild)
+    allDuration = datetime.timedelta(seconds=time.time() - allStart)
+    mx.log('TOTAL TIME:   ' + '[' + str(allDuration) + ']')
+
+
+def _jvmci_gate_runner(args, tasks):
+    # Build server-jvmci now so we can run the unit tests
+    with Task('BuildHotSpotJVMCI: product', tasks) as t:
+        if t: buildvms(['--vms', 'server', '--builds', 'product'])
+
+    # Run unit tests on server-hosted-jvmci
+    with VM('server', 'product'):
+        with JVMCIMode('hosted'):
+            with Task('JVMCI UnitTests: hosted-product', tasks) as t:
+                if t: unittest(['--suite', 'jvmci', '--enable-timing', '--verbose', '--fail-fast'])
+
+    # Build the fastdebug VM
+    with Task('BuildHotSpotJVMCI: fastdebug', tasks) as t:
+        if t:
+            buildvms(['--vms', 'server', '--builds', 'fastdebug'])
+            run_vm(['-XX:+ExecuteInternalVMTests', '-version'], vm='server', vmbuild='fastdebug')
+
+    with Task('CleanAndBuildIdealGraphVisualizer', tasks, disableJacoco=True) as t:
+        if t and platform.processor() != 'sparc':
+            buildxml = mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'))
+            mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=_igvBuildEnv())
+
+    # Prevent JVMCI modifications from breaking the standard builds
+    if args.buildNonJVMCI:
+        with Task('BuildHotSpotVarieties', tasks, disableJacoco=True) as t:
+            if t:
+                buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product'])
+
+mx_gate.add_gate_runner(_suite, _jvmci_gate_runner)
+mx_gate.add_gate_argument('-g', '--only-build-jvmci', action='store_false', dest='buildNonJVMCI', help='only build the JVMCI VM')
+
+def deoptalot(args):
+    """bootstrap a VM with DeoptimizeALot and VerifyOops on
+
+    If the first argument is a number, the process will be repeated
+    this number of times. All other arguments are passed to the VM."""
+    count = 1
+    if len(args) > 0 and args[0].isdigit():
+        count = int(args[0])
+        del args[0]
+
+    for _ in range(count):
+        if not run_vm(['-XX:-TieredCompilation', '-XX:+DeoptimizeALot', '-XX:+VerifyOops'] + args + ['-version']) == 0:
+            mx.abort("Failed")
+
+def longtests(args):
+
+    deoptalot(['15', '-Xmx48m'])
+
+def _igvJdk():
+    v8u20 = mx.VersionSpec("1.8.0_20")
+    v8u40 = mx.VersionSpec("1.8.0_40")
+    v8 = mx.VersionSpec("1.8")
+    def _igvJdkVersionCheck(version):
+        return version >= v8 and (version < v8u20 or version >= v8u40)
+    return mx.get_jdk(_igvJdkVersionCheck, versionDescription='>= 1.8 and < 1.8.0u20 or >= 1.8.0u40', purpose="building & running IGV").home
+
+def _igvBuildEnv():
+        # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs
+    env = dict(os.environ)
+    proxy = os.environ.get('http_proxy')
+    if not (proxy is None) and len(proxy) > 0:
+        if '://' in proxy:
+            # Remove the http:// prefix (or any other protocol prefix)
+            proxy = proxy.split('://', 1)[1]
+        # Separate proxy server name and port number
+        proxyName, proxyPort = proxy.split(':', 1)
+        proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort
+        env['ANT_OPTS'] = proxyEnv
+
+    env['JAVA_HOME'] = _igvJdk()
+    return env
+
+def igv(args):
+    """run the Ideal Graph Visualizer"""
+    logFile = join(_suite.dir, '.ideal_graph_visualizer.log')
+    with open(logFile, 'w') as fp:
+        mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']')
+        nbplatform = join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')
+
+        # Remove NetBeans platform if it is earlier than the current supported version
+        if exists(nbplatform):
+            updateTrackingFile = join(nbplatform, 'platform', 'update_tracking', 'org-netbeans-core.xml')
+            if not exists(updateTrackingFile):
+                mx.log('Could not find \'' + updateTrackingFile + '\', removing NetBeans platform')
+                shutil.rmtree(nbplatform)
+            else:
+                dom = xml.dom.minidom.parse(updateTrackingFile)
+                currentVersion = mx.VersionSpec(dom.getElementsByTagName('module_version')[0].getAttribute('specification_version'))
+                supportedVersion = mx.VersionSpec('3.43.1')
+                if currentVersion < supportedVersion:
+                    mx.log('Replacing NetBeans platform version ' + str(currentVersion) + ' with version ' + str(supportedVersion))
+                    shutil.rmtree(nbplatform)
+                elif supportedVersion < currentVersion:
+                    mx.log('Supported NetBeans version in igv command should be updated to ' + str(currentVersion))
+
+        if not exists(nbplatform):
+            mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]')
+
+        env = _igvBuildEnv()
+        # make the jar for Batik 1.7 available.
+        env['IGV_BATIK_JAR'] = mx.library('BATIK').get_path(True)
+        if mx.run(['ant', '-f', mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')), '-l', mx._cygpathU2W(fp.name), 'run'], env=env, nonZeroIsFatal=False):
+            mx.abort("IGV ant build & launch failed. Check '" + logFile + "'. You can also try to delete " + join(_suite.dir, 'src/share/tools/IdealGraphVisualizer/nbplatform') + ".")
+
+def c1visualizer(args):
+    """run the Cl Compiler Visualizer"""
+    extractPath = join(_suite.get_output_root())
+    if mx.get_os() == 'windows':
+        executable = join(extractPath, 'c1visualizer', 'bin', 'c1visualizer.exe')
+    else:
+        executable = join(extractPath, 'c1visualizer', 'bin', 'c1visualizer')
+
+    # Check whether the current C1Visualizer installation is up-to-date
+    if exists(executable) and not exists(mx.library('C1VISUALIZER_DIST').get_path(resolve=False)):
+        mx.log('Updating C1Visualizer')
+        shutil.rmtree(join(extractPath, 'c1visualizer'))
+
+    archive = mx.library('C1VISUALIZER_DIST').get_path(resolve=True)
+
+    if not exists(executable):
+        zf = zipfile.ZipFile(archive, 'r')
+        zf.extractall(extractPath)
+
+    if not exists(executable):
+        mx.abort('C1Visualizer binary does not exist: ' + executable)
+
+    if mx.get_os() != 'windows':
+        # Make sure that execution is allowed. The zip file does not always specfiy that correctly
+        os.chmod(executable, 0777)
+
+    mx.run([executable])
+
+
+def hsdis(args, copyToDir=None):
+    """download the hsdis library
+
+    This is needed to support HotSpot's assembly dumping features.
+    By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax."""
+    flavor = None
+    if mx.get_arch() == "amd64":
+        flavor = 'intel'
+        if 'att' in args:
+            flavor = 'att'
+
+    libpattern = mx.add_lib_suffix('hsdis-' + mx.get_arch() + '-' + mx.get_os() + '-%s')
+
+    sha1s = {
+        'att/hsdis-amd64-windows-%s.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72',
+        'att/hsdis-amd64-linux-%s.so' : '36a0b8e30fc370727920cc089f104bfb9cd508a0',
+        'att/hsdis-amd64-darwin-%s.dylib' : 'c1865e9a58ca773fdc1c5eea0a4dfda213420ffb',
+        'intel/hsdis-amd64-windows-%s.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30',
+        'intel/hsdis-amd64-linux-%s.so' : '0d031013db9a80d6c88330c42c983fbfa7053193',
+        'intel/hsdis-amd64-darwin-%s.dylib' : '67f6d23cbebd8998450a88b5bef362171f66f11a',
+        'hsdis-sparcv9-solaris-%s.so': '970640a9af0bd63641f9063c11275b371a59ee60',
+        'hsdis-sparcv9-linux-%s.so': '0c375986d727651dee1819308fbbc0de4927d5d9',
+    }
+
+    if flavor:
+        flavoredLib = flavor + "/" + libpattern
+    else:
+        flavoredLib = libpattern
+    if flavoredLib not in sha1s:
+        mx.warn("hsdis with flavor '{}' not supported on this plattform or architecture".format(flavor))
+        return
+
+    sha1 = sha1s[flavoredLib]
+    lib = flavoredLib % (sha1)
+    path = join(_suite.get_output_root(), lib)
+    if not exists(path):
+        sha1path = path + '.sha1'
+        mx.download_file_with_sha1('hsdis', path, ['https://lafo.ssw.uni-linz.ac.at/pub/hsdis/' + lib], sha1, sha1path, True, True, sources=False)
+    if copyToDir is not None and exists(copyToDir):
+        destFileName = mx.add_lib_suffix('hsdis-' + mx.get_arch())
+        shutil.copy(path, copyToDir + os.sep + destFileName)
+
+def hcfdis(args):
+    """disassemble HexCodeFiles embedded in text files
+
+    Run a tool over the input files to convert all embedded HexCodeFiles
+    to a disassembled format."""
+
+    parser = ArgumentParser(prog='mx hcfdis')
+    parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output')
+    parser.add_argument('files', nargs=REMAINDER, metavar='files...')
+
+    args = parser.parse_args(args)
+
+    path = mx.library('HCFDIS').get_path(resolve=True)
+    mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files)
+
+    if args.map is not None:
+        addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)')
+        with open(args.map) as fp:
+            lines = fp.read().splitlines()
+        symbols = dict()
+        for l in lines:
+            addressAndSymbol = l.split(' ', 1)
+            if len(addressAndSymbol) == 2:
+                address, symbol = addressAndSymbol
+                if address.startswith('0x'):
+                    address = long(address, 16)
+                    symbols[address] = symbol
+        for f in args.files:
+            with open(f) as fp:
+                lines = fp.read().splitlines()
+            updated = False
+            for i in range(0, len(lines)):
+                l = lines[i]
+                for m in addressRE.finditer(l):
+                    sval = m.group(0)
+                    val = long(sval, 16)
+                    sym = symbols.get(val)
+                    if sym:
+                        l = l.replace(sval, sym)
+                        updated = True
+                        lines[i] = l
+            if updated:
+                mx.log('updating ' + f)
+                with open('new_' + f, "w") as fp:
+                    for l in lines:
+                        print >> fp, l
+
+def isJVMCIEnabled(vm):
+    return vm != 'original' and not vm.endswith('nojvmci')
+
+def jol(args):
+    """Java Object Layout"""
+    joljar = mx.library('JOL_INTERNALS').get_path(resolve=True)
+    candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s))
+
+    if len(candidates) > 0:
+        candidates = mx.select_items(sorted(candidates))
+    else:
+        # mx.findclass can be mistaken, don't give up yet
+        candidates = args
+
+    run_vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(jdk=get_jvmci_jdk()), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates)
+
+def deploy_binary(args):
+    for vmbuild in ['product', 'fastdebug']:
+        for vm in ['server']:
+            if vmbuild != _vmbuild or vm != get_vm():
+                mx.instantiateDistribution('JVM_<vmbuild>_<vm>', dict(vmbuild=vmbuild, vm=vm))
+    mx.deploy_binary(args)
+
+mx.update_commands(_suite, {
+    'build': [build, ''],
+    'buildvars': [buildvars, ''],
+    'buildvms': [buildvms, '[-options]'],
+    'c1visualizer' : [c1visualizer, ''],
+    'deploy-binary' : [deploy_binary, ''],
+    'export': [export, '[-options] [zipfile]'],
+    'hsdis': [hsdis, '[att]'],
+    'hcfdis': [hcfdis, ''],
+    'igv' : [igv, ''],
+    'jdkhome': [print_jdkhome, ''],
+    'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix],
+    'vm': [run_vm, '[-options] class [args...]'],
+    'deoptalot' : [deoptalot, '[n]'],
+    'longtests' : [longtests, ''],
+    'jol' : [jol, ''],
+})
+
+mx.add_argument('--vmcwd', dest='vm_cwd', help='current directory will be changed to <path> before the VM is executed', default=None, metavar='<path>')
+mx.add_argument('--installed-jdks', help='the base directory in which the JDKs cloned from $JAVA_HOME exist. ' +
+                'The VM selected by --vm and --vmbuild options is under this directory (i.e., ' +
+                join('<path>', '<jdk-version>', '<vmbuild>', 'jre', 'lib', '<vm>', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='<path>')
+
+mx.add_argument('-M', '--jvmci-mode', action='store', dest='jvmci_mode', choices=_jvmciModes.keys(), help='the JVMCI mode to use (default: ' + _jvmciMode.jvmciMode + ')')
+mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys() + _vmAliases.keys(), help='the VM type to build/run')
+mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')')
+mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')
+mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='<prefix>')
+mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"')
+mx.add_argument('--lldb', action='store_const', const='lldb --', dest='vm_prefix', help='alias for --vmprefix "lldb --"')
+
+_jvmci_bootstrap_jdk = None
+
+def get_jvmci_bootstrap_jdk():
+    """
+    Gets the JDK from which a JVMCI JDK is created.
+    """
+    global _jvmci_bootstrap_jdk
+    if not _jvmci_bootstrap_jdk:
+        def _versionCheck(version):
+            return version >= _minVersion and ((not _untilVersion) or version < _untilVersion)
+        versionDesc = ">=" + str(_minVersion)
+        if _untilVersion:
+            versionDesc += " and <" + str(_untilVersion)
+        _jvmci_bootstrap_jdk = mx.get_jdk(_versionCheck, versionDescription=versionDesc, tag='default')
+    return _jvmci_bootstrap_jdk
+
+_jvmci_bootclasspath_prepends = []
+
+def add_bootclasspath_prepend(dep):
+    assert isinstance(dep, mx.ClasspathDependency)
+    _jvmci_bootclasspath_prepends.append(dep)
+
+class JVMCI8JDKConfig(mx.JDKConfig):
+    def __init__(self, vmbuild):
+        # Ignore the deployable distributions here - they are only deployed during building.
+        # This significantly reduces the latency of the "mx java" command.
+        self.vmbuild = vmbuild
+        jdkDir = get_jvmci_jdk_dir(build=self.vmbuild, create=True, deployDists=False)
+        mx.JDKConfig.__init__(self, jdkDir, tag=_JVMCI_JDK_TAG)
+
+    def parseVmArgs(self, args, addDefaultArgs=True):
+        args = mx.expand_project_in_args(args, insitu=False)
+        jacocoArgs = mx_gate.get_jacoco_agent_args()
+        if jacocoArgs:
+            args = jacocoArgs + args
+
+        args = ['-Xbootclasspath/p:' + dep.classpath_repr() for dep in _jvmci_bootclasspath_prepends] + args
+
+        if '-version' in args:
+            ignoredArgs = args[args.index('-version') + 1:]
+            if  len(ignoredArgs) > 0:
+                mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
+        return self.processArgs(args, addDefaultArgs=addDefaultArgs)
+
+    # Overrides JDKConfig
+    def run_java(self, args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, env=None, addDefaultArgs=True):
+        if vm is None:
+            vm = get_vm()
+
+        if not isVMSupported(vm):
+            mx.abort('The ' + vm + ' is not supported on this platform')
+
+        if cwd is None:
+            cwd = _vm_cwd
+        elif _vm_cwd is not None and _vm_cwd != cwd:
+            mx.abort("conflicting working directories: do not set --vmcwd for this command")
+
+        args = self.parseVmArgs(args, addDefaultArgs=addDefaultArgs)
+        if _make_eclipse_launch:
+            mx.make_eclipse_launch(_suite, args, _suite.name + '-' + build, name=None, deps=mx.dependencies())
+
+        pfx = _vm_prefix.split() if _vm_prefix is not None else []
+        if not vm.endswith('nojvmci'):
+            args = get_jvmci_mode_args() + args
+        cmd = pfx + [self.java] + ['-' + vm] + args
+        return mx.run(cmd, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
+
+"""
+The dict of JVMCI JDKs indexed by vmbuild names.
+"""
+_jvmci_jdks = {}
+
+def get_jvmci_jdk(vmbuild=None):
+    """
+    Gets the JVMCI JDK corresponding to 'vmbuild'.
+    """
+    if not vmbuild:
+        vmbuild = _vmbuild
+    jdk = _jvmci_jdks.get(vmbuild)
+    if jdk is None:
+        jdk = JVMCI8JDKConfig(vmbuild)
+        _jvmci_jdks[vmbuild] = jdk
+    return jdk
+
+mx_unittest.set_vm_launcher('JVMCI VM launcher', _unittest_vm_launcher, get_jvmci_jdk)
+
+class JVMCI8JDKFactory(mx.JDKFactory):
+    def getJDKConfig(self):
+        jdk = get_jvmci_jdk(_vmbuild)
+        check_VM_exists(get_vm(), jdk.home)
+        return jdk
+
+    def description(self):
+        return "JVMCI JDK"
+
+mx.addJDKFactory(_JVMCI_JDK_TAG, mx.JavaCompliance('8'), JVMCI8JDKFactory())
+
+def mx_post_parse_cmd_line(opts):
+    mx.set_java_command_default_jdk_tag(_JVMCI_JDK_TAG)
+
+    # Execute for the side-effect of checking that the
+    # boot strap JDK has a compatible version
+    get_jvmci_bootstrap_jdk()
+
+    jdkTag = mx.get_jdk_option().tag
+    if hasattr(opts, 'vm') and opts.vm is not None:
+        global _vm
+        _vm = dealiased_vm(opts.vm)
+        if jdkTag and jdkTag != _JVMCI_JDK_TAG:
+            mx.warn('Ignoring "--vm" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"')
+    if opts.jvmci_mode is not None:
+        global _jvmciMode
+        _jvmciMode = JVMCIMode(opts.jvmci_mode)
+    if hasattr(opts, 'vmbuild') and opts.vmbuild is not None:
+        global _vmbuild
+        _vmbuild = opts.vmbuild
+        if jdkTag and jdkTag != _JVMCI_JDK_TAG:
+            mx.warn('Ignoring "--vmbuild" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"')
+
+    global _make_eclipse_launch
+    _make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False)
+    global _vm_cwd
+    _vm_cwd = opts.vm_cwd
+    global _installed_jdks
+    _installed_jdks = opts.installed_jdks
+    global _vm_prefix
+    _vm_prefix = opts.vm_prefix
+
+    mx.instantiateDistribution('JVM_<vmbuild>_<vm>', dict(vmbuild=_vmbuild, vm=get_vm()))
+
+    for jdkDist in jdkDeployedDists:
+        jdkDist.post_parse_cmd_line()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx.jvmci/suite.py	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,329 @@
+suite = {
+  "mxversion" : "5.33.1",
+  "name" : "jvmci",
+  "url" : "http://openjdk.java.net/projects/graal",
+  "developer" : {
+    "name" : "Truffle and Graal developers",
+    "email" : "graal-dev@openjdk.java.net",
+    "organization" : "Graal",
+    "organizationUrl" : "http://openjdk.java.net/projects/graal",
+  },
+  "repositories" : {
+    "lafo-snapshots" : {
+      "url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots",
+      "licenses" : ["GPLv2-CPE", "UPL"]
+    },
+  },
+
+  "licenses" : {
+    "UPL" : {
+      "name" : "Universal Permissive License, Version 1.0",
+      "url" : "http://opensource.org/licenses/UPL",
+    }
+  },
+
+  "defaultLicense" : "GPLv2-CPE",
+
+    # ------------- Libraries -------------
+
+  "libraries" : {
+
+    # ------------- Libraries -------------
+
+    "HCFDIS" : {
+      "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/hcfdis-3.jar"],
+      "sha1" : "a71247c6ddb90aad4abf7c77e501acc60674ef57",
+    },
+
+    "C1VISUALIZER_DIST" : {
+      "urls" : ["https://java.net/downloads/c1visualizer/c1visualizer_2015-07-22.zip"],
+      "sha1" : "7ead6b2f7ed4643ef4d3343a5562e3d3f39564ac",
+    },
+
+    "JOL_INTERNALS" : {
+      "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/truffle/jol/jol-internals.jar"],
+      "sha1" : "508bcd26a4d7c4c44048990c6ea789a3b11a62dc",
+    },
+
+    "BATIK" : {
+      "sha1" : "122b87ca88e41a415cf8b523fd3d03b4325134a3",
+      "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/batik-all-1.7.jar"],
+    },
+  },
+
+  "jrelibraries" : {
+    "JFR" : {
+      "jar" : "jfr.jar",
+    }
+  },
+
+  "projects" : {
+
+    # ------------- JVMCI:Service -------------
+
+    "jdk.vm.ci.services" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,JVMCI",
+    },
+
+    # ------------- JVMCI:API -------------
+
+    "jdk.vm.ci.common" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,JVMCI",
+    },
+
+    "jdk.vm.ci.meta" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,JVMCI",
+    },
+
+    "jdk.vm.ci.code" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : ["jdk.vm.ci.meta"],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,JVMCI",
+    },
+
+    "jdk.vm.ci.runtime" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "jdk.vm.ci.code",
+      ],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,JVMCI",
+    },
+
+    "jdk.vm.ci.runtime.test" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "mx:JUNIT",
+        "jdk.vm.ci.common",
+        "jdk.vm.ci.runtime",
+      ],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,JVMCI",
+    },
+
+    # ------------- JVMCI:HotSpot -------------
+
+    "jdk.vm.ci.aarch64" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : ["jdk.vm.ci.code"],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI,AArch64",
+    },
+
+    "jdk.vm.ci.amd64" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : ["jdk.vm.ci.code"],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI,AMD64",
+    },
+
+    "jdk.vm.ci.sparc" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : ["jdk.vm.ci.code"],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI,SPARC",
+    },
+
+    "jdk.vm.ci.hotspot" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "jdk.vm.ci.services",
+        "jdk.vm.ci.common",
+        "jdk.vm.ci.runtime",
+      ],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI",
+    },
+
+    "jdk.vm.ci.hotspot.aarch64" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "jdk.vm.ci.aarch64",
+        "jdk.vm.ci.hotspot",
+      ],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI,HotSpot,AArch64",
+    },
+
+    "jdk.vm.ci.hotspot.amd64" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "jdk.vm.ci.amd64",
+        "jdk.vm.ci.hotspot",
+      ],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI,HotSpot,AMD64",
+    },
+
+    "jdk.vm.ci.hotspot.sparc" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "jdk.vm.ci.sparc",
+        "jdk.vm.ci.hotspot",
+      ],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI,HotSpot,SPARC",
+    },
+
+    "jdk.vm.ci.hotspot.jfr" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "jdk.vm.ci.hotspot",
+        "JFR",
+      ],
+      "checkstyle" : "jdk.vm.ci.services",
+      "javaCompliance" : "1.8",
+      "profile" : "",
+      "workingSets" : "JVMCI,HotSpot",
+    },
+
+    "hotspot" : {
+      "native" : True,
+      "dependencies" : [
+        "jdk.vm.ci.hotspot",
+      ],
+      "class" : "HotSpotProject",
+      "output" : "build<nojvmci>",
+      # vs-<arch>/<buildname>/generated/jvmtifiles/jvmti.h
+      # vs-<arch>/<buildname>/<vmbuild>/<lib:jvm>
+      # vs-<arch>/<buildname>/<vmbuild>/<libdebug:jvm>
+      "os_arch" : {
+        "windows" : {
+          "<others>" : {
+            "results" : [
+              'vs-<arch>/<buildname>/generated/jvmtifiles/jvmti.h',
+              'vs-<arch>/<buildname>/<vmbuild>/<lib:jvm>',
+              'vs-<arch>/<buildname>/<vmbuild>/<libdebug:jvm>',
+            ]
+          }
+        },
+        "<others>": {
+          "<others>" : {
+            "results" : [
+              '<os>/<os>_<arch>_<buildname>/generated/jvmtifiles/jvmti.h',
+              '<os>/<os>_<arch>_<buildname>/generated/sa-jdi.jar',
+              '<os>/<os>_<arch>_<buildname>/<vmbuild>/<lib:jvm>',
+              '<os>/<os>_<arch>_<buildname>/<vmbuild>/<libdebug:jvm>',
+              '<os>/<os>_<arch>_<buildname>/<vmbuild>/<lib:saproc>',
+              '<os>/<os>_<arch>_<buildname>/<vmbuild>/<libdebug:saproc>',
+              '<os>/<os>_<arch>_<buildname>/<vmbuild>/<lib:jsig>',
+              '<os>/<os>_<arch>_<buildname>/<vmbuild>/<libdebug:jsig>',
+            ]
+          }
+        },
+      },
+    }
+  },
+
+  "distributions" : {
+
+    # ------------- Distributions -------------
+
+    "JVM_<vmbuild>_<vm>" : {
+      "dependencies" : ["hotspot"],
+      "native" : True,
+      "os_arch" : {
+        "linux" : {
+          "amd64" : {
+            "path" : "build/<vmbuild>/linux/amd64/<vm>/jvm.tar",
+          },
+          "sparcv9" : {
+            "path" : "build/<vmbuild>/linux/sparcv9/<vm>/jvm.tar",
+          }
+        },
+        "darwin" : {
+          "amd64" : {
+            "path" : "build/<vmbuild>/darwin/amd64/<vm>/jvm.tar",
+          }
+        },
+        "windows" : {
+          "amd64" : {
+            "path" : "build/<vmbuild>/windows/amd64/<vm>/jvm.tar",
+          }
+        },
+        "solaris" : {
+          "sparcv9" : {
+            "path" : "build/<vmbuild>/solaris/sparcv9/<vm>/jvm.tar",
+          }
+        },
+      },
+    },
+
+    "JVMCI_SERVICES" : {
+      "subDir" : "jvmci",
+      "dependencies" : ["jdk.vm.ci.services"],
+    },
+
+    "JVMCI_API" : {
+      "subDir" : "jvmci",
+      "dependencies" : [
+        "jdk.vm.ci.runtime",
+        "jdk.vm.ci.common",
+        "jdk.vm.ci.aarch64",
+        "jdk.vm.ci.amd64",
+        "jdk.vm.ci.sparc",
+      ],
+      "distDependencies" : [
+        "JVMCI_SERVICES",
+      ],
+    },
+
+    "JVMCI_HOTSPOT" : {
+      "subDir" : "jvmci",
+      "dependencies" : [
+        "jdk.vm.ci.hotspot.aarch64",
+        "jdk.vm.ci.hotspot.amd64",
+        "jdk.vm.ci.hotspot.sparc",
+        "jdk.vm.ci.hotspot.jfr",
+      ],
+      "distDependencies" : [
+        "JVMCI_SERVICES",
+        "JVMCI_API",
+      ],
+    },
+
+    "JVMCI_TEST" : {
+      "subDir" : "jvmci",
+      "dependencies" : [
+        "jdk.vm.ci.runtime.test",
+      ],
+      "distDependencies" : [
+        "JVMCI_API",
+      ],
+      "exclude" : ["mx:JUNIT"],
+    },
+  },
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/ppc/vm/jvmciGlobals_ppc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_PPC_VM_GRAALGLOBALS_PPC_HPP
+#define CPU_PPC_VM_GRAALGLOBALS_PPC_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+// Sets the default values for platform dependent flags used by the JVMCI compiler.
+// (see jvmciGlobals.hpp)
+
+#if INCLUDE_JVMCI
+#error Unimplemented
+#endif // INCLUDE_JVMCI
+
+#endif // CPU_PPC_VM_JVMCIGLOBALS_PPC_HPP
--- a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2856,7 +2856,7 @@
   __ set_last_Java_frame(R1_SP, noreg);
 
   // With EscapeAnalysis turned on, this call may safepoint!
-  __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), R16_thread);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), R16_thread, exec_mode_reg);
   address calls_return_pc = __ last_calls_return_pc();
   // Set an oopmap for the call site that describes all our saved registers.
   oop_maps->add_gc_map(calls_return_pc - start, map);
@@ -2869,6 +2869,8 @@
   // by save_volatile_registers(...).
   RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes);
 
+  // reload the exec mode from the UnrollBlock (it might have changed)
+  __ lwz(exec_mode_reg, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes(), unroll_block_reg);
   // In excp_deopt_mode, restore and clear exception oop which we
   // stored in the thread during exception entry above. The exception
   // oop will be the return value of this stub.
@@ -3004,8 +3006,9 @@
   __ set_last_Java_frame(/*sp*/R1_SP, /*pc*/R11_scratch1);
 
   __ mr(klass_index_reg, R3);
+  __ li(R5, Deoptimization::Unpack_exception);
   __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap),
-                  R16_thread, klass_index_reg);
+                  R16_thread, klass_index_reg, R5);
 
   // Set an oopmap for the call site.
   oop_maps->add_gc_map(gc_map_pc - start, map);
@@ -3025,6 +3028,12 @@
 
   // stack: (caller_of_deoptee, ...).
 
+#ifdef ASSERT
+  __ lwz(R22_tmp2, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes(), unroll_block_reg);
+  __ cmpdi(CCR0, R22_tmp2, Deoptimization::Unpack_uncommon_trap);
+  __ asm_assert_eq("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap", 0);
+#endif
+
   // Allocate new interpreter frame(s) and possibly a c2i adapter
   // frame.
   push_skeleton_frames(masm, false/*deopt*/,
--- a/src/cpu/ppc/vm/templateInterpreter_ppc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/ppc/vm/templateInterpreter_ppc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -192,7 +192,7 @@
   return entry;
 }
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
+address InterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
   address entry = __ pc();
   // If state != vtos, we're returning from a native method, which put it's result
   // into the result register. So move the value out of the return register back
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1610,10 +1610,9 @@
 
 int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
   __ set((intptr_t)os::get_polling_page(), tmp->as_register());
+  __ relocate(relocInfo::poll_type);
   if (info != NULL) {
     add_debug_info_for_branch(info);
-  } else {
-    __ relocate(relocInfo::poll_type);
   }
 
   int offset = __ offset();
@@ -3050,8 +3049,10 @@
   Bytecodes::Code bc = method->java_code_at_bci(bci);
   const bool callee_is_static = callee->is_loaded() && callee->is_static();
   // Perform additional virtual call profiling for invokevirtual and
-  // invokeinterface bytecodes
-  if ((bc == Bytecodes::_invokevirtual || bc == Bytecodes::_invokeinterface) &&
+  // invokeinterface bytecodes.  For invokevirtual don't update the profile if
+  // the method can_be_statically_bound().  See
+  // InterpreterMacroAssembler::profile_final_call.
+  if (((bc == Bytecodes::_invokevirtual && !callee->can_be_statically_bound()) || bc == Bytecodes::_invokeinterface) &&
       !callee_is_static &&  // required for optimized MH invokes
       C1ProfileVirtualCalls) {
     assert(op->recv()->is_single_cpu(), "recv must be allocated");
--- a/src/cpu/sparc/vm/c1_globals_sparc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/c1_globals_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -56,6 +56,7 @@
 define_pd_global(intx, NewSizeThreadIncrease,        16*K );
 define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
 define_pd_global(intx, InitialCodeCacheSize,         160*K);
+define_pd_global(intx, TypeProfileWidth,             0);
 #endif // !TIERED
 
 define_pd_global(bool, UseTypeProfile,               false);
--- a/src/cpu/sparc/vm/c2_globals_sparc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -37,6 +37,7 @@
 define_pd_global(bool, PreferInterpreterNativeStubs, false);
 define_pd_global(bool, ProfileTraps,                 true);
 define_pd_global(bool, UseOnStackReplacement,        true);
+define_pd_global(intx, TypeProfileWidth,             2   );
 #ifdef CC_INTERP
 define_pd_global(bool, ProfileInterpreter,           false);
 #else
--- a/src/cpu/sparc/vm/compiledIC_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/compiledIC_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -53,14 +53,15 @@
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
-#ifdef COMPILER2
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
   // Stub is fixed up when the corresponding call is converted from calling
   // compiled code to calling interpreted code.
   // set (empty), G5
   // jmp -1
 
-  address mark = cbuf.insts_mark();  // Get mark within main instrs section.
+  if (mark == NULL) {
+    mark = cbuf.insts_mark();  // Get mark within main instrs section.
+  }
 
   MacroAssembler _masm(&cbuf);
 
@@ -72,7 +73,7 @@
   // Static stub relocation stores the instruction address of the call.
   __ relocate(static_stub_Relocation::spec(mark));
 
-  __ set_metadata(NULL, as_Register(Matcher::inline_cache_reg_encode()));
+  __ set_metadata(NULL, G5);
 
   __ set_inst_mark();
   AddressLiteral addrlit(-1);
@@ -80,12 +81,11 @@
 
   __ delayed()->nop();
 
+  assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size");
+
   // Update current stubs pointer and restore code_end.
   __ end_a_stub();
   return base;
-#else
-  ShouldNotReachHere();
-#endif
 }
 #undef __
 
--- a/src/cpu/sparc/vm/interp_masm_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1691,26 +1691,73 @@
     bind(skip_receiver_profile);
 
     // The method data pointer needs to be updated to reflect the new target.
+#if INCLUDE_JVMCI
+    if (MethodProfileWidth == 0) {
+      update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
+    }
+#else
     update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
-    bind (profile_continue);
+#endif
+    bind(profile_continue);
   }
 }
 
-void InterpreterMacroAssembler::record_klass_in_profile_helper(
-                                        Register receiver, Register scratch,
-                                        int start_row, Label& done, bool is_virtual_call) {
+#if INCLUDE_JVMCI
+void InterpreterMacroAssembler::profile_called_method(Register method, Register scratch) {
+  assert_different_registers(method, scratch);
+  if (ProfileInterpreter && MethodProfileWidth > 0) {
+    Label profile_continue;
+
+    // If no method data exists, go to profile_continue.
+    test_method_data_pointer(profile_continue);
+
+    Label done;
+    record_item_in_profile_helper(method, scratch, 0, done, MethodProfileWidth,
+      &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset()));
+    bind(done);
+
+    update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
+    bind(profile_continue);
+  }
+}
+#endif
+
+void InterpreterMacroAssembler::record_klass_in_profile_helper(Register receiver, Register scratch,
+                                                               Label& done, bool is_virtual_call) {
   if (TypeProfileWidth == 0) {
     if (is_virtual_call) {
       increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch);
     }
-    return;
+#if INCLUDE_JVMCI
+    else if (EnableJVMCI) {
+      increment_mdp_data_at(in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()), scratch);
+    }
+#endif
+  } else {
+    int non_profiled_offset = -1;
+    if (is_virtual_call) {
+      non_profiled_offset = in_bytes(CounterData::count_offset());
+    }
+#if INCLUDE_JVMCI
+    else if (EnableJVMCI) {
+      non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
+    }
+#endif
+
+    record_item_in_profile_helper(receiver, scratch, 0, done, TypeProfileWidth,
+      &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset);
   }
-
-  int last_row = VirtualCallData::row_limit() - 1;
+}
+
+void InterpreterMacroAssembler::record_item_in_profile_helper(Register item,
+                                          Register scratch, int start_row, Label& done, int total_rows,
+                                          OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+                                          int non_profiled_offset) {
+  int last_row = total_rows - 1;
   assert(start_row <= last_row, "must be work left to do");
-  // Test this row for both the receiver and for null.
+  // Test this row for both the item and for null.
   // Take any of three different outcomes:
-  //   1. found receiver => increment count and goto done
+  //   1. found item => increment count and goto done
   //   2. found null => keep looking for case 1, maybe allocate this cell
   //   3. found something else => keep looking for cases 1 and 2
   // Case 3 is handled by a recursive call.
@@ -1718,28 +1765,28 @@
     Label next_test;
     bool test_for_null_also = (row == start_row);
 
-    // See if the receiver is receiver[n].
-    int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row));
-    test_mdp_data_at(recvr_offset, receiver, next_test, scratch);
+    // See if the item is item[n].
+    int item_offset = in_bytes(item_offset_fn(row));
+    test_mdp_data_at(item_offset, item, next_test, scratch);
     // delayed()->tst(scratch);
 
-    // The receiver is receiver[n].  Increment count[n].
-    int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row));
+    // The receiver is item[n].  Increment count[n].
+    int count_offset = in_bytes(item_count_offset_fn(row));
     increment_mdp_data_at(count_offset, scratch);
     ba_short(done);
     bind(next_test);
 
     if (test_for_null_also) {
       Label found_null;
-      // Failed the equality check on receiver[n]...  Test for null.
+      // Failed the equality check on item[n]...  Test for null.
       if (start_row == last_row) {
         // The only thing left to do is handle the null case.
-        if (is_virtual_call) {
+        if (non_profiled_offset >= 0) {
           brx(Assembler::zero, false, Assembler::pn, found_null);
           delayed()->nop();
-          // Receiver did not match any saved receiver and there is no empty row for it.
+          // Item did not match any saved item and there is no empty row for it.
           // Increment total counter to indicate polymorphic case.
-          increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch);
+          increment_mdp_data_at(non_profiled_offset, scratch);
           ba_short(done);
           bind(found_null);
         } else {
@@ -1753,21 +1800,22 @@
       delayed()->nop();
 
       // Put all the "Case 3" tests here.
-      record_klass_in_profile_helper(receiver, scratch, start_row + 1, done, is_virtual_call);
-
-      // Found a null.  Keep searching for a matching receiver,
+      record_item_in_profile_helper(item, scratch, start_row + 1, done, total_rows,
+        item_offset_fn, item_count_offset_fn, non_profiled_offset);
+
+      // Found a null.  Keep searching for a matching item,
       // but remember that this is an empty (unused) slot.
       bind(found_null);
     }
   }
 
-  // In the fall-through case, we found no matching receiver, but we
-  // observed the receiver[start_row] is NULL.
-
-  // Fill in the receiver field and increment the count.
-  int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row));
-  set_mdp_data_at(recvr_offset, receiver);
-  int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row));
+  // In the fall-through case, we found no matching item, but we
+  // observed the item[start_row] is NULL.
+
+  // Fill in the item field and increment the count.
+  int item_offset = in_bytes(item_offset_fn(start_row));
+  set_mdp_data_at(item_offset, item);
+  int count_offset = in_bytes(item_count_offset_fn(start_row));
   mov(DataLayout::counter_increment, scratch);
   set_mdp_data_at(count_offset, scratch);
   if (start_row > 0) {
@@ -1780,7 +1828,7 @@
   assert(ProfileInterpreter, "must be profiling");
   Label done;
 
-  record_klass_in_profile_helper(receiver, scratch, 0, done, is_virtual_call);
+  record_klass_in_profile_helper(receiver, scratch, done, is_virtual_call);
 
   bind (done);
 }
@@ -1836,7 +1884,7 @@
     // The method data pointer needs to be updated.
     int mdp_delta = in_bytes(BitData::bit_data_size());
     if (TypeProfileCasts) {
-      mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+      mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
     }
     update_mdp_by_constant(mdp_delta);
 
@@ -1854,7 +1902,7 @@
 
     int mdp_delta = in_bytes(BitData::bit_data_size());
     if (TypeProfileCasts) {
-      mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+      mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
 
       // Record the object type.
       record_klass_in_profile(klass, scratch, false);
@@ -1876,7 +1924,7 @@
 
     int count_offset = in_bytes(CounterData::count_offset());
     // Back up the address, since we have already bumped the mdp.
-    count_offset -= in_bytes(VirtualCallData::virtual_call_data_size());
+    count_offset -= in_bytes(ReceiverTypeData::receiver_type_data_size());
 
     // *Decrement* the counter.  We expect to see zero or small negatives.
     increment_mdp_data_at(count_offset, scratch, true);
--- a/src/cpu/sparc/vm/interp_masm_sparc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/interp_masm_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -30,6 +30,8 @@
 
 // This file specializes the assember with interpreter-specific macros
 
+typedef ByteSize (*OffsetFunction)(uint);
+
 REGISTER_DECLARATION(     Register, Otos_i , O0); // tos for ints, etc
 REGISTER_DECLARATION(     Register, Otos_l , O0); // for longs
 REGISTER_DECLARATION(     Register, Otos_l1, O0); // for 1st part of longs
@@ -302,7 +304,11 @@
 
   void record_klass_in_profile(Register receiver, Register scratch, bool is_virtual_call);
   void record_klass_in_profile_helper(Register receiver, Register scratch,
-                                      int start_row, Label& done, bool is_virtual_call);
+                                      Label& done, bool is_virtual_call);
+  void record_item_in_profile_helper(Register item,
+                                     Register scratch, int start_row, Label& done, int total_rows,
+                                     OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+                                     int non_profiled_offset);
 
   void update_mdp_by_offset(int offset_of_disp, Register scratch);
   void update_mdp_by_offset(Register reg, int offset_of_disp,
@@ -315,6 +321,7 @@
   void profile_call(Register scratch);
   void profile_final_call(Register scratch);
   void profile_virtual_call(Register receiver, Register scratch, bool receiver_can_be_null = false);
+  void profile_called_method(Register method, Register scratch);
   void profile_ret(TosState state, Register return_bci, Register scratch);
   void profile_null_seen(Register scratch);
   void profile_typecheck(Register klass, Register scratch);
--- a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -27,6 +27,8 @@
 
  friend class AbstractInterpreterGenerator;
 
+  address generate_deopt_entry_for(TosState state, int step);
+
  private:
 
   address generate_normal_entry(bool synchronized);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "vmreg_sparc.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
+  if (inst->is_call() || inst->is_jump()) {
+    return pc_offset + NativeCall::instruction_size;
+  } else if (inst->is_call_reg()) {
+    return pc_offset + NativeCallReg::instruction_size;
+  } else if (inst->is_sethi()) {
+    return pc_offset + NativeFarCall::instruction_size;
+  } else {
+    JVMCI_ERROR_0("unsupported type of instruction for call site");
+    return 0;
+  }
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
+  address pc = _instructions->start() + pc_offset;
+  Handle obj = HotSpotObjectConstantImpl::object(constant);
+  jobject value = JNIHandles::make_local(obj());
+  if (HotSpotObjectConstantImpl::compressed(constant)) {
+#ifdef _LP64
+    int oop_index = _oop_recorder->find_index(value);
+    RelocationHolder rspec = oop_Relocation::spec(oop_index);
+    _instructions->relocate(pc, rspec, 1);
+#else
+    JVMCI_ERROR("compressed oop on 32bit");
+#endif
+  } else {
+    NativeMovConstReg* move = nativeMovConstReg_at(pc);
+    move->set_data((intptr_t) value);
+
+    // We need two relocations:  one on the sethi and one on the add.
+    int oop_index = _oop_recorder->find_index(value);
+    RelocationHolder rspec = oop_Relocation::spec(oop_index);
+    _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
+    _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
+  }
+}
+
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
+  address pc = _instructions->start() + pc_offset;
+  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+#ifdef _LP64
+    NativeMovConstReg32* move = nativeMovConstReg32_at(pc);
+    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, CHECK);
+    move->set_data((intptr_t)narrowOop);
+    TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop);
+#else
+    JVMCI_ERROR("compressed Klass* on 32bit");
+#endif
+  } else {
+    NativeMovConstReg* move = nativeMovConstReg_at(pc);
+    void* reference = record_metadata_reference(_instructions, pc, constant, CHECK);
+    move->set_data((intptr_t)reference);
+    TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference));
+  }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+  address pc = _instructions->start() + pc_offset;
+  NativeInstruction* inst = nativeInstruction_at(pc);
+  NativeInstruction* inst1 = nativeInstruction_at(pc + 4);
+  if(inst->is_sethi() && inst1->is_nop()) {
+      address const_start = _constants->start();
+      address dest = _constants->start() + data_offset;
+      if(_constants_size > 0) {
+        _instructions->relocate(pc + NativeMovConstReg::sethi_offset, internal_word_Relocation::spec((address) dest));
+        _instructions->relocate(pc + NativeMovConstReg::add_offset, internal_word_Relocation::spec((address) dest));
+      }
+      TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
+  }else {
+    int const_size = align_size_up(_constants->end()-_constants->start(), CodeEntryAlignment);
+    NativeMovRegMem* load = nativeMovRegMem_at(pc);
+    // This offset must match with SPARCLoadConstantTableBaseOp.emitCode
+    load->set_offset(- (const_size - data_offset + Assembler::min_simm13()));
+    TRACE_jvmci_3("relocating ld at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
+  }
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
+  address pc = (address) inst;
+  if (inst->is_call()) {
+    NativeCall* call = nativeCall_at(pc);
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
+  } else if (inst->is_sethi()) {
+    NativeJump* jump = nativeJump_at(pc);
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
+  } else {
+    JVMCI_ERROR("unknown call or jump instruction at " PTR_FORMAT, p2i(pc));
+  }
+  TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(Handle hotspot_method, jint pc_offset, TRAPS) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method());
+  }
+#endif
+  switch (_next_call_type) {
+    case INLINE_INVOKE:
+      break;
+    case INVOKEVIRTUAL:
+    case INVOKEINTERFACE: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
+      break;
+    }
+    case INVOKESTATIC: {
+      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+      _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
+      break;
+    }
+    case INVOKESPECIAL: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
+      break;
+    }
+    default:
+      JVMCI_ERROR("invalid _next_call_type value");
+      break;
+  }
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
+  switch (mark) {
+    case POLL_NEAR:
+      JVMCI_ERROR("unimplemented");
+      break;
+    case POLL_FAR:
+      _instructions->relocate(pc, relocInfo::poll_type);
+      break;
+    case POLL_RETURN_NEAR:
+      JVMCI_ERROR("unimplemented");
+      break;
+    case POLL_RETURN_FAR:
+      _instructions->relocate(pc, relocInfo::poll_return_type);
+      break;
+    default:
+      JVMCI_ERROR("invalid mark value");
+      break;
+  }
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
+  // JVMCI Registers are numbered as follows:
+  //   0..31: Thirty-two General Purpose registers (CPU Registers)
+  //   32..63: Thirty-two single precision float registers
+  //   64..95: Thirty-two double precision float registers
+  //   96..111: Sixteen quad precision float registers
+  if (jvmci_reg < 32) {
+    return as_Register(jvmci_reg)->as_VMReg();
+  } else {
+    jint floatRegisterNumber;
+    if(jvmci_reg < 64) { // Single precision
+      floatRegisterNumber = jvmci_reg - 32;
+    } else if(jvmci_reg < 96) {
+      floatRegisterNumber = 2 * (jvmci_reg - 64);
+    } else if(jvmci_reg < 112) {
+      floatRegisterNumber = 4 * (jvmci_reg - 96);
+    } else {
+      JVMCI_ERROR_NULL("invalid register number: %d", jvmci_reg);
+    }
+    return as_FloatRegister(floatRegisterNumber)->as_VMReg();
+  }
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+  return !hotspotRegister->is_FloatRegister();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/sparc/vm/jvmci_globals_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_SPARC_VM_JVMCI_GLOBALS_SPARC_HPP
+#define CPU_SPARC_VM_JVMCI_GLOBALS_SPARC_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+// Sets the default values for platform dependent flags used by the JVMCI compiler.
+// (see jvmci_globals.hpp)
+
+#if !defined(COMPILER2) && !defined(COMPILER1)
+define_pd_global(bool, BackgroundCompilation,        true );
+define_pd_global(bool, UseTLAB,                      true );
+define_pd_global(bool, ResizeTLAB,                   true );
+define_pd_global(bool, InlineIntrinsics,             true );
+define_pd_global(bool, PreferInterpreterNativeStubs, false);
+define_pd_global(bool, TieredCompilation,            trueInTiered);
+define_pd_global(intx, BackEdgeThreshold,            100000);
+
+define_pd_global(intx, OnStackReplacePercentage,     933  );
+define_pd_global(intx, FreqInlineSize,               325  );
+define_pd_global(intx, NewSizeThreadIncrease,        4*K  );
+define_pd_global(uintx,MetaspaceSize,                12*M );
+define_pd_global(bool, NeverActAsServerClassMachine, false);
+define_pd_global(uint64_t,MaxRAM,                    128ULL*G);
+define_pd_global(bool, CICompileOSR,                 true );
+define_pd_global(bool, ProfileTraps,                 true );
+define_pd_global(bool, UseOnStackReplacement,        true );
+define_pd_global(intx, CompileThreshold,             10000);
+define_pd_global(intx, InitialCodeCacheSize,         16*M );
+define_pd_global(intx, ReservedCodeCacheSize,        64*M );
+define_pd_global(bool, ProfileInterpreter,           true );
+define_pd_global(intx, CodeCacheExpansionSize,       64*K );
+define_pd_global(uintx,CodeCacheMinBlockLength,      4);
+define_pd_global(uintx, CodeCacheMinimumUseSpace,    400*K);
+define_pd_global(intx, TypeProfileWidth,             8);
+#endif
+
+define_pd_global(intx, MaxVectorSize,                8);
+
+#endif // CPU_SPARC_VM_JVMCI_GLOBALS_SPARC_HPP
--- a/src/cpu/sparc/vm/nativeInst_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/nativeInst_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -24,6 +24,8 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "code/codeCache.hpp"
 #include "memory/resourceArea.hpp"
 #include "nativeInst_sparc.hpp"
 #include "oops/oop.inline.hpp"
@@ -421,6 +423,67 @@
 
 //-------------------------------------------------------------------
 
+void NativeMovConstReg32::verify() {
+  NativeInstruction::verify();
+  // make sure code pattern is actually a "set_metadata" synthetic instruction
+  // see MacroAssembler::set_oop()
+  int i0 = long_at(sethi_offset);
+  int i1 = long_at(add_offset);
+
+  // verify the pattern "sethi %hi22(imm), reg ;  add reg, %lo10(imm), reg"
+  Register rd = inv_rd(i0);
+  if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) {
+    fatal("not a set_metadata");
+  }
+}
+
+
+void NativeMovConstReg32::print() {
+  tty->print_cr(INTPTR_FORMAT ": mov reg, " INTPTR_FORMAT, instruction_address(), data());
+}
+
+
+intptr_t NativeMovConstReg32::data() const {
+  return data32(long_at(sethi_offset), long_at(add_offset));
+}
+
+
+void NativeMovConstReg32::set_data(intptr_t x) {
+  set_long_at(sethi_offset, set_data32_sethi(  long_at(sethi_offset), x));
+  set_long_at(add_offset,   set_data32_simm13( long_at(add_offset),   x));
+
+  // also store the value into an oop_Relocation cell, if any
+  CodeBlob* cb = CodeCache::find_blob(instruction_address());
+  nmethod*  nm = cb ? cb->as_nmethod_or_null() : NULL;
+  if (nm != NULL) {
+    RelocIterator iter(nm, instruction_address(), next_instruction_address());
+    oop* oop_addr = NULL;
+    Metadata** metadata_addr = NULL;
+    while (iter.next()) {
+      if (iter.type() == relocInfo::oop_type) {
+        oop_Relocation *r = iter.oop_reloc();
+        if (oop_addr == NULL) {
+          oop_addr = r->oop_addr();
+          *oop_addr = cast_to_oop(x);
+        } else {
+          assert(oop_addr == r->oop_addr(), "must be only one set-oop here");
+        }
+      }
+      if (iter.type() == relocInfo::metadata_type) {
+        metadata_Relocation *r = iter.metadata_reloc();
+        if (metadata_addr == NULL) {
+          metadata_addr = r->metadata_addr();
+          *metadata_addr = (Metadata*)x;
+        } else {
+          assert(metadata_addr == r->metadata_addr(), "must be only one set-metadata here");
+        }
+      }
+    }
+  }
+}
+
+//-------------------------------------------------------------------
+
 void NativeMovConstRegPatching::verify() {
   NativeInstruction::verify();
   // Make sure code pattern is sethi/nop/add.
--- a/src/cpu/sparc/vm/nativeInst_sparc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/nativeInst_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -55,6 +55,7 @@
   bool is_dtrace_trap();
   bool is_nop()                        { return long_at(0) == nop_instruction(); }
   bool is_call()                       { return is_op(long_at(0), Assembler::call_op); }
+  bool is_call_reg()                   { return is_op(long_at(0), Assembler::arith_op); }
   bool is_sethi()                      { return (is_op2(long_at(0), Assembler::sethi_op2)
                                           && inv_rd(long_at(0)) != G0); }
 
@@ -417,6 +418,19 @@
   return call;
 }
 
+class NativeCallReg: public NativeInstruction {
+ public:
+  enum Sparc_specific_constants {
+    instruction_size      = 8,
+    return_address_offset = 8,
+    instruction_offset    = 0
+  };
+
+  address next_instruction_address() const {
+    return addr_at(instruction_size);
+  }
+};
+
 // The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere
 // instructions in the sparcv9 vm.  Used to call native methods which may be loaded
 // anywhere in the address space, possibly out of reach of a call instruction.
@@ -506,6 +520,46 @@
 
 #endif // _LP64
 
+// An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions
+// (used to manipulate inlined data references, etc.)
+//      set_metadata imm, reg
+//      == sethi %hi22(imm), reg ;  add reg, %lo10(imm), reg
+class NativeMovConstReg32;
+inline NativeMovConstReg32* nativeMovConstReg32_at(address address);
+class NativeMovConstReg32: public NativeInstruction {
+ public:
+  enum Sparc_specific_constants {
+    sethi_offset           = 0,
+    add_offset             = 4,
+    instruction_size       = 8
+  };
+
+  address instruction_address() const       { return addr_at(0); }
+  address next_instruction_address() const  { return addr_at(instruction_size); }
+
+  // (The [set_]data accessor respects oop_type relocs also.)
+  intptr_t data() const;
+  void set_data(intptr_t x);
+
+  // report the destination register
+  Register destination() { return inv_rd(long_at(sethi_offset)); }
+
+  void  verify();
+  void  print();
+
+  // unit test stuff
+  static void test();
+
+  // Creation
+  friend inline NativeMovConstReg32* nativeMovConstReg32_at(address address) {
+    NativeMovConstReg32* test = (NativeMovConstReg32*)address;
+    #ifdef ASSERT
+      test->verify();
+    #endif
+    return test;
+  }
+};
+
 // An interface for accessing/manipulating native set_metadata imm, reg instructions.
 // (used to manipulate inlined data references, etc.)
 //      set_metadata imm, reg
--- a/src/cpu/sparc/vm/relocInfo_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/relocInfo_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -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) {
 }
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -43,6 +43,9 @@
 #include "compiler/compileBroker.hpp"
 #include "shark/sharkCompiler.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
 
 #define __ masm->
 
@@ -513,10 +516,10 @@
                               const VMRegPair *regs,
                               Label& skip_fixup);
   void gen_i2c_adapter(int total_args_passed,
-                              // VMReg max_arg,
-                              int comp_args_on_stack, // VMRegStackSlots
-                              const BasicType *sig_bt,
-                              const VMRegPair *regs);
+                       // VMReg max_arg,
+                       int comp_args_on_stack, // VMRegStackSlots
+                       const BasicType *sig_bt,
+                       const VMRegPair *regs);
 
   AdapterGenerator(MacroAssembler *_masm) : masm(_masm) {}
 };
@@ -760,13 +763,11 @@
   __ bind(L_fail);
 }
 
-void AdapterGenerator::gen_i2c_adapter(
-                            int total_args_passed,
-                            // VMReg max_arg,
-                            int comp_args_on_stack, // VMRegStackSlots
-                            const BasicType *sig_bt,
-                            const VMRegPair *regs) {
-
+void AdapterGenerator::gen_i2c_adapter(int total_args_passed,
+                                       // VMReg max_arg,
+                                       int comp_args_on_stack, // VMRegStackSlots
+                                       const BasicType *sig_bt,
+                                       const VMRegPair *regs) {
   // Generate an I2C adapter: adjust the I-frame to make space for the C-frame
   // layout.  Lesp was saved by the calling I-frame and will be restored on
   // return.  Meanwhile, outgoing arg space is all owned by the callee
@@ -990,6 +991,21 @@
 
   // Jump to the compiled code just as if compiled code was doing it.
   __ ld_ptr(G5_method, in_bytes(Method::from_compiled_offset()), G3);
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    // check if this call should be routed towards a specific entry point
+    __ ld_ptr(Address(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), G1);
+    __ cmp(G0, G1);
+    Label no_alternative_target;
+    __ br(Assembler::equal, false, Assembler::pn, no_alternative_target);
+    __ delayed()->nop();
+
+    __ ld_ptr(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset()), G3);
+    __ st_ptr(G0, Address(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
+
+    __ bind(no_alternative_target);
+  }
+#endif
 
   // 6243940 We might end up in handle_wrong_method if
   // the callee is deoptimized as we race thru here. If that
@@ -1006,6 +1022,15 @@
   __ delayed()->nop();
 }
 
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+                                    int total_args_passed,
+                                    int comp_args_on_stack,
+                                    const BasicType *sig_bt,
+                                    const VMRegPair *regs) {
+  AdapterGenerator agen(masm);
+  agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs);
+}
+
 // ---------------------------------------------------------------
 AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
                                                             int total_args_passed,
@@ -1016,9 +1041,7 @@
                                                             AdapterFingerPrint* fingerprint) {
   address i2c_entry = __ pc();
 
-  AdapterGenerator agen(masm);
-
-  agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs);
+  gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
 
 
   // -------------------------------------------------------------------------
@@ -1063,7 +1086,7 @@
   }
 
   address c2i_entry = __ pc();
-
+  AdapterGenerator agen(masm);
   agen.gen_c2i_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs, L_skip_fixup);
 
   __ flush();
@@ -1995,23 +2018,33 @@
   int vep_offset = ((intptr_t)__ pc()) - start;
 
 #ifdef COMPILER1
-  if (InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) {
-    // Object.hashCode can pull the hashCode from the header word
-    // instead of doing a full VM transition once it's been computed.
-    // Since hashCode is usually polymorphic at call sites we can't do
-    // this optimization at the call site without a lot of work.
+  if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) ||
+       method->intrinsic_id() == vmIntrinsics::_identityHashCode) {
+    // Object.hashCode, System.identityHashCode can pull the hashCode from the
+    // header word instead of doing a full VM transition once it's been computed.
+    // Since hashCode is usually polymorphic at call sites we can't do this
+    // optimization at the call site without a lot of work.
     Label slowCase;
-    Register receiver             = O0;
+    Label done;
+    Register obj_reg              = O0;
     Register result               = O0;
     Register header               = G3_scratch;
     Register hash                 = G3_scratch; // overwrite header value with hash value
     Register mask                 = G1;         // to get hash field from header
 
-    // Read the header and build a mask to get its hash field.  Give up if the object is not unlocked.
+    // Unlike for Object.hashCode, System.identityHashCode is static method and
+    // gets the object as argument instead of the receiver.
+    if (method->intrinsic_id() == vmIntrinsics::_identityHashCode) {
+      assert(method->is_static(), "method should be static");
+      // return 0 for null reference input
+      __ br_null(obj_reg, false, Assembler::pn, done);
+      __ delayed()->mov(obj_reg, hash);
+    }    // Read the header and build a mask to get its hash field.  Give up if the object is not unlocked.
+
     // We depend on hash_mask being at most 32 bits and avoid the use of
     // hash_mask_in_place because it could be larger than 32 bits in a 64-bit
     // vm: see markOop.hpp.
-    __ ld_ptr(receiver, oopDesc::mark_offset_in_bytes(), header);
+    __ ld_ptr(obj_reg, oopDesc::mark_offset_in_bytes(), header);
     __ sethi(markOopDesc::hash_mask, mask);
     __ btst(markOopDesc::unlocked_value, header);
     __ br(Assembler::zero, false, Assembler::pn, slowCase);
@@ -2034,6 +2067,7 @@
     __ delayed()->nop();
 
     // leaf return.
+    __ bind(done);
     __ retl();
     __ delayed()->mov(hash, result);
     __ bind(slowCase);
@@ -3450,6 +3484,11 @@
     pad += StackShadowPages*16 + 32;
   }
 #endif
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    pad += 512; // Increase the buffer size when compiling for JVMCI
+  }
+#endif
 #ifdef _LP64
   CodeBuffer buffer("deopt_blob", 2100+pad, 512);
 #else
@@ -3516,6 +3555,45 @@
   __ ba(cont);
   __ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode);
 
+
+#if INCLUDE_JVMCI
+  Label after_fetch_unroll_info_call;
+  int implicit_exception_uncommon_trap_offset = 0;
+  int uncommon_trap_offset = 0;
+
+  if (EnableJVMCI) {
+    masm->block_comment("BEGIN implicit_exception_uncommon_trap");
+    implicit_exception_uncommon_trap_offset = __ offset() - start;
+    __ ld_ptr(G2_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset()), O7);
+    __ st_ptr(G0, Address(G2_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
+    __ add(O7, -8, O7);
+
+    uncommon_trap_offset = __ offset() - start;
+
+    // Save everything in sight.
+    (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
+    __ set_last_Java_frame(SP, NULL);
+
+    __ ld(G2_thread, in_bytes(JavaThread::pending_deoptimization_offset()), O1);
+    __ sub(G0, 1, L1);
+    __ st(L1, G2_thread, in_bytes(JavaThread::pending_deoptimization_offset()));
+
+    __ mov((int32_t)Deoptimization::Unpack_reexecute, L0deopt_mode);
+    __ mov(G2_thread, O0);
+    __ mov(L0deopt_mode, O2);
+    __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap));
+    __ delayed()->nop();
+    oop_maps->add_gc_map( __ offset()-start, map->deep_copy());
+    __ get_thread();
+    __ add(O7, 8, O7);
+    __ reset_last_Java_frame();
+
+    __ ba(after_fetch_unroll_info_call);
+    __ delayed()->nop(); // Delay slot
+    masm->block_comment("END implicit_exception_uncommon_trap");
+  } // EnableJVMCI
+#endif // INCLUDE_JVMCI
+
   int exception_offset = __ offset() - start;
 
   // restore G2, the trampoline destroyed it
@@ -3538,6 +3616,7 @@
   int exception_in_tls_offset = __ offset() - start;
 
   // No need to update oop_map  as each call to save_live_registers will produce identical oopmap
+  // Opens a new stack frame
   (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
 
   // Restore G2_thread
@@ -3569,7 +3648,12 @@
   // Reexecute entry, similar to c2 uncommon trap
   //
   int reexecute_offset = __ offset() - start;
-
+#if INCLUDE_JVMCI && !defined(COMPILER1)
+  if (UseJVMCICompiler) {
+    // JVMCI does not use this kind of deoptimization
+    __ should_not_reach_here();
+  }
+#endif
   // No need to update oop_map  as each call to save_live_registers will produce identical oopmap
   (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
 
@@ -3582,6 +3666,7 @@
   // do the call by hand so we can get the oopmap
 
   __ mov(G2_thread, L7_thread_cache);
+  __ mov(L0deopt_mode, O1);
   __ call(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), relocInfo::runtime_call_type);
   __ delayed()->mov(G2_thread, O0);
 
@@ -3593,6 +3678,11 @@
 
   __ reset_last_Java_frame();
 
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    __ bind(after_fetch_unroll_info_call);
+  }
+#endif
   // NOTE: we know that only O0/O1 will be reloaded by restore_result_registers
   // so this move will survive
 
@@ -3602,6 +3692,7 @@
 
   RegisterSaver::restore_result_registers(masm);
 
+  __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes(), G4deopt_mode);
   Label noException;
   __ cmp_and_br_short(G4deopt_mode, Deoptimization::Unpack_exception, Assembler::notEqual, Assembler::pt, noException);
 
@@ -3658,6 +3749,12 @@
   masm->flush();
   _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_words);
   _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
+    _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
+  }
+#endif
 }
 
 #ifdef COMPILER2
@@ -3719,7 +3816,8 @@
   __ save_frame(0);
   __ set_last_Java_frame(SP, noreg);
   __ mov(I0, O2klass_index);
-  __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), G2_thread, O2klass_index);
+  __ mov(Deoptimization::Unpack_uncommon_trap, O3); // exec mode
+  __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), G2_thread, O2klass_index, O3);
   __ reset_last_Java_frame();
   __ mov(O0, O2UnrollBlock->after_save());
   __ restore();
@@ -3728,6 +3826,15 @@
   __ mov(O2UnrollBlock, O2UnrollBlock->after_save());
   __ restore();
 
+#ifdef ASSERT
+  { Label L;
+    __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes(), O1);
+    __  cmp_and_br_short(O1, Deoptimization::Unpack_uncommon_trap, Assembler::equal, Assembler::pt, L);
+    __ stop("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap");
+    __ bind(L);
+  }
+#endif
+
   // Allocate new interpreter frame(s) and possible c2i adapter frame
 
   make_new_frames(masm, false);
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -200,9 +200,33 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
+address InterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
   address entry = __ pc();
   __ get_constant_pool_cache(LcpoolCache); // load LcpoolCache
+#if INCLUDE_JVMCI
+  // Check if we need to take lock at entry of synchronized method.  This can
+  // only occur on method entry so emit it only for vtos with step 0.
+  if (state == vtos && step == 0) {
+    Label L;
+    Address pending_monitor_enter_addr(G2_thread, JavaThread::pending_monitorenter_offset());
+    __ ldbool(pending_monitor_enter_addr, Gtemp);  // Load if pending monitor enter
+    __ cmp_and_br_short(Gtemp, G0, Assembler::equal, Assembler::pn, L);
+    // Clear flag.
+    __ stbool(G0, pending_monitor_enter_addr);
+    // Take lock.
+    lock_method();
+    __ bind(L);
+  } else {
+#ifdef ASSERT
+    Label L;
+    Address pending_monitor_enter_addr(G2_thread, JavaThread::pending_monitorenter_offset());
+    __ ldbool(pending_monitor_enter_addr, Gtemp);  // Load if pending monitor enter
+    __ cmp_and_br_short(Gtemp, G0, Assembler::equal, Assembler::pn, L);
+    __ stop("unexpected pending monitor in deopt entry");
+    __ bind(L);
+#endif
+  }
+#endif
   { Label L;
     Address exception_addr(G2_thread, Thread::pending_exception_offset());
     __ ld_ptr(exception_addr, Gtemp);  // Load pending exception.
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -37,9 +37,9 @@
 #ifdef _LP64
   // The sethi() instruction generates lots more instructions when shell
   // stack limit is unlimited, so that's why this is much bigger.
-  const static int InterpreterCodeSize = 210 * K;
+  const static int InterpreterCodeSize = 260 * K;
 #else
-  const static int InterpreterCodeSize = 180 * K;
+  const static int InterpreterCodeSize = 230 * K;
 #endif
 
 #endif // CPU_SPARC_VM_TEMPLATEINTERPRETER_SPARC_HPP
--- a/src/cpu/sparc/vm/templateTable_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/templateTable_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2999,12 +2999,16 @@
 
 
 void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) {
+  Register Rtemp = G4_scratch;
   Register Rcall = Rindex;
   assert_different_registers(Rcall, G5_method, Gargs, Rret);
 
   // get target Method* & entry point
   __ lookup_virtual_method(Rrecv, Rindex, G5_method);
   __ profile_arguments_type(G5_method, Rcall, Gargs, true);
+#if INCLUDE_JVMCI
+  __ profile_called_method(G5_method, Rtemp);
+#endif
   __ call_from_interpreter(Rcall, Gargs, Rret);
 }
 
@@ -3259,6 +3263,9 @@
   assert_different_registers(Rcall, G5_method, Gargs, Rret);
 
   __ profile_arguments_type(G5_method, Rcall, Gargs, true);
+#if INCLUDE_JVMCI
+  __ profile_called_method(G5_method, Rscratch);
+#endif
   __ call_from_interpreter(Rcall, Gargs, Rret);
 }
 
@@ -3551,7 +3558,8 @@
   Register RspecifiedKlass = O4;
 
   // Check for casting a NULL
-  __ br_null_short(Otos_i, Assembler::pn, is_null);
+  __ br_null(Otos_i, false, Assembler::pn, is_null);
+  __ delayed()->nop();
 
   // Get value klass in RobjKlass
   __ load_klass(Otos_i, RobjKlass); // get value klass
@@ -3607,7 +3615,8 @@
   Register RspecifiedKlass = O4;
 
   // Check for casting a NULL
-  __ br_null_short(Otos_i, Assembler::pt, is_null);
+  __ br_null(Otos_i, false, Assembler::pt, is_null);
+  __ delayed()->nop();
 
   // Get value klass in RobjKlass
   __ load_klass(Otos_i, RobjKlass); // get value klass
--- a/src/cpu/sparc/vm/vmStructs_sparc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/vmStructs_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -37,10 +37,11 @@
   /******************************/                                                                                                   \
   /* JavaFrameAnchor            */                                                                                                   \
   /******************************/                                                                                                   \
-  volatile_nonstatic_field(JavaFrameAnchor,     _flags,                                          int)
+  volatile_nonstatic_field(JavaFrameAnchor,     _flags,                                          int)                                \
+  static_field(VM_Version, _features, int)
 
-#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
-
+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
+  declare_toplevel_type(VM_Version)
 
 #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)                                                              \
   /******************************/                                        \
@@ -78,7 +79,30 @@
   declare_c2_constant(R_G4_num)                                           \
   declare_c2_constant(R_G5_num)                                           \
   declare_c2_constant(R_G6_num)                                           \
-  declare_c2_constant(R_G7_num)
+  declare_c2_constant(R_G7_num)                                           \
+  declare_constant(VM_Version::vis1_instructions_m)                       \
+  declare_constant(VM_Version::vis2_instructions_m)                       \
+  declare_constant(VM_Version::vis3_instructions_m)                       \
+  declare_constant(VM_Version::cbcond_instructions_m)                     \
+  declare_constant(VM_Version::v8_instructions_m)                         \
+  declare_constant(VM_Version::hardware_mul32_m)                          \
+  declare_constant(VM_Version::hardware_div32_m)                          \
+  declare_constant(VM_Version::hardware_fsmuld_m)                         \
+  declare_constant(VM_Version::hardware_popc_m)                           \
+  declare_constant(VM_Version::v9_instructions_m)                         \
+  declare_constant(VM_Version::sun4v_m)                                   \
+  declare_constant(VM_Version::blk_init_instructions_m)                   \
+  declare_constant(VM_Version::fmaf_instructions_m)                       \
+  declare_constant(VM_Version::fmau_instructions_m)                       \
+  declare_constant(VM_Version::sparc64_family_m)                          \
+  declare_constant(VM_Version::M_family_m)                                \
+  declare_constant(VM_Version::T_family_m)                                \
+  declare_constant(VM_Version::T1_model_m)                                \
+  declare_constant(VM_Version::sparc5_instructions_m)                     \
+  declare_constant(VM_Version::aes_instructions_m)                        \
+  declare_constant(VM_Version::sha1_instruction_m)                        \
+  declare_constant(VM_Version::sha256_instruction_m)                      \
+  declare_constant(VM_Version::sha512_instruction_m)
 
 #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
 
--- a/src/cpu/sparc/vm/vm_version_sparc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/sparc/vm/vm_version_sparc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -29,6 +29,7 @@
 #include "runtime/vm_version.hpp"
 
 class VM_Version: public Abstract_VM_Version {
+  friend class VMStructs;
 protected:
   enum Feature_Flag {
     v8_instructions      = 0,
--- a/src/cpu/x86/vm/assembler_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -559,9 +559,12 @@
     case 0x55: // andnps
     case 0x56: // orps
     case 0x57: // xorps
+    case 0x58: // addpd
+    case 0x59: // mulpd
     case 0x6E: // movd
     case 0x7E: // movd
     case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush
+    case 0xFE: // paddd
       debug_only(has_disp32 = true);
       break;
 
@@ -666,14 +669,52 @@
     // Check second byte
     NOT_LP64(assert((0xC0 & *ip) == 0xC0, "shouldn't have LDS and LES instructions"));
 
+    int vex_opcode;
     // First byte
     if ((0xFF & *inst) == VEX_3bytes) {
+      vex_opcode = VEX_OPCODE_MASK & *ip;
       ip++; // third byte
       is_64bit = ((VEX_W & *ip) == VEX_W);
+    } else {
+      vex_opcode = VEX_OPCODE_0F;
     }
     ip++; // opcode
     // To find the end of instruction (which == end_pc_operand).
+    switch (vex_opcode) {
+      case VEX_OPCODE_0F:
+        switch (0xFF & *ip) {
+        case 0x70: // pshufd r, r/a, #8
+        case 0x71: // ps[rl|ra|ll]w r, #8
+        case 0x72: // ps[rl|ra|ll]d r, #8
+        case 0x73: // ps[rl|ra|ll]q r, #8
+        case 0xC2: // cmp[ps|pd|ss|sd] r, r, r/a, #8
+        case 0xC4: // pinsrw r, r, r/a, #8
+        case 0xC5: // pextrw r/a, r, #8
+        case 0xC6: // shufp[s|d] r, r, r/a, #8
+          tail_size = 1;  // the imm8
+          break;
+        }
+        break;
+      case VEX_OPCODE_0F_3A:
+        tail_size = 1;
+        break;
+    }
+    ip++; // skip opcode
+    debug_only(has_disp32 = true); // has both kinds of operands!
+    break;
+
+  case 0x62: // EVEX_4bytes
+    assert((UseAVX > 0), "shouldn't have EVEX prefix");
+    assert(ip == inst+1, "no prefixes allowed");
+    // no EVEX collisions, all instructions that have 0x62 opcodes
+    // have EVEX versions and are subopcodes of 0x66
+    ip++; // skip P0 and exmaine W in P1
+    is_64bit = ((VEX_W & *ip) == VEX_W);
+    ip++; // move to P2
+    ip++; // skip P2, move to opcode
+    // To find the end of instruction (which == end_pc_operand).
     switch (0xFF & *ip) {
+    case 0x22: // pinsrd r, r/a, #8
     case 0x61: // pcmpestri r, r/a, #8
     case 0x70: // pshufd r, r/a, #8
     case 0x73: // psrldq r, #8
@@ -1883,7 +1924,7 @@
 
 void Assembler::movsbl(Register dst, Register src) { // movsxb
   NOT_LP64(assert(src->has_byte_register(), "must have byte register"));
-  int encode = prefix_and_encode(dst->encoding(), src->encoding(), true);
+  int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true);
   emit_int8(0x0F);
   emit_int8((unsigned char)0xBE);
   emit_int8((unsigned char)(0xC0 | encode));
@@ -1976,7 +2017,7 @@
 
 void Assembler::movzbl(Register dst, Register src) { // movzxb
   NOT_LP64(assert(src->has_byte_register(), "must have byte register"));
-  int encode = prefix_and_encode(dst->encoding(), src->encoding(), true);
+  int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true);
   emit_int8(0x0F);
   emit_int8((unsigned char)0xB6);
   emit_int8(0xC0 | encode);
@@ -4694,12 +4735,12 @@
   return reg_enc;
 }
 
-int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) {
+int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) {
   if (dst_enc < 8) {
     if (src_enc >= 8) {
       prefix(REX_B);
       src_enc -= 8;
-    } else if (byteinst && src_enc >= 4) {
+    } else if ((src_is_byte && src_enc >= 4) || (dst_is_byte && dst_enc >= 4)) {
       prefix(REX);
     }
   } else {
--- a/src/cpu/x86/vm/assembler_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/assembler_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -523,7 +523,8 @@
     VEX_OPCODE_NONE  = 0x0,
     VEX_OPCODE_0F    = 0x1,
     VEX_OPCODE_0F_38 = 0x2,
-    VEX_OPCODE_0F_3A = 0x3
+    VEX_OPCODE_0F_3A = 0x3,
+    VEX_OPCODE_MASK  = 0x1F
   };
 
   enum WhichOperand {
@@ -558,7 +559,10 @@
   int prefix_and_encode(int reg_enc, bool byteinst = false);
   int prefixq_and_encode(int reg_enc);
 
-  int prefix_and_encode(int dst_enc, int src_enc, bool byteinst = false);
+  int prefix_and_encode(int dst_enc, int src_enc) {
+    return prefix_and_encode(dst_enc, false, src_enc, false);
+  }
+  int prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte);
   int prefixq_and_encode(int dst_enc, int src_enc);
 
   void prefix(Register reg);
--- a/src/cpu/x86/vm/assembler_x86.inline.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/assembler_x86.inline.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -33,7 +33,7 @@
 inline int Assembler::prefix_and_encode(int reg_enc, bool byteinst) { return reg_enc; }
 inline int Assembler::prefixq_and_encode(int reg_enc) { return reg_enc; }
 
-inline int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) { return dst_enc << 3 | src_enc; }
+inline int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) { return dst_enc << 3 | src_enc; }
 inline int Assembler::prefixq_and_encode(int dst_enc, int src_enc) { return dst_enc << 3 | src_enc; }
 
 inline void Assembler::prefix(Register reg) {}
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -3608,8 +3608,10 @@
   Bytecodes::Code bc = method->java_code_at_bci(bci);
   const bool callee_is_static = callee->is_loaded() && callee->is_static();
   // Perform additional virtual call profiling for invokevirtual and
-  // invokeinterface bytecodes
-  if ((bc == Bytecodes::_invokevirtual || bc == Bytecodes::_invokeinterface) &&
+  // invokeinterface bytecodes.  For invokevirtual don't update the profile if
+  // the method can_be_statically_bound().  See
+  // InterpreterMacroAssembler::profile_final_call.
+  if (((bc == Bytecodes::_invokevirtual && !callee->can_be_statically_bound()) || bc == Bytecodes::_invokeinterface) &&
       !callee_is_static &&  // required for optimized MH invokes
       C1ProfileVirtualCalls) {
     assert(op->recv()->is_single_cpu(), "recv must be allocated");
--- a/src/cpu/x86/vm/c1_globals_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/c1_globals_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -56,6 +56,7 @@
 define_pd_global(bool, NeverActAsServerClassMachine, true );
 define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
 define_pd_global(bool, CICompileOSR,                 true );
+define_pd_global(intx, TypeProfileWidth,             0);
 #endif // !TIERED
 define_pd_global(bool, UseTypeProfile,               false);
 define_pd_global(bool, RoundFPResults,               true );
--- a/src/cpu/x86/vm/c2_globals_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/c2_globals_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -38,6 +38,7 @@
 define_pd_global(bool, PreferInterpreterNativeStubs, false);
 define_pd_global(bool, ProfileTraps,                 true);
 define_pd_global(bool, UseOnStackReplacement,        true);
+define_pd_global(intx, TypeProfileWidth,             2   );
 #ifdef CC_INTERP
 define_pd_global(bool, ProfileInterpreter,           false);
 #else
--- a/src/cpu/x86/vm/compiledIC_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/compiledIC_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -50,13 +50,15 @@
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
   // Stub is fixed up when the corresponding call is converted from
   // calling compiled code to calling interpreted code.
   // movq rbx, 0
   // jmp -5 # to self
 
-  address mark = cbuf.insts_mark();  // Get mark within main instrs section.
+  if (mark == NULL) {
+    mark = cbuf.insts_mark();  // Get mark within main instrs section.
+  }
 
   // Note that the code buffer's insts_mark is always relative to insts.
   // That's why we must use the macroassembler to generate a stub.
@@ -73,6 +75,8 @@
   // This is recognized as unresolved by relocs/nativeinst/ic code.
   __ jump(RuntimeAddress(__ pc()));
 
+  assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size");
+
   // Update current stubs pointer and restore insts_end.
   __ end_a_stub();
   return base;
@@ -104,10 +108,15 @@
   NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
   NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
 
-  assert(method_holder->data() == 0 || method_holder->data() == (intptr_t)callee(),
+#ifdef ASSERT
+  // read the value once
+  intptr_t data = method_holder->data();
+  address destination = jump->jump_destination();
+  assert(data == 0 || data == (intptr_t)callee(),
          "a) MT-unsafe modification of inline cache");
-  assert(jump->jump_destination() == (address)-1 || jump->jump_destination() == entry,
+  assert(destination == (address)-1 || destination == entry,
          "b) MT-unsafe modification of inline cache");
+#endif
 
   // Update stub.
   method_holder->set_data((intptr_t)callee());
--- a/src/cpu/x86/vm/frame_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/frame_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -450,11 +450,11 @@
   // This is the sp before any possible extension (adapter/locals).
   intptr_t* unextended_sp = interpreter_frame_sender_sp();
 
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   if (map->update_map()) {
     update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
   }
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
 
   return frame(sender_sp, unextended_sp, link(), sender_pc());
 }
@@ -686,9 +686,18 @@
     DESCRIBE_FP_OFFSET(interpreter_frame_locals);
     DESCRIBE_FP_OFFSET(interpreter_frame_bcx);
     DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
+#ifdef AMD64
+  } else if (is_entry_frame()) {
+    // This could be more descriptive if we use the enum in
+    // stubGenerator to map to real names but it's most important to
+    // claim these frame slots so the error checking works.
+    for (int i = 0; i < entry_frame_after_call_words; i++) {
+      values.describe(frame_no, fp() - i, err_msg("call_stub word fp - %d", i));
+    }
+#endif // AMD64
   }
 }
-#endif
+#endif // !PRODUCT
 
 intptr_t *frame::initial_deoptimization_info() {
   // used to reset the saved FP
--- a/src/cpu/x86/vm/globals_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/globals_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -47,7 +47,7 @@
 // the the vep is aligned at CodeEntryAlignment whereas c2 only aligns
 // the uep and the vep doesn't get real alignment but just slops on by
 // only assured that the entry instruction meets the 5 byte size requirement.
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
 define_pd_global(intx, CodeEntryAlignment,       32);
 #else
 define_pd_global(intx, CodeEntryAlignment,       16);
@@ -80,7 +80,12 @@
 // GC Ergo Flags
 define_pd_global(uintx, CMSYoungGenPerWorker, 64*M);  // default max size of CMS young gen, per GC worker thread
 
+#ifdef COMPILER_JVMCI
+// Don't bother enabling type profiling since JVMCI doesn't currently expose it
+define_pd_global(uintx, TypeProfileLevel, 0);
+#else
 define_pd_global(uintx, TypeProfileLevel, 111);
+#endif
 
 define_pd_global(bool, PreserveFramePointer, false);
 
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1132,13 +1132,37 @@
     bind(skip_receiver_profile);
 
     // The method data pointer needs to be updated to reflect the new target.
-    update_mdp_by_constant(mdp,
-                           in_bytes(VirtualCallData::
-                                    virtual_call_data_size()));
+#if INCLUDE_JVMCI
+    if (MethodProfileWidth == 0) {
+      update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+    }
+#else
+    update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+#endif
     bind(profile_continue);
   }
 }
 
+#if INCLUDE_JVMCI
+void InterpreterMacroAssembler::profile_called_method(Register method, Register mdp, Register reg2) {
+  assert_different_registers(method, mdp, reg2);
+  if (ProfileInterpreter && MethodProfileWidth > 0) {
+    Label profile_continue;
+
+    // If no method data exists, go to profile_continue.
+    test_method_data_pointer(mdp, profile_continue);
+    
+    Label done;
+    record_item_in_profile_helper(method, mdp, reg2, 0, done, MethodProfileWidth,
+      &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset()));
+    bind(done);
+
+    update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+    bind(profile_continue);
+  }
+}
+#endif
+
 // This routine creates a state machine for updating the multi-row
 // type profile at a virtual call site (or other type-sensitive bytecode).
 // The machine visits each row (of receiver/count) until the receiver type
@@ -1152,20 +1176,41 @@
 // See below for example code.
 void InterpreterMacroAssembler::record_klass_in_profile_helper(
                                         Register receiver, Register mdp,
-                                        Register reg2, int start_row,
-                                        Label& done, bool is_virtual_call) {
+                                        Register reg2, Label& done, bool is_virtual_call) {
   if (TypeProfileWidth == 0) {
     if (is_virtual_call) {
       increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
     }
-    return;
-  }
+#if INCLUDE_JVMCI
+    else if (EnableJVMCI) {
+      increment_mdp_data_at(mdp, in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()));
+    }
+#endif
+  } else {                                      
+    int non_profiled_offset = -1;
+    if (is_virtual_call) {
+      non_profiled_offset = in_bytes(CounterData::count_offset());
+    }
+#if INCLUDE_JVMCI
+    else if (EnableJVMCI) {
+      non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
+    }
+#endif
 
-  int last_row = VirtualCallData::row_limit() - 1;
+    record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth,
+      &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset);
+  }
+}
+
+void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp,
+                                        Register reg2, int start_row, Label& done, int total_rows,
+                                        OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+                                        int non_profiled_offset) {
+  int last_row = total_rows - 1;
   assert(start_row <= last_row, "must be work left to do");
-  // Test this row for both the receiver and for null.
+  // Test this row for both the item and for null.
   // Take any of three different outcomes:
-  //   1. found receiver => increment count and goto done
+  //   1. found item => increment count and goto done
   //   2. found null => keep looking for case 1, maybe allocate this cell
   //   3. found something else => keep looking for cases 1 and 2
   // Case 3 is handled by a recursive call.
@@ -1173,30 +1218,30 @@
     Label next_test;
     bool test_for_null_also = (row == start_row);
 
-    // See if the receiver is receiver[n].
-    int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row));
-    test_mdp_data_at(mdp, recvr_offset, receiver,
+    // See if the item is item[n].
+    int item_offset = in_bytes(item_offset_fn(row));
+    test_mdp_data_at(mdp, item_offset, item,
                      (test_for_null_also ? reg2 : noreg),
                      next_test);
-    // (Reg2 now contains the receiver from the CallData.)
+    // (Reg2 now contains the item from the CallData.)
 
-    // The receiver is receiver[n].  Increment count[n].
-    int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row));
+    // The item is item[n].  Increment count[n].
+    int count_offset = in_bytes(item_count_offset_fn(row));
     increment_mdp_data_at(mdp, count_offset);
     jmp(done);
     bind(next_test);
 
     if (test_for_null_also) {
       Label found_null;
-      // Failed the equality check on receiver[n]...  Test for null.
+      // Failed the equality check on item[n]...  Test for null.
       testptr(reg2, reg2);
       if (start_row == last_row) {
         // The only thing left to do is handle the null case.
-        if (is_virtual_call) {
+        if (non_profiled_offset >= 0) {
           jccb(Assembler::zero, found_null);
-          // Receiver did not match any saved receiver and there is no empty row for it.
+          // Item did not match any saved item and there is no empty row for it.
           // Increment total counter to indicate polymorphic case.
-          increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
+          increment_mdp_data_at(mdp, non_profiled_offset);
           jmp(done);
           bind(found_null);
         } else {
@@ -1208,21 +1253,22 @@
       jcc(Assembler::zero, found_null);
 
       // Put all the "Case 3" tests here.
-      record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call);
+      record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows,
+        item_offset_fn, item_count_offset_fn, non_profiled_offset);
 
-      // Found a null.  Keep searching for a matching receiver,
+      // Found a null.  Keep searching for a matching item,
       // but remember that this is an empty (unused) slot.
       bind(found_null);
     }
   }
 
-  // In the fall-through case, we found no matching receiver, but we
-  // observed the receiver[start_row] is NULL.
+  // In the fall-through case, we found no matching item, but we
+  // observed the item[start_row] is NULL.
 
-  // Fill in the receiver field and increment the count.
-  int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row));
-  set_mdp_data_at(mdp, recvr_offset, receiver);
-  int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row));
+  // Fill in the item field and increment the count.
+  int item_offset = in_bytes(item_offset_fn(start_row));
+  set_mdp_data_at(mdp, item_offset, item);
+  int count_offset = in_bytes(item_count_offset_fn(start_row));
   movl(reg2, DataLayout::counter_increment);
   set_mdp_data_at(mdp, count_offset, reg2);
   if (start_row > 0) {
@@ -1260,7 +1306,7 @@
   assert(ProfileInterpreter, "must be profiling");
   Label done;
 
-  record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call);
+  record_klass_in_profile_helper(receiver, mdp, reg2, done, is_virtual_call);
 
   bind (done);
 }
@@ -1315,7 +1361,7 @@
     // The method data pointer needs to be updated.
     int mdp_delta = in_bytes(BitData::bit_data_size());
     if (TypeProfileCasts) {
-      mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+      mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
     }
     update_mdp_by_constant(mdp, mdp_delta);
 
@@ -1333,7 +1379,7 @@
 
     int count_offset = in_bytes(CounterData::count_offset());
     // Back up the address, since we have already bumped the mdp.
-    count_offset -= in_bytes(VirtualCallData::virtual_call_data_size());
+    count_offset -= in_bytes(ReceiverTypeData::receiver_type_data_size());
 
     // *Decrement* the counter.  We expect to see zero or small negatives.
     increment_mdp_data_at(mdp, count_offset, true);
@@ -1353,7 +1399,7 @@
     // The method data pointer needs to be updated.
     int mdp_delta = in_bytes(BitData::bit_data_size());
     if (TypeProfileCasts) {
-      mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+      mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
 
       // Record the object type.
       record_klass_in_profile(klass, mdp, reg2, false);
--- a/src/cpu/x86/vm/interp_masm_x86_64.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -22,6 +22,7 @@
  *
  */
 
+typedef ByteSize (*OffsetFunction)(uint);
 #ifndef CC_INTERP
  protected:
   // Interpreter specific version of call_VM_base
@@ -202,8 +203,11 @@
   void record_klass_in_profile(Register receiver, Register mdp,
                                Register reg2, bool is_virtual_call);
   void record_klass_in_profile_helper(Register receiver, Register mdp,
-                                      Register reg2, int start_row,
-                                      Label& done, bool is_virtual_call);
+                                      Register reg2, Label& done, bool is_virtual_call);
+  void record_item_in_profile_helper(Register item, Register mdp,
+                                        Register reg2, int start_row, Label& done, int total_rows,
+                                        OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+                                        int non_profiled_offset);
 
   void update_mdp_by_offset(Register mdp_in, int offset_of_offset);
   void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp);
@@ -217,6 +221,7 @@
   void profile_virtual_call(Register receiver, Register mdp,
                             Register scratch2,
                             bool receiver_can_be_null = false);
+  void profile_called_method(Register method, Register mdp, Register reg2);
   void profile_ret(Register return_bci, Register mdp);
   void profile_null_seen(Register mdp);
   void profile_typecheck(Register mdp, Register klass, Register scratch);
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -30,6 +30,8 @@
 //
   friend class AbstractInterpreterGenerator;
 
+  address generate_deopt_entry_for(TosState state, int step);
+
  private:
 
   address generate_normal_entry(bool synchronized);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "compiler/disassembler.hpp"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+#include "vmreg_x86.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
+  if (inst->is_call() || inst->is_jump()) {
+    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
+    return (pc_offset + NativeCall::instruction_size);
+  } else if (inst->is_mov_literal64()) {
+    // mov+call instruction pair
+    jint offset = pc_offset + NativeMovConstReg::instruction_size;
+    u_char* call = (u_char*) (_instructions->start() + offset);
+    if (call[0] == Assembler::REX_B) {
+      offset += 1; /* prefix byte for extended register R8-R15 */
+      call++;
+    }
+    assert(call[0] == 0xFF, "expected call");
+    offset += 2; /* opcode byte + modrm byte */
+    return (offset);
+  } else if (inst->is_call_reg()) {
+    // the inlined vtable stub contains a "call register" instruction
+    assert(method.not_null(), "only valid for virtual calls");
+    return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
+  } else if (inst->is_cond_jump()) {
+    address pc = (address) (inst);
+    return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc);
+  } else {
+    JVMCI_ERROR_0("unsupported type of instruction for call site");
+  }
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
+  address pc = _instructions->start() + pc_offset;
+  Handle obj = HotSpotObjectConstantImpl::object(constant);
+  jobject value = JNIHandles::make_local(obj());
+  if (HotSpotObjectConstantImpl::compressed(constant)) {
+#ifdef _LP64
+    address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
+    int oop_index = _oop_recorder->find_index(value);
+    _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
+    TRACE_jvmci_3("relocating (narrow oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+#else
+    JVMCI_ERROR("compressed oop on 32bit");
+#endif
+  } else {
+    address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+    *((jobject*) operand) = value;
+    _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+    TRACE_jvmci_3("relocating (oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+  }
+}
+
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
+  address pc = _instructions->start() + pc_offset;
+  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+#ifdef _LP64
+    address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
+    *((narrowKlass*) operand) = record_narrow_metadata_reference(_instructions, operand, constant, CHECK);
+    TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+#else
+    JVMCI_ERROR("compressed Klass* on 32bit");
+#endif
+  } else {
+    address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+    *((void**) operand) = record_metadata_reference(_instructions, operand, constant, CHECK);
+    TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+  }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+  address pc = _instructions->start() + pc_offset;
+
+  address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
+  address next_instruction = Assembler::locate_next_instruction(pc);
+  address dest = _constants->start() + data_offset;
+
+  long disp = dest - next_instruction;
+  assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+  *((jint*) operand) = (jint) disp;
+
+  _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+  TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset);
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
+  address pc = (address) inst;
+  if (inst->is_call()) {
+    // NOTE: for call without a mov, the offset must fit a 32-bit immediate
+    //       see also CompilerToVM.getMaxCallTargetOffset()
+    NativeCall* call = nativeCall_at(pc);
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else if (inst->is_mov_literal64()) {
+    NativeMovConstReg* mov = nativeMovConstReg_at(pc);
+    mov->set_data((intptr_t) foreign_call_destination);
+    _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
+  } else if (inst->is_jump()) {
+    NativeJump* jump = nativeJump_at(pc);
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else if (inst->is_cond_jump()) {
+    address old_dest = nativeGeneralJump_at(pc)->jump_destination();
+    address disp = Assembler::locate_operand(pc, Assembler::call32_operand);
+    *(jint*) disp += ((address) foreign_call_destination) - old_dest;
+    _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else {
+    JVMCI_ERROR("unsupported relocation for foreign call");
+  }
+
+  TRACE_jvmci_3("relocating (foreign call)  at " PTR_FORMAT, p2i(inst));
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(Handle hotspot_method, jint pc_offset, TRAPS) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method());
+  }
+#endif
+  switch (_next_call_type) {
+    case INLINE_INVOKE:
+      break;
+    case INVOKEVIRTUAL:
+    case INVOKEINTERFACE: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             virtual_call_Relocation::spec(_invoke_mark_pc),
+                                             Assembler::call32_operand);
+      break;
+    }
+    case INVOKESTATIC: {
+      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             relocInfo::static_call_type, Assembler::call32_operand);
+      break;
+    }
+    case INVOKESPECIAL: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                              relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+      break;
+    }
+    default:
+      JVMCI_ERROR("invalid _next_call_type value");
+      break;
+  }
+}
+
+static void relocate_poll_near(address pc) {
+  NativeInstruction* ni = nativeInstruction_at(pc);
+  int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
+  int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
+  intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
+  *disp = (int32_t)new_disp;
+}
+
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
+  switch (mark) {
+    case POLL_NEAR: {
+      relocate_poll_near(pc);
+      _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
+      break;
+    }
+    case POLL_FAR:
+      // This is a load from a register so there is no relocatable operand.
+      // We just have to ensure that the format is not disp32_operand
+      // so that poll_Relocation::fix_relocation_after_move does the right
+      // thing (i.e. ignores this relocation record)
+      _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand);
+      break;
+    case POLL_RETURN_NEAR: {
+      relocate_poll_near(pc);
+      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand);
+      break;
+    }
+    case POLL_RETURN_FAR:
+      // see comment above for POLL_FAR
+      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
+      break;
+    default:
+      JVMCI_ERROR("invalid mark value: %d", mark);
+      break;
+  }
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
+  if (jvmci_reg < RegisterImpl::number_of_registers) {
+    return as_Register(jvmci_reg)->as_VMReg();
+  } else {
+    jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
+    if (floatRegisterNumber < XMMRegisterImpl::number_of_registers) {
+      return as_XMMRegister(floatRegisterNumber)->as_VMReg();
+    }
+    JVMCI_ERROR_NULL("invalid register number: %d", jvmci_reg);
+  }
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+  return !(hotspotRegister->is_FloatRegister() || hotspotRegister->is_XMMRegister());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/jvmci_globals_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_X86_VM_JVMCI_GLOBALS_X86_HPP
+#define CPU_X86_VM_JVMCI_GLOBALS_X86_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+// Sets the default values for platform dependent flags used by the JVMCI compiler.
+// (see jvmci_globals.hpp)
+
+#if !defined(COMPILER2) && !defined(COMPILER1)
+define_pd_global(bool, BackgroundCompilation,        true );
+define_pd_global(bool, UseTLAB,                      true );
+define_pd_global(bool, ResizeTLAB,                   true );
+define_pd_global(bool, InlineIntrinsics,             true );
+define_pd_global(bool, PreferInterpreterNativeStubs, false);
+define_pd_global(bool, TieredCompilation,            trueInTiered);
+define_pd_global(intx, BackEdgeThreshold,            100000);
+
+define_pd_global(intx, OnStackReplacePercentage,     933  );
+define_pd_global(intx, FreqInlineSize,               325  );
+define_pd_global(intx, NewSizeThreadIncrease,        4*K  );
+define_pd_global(uintx,MetaspaceSize,                12*M );
+define_pd_global(bool, NeverActAsServerClassMachine, false);
+define_pd_global(uint64_t,MaxRAM,                    128ULL*G);
+define_pd_global(bool, CICompileOSR,                 true );
+define_pd_global(bool, ProfileTraps,                 true );
+define_pd_global(bool, UseOnStackReplacement,        true );
+define_pd_global(intx, CompileThreshold,             10000);
+define_pd_global(intx, InitialCodeCacheSize,         16*M );
+define_pd_global(intx, ReservedCodeCacheSize,        64*M );
+define_pd_global(bool, ProfileInterpreter,           true );
+define_pd_global(intx, CodeCacheExpansionSize,       64*K );
+define_pd_global(uintx,CodeCacheMinBlockLength,      4);
+define_pd_global(uintx, CodeCacheMinimumUseSpace,    400*K);
+define_pd_global(intx, TypeProfileWidth,             8);
+define_pd_global(intx, MethodProfileWidth,           0);
+#endif
+
+define_pd_global(intx, MaxVectorSize,                32);
+
+#endif // CPU_X86_VM_JVMCI_GLOBALS_X86_HPP
--- a/src/cpu/x86/vm/macroAssembler_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/macroAssembler_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2945,7 +2945,7 @@
 }
 
 // !defined(COMPILER2) is because of stupid core builds
-#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2)
+#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) || INCLUDE_JVMCI
 void MacroAssembler::empty_FPU_stack() {
   if (VM_Version::supports_mmx()) {
     emms();
@@ -2953,7 +2953,7 @@
     for (int i = 8; i-- > 0; ) ffree(i);
   }
 }
-#endif // !LP64 || C1 || !C2
+#endif // !LP64 || C1 || !C2 || JVMCI
 
 
 // Defines obj, preserves var_size_in_bytes
--- a/src/cpu/x86/vm/nativeInst_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/nativeInst_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -474,6 +474,7 @@
 //
 // In C2 the 5+ byte sized instruction is enforced by code in MachPrologNode::emit.
 // In C1 the restriction is enforced by CodeEmitter::method_entry
+// In JVMCI, the restriction is enforced by HotSpotFrameContext.enter(...)
 //
 void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
   // complete jump instruction (to be inserted) is in code_buffer;
--- a/src/cpu/x86/vm/nativeInst_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/nativeInst_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -61,6 +61,7 @@
   bool is_nop()                        { return ubyte_at(0) == nop_instruction_code; }
   bool is_dtrace_trap();
   inline bool is_call();
+  inline bool is_call_reg();
   inline bool is_illegal();
   inline bool is_return();
   inline bool is_jump();
@@ -181,6 +182,24 @@
   return call;
 }
 
+class NativeCallReg: public NativeInstruction {
+ public:
+  enum Intel_specific_constants {
+    instruction_code            = 0xFF,
+    instruction_offset          =    0,
+    return_address_offset_norex =    2,
+    return_address_offset_rex   =    3
+  };
+
+  int next_instruction_offset() const  {
+    if (ubyte_at(0) == NativeCallReg::instruction_code) {
+      return return_address_offset_norex;
+    } else {
+      return return_address_offset_rex;
+    }
+  }
+};
+
 // An interface for accessing/manipulating native mov reg, imm32 instructions.
 // (used to manipulate inlined 32bit data dll calls, etc.)
 class NativeMovConstReg: public NativeInstruction {
@@ -532,6 +551,9 @@
 
 inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
 inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }
+inline bool NativeInstruction::is_call_reg()     { return ubyte_at(0) == NativeCallReg::instruction_code ||
+                                                          (ubyte_at(1) == NativeCallReg::instruction_code &&
+                                                           (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
 inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
@@ -540,26 +562,24 @@
                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
 inline bool NativeInstruction::is_safepoint_poll() {
 #ifdef AMD64
-  if (Assembler::is_polling_page_far()) {
-    // two cases, depending on the choice of the base register in the address.
-    if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
-         ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
-         (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
-        ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
-        (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
-      return true;
-    } else {
-      return false;
-    }
-  } else {
-    if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
-        ubyte_at(1) == 0x05) { // 00 rax 101
-      address fault = addr_at(6) + int_at(2);
-      return os::is_poll_address(fault);
-    } else {
-      return false;
-    }
+  // Try decoding a near safepoint first:
+  if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+      ubyte_at(1) == 0x05) { // 00 rax 101
+    address fault = addr_at(6) + int_at(2);
+    NOT_JVMCI(assert(!Assembler::is_polling_page_far(), "unexpected poll encoding");)
+    return os::is_poll_address(fault);
   }
+  // Now try decoding a far safepoint:
+  // two cases, depending on the choice of the base register in the address.
+  if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
+       ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
+       (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
+      ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+      (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
+    NOT_JVMCI(assert(Assembler::is_polling_page_far(), "unexpected poll encoding");)
+    return true;
+  }
+  return false;
 #else
   return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
            ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/registerMap_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include <runtime/registerMap.hpp>
+#include "vmreg_x86.inline.hpp"
+
+address RegisterMap::pd_location(VMReg reg) const {
+  if (reg->is_XMMRegister()) {
+    int regBase = reg->value() - ConcreteRegisterImpl::max_fpr;
+    if (regBase % 4 == 0) {
+      // Reads of the low and high 16 byte parts should be handled by location itself
+      return NULL;
+    }
+    VMReg baseReg = as_XMMRegister(regBase >> 3)->as_VMReg();
+    intptr_t offset = (reg->value() - baseReg->value()) * 4;
+    if (offset >= 16) {
+      // The high part of YMM registers are saved in a their own area in the frame
+      baseReg = baseReg->next()->next()->next()->next();
+      offset -= 16;
+    }
+    address baseLocation = location(baseReg);
+    if (baseLocation != NULL) {
+      return baseLocation + offset;
+    }
+  }
+  return NULL;
+}
--- a/src/cpu/x86/vm/registerMap_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/registerMap_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -31,11 +31,7 @@
  private:
   // This is the hook for finding a register in an "well-known" location,
   // such as a register block of a predetermined format.
-  // Since there is none, we just return NULL.
-  // See registerMap_sparc.hpp for an example of grabbing registers
-  // from register save areas of a standard layout.
-   address pd_location(VMReg reg) const {return NULL;}
-
+  address pd_location(VMReg reg) const;
   // no PD state to clear or copy:
   void pd_clear() {}
   void pd_initialize() {}
--- a/src/cpu/x86/vm/register_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/register_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -64,3 +64,28 @@
   };
   return is_valid() ? names[encoding()] : "xnoreg";
 }
+
+const char* XMMRegisterImpl::sub_word_name(int i) const {
+  const char* names[number_of_registers * 8] = {
+      "xmm0:0", "xmm0:1", "xmm0:2", "xmm0:3", "xmm0:4", "xmm0:5", "xmm0:6", "xmm0:7",
+      "xmm1:0", "xmm1:1", "xmm1:2", "xmm1:3", "xmm1:4", "xmm1:5", "xmm1:6", "xmm1:7",
+      "xmm2:0", "xmm2:1", "xmm2:2", "xmm2:3", "xmm2:4", "xmm2:5", "xmm2:6", "xmm2:7",
+      "xmm3:0", "xmm3:1", "xmm3:2", "xmm3:3", "xmm3:4", "xmm3:5", "xmm3:6", "xmm3:7",
+      "xmm4:0", "xmm4:1", "xmm4:2", "xmm4:3", "xmm4:4", "xmm4:5", "xmm4:6", "xmm4:7",
+      "xmm5:0", "xmm5:1", "xmm5:2", "xmm5:3", "xmm5:4", "xmm5:5", "xmm5:6", "xmm5:7",
+      "xmm6:0", "xmm6:1", "xmm6:2", "xmm6:3", "xmm6:4", "xmm6:5", "xmm6:6", "xmm6:7",
+      "xmm7:0", "xmm7:1", "xmm7:2", "xmm7:3", "xmm7:4", "xmm7:5", "xmm7:6", "xmm7:7",
+#ifdef AMD64
+      "xmm8:0", "xmm8:1", "xmm8:2", "xmm8:3", "xmm8:4", "xmm8:5", "xmm8:6", "xmm8:7",
+      "xmm9:0", "xmm9:1", "xmm9:2", "xmm9:3", "xmm9:4", "xmm9:5", "xmm9:6", "xmm9:7",
+      "xmm10:0", "xmm10:1", "xmm10:2", "xmm10:3", "xmm10:4", "xmm10:5", "xmm10:6", "xmm10:7",
+      "xmm11:0", "xmm11:1", "xmm11:2", "xmm11:3", "xmm11:4", "xmm11:5", "xmm11:6", "xmm11:7",
+      "xmm12:0", "xmm12:1", "xmm12:2", "xmm12:3", "xmm12:4", "xmm12:5", "xmm12:6", "xmm12:7",
+      "xmm13:0", "xmm13:1", "xmm13:2", "xmm13:3", "xmm13:4", "xmm13:5", "xmm13:6", "xmm13:7",
+      "xmm14:0", "xmm14:1", "xmm14:2", "xmm14:3", "xmm14:4", "xmm14:5", "xmm14:6", "xmm14:7",
+      "xmm15:0", "xmm15:1", "xmm15:2", "xmm15:3", "xmm15:4", "xmm15:5", "xmm15:6", "xmm15:7",
+#endif // AMD64
+  };
+  assert(i >= 0 && i < 8, "offset too large");
+  return is_valid() ? names[encoding() * 8 + i] : "xnoreg";
+}
--- a/src/cpu/x86/vm/register_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/register_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -161,6 +161,7 @@
   int   encoding() const                          { assert(is_valid(), err_msg("invalid register (%d)", (int)(intptr_t)this )); return (intptr_t)this; }
   bool  is_valid() const                          { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
   const char* name() const;
+  const char* sub_word_name(int offset) const;
 };
 
 
--- a/src/cpu/x86/vm/relocInfo_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/relocInfo_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -179,39 +179,17 @@
 
 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;
+  typedef Assembler::WhichOperand WhichOperand;
+  WhichOperand which = (WhichOperand) format();
+#if !INCLUDE_JVMCI
+  assert((which == Assembler::disp32_operand) == !Assembler::is_polling_page_far(), "format not set correctly");
+#endif
+  if (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()) {
-    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;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/sharedRuntime_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "vmreg_x86.inline.hpp"
+#ifdef COMPILER1
+#include "c1/c1_Runtime1.hpp"
+#endif //COMPILER1
+
+#define __ masm->
+
+#ifdef COMPILER1
+// ---------------------------------------------------------------------------
+// Object.hashCode, System.identityHashCode can pull the hashCode from the
+// header word instead of doing a full VM transition once it's been computed.
+// Since hashCode is usually polymorphic at call sites we can't do this
+// optimization at the call site without a lot of work.
+void SharedRuntime::inline_check_hashcode_from_object_header(MacroAssembler* masm,
+                                 methodHandle method,
+                                 Register obj_reg,
+                                 Register result) {
+  Label slowCase;
+
+  // Unlike for Object.hashCode, System.identityHashCode is static method and
+  // gets object as argument instead of the receiver.
+  if (method->intrinsic_id() == vmIntrinsics::_identityHashCode) {
+    Label Continue;
+    // return 0 for null reference input
+    __ cmpptr(obj_reg, (int32_t)NULL_WORD);
+    __ jcc(Assembler::notEqual, Continue);
+    __ xorptr(result, result);
+    __ ret(0);
+    __ bind(Continue);
+  }
+
+  __ movptr(result, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
+
+  // check if locked
+  __ testptr(result, markOopDesc::unlocked_value);
+  __ jcc(Assembler::zero, slowCase);
+
+  if (UseBiasedLocking) {
+    // Check if biased and fall through to runtime if so
+    __ testptr(result, markOopDesc::biased_lock_bit_in_place);
+    __ jcc(Assembler::notZero, slowCase);
+  }
+
+  // get hash
+#ifdef _LP64
+  // Read the header and build a mask to get its hash field.
+  // Depend on hash_mask being at most 32 bits and avoid the use of hash_mask_in_place
+  // because it could be larger than 32 bits in a 64-bit vm. See markOop.hpp.
+  __ shrptr(result, markOopDesc::hash_shift);
+  __ andptr(result, markOopDesc::hash_mask);
+#else
+  __ andptr(result, markOopDesc::hash_mask_in_place);
+#endif //_LP64
+
+  // test if hashCode exists
+  __ jcc(Assembler::zero, slowCase);
+#ifndef _LP64
+  __ shrptr(result, markOopDesc::hash_shift);
+#endif
+  __ ret(0);
+  __ bind(slowCase);
+}
+#endif //COMPILER1
+
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -711,12 +711,11 @@
   __ bind(L_fail);
 }
 
-static void gen_i2c_adapter(MacroAssembler *masm,
-                            int total_args_passed,
-                            int comp_args_on_stack,
-                            const BasicType *sig_bt,
-                            const VMRegPair *regs) {
-
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+                                    int total_args_passed,
+                                    int comp_args_on_stack,
+                                    const BasicType *sig_bt,
+                                    const VMRegPair *regs) {
   // Note: rsi contains the senderSP on entry. We must preserve it since
   // we may do a i2c -> c2i transition if we lose a race where compiled
   // code goes non-entrant while we get args ready.
@@ -1766,33 +1765,9 @@
   int vep_offset = ((intptr_t)__ pc()) - start;
 
 #ifdef COMPILER1
-  if (InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) {
-    // Object.hashCode can pull the hashCode from the header word
-    // instead of doing a full VM transition once it's been computed.
-    // Since hashCode is usually polymorphic at call sites we can't do
-    // this optimization at the call site without a lot of work.
-    Label slowCase;
-    Register receiver = rcx;
-    Register result = rax;
-    __ movptr(result, Address(receiver, oopDesc::mark_offset_in_bytes()));
-
-    // check if locked
-    __ testptr(result, markOopDesc::unlocked_value);
-    __ jcc (Assembler::zero, slowCase);
-
-    if (UseBiasedLocking) {
-      // Check if biased and fall through to runtime if so
-      __ testptr(result, markOopDesc::biased_lock_bit_in_place);
-      __ jcc (Assembler::notZero, slowCase);
-    }
-
-    // get hash
-    __ andptr(result, markOopDesc::hash_mask_in_place);
-    // test if hashCode exists
-    __ jcc  (Assembler::zero, slowCase);
-    __ shrptr(result, markOopDesc::hash_shift);
-    __ ret(0);
-    __ bind (slowCase);
+  // For Object.hashCode, System.identityHashCode try to pull hashCode from object header if available.
+  if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {
+    inline_check_hashcode_from_object_header(masm, method, rcx /*obj_reg*/, rax /*result*/);
   }
 #endif // COMPILER1
 
@@ -2947,7 +2922,8 @@
 
   oop_maps->add_gc_map( __ pc()-start, map);
 
-  // Discard arg to fetch_unroll_info
+  // Discard args to fetch_unroll_info
+  __ pop(rcx);
   __ pop(rcx);
 
   __ get_thread(rcx);
@@ -2960,9 +2936,8 @@
   // we are very short of registers
 
   Address unpack_kind(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes());
-  // retrieve the deopt kind from where we left it.
-  __ pop(rax);
-  __ movl(unpack_kind, rax);                      // save the unpack_kind value
+  // retrieve the deopt kind from the UnrollBlock.
+  __ movl(rax, unpack_kind);
 
    Label noException;
   __ cmpl(rax, Deoptimization::Unpack_exception);   // Was exception pending?
@@ -3172,11 +3147,12 @@
   enum frame_layout {
     arg0_off,      // thread                     sp + 0 // Arg location for
     arg1_off,      // unloaded_class_index       sp + 1 // calling C
+    arg2_off,      // exec_mode                  sp + 2
     // The frame sender code expects that rbp will be in the "natural" place and
     // will override any oopMap setting for it. We must therefore force the layout
     // so that it agrees with the frame sender code.
-    rbp_off,       // callee saved register      sp + 2
-    return_off,    // slot for return address    sp + 3
+    rbp_off,       // callee saved register      sp + 3
+    return_off,    // slot for return address    sp + 4
     framesize
   };
 
@@ -3208,6 +3184,7 @@
   __ movptr(Address(rsp, arg0_off*wordSize), rdx);
   // argument already in ECX
   __ movl(Address(rsp, arg1_off*wordSize),rcx);
+  __ movl(Address(rsp, arg2_off*wordSize), Deoptimization::Unpack_uncommon_trap);
   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
 
   // Set an oopmap for the call site
@@ -3224,6 +3201,16 @@
   // Load UnrollBlock into EDI
   __ movptr(rdi, rax);
 
+#ifdef ASSERT
+  { Label L;
+    __ cmpptr(Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()),
+            (int32_t)Deoptimization::Unpack_uncommon_trap);
+    __ jcc(Assembler::equal, L);
+    __ stop("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap");
+    __ bind(L);
+  }
+#endif
+
   // Pop all the frames we must move/replace.
   //
   // Frame picture (youngest to oldest)
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -43,6 +43,9 @@
 #ifdef COMPILER2
 #include "opto/runtime.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
 
 #define __ masm->
 
@@ -129,6 +132,7 @@
   static int rax_offset_in_bytes(void)    { return BytesPerInt * rax_off; }
   static int rdx_offset_in_bytes(void)    { return BytesPerInt * rdx_off; }
   static int rbx_offset_in_bytes(void)    { return BytesPerInt * rbx_off; }
+  static int r10_offset_in_bytes(void)    { return BytesPerInt * r10_off; }
   static int xmm0_offset_in_bytes(void)   { return BytesPerInt * xmm0_off; }
   static int return_offset_in_bytes(void) { return BytesPerInt * return_off; }
 
@@ -139,16 +143,18 @@
 
 OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
   int vect_words = 0;
-#ifdef COMPILER2
+  int ymmhi_offset = -1;
+#if defined(COMPILER2) || INCLUDE_JVMCI
   if (save_vectors) {
     assert(UseAVX > 0, "256bit vectors are supported only with AVX");
     assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
     // Save upper half of YMM registes
     vect_words = 16 * 16 / wordSize;
+    ymmhi_offset = additional_frame_words;
     additional_frame_words += vect_words;
   }
 #else
-  assert(!save_vectors, "vectors are generated only by C2");
+  assert(!save_vectors, "vectors are generated only by C2 and JVMCI");
 #endif
 
   // Always make the frame size 16-byte aligned
@@ -205,6 +211,7 @@
   OopMap* map = new OopMap(frame_size_in_slots, 0);
 
 #define STACK_OFFSET(x) VMRegImpl::stack2reg((x) + additional_frame_slots)
+#define YMMHI_STACK_OFFSET(x) VMRegImpl::stack2reg((x / VMRegImpl::stack_slot_size) + ymmhi_offset)
 
   map->set_callee_saved(STACK_OFFSET( rax_off ), rax->as_VMReg());
   map->set_callee_saved(STACK_OFFSET( rcx_off ), rcx->as_VMReg());
@@ -239,6 +246,29 @@
   map->set_callee_saved(STACK_OFFSET(xmm14_off), xmm14->as_VMReg());
   map->set_callee_saved(STACK_OFFSET(xmm15_off), xmm15->as_VMReg());
 
+
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  if (save_vectors) {
+    assert(ymmhi_offset != -1, "save area must exist");
+    map->set_callee_saved(YMMHI_STACK_OFFSET(  0), xmm0->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET( 16), xmm1->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET( 32), xmm2->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET( 48), xmm3->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET( 64), xmm4->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET( 80), xmm5->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET( 96), xmm6->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(112), xmm7->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(128), xmm8->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(144), xmm9->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(160), xmm10->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(176), xmm11->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(192), xmm12->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(208), xmm13->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(224), xmm14->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(240), xmm15->as_VMReg()->next()->next()->next()->next());
+  }
+#endif
+
   // %%% These should all be a waste but we'll keep things as they were for now
   if (true) {
     map->set_callee_saved(STACK_OFFSET( raxH_off ), rax->as_VMReg()->next());
@@ -282,7 +312,7 @@
     // Pop arg register save area
     __ addptr(rsp, frame::arg_reg_save_area_bytes);
   }
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   if (restore_vectors) {
     // Restore upper half of YMM registes.
     assert(UseAVX > 0, "256bit vectors are supported only with AVX");
@@ -306,7 +336,7 @@
     __ addptr(rsp, 256);
   }
 #else
-  assert(!restore_vectors, "vectors are generated only by C2");
+  assert(!restore_vectors, "vectors are generated only by C2 and JVMCI");
 #endif
   // Recover CPU state
   __ pop_CPU_state();
@@ -641,11 +671,11 @@
   __ bind(L_fail);
 }
 
-static void gen_i2c_adapter(MacroAssembler *masm,
-                            int total_args_passed,
-                            int comp_args_on_stack,
-                            const BasicType *sig_bt,
-                            const VMRegPair *regs) {
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+                                    int total_args_passed,
+                                    int comp_args_on_stack,
+                                    const BasicType *sig_bt,
+                                    const VMRegPair *regs) {
 
   // Note: r13 contains the senderSP on entry. We must preserve it since
   // we may do a i2c -> c2i transition if we lose a race where compiled
@@ -738,6 +768,18 @@
   // Pre-load the register-jump target early, to schedule it better.
   __ movptr(r11, Address(rbx, in_bytes(Method::from_compiled_offset())));
 
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    // check if this call should be routed towards a specific entry point
+    __ cmpptr(Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), 0);
+    Label no_alternative_target;
+    __ jcc(Assembler::equal, no_alternative_target);
+    __ movptr(r11, Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
+    __ movptr(Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), 0);
+    __ bind(no_alternative_target);
+  }
+#endif
+
   // Now generate the shuffle code.  Pick up all register args and move the
   // rest through the floating point stack top.
   for (int i = 0; i < total_args_passed; i++) {
@@ -1994,6 +2036,13 @@
 
   int vep_offset = ((intptr_t)__ pc()) - start;
 
+#ifdef COMPILER1
+  // For Object.hashCode, System.identityHashCode try to pull hashCode from object header if available.
+  if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {
+    inline_check_hashcode_from_object_header(masm, method, j_rarg0 /*obj_reg*/, rax /*result*/);
+  }
+#endif // COMPILER1
+
   // The instruction at the verified entry point must be 5 bytes or longer
   // because it can be patched on the fly by make_non_entrant. The stack bang
   // instruction fits that requirement.
@@ -3342,6 +3391,12 @@
   __ jmp(cont);
 
   int reexecute_offset = __ pc() - start;
+#if INCLUDE_JVMCI && !defined(COMPILER1)
+  if (UseJVMCICompiler) {
+    // JVMCI does not use this kind of deoptimization
+    __ should_not_reach_here();
+  }
+#endif
 
   // Reexecute case
   // return address is the pc describes what bci to do re-execute at
@@ -3352,6 +3407,39 @@
   __ movl(r14, Deoptimization::Unpack_reexecute); // callee-saved
   __ jmp(cont);
 
+#if INCLUDE_JVMCI
+  Label after_fetch_unroll_info_call;
+  int implicit_exception_uncommon_trap_offset = 0;
+  int uncommon_trap_offset = 0;
+
+  if (EnableJVMCI) {
+    implicit_exception_uncommon_trap_offset = __ pc() - start;
+
+    __ pushptr(Address(r15_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
+    __ movptr(Address(r15_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())), (int32_t)NULL_WORD);
+
+    uncommon_trap_offset = __ pc() - start;
+
+    // Save everything in sight.
+    RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
+    // fetch_unroll_info needs to call last_java_frame()
+    __ set_last_Java_frame(noreg, noreg, NULL);
+
+    __ movl(c_rarg1, Address(r15_thread, in_bytes(JavaThread::pending_deoptimization_offset())));
+    __ movl(Address(r15_thread, in_bytes(JavaThread::pending_deoptimization_offset())), -1);
+
+    __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
+    __ mov(c_rarg0, r15_thread);
+    __ movl(c_rarg2, r14); // exec mode
+    __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
+    oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
+
+    __ reset_last_Java_frame(false, false);
+
+    __ jmp(after_fetch_unroll_info_call);
+  } // EnableJVMCI
+#endif // INCLUDE_JVMCI
+
   int exception_offset = __ pc() - start;
 
   // Prolog for exception case
@@ -3429,6 +3517,7 @@
   }
 #endif // ASSERT
   __ mov(c_rarg0, r15_thread);
+  __ movl(c_rarg1, r14); // exec_mode
   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info)));
 
   // Need to have an oopmap that tells fetch_unroll_info where to
@@ -3437,9 +3526,16 @@
 
   __ reset_last_Java_frame(false, false);
 
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    __ bind(after_fetch_unroll_info_call);
+  }
+#endif
+
   // Load UnrollBlock* into rdi
   __ mov(rdi, rax);
 
+  __ movl(r14, Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()));
    Label noException;
   __ cmpl(r14, Deoptimization::Unpack_exception);   // Was exception pending?
   __ jcc(Assembler::notEqual, noException);
@@ -3611,6 +3707,12 @@
 
   _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
   _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
+    _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
+  }
+#endif
 }
 
 #ifdef COMPILER2
@@ -3652,6 +3754,7 @@
   // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index);
 
   __ mov(c_rarg0, r15_thread);
+  __ movl(c_rarg2, Deoptimization::Unpack_uncommon_trap);
   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
 
   // Set an oopmap for the call site
@@ -3667,6 +3770,16 @@
   // Load UnrollBlock* into rdi
   __ mov(rdi, rax);
 
+#ifdef ASSERT
+  { Label L;
+    __ cmpptr(Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()),
+            (int32_t)Deoptimization::Unpack_uncommon_trap);
+    __ jcc(Assembler::equal, L);
+    __ stop("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap");
+    __ bind(L);
+  }
+#endif
+
   // Pop all the frames we must move/replace.
   //
   // Frame picture (youngest to oldest)
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2650,7 +2650,7 @@
     {
       BLOCK_COMMENT("assert primitive array {");
       Label L;
-      __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
+      __ cmpl(rax_lh, ((unsigned)Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
       __ jcc(Assembler::greaterEqual, L);
       __ stop("must be a primitive array");
       __ bind(L);
--- a/src/cpu/x86/vm/templateInterpreter_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/templateInterpreter_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -34,7 +34,7 @@
   // Run with +PrintInterpreter to get the VM to print out the size.
   // Max size with JVMTI
 #ifdef AMD64
-  const static int InterpreterCodeSize = 256 * 1024;
+  const static int InterpreterCodeSize = JVMCI_ONLY(264) NOT_JVMCI(256) * 1024;
 #else
   const static int InterpreterCodeSize = 224 * 1024;
 #endif // AMD64
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -213,7 +213,7 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
+address InterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
   address entry = __ pc();
 
   // In SSE mode, FP results are in xmm0
@@ -443,6 +443,7 @@
   __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rax);
 
   __ movptr(rbx, Address(rbp, method_offset));   // restore Method*
+  __ set_method_data_pointer_for_bcp();
 
   // Preserve invariant that rsi/rdi contain bcp/locals of sender frame
   // and jump to the interpreted entry.
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -197,13 +197,37 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
+address InterpreterGenerator::generate_deopt_entry_for(TosState state,
                                                                int step) {
   address entry = __ pc();
   // NULL last_sp until next java call
   __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
   __ restore_bcp();
   __ restore_locals();
+#if INCLUDE_JVMCI
+  // Check if we need to take lock at entry of synchronized method.  This can
+  // only occur on method entry so emit it only for vtos with step 0.
+  if (state == vtos && step == 0) {
+    Label L;
+    __ cmpb(Address(r15_thread, JavaThread::pending_monitorenter_offset()), 0);
+    __ jcc(Assembler::zero, L);
+    // Clear flag.
+    __ movb(Address(r15_thread, JavaThread::pending_monitorenter_offset()), 0);
+    // Satisfy calling convention for lock_method().
+    __ get_method(rbx);
+    // Take lock.
+    lock_method();
+    __ bind(L);
+  } else {
+#ifdef ASSERT
+    Label L;
+    __ cmpb(Address(r15_thread, JavaThread::pending_monitorenter_offset()), 0);
+    __ jccb(Assembler::zero, L);
+    __ stop("unexpected pending monitor in deopt entry");
+    __ bind(L);
+#endif
+  }
+#endif
   // handle exceptions
   {
     Label L;
@@ -389,6 +413,7 @@
              c_rarg1);
 
   __ movptr(rbx, Address(rbp, method_offset));   // restore Method*
+  __ set_method_data_pointer_for_bcp();
   // Preserve invariant that r13/r14 contain bcp/locals of sender frame
   // and jump to the interpreted entry.
   __ jmp(*do_continue, relocInfo::none);
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/templateTable_x86_32.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1726,17 +1726,18 @@
       call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rdx);
       __ load_unsigned_byte(rbx, Address(rsi, 0));  // restore target bytecode
 
-      // rax,: osr nmethod (osr ok) or NULL (osr not possible)
-      // rbx,: target bytecode
+      Label maybe_load_mdp;
+      // rax: osr nmethod (osr ok) or NULL (osr not possible)
+      // rbx: target bytecode
       // rdx: scratch
       // rdi: locals pointer
       // rsi: bcp
-      __ testptr(rax, rax);                      // test result
-      __ jcc(Assembler::zero, dispatch);         // no osr if null
+      __ testptr(rax, rax);                        // test result
+      __ jcc(Assembler::zero, maybe_load_mdp);     // no osr if null
       // nmethod may have been invalidated (VM may block upon call_VM return)
       __ movl(rcx, Address(rax, nmethod::entry_bci_offset()));
       __ cmpl(rcx, InvalidOSREntryBci);
-      __ jcc(Assembler::equal, dispatch);
+      __ jcc(Assembler::equal, maybe_load_mdp);
 
       // We have the address of an on stack replacement routine in rax,
       // We need to prepare to execute the OSR method. First we must
@@ -1766,6 +1767,11 @@
 
       // and begin the OSR nmethod
       __ jmp(Address(rbx, nmethod::osr_entry_point_offset()));
+
+      // Load the MDO in case it was created by frequency_counter_overflow
+      __ bind(maybe_load_mdp);
+      __ set_method_data_pointer_for_bcp();
+      __ jmp(dispatch);
     }
   }
 }
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -107,10 +107,6 @@
   return Address(rsp,  Interpreter::expr_offset_in_bytes(2));
 }
 
-static inline Address at_tos_p3() {
-  return Address(rsp,  Interpreter::expr_offset_in_bytes(3));
-}
-
 // Condition conversion
 static Assembler::Condition j_not(TemplateTable::Condition cc) {
   switch (cc) {
@@ -1757,17 +1753,18 @@
                  rdx);
       __ load_unsigned_byte(rbx, Address(r13, 0));  // restore target bytecode
 
+      Label maybe_load_mdp;
       // rax: osr nmethod (osr ok) or NULL (osr not possible)
-      // ebx: target bytecode
+      // rbx: target bytecode
       // rdx: scratch
       // r14: locals pointer
       // r13: bcp
       __ testptr(rax, rax);                        // test result
-      __ jcc(Assembler::zero, dispatch);         // no osr if null
+      __ jcc(Assembler::zero, maybe_load_mdp);     // no osr if null
       // nmethod may have been invalidated (VM may block upon call_VM return)
       __ movl(rcx, Address(rax, nmethod::entry_bci_offset()));
       __ cmpl(rcx, InvalidOSREntryBci);
-      __ jcc(Assembler::equal, dispatch);
+      __ jcc(Assembler::equal, maybe_load_mdp);
 
       // We have the address of an on stack replacement routine in eax
       // We need to prepare to execute the OSR method. First we must
@@ -1803,6 +1800,11 @@
 
       // and begin the OSR nmethod
       __ jmp(Address(r13, nmethod::osr_entry_point_offset()));
+
+      // Load the MDO in case it was created by frequency_counter_overflow
+      __ bind(maybe_load_mdp);
+      __ set_method_data_pointer_for_bcp();
+      __ jmp(dispatch);
     }
   }
 }
@@ -3096,7 +3098,12 @@
 
   // get target Method* & entry point
   __ lookup_virtual_method(rax, index, method);
+#if INCLUDE_JVMCI
+  // r14: MethodDataPointer (r14 is callee saved)
+  __ profile_called_method(method, r14, r13);
+#endif
   __ profile_arguments_type(rdx, method, r13, true);
+
   __ jump_from_interpreted(method, rdx);
 }
 
@@ -3183,7 +3190,7 @@
   __ lookup_interface_method(// inputs: rec. class, interface, itable index
                              rdx, rax, rbx,
                              // outputs: method, scan temp. reg
-                             rbx, r13,
+                             rbx, r14,
                              no_such_interface);
 
   // rbx: Method* to call
@@ -3195,6 +3202,10 @@
   __ testptr(rbx, rbx);
   __ jcc(Assembler::zero, no_such_method);
 
+#if INCLUDE_JVMCI
+  // r13: MethodDataPointer (r13 is callee saved)
+  __ profile_called_method(rbx, r13, r14);
+#endif
   __ profile_arguments_type(rdx, rbx, r13, true);
 
   // do the call
--- a/src/cpu/x86/vm/vmStructs_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/vmStructs_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,13 +37,44 @@
   /******************************/                                                                                                   \
   /* JavaFrameAnchor            */                                                                                                   \
   /******************************/                                                                                                   \
-  volatile_nonstatic_field(JavaFrameAnchor,     _last_Java_fp,                                    intptr_t*)
+  volatile_nonstatic_field(JavaFrameAnchor,     _last_Java_fp,                                    intptr_t*)                         \
+  static_field(VM_Version, _cpuFeatures, int)
 
 
 
-#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
+  declare_toplevel_type(VM_Version)
 
-#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
+  LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes))       \
+  declare_constant(frame::interpreter_frame_sender_sp_offset)       \
+  declare_constant(frame::interpreter_frame_last_sp_offset)         \
+  declare_constant(VM_Version::CPU_CX8)                             \
+  declare_constant(VM_Version::CPU_CMOV)                            \
+  declare_constant(VM_Version::CPU_FXSR)                            \
+  declare_constant(VM_Version::CPU_HT)                              \
+  declare_constant(VM_Version::CPU_MMX)                             \
+  declare_constant(VM_Version::CPU_3DNOW_PREFETCH)                  \
+  declare_constant(VM_Version::CPU_SSE)                             \
+  declare_constant(VM_Version::CPU_SSE2)                            \
+  declare_constant(VM_Version::CPU_SSE3)                            \
+  declare_constant(VM_Version::CPU_SSSE3)                           \
+  declare_constant(VM_Version::CPU_SSE4A)                           \
+  declare_constant(VM_Version::CPU_SSE4_1)                          \
+  declare_constant(VM_Version::CPU_SSE4_2)                          \
+  declare_constant(VM_Version::CPU_POPCNT)                          \
+  declare_constant(VM_Version::CPU_LZCNT)                           \
+  declare_constant(VM_Version::CPU_TSC)                             \
+  declare_constant(VM_Version::CPU_TSCINV)                          \
+  declare_constant(VM_Version::CPU_AVX)                             \
+  declare_constant(VM_Version::CPU_AVX2)                            \
+  declare_constant(VM_Version::CPU_AES)                             \
+  declare_constant(VM_Version::CPU_ERMS)                            \
+  declare_constant(VM_Version::CPU_CLMUL)                           \
+  declare_constant(VM_Version::CPU_BMI1)                            \
+  declare_constant(VM_Version::CPU_BMI2)                            \
+  declare_constant(VM_Version::CPU_RTM)                             \
+  declare_constant(VM_Version::CPU_ADX)
 
 #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
 
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -667,6 +667,8 @@
       FLAG_SET_DEFAULT(UseFPUForSpilling, false);
     }
   }
+#endif
+#if defined(COMPILER2) || INCLUDE_JVMCI
   if (MaxVectorSize > 0) {
     if (!is_power_of_2(MaxVectorSize)) {
       warning("MaxVectorSize must be a power of 2");
@@ -684,7 +686,7 @@
       FLAG_SET_DEFAULT(MaxVectorSize, 0);
     }
 #ifdef ASSERT
-    if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
+    if (supports_avx() && PrintMiscellaneous && Verbose) {
       tty->print_cr("State of YMM registers after signal handle:");
       int nreg = 2 LP64_ONLY(+2);
       const char* ymm_name[4] = {"0", "7", "8", "15"};
@@ -698,7 +700,9 @@
     }
 #endif
   }
+#endif
 
+#ifdef COMPILER2
 #ifdef _LP64
   if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
     UseMultiplyToLenIntrinsic = true;
--- a/src/cpu/x86/vm/vm_version_x86.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/vm_version_x86.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -29,6 +29,7 @@
 #include "runtime/vm_version.hpp"
 
 class VM_Version : public Abstract_VM_Version {
+  friend class VMStructs;
 public:
   // cpuid result register layouts.  These are all unions of a uint32_t
   // (in case anyone wants access to the register as a whole) and a bitfield.
--- a/src/cpu/x86/vm/vmreg_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/cpu/x86/vm/vmreg_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -48,8 +48,9 @@
 
   XMMRegister xreg = ::as_XMMRegister(0);
   for ( ; i < ConcreteRegisterImpl::max_xmm ; ) {
-    for (int j = 0 ; j < 8 ; j++) {
-      regName[i++] = xreg->name();
+    regName[i++] = xreg->name();
+    for (int j = 1 ; j < 8 ; j++) {
+      regName[i++] = xreg->sub_word_name(j);
     }
     xreg = xreg->successor();
   }
--- a/src/os/solaris/vm/os_solaris.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/os/solaris/vm/os_solaris.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -4156,7 +4156,6 @@
   return fetcher.result();
 }
 
-
 // This does not do anything on Solaris. This is basically a hook for being
 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
 void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
--- a/src/os/solaris/vm/os_solaris.inline.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/os/solaris/vm/os_solaris.inline.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -71,6 +71,8 @@
 }
 inline void os::dll_unload(void *lib) { ::dlclose(lib); }
 
+inline const int os::default_file_open_flags() { return 0;}
+
 inline DIR* os::opendir(const char* dirname) {
   assert(dirname != NULL, "just checking");
   return ::opendir(dirname);
--- a/src/os/windows/vm/os_windows.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/os/windows/vm/os_windows.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2258,12 +2258,25 @@
   #ifdef  _M_AMD64
   PCONTEXT ctx = exceptionInfo->ContextRecord;
   address pc = (address)ctx->Rip;
+#if INCLUDE_JVMCI
+  assert(pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && pc[1] == 0xF7 || pc[0] == 0xF7, "not an idiv opcode");
+  if (pc[0] == 0xF7) {
+    // set correct result values and continue after idiv instruction
+    ctx->Rip = (DWORD64)pc + 2;        // idiv reg, reg  is 2 bytes
+  } else {
+    ctx->Rip = (DWORD64)pc + 3;        // REX idiv reg, reg  is 3 bytes
+  }
+  // do not set ctx->Rax as it already contains the correct value (either 32 or 64 bit, depending on the operation)
+  // this is the case because the exception only happens for -MinValue/-1 and -MinValue is always in rax because of the
+  // idiv opcode (0xF7)
+#else
   assert(pc[0] == 0xF7, "not an idiv opcode");
   assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands");
   assert(ctx->Rax == min_jint, "unexpected idiv exception");
   // set correct result values and continue after idiv instruction
   ctx->Rip = (DWORD)pc + 2;        // idiv reg, reg  is 2 bytes
   ctx->Rax = (DWORD)min_jint;      // result
+#endif // JVMCI
   ctx->Rdx = (DWORD)0;             // remainder
   // Continue the execution
   #else
--- a/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -66,8 +66,8 @@
 
     frame ret_frame(ret_sp, ret_fp, addr.pc());
     if (!ret_frame.safe_for_sender(jt)) {
-#ifdef COMPILER2
-      // C2 uses ebp as a general register see if NULL fp helps
+#if defined(COMPILER2) || INCLUDE_JVMCI
+      // C2 and JVMCI use ebp as a general register see if NULL fp helps
       frame ret_frame2(ret_sp, NULL, addr.pc());
       if (!ret_frame2.safe_for_sender(jt)) {
         // nothing else to try if the frame isn't good
@@ -77,7 +77,7 @@
 #else
       // nothing else to try if the frame isn't good
       return false;
-#endif /* COMPILER2 */
+#endif /* COMPILER2 || INCLUDE_JVMCI */
     }
     *fr_addr = ret_frame;
     return true;
--- a/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -67,8 +67,8 @@
 
     frame ret_frame(ret_sp, ret_fp, addr.pc());
     if (!ret_frame.safe_for_sender(jt)) {
-#ifdef COMPILER2
-      // C2 uses ebp as a general register see if NULL fp helps
+#if defined(COMPILER2) || INCLUDE_JVMCI
+      // C2 and JVMCI use ebp as a general register see if NULL fp helps
       frame ret_frame2(ret_sp, NULL, addr.pc());
       if (!ret_frame2.safe_for_sender(jt)) {
         // nothing else to try if the frame isn't good
@@ -78,7 +78,7 @@
 #else
       // nothing else to try if the frame isn't good
       return false;
-#endif /* COMPILER2 */
+#endif /* COMPILER2 || INCLUDE_JVMCI */
     }
     *fr_addr = ret_frame;
     return true;
--- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -24,6 +24,7 @@
 
 // no precompiled headers
 #include "asm/macroAssembler.hpp"
+#include "macroAssembler_sparc.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
--- a/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -74,8 +74,8 @@
 
     frame ret_frame(ret_sp, ret_fp, addr.pc());
     if (!ret_frame.safe_for_sender(jt)) {
-#ifdef COMPILER2
-      // C2 uses ebp as a general register see if NULL fp helps
+#if defined(COMPILER2) || INCLUDE_JVMCI
+      // C2 and JVMCI use ebp as a general register see if NULL fp helps
       frame ret_frame2(ret_sp, NULL, addr.pc());
       if (!ret_frame2.safe_for_sender(jt)) {
         // nothing else to try if the frame isn't good
@@ -85,7 +85,7 @@
 #else
       // nothing else to try if the frame isn't good
       return false;
-#endif /* COMPILER2 */
+#endif /* COMPILER2 || INCLUDE_JVMCI */
     }
     *fr_addr = ret_frame;
     return true;
--- a/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/build-impl.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/build-impl.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="com.sun.hotspot.igv.svg-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/suite-private.properties"/>
     <property file="nbproject/suite.properties"/>
     <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
@@ -16,13 +23,21 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
             </not>
         </condition>
     </fail>
--- a/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/genfiles.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/genfiles.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=ebcf0422
-build.xml.script.CRC32=d7a2678d
-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=ebcf0422
-nbproject/build-impl.xml.script.CRC32=57997f94
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.script.CRC32=42ef3ff6
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- a/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,40 +25,58 @@
 
 import java.awt.Graphics2D;
 import java.io.Writer;
+import java.io.File;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
 import org.w3c.dom.DOMImplementation;
 
 /**
- *
+ * Utility class
  * @author Thomas Wuerthinger
  */
 public class BatikSVG {
 
+    private BatikSVG() {
+    }
+
     private static Constructor SVGGraphics2DConstructor;
-    private static Method Method_stream;
-    private static Method Method_createDefault;
-    private static Method Method_getDOMImplementation;
-    private static Method Method_setEmbeddedFontsOn;
+    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 Class_GenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation");
-                Class Class_SVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext");
-                Class Class_SVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D");
-                Method_getDOMImplementation = Class_GenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]);
-                Method_createDefault = Class_SVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class});
-                Method_setEmbeddedFontsOn = Class_SVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class});
-                Method_stream = Class_SVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class);
-                SVGGraphics2DConstructor = Class_SVGGraphics2D.getConstructor(Class_SVGGeneratorContext, boolean.class);
+                String batikJar = System.getenv().get("IGV_BATIK_JAR");
+                if (batikJar == null) {
+                    return null;
+                }
+                // Load batik in it's own class loader since some it's support jars interfere with the JDK
+                URL url = new File(batikJar).toURI().toURL();
+                ClassLoader cl = new URLClassLoader(new URL[] { url });
+                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) Method_getDOMImplementation.invoke(null);
+            DOMImplementation dom = (DOMImplementation) getDOMImplementationMethod.invoke(null);
             org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null);
-            Object ctx = Method_createDefault.invoke(null, document);
-            Method_setEmbeddedFontsOn.invoke(ctx, true);
+            Object ctx = createDefaultMethod.invoke(null, document);
+            setEmbeddedFontsOnMethod.invoke(ctx, true);
             Graphics2D svgGenerator = (Graphics2D) SVGGraphics2DConstructor.newInstance(ctx, true);
             return svgGenerator;
         } catch (ClassNotFoundException e) {
@@ -71,12 +89,22 @@
             return null;
         } catch (InstantiationException e) {
             return null;
+        } catch (MalformedURLException 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 {
-            Method_stream.invoke(svgGenerator, stream, useCSS);
+            streamMethod.invoke(svgGenerator, stream, useCSS);
         } catch (IllegalAccessException e) {
             assert false;
         } catch (InvocationTargetException e) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/package-info.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+/**
+ * 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;
+
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/manifest.mf	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/manifest.mf	Mon Feb 06 17:18:57 2017 +0100
@@ -1,6 +1,6 @@
-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
-
+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
+
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -15,12 +15,36 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.jdesktop.layout</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.39.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -28,7 +52,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11</specification-version>
+                        <specification-version>6.34.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -36,7 +60,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -44,7 +68,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +84,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
-CTL_BytecodeViewAction=Open BytecodeView Window
-CTL_BytecodeViewTopComponent=BytecodeView Window
+CTL_BytecodeViewAction=Bytecode
+CTL_BytecodeViewTopComponent=Bytecode
 CTL_SelectBytecodesAction=Select nodes
-HINT_BytecodeViewTopComponent=This is a BytecodeView window
+HINT_BytecodeViewTopComponent=Shows the bytecode associated with the displayed graph.
 OpenIDE-Module-Name=Bytecodes
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,14 +29,14 @@
 import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
 import java.awt.Image;
-import java.util.HashSet;
+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.Utilities;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -49,29 +49,35 @@
     public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) {
 
         super(Children.LEAF);
-        this.setDisplayName(bytecode.getBci() + " " + bytecode.getName());
+        String displayName = bytecode.getBci() + " " + bytecode.getName() + " " + bytecode.getOperands();
 
         bciValue = bytecode.getBci() + " " + bciValue;
         bciValue = bciValue.trim();
 
-        Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<InputNode>(graph.getNodes());
+        Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(graph.getNodes());
         StringPropertyMatcher matcher = new StringPropertyMatcher("bci", bciValue);
         List<InputNode> nodeList = selector.selectMultiple(matcher);
         if (nodeList.size() > 0) {
-            nodes = new HashSet<InputNode>();
+            nodes = new LinkedHashSet<>();
             for (InputNode n : nodeList) {
                 nodes.add(n);
             }
-            this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)");
+            displayName += " (" + nodes.size() + " nodes)";
         }
+
+        if (bytecode.getComment() != null) {
+            displayName += " // " + bytecode.getComment();
+        }
+
+        this.setDisplayName(displayName);
     }
 
     @Override
     public Image getIcon(int i) {
         if (nodes != null) {
-            return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.gif");
+            return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.png");
         } else {
-            return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.gif");
+            return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.png");
         }
     }
 
@@ -91,6 +97,7 @@
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
         if (aClass == SelectBytecodesCookie.class && nodes != null) {
             return (T) (new SelectBytecodesCookie(nodes));
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
         super(NbBundle.getMessage(BytecodeViewAction.class, "CTL_BytecodeViewAction"));
     }
 
+    @Override
     public void actionPerformed(ActionEvent evt) {
         TopComponent win = BytecodeViewTopComponent.findInstance();
         win.open();
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form	Mon Feb 06 17:18:57 2017 +0100
@@ -3,6 +3,8 @@
 <Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 import com.sun.hotspot.igv.data.Group;
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
 import java.awt.BorderLayout;
 import java.io.Serializable;
 import javax.swing.SwingUtilities;
@@ -33,11 +34,7 @@
 import org.openide.explorer.ExplorerManager;
 import org.openide.explorer.ExplorerUtils;
 import org.openide.explorer.view.BeanTreeView;
-import org.openide.util.Lookup;
-import org.openide.util.LookupEvent;
-import org.openide.util.LookupListener;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
+import org.openide.util.*;
 import org.openide.windows.TopComponent;
 import org.openide.windows.WindowManager;
 
@@ -91,6 +88,7 @@
     }// </editor-fold>//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.
@@ -126,7 +124,7 @@
 
     @Override
     public void componentOpened() {
-        Lookup.Template tpl = new Lookup.Template(Object.class);
+        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<>(InputGraphProvider.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
     }
@@ -147,23 +145,47 @@
         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 = Lookup.getDefault().lookup(InputGraphProvider.class);
-        if (p != null) {
+        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
             SwingUtilities.invokeLater(new Runnable() {
+                @Override
                 public void run() {
-            InputGraph graph = p.getGraph();
-            if (graph != null) {
-                Group g = graph.getGroup();
-                rootNode.update(graph, g.getMethod());
-            }
-        }
+                if (p != null) {
+                    InputGraph graph = p.getGraph();
+                    if (graph != null) {
+                        Group g = graph.getGroup();
+                        rootNode.update(graph, g.getMethod());
+                        return;
+                    }
+                }
+                        rootNode.update(null, null);
+                    }
             });
-        }
+
     }
 
     final static class ResolvableHelper implements Serializable {
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Utilities;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -38,7 +38,7 @@
  */
 public class MethodNode extends AbstractNode {
 
-    private static class MethodNodeChildren extends Children.Keys {
+    private static class MethodNodeChildren extends Children.Keys<InputBytecode> {
 
         private InputMethod method;
         private InputGraph graph;
@@ -50,9 +50,8 @@
             this.graph = graph;
         }
 
-        protected Node[] createNodes(Object object) {
-            assert object instanceof InputBytecode;
-            InputBytecode bc = (InputBytecode) object;
+        @Override
+        protected Node[] createNodes(InputBytecode bc) {
             if (bc.getInlined() == null) {
                 return new Node[]{new BytecodeNode(bc, graph, bciString)};
             } else {
@@ -84,7 +83,7 @@
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.png");
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,9 +24,9 @@
 package com.sun.hotspot.igv.bytecodes;
 
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
 import org.openide.util.actions.CookieAction;
 
@@ -36,22 +36,26 @@
  */
 public final class SelectBytecodesAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class);
-        InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        InputGraphProvider p = 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
@@ -64,6 +68,7 @@
         putValue("noIconInMenu", Boolean.TRUE);
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -73,3 +78,4 @@
         return false;
     }
 }
+
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesCookie.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesCookie.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.png has changed
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/manifest.mf	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/manifest.mf	Mon Feb 06 17:18:57 2017 +0100
@@ -1,6 +1,6 @@
-Manifest-Version: 1.0
-OpenIDE-Module: com.sun.hotspot.igv.controlflow
-OpenIDE-Module-Layer: com/sun/hotspot/igv/controlflow/layer.xml
-OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/controlflow/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.0
-
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.controlflow
+OpenIDE-Module-Layer: com/sun/hotspot/igv/controlflow/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/controlflow/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -31,12 +31,20 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.jdesktop.layout</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +60,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockConnectionWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockConnectionWidget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,9 @@
 import com.sun.hotspot.igv.data.InputBlockEdge;
 import com.sun.hotspot.igv.layout.Link;
 import com.sun.hotspot.igv.layout.Port;
+import java.awt.BasicStroke;
 import java.awt.Point;
+import java.awt.Stroke;
 import java.util.ArrayList;
 import java.util.List;
 import org.netbeans.api.visual.widget.ConnectionWidget;
@@ -37,12 +39,19 @@
  */
 public class BlockConnectionWidget extends ConnectionWidget implements Link {
 
+    private static final Stroke NORMAL_STROKE = new BasicStroke(1.0f);
+    private static final Stroke BOLD_STROKE = new BasicStroke(2.5f);
+    private static final Stroke DASHED_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{5, 5}, 0);
+    private static final Stroke BOLD_DASHED_STROKE = new BasicStroke(2.5f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{5, 5}, 0);
+
     private BlockWidget from;
     private BlockWidget to;
     private Port inputSlot;
     private Port outputSlot;
     private List<Point> points;
     private InputBlockEdge edge;
+    private boolean isDashed = false;
+    private boolean isBold = false;
 
     public BlockConnectionWidget(ControlFlowScene scene, InputBlockEdge edge) {
         super(scene);
@@ -67,6 +76,30 @@
         return outputSlot;
     }
 
+    public void setBold(boolean bold) {
+        this.isBold = bold;
+        updateStroke();
+    }
+
+    public void setDashed(boolean dashed) {
+        this.isDashed = dashed;
+        updateStroke();
+    }
+
+    private void updateStroke() {
+        Stroke stroke = NORMAL_STROKE;
+        if (isBold) {
+            if (isDashed) {
+                stroke = BOLD_DASHED_STROKE;
+            } else {
+                stroke = BOLD_STROKE;
+            }
+        } else if (isDashed) {
+            stroke = DASHED_STROKE;
+        }
+        setStroke(stroke);
+    }
+
     public void setControlPoints(List<Point> p) {
         this.points = p;
     }
@@ -80,4 +113,9 @@
     public String toString() {
         return "Connection[ " + from.toString() + " - " + to.toString() + "]";
     }
+
+    @Override
+    public boolean isVIP() {
+        return isBold;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockWidget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.Point;
+import java.awt.Rectangle;
 import org.netbeans.api.visual.border.BorderFactory;
 import org.netbeans.api.visual.model.ObjectState;
 import org.netbeans.api.visual.widget.LabelWidget;
@@ -41,13 +42,13 @@
  */
 public class BlockWidget extends LabelWidget implements Vertex {
 
-    public static final Dimension SIZE = new Dimension(20, 20);
+    public static final Dimension MIN_SIZE = new Dimension(20, 20);
     private InputBlock block;
     private Port inputSlot;
     private Port outputSlot;
     private Cluster cluster;
     private boolean root;
-    private static final Font font = new Font(Font.SERIF, Font.PLAIN, 12);
+    private static final Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
     private static final Font boldFont = font.deriveFont(Font.BOLD);
     public static final Color NORMAL_FOREGROUND_COLOR = Color.BLACK;
     public static final Color HOVER_FOREGROUND_COLOR = Color.BLUE;
@@ -59,29 +60,24 @@
         this.setLabel(block.getName());
         this.setForeground(NORMAL_FOREGROUND_COLOR);
         this.setBorder(BorderFactory.createLineBorder(1, NORMAL_FOREGROUND_COLOR));
-        this.setMinimumSize(SIZE);
-        this.setMaximumSize(SIZE);
+        this.setMinimumSize(MIN_SIZE);
 
         this.setFont(font);
+        this.setAlignment(Alignment.CENTER);
 
         final BlockWidget widget = this;
         inputSlot = new Port() {
-
             public Point getRelativePosition() {
-                return new Point((int) (SIZE.getWidth() / 2), (int) (SIZE.getHeight() / 2));
+                return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
             }
-
             public Vertex getVertex() {
                 return widget;
             }
         };
-
         outputSlot = new Port() {
-
             public Point getRelativePosition() {
-                return new Point((int) (SIZE.getWidth() / 2), (int) (SIZE.getHeight() / 2));
+                return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
             }
-
             public Vertex getVertex() {
                 return widget;
             }
@@ -101,7 +97,12 @@
     }
 
     public Dimension getSize() {
-        return SIZE;
+        Rectangle bounds = getBounds();
+        if (bounds != null) {
+            return bounds.getSize();
+        } else {
+            return MIN_SIZE;
+        }
     }
 
     public void setPosition(Point p) {
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,4 +1,4 @@
-CTL_ControlFlowAction=Open ControlFlow Window
-CTL_ControlFlowTopComponent=ControlFlow Window
-HINT_ControlFlowTopComponent=This is a ControlFlow window
+CTL_ControlFlowAction=Control Flow
+CTL_ControlFlowTopComponent=Control Flow
+HINT_ControlFlowTopComponent=Shows the blocks of the current graph.
 OpenIDE-Module-Name=ControlFlow
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,17 +23,17 @@
  */
 package com.sun.hotspot.igv.controlflow;
 
+import com.sun.hotspot.igv.data.InputBlockEdge;
 import com.sun.hotspot.igv.data.InputBlock;
-import com.sun.hotspot.igv.data.InputBlockEdge;
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.util.LookupHistory;
 import java.awt.Color;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.HashMap;
 import java.util.Set;
 import javax.swing.BorderFactory;
 import org.netbeans.api.visual.action.ActionFactory;
@@ -44,15 +44,14 @@
 import org.netbeans.api.visual.action.WidgetAction;
 import org.netbeans.api.visual.anchor.AnchorFactory;
 import org.netbeans.api.visual.anchor.AnchorShape;
-import org.netbeans.api.visual.layout.LayoutFactory;
 import org.netbeans.api.visual.router.RouterFactory;
 import org.netbeans.api.visual.widget.LayerWidget;
 import org.netbeans.api.visual.widget.Widget;
 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.widget.ConnectionWidget;
-import org.openide.util.Lookup;
 
 /**
  *
@@ -61,13 +60,12 @@
 public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider {
 
     private HashSet<BlockWidget> selection;
-    private HashMap<InputBlock, BlockWidget> blockMap;
     private InputGraph oldGraph;
     private LayerWidget edgeLayer;
     private LayerWidget mainLayer;
     private LayerWidget selectLayer;
     private WidgetAction hoverAction = this.createWidgetHoverAction();
-    private WidgetAction selectAction = ActionFactory.createSelectAction(this);
+    private WidgetAction selectAction = new DoubleClickSelectAction(this);
     private WidgetAction moveAction = ActionFactory.createMoveAction(null, this);
 
     public ControlFlowScene() {
@@ -111,27 +109,21 @@
             addNode(b);
         }
 
-        for (InputBlock b : g.getBlocks()) {
-            for (InputBlockEdge e : b.getOutputs()) {
-                addEdge(e);
-                assert g.getBlocks().contains(e.getFrom());
-                assert g.getBlocks().contains(e.getTo());
-                this.setEdgeSource(e, e.getFrom());
-                this.setEdgeTarget(e, e.getTo());
-            }
+        for (InputBlockEdge e : g.getBlockEdges()) {
+            addEdge(e);
+            assert g.getBlocks().contains(e.getFrom());
+            assert g.getBlocks().contains(e.getTo());
+            this.setEdgeSource(e, e.getFrom());
+            this.setEdgeTarget(e, e.getTo());
         }
 
-        GraphLayout layout = new HierarchicalGraphLayout();//GridGraphLayout();
+        GraphLayout<InputBlock, InputBlockEdge> layout = new HierarchicalGraphLayout<InputBlock, InputBlockEdge>();//GridGraphLayout();
         SceneLayout sceneLayout = LayoutFactory.createSceneGraphLayout(this, layout);
         sceneLayout.invokeLayout();
 
         this.validate();
     }
 
-    public BlockWidget getBlockWidget(InputBlock b) {
-        return blockMap.get(b);
-    }
-
     public void clearSelection() {
         for (BlockWidget w : selection) {
             w.setState(w.getState().deriveSelected(false));
@@ -141,7 +133,7 @@
     }
 
     public void selectionChanged() {
-        InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
         if (p != null) {
             Set<InputNode> inputNodes = new HashSet<InputNode>();
             for (BlockWidget w : selection) {
@@ -204,15 +196,19 @@
     }
 
     public void setNewLocation(Widget widget, Point location) {
-        Point originalLocation = getOriginalLocation(widget);
-        int xOffset = location.x - originalLocation.x;
-        int yOffset = location.y - originalLocation.y;
-        for (Widget w : this.selection) {
-            Point p = new Point(w.getPreferredLocation());
-            p.translate(xOffset, yOffset);
-            w.setPreferredLocation(p);
+        if (selection.contains(widget)) {
+            // move entire selection
+            Point originalLocation = getOriginalLocation(widget);
+            int xOffset = location.x - originalLocation.x;
+            int yOffset = location.y - originalLocation.y;
+            for (Widget w : selection) {
+                Point p = new Point(w.getPreferredLocation());
+                p.translate(xOffset, yOffset);
+                w.setPreferredLocation(p);
+            }
+        } else {
+            widget.setPreferredLocation(location);
         }
-
     }
 
     public Widget createSelectionWidget() {
@@ -271,7 +267,15 @@
     }
 
     protected Widget attachEdgeWidget(InputBlockEdge edge) {
-        ConnectionWidget w = new BlockConnectionWidget(this, edge);
+        BlockConnectionWidget w = new BlockConnectionWidget(this, edge);
+        switch (edge.getState()) {
+            case NEW:
+                w.setBold(true);
+                break;
+            case DELETED:
+                w.setDashed(true);
+                break;
+        }
         w.setRouter(RouterFactory.createDirectRouter());
         w.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
         edgeLayer.addChild(w);
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.form	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.form	Mon Feb 06 17:18:57 2017 +0100
@@ -3,6 +3,8 @@
 <Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
 import java.awt.BorderLayout;
 import java.io.Serializable;
 import javax.swing.JScrollPane;
@@ -63,17 +64,7 @@
         this.add(panel, BorderLayout.CENTER);
     }
 
-    @Override
-    public void requestFocus() {
-        super.requestFocus();
-        scene.getView().requestFocus();
-    }
 
-    @Override
-    public boolean requestFocusInWindow() {
-        super.requestFocusInWindow();
-        return scene.getView().requestFocusInWindow();
-    }
 
     /** This method is called from within the constructor to
      * initialize the form.
@@ -96,6 +87,7 @@
     }// </editor-fold>//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.
@@ -131,7 +123,7 @@
 
     @Override
     public void componentOpened() {
-        Lookup.Template tpl = new Lookup.Template(Object.class);
+        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<InputGraphProvider>(InputGraphProvider.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
     }
@@ -143,16 +135,16 @@
     }
 
     public void resultChanged(LookupEvent lookupEvent) {
-
-        final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
         if (p != null) {
             SwingUtilities.invokeLater(new Runnable() {
+
                 public void run() {
-            InputGraph g = p.getGraph();
-            if (g != null) {
-                scene.setGraph(g);
-            }
-        }
+                    InputGraph g = p.getGraph();
+                    if (g != null) {
+                        scene.setGraph(g);
+                    }
+                }
             });
         }
     }
@@ -169,8 +161,8 @@
 
     @Override
     public void requestActive() {
-        scene.getView().requestFocusInWindow();
         super.requestActive();
+        scene.getView().requestFocus();
     }
 
     final static class ResolvableHelper implements Serializable {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/DoubleClickSelectAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.controlflow;
+
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import org.netbeans.api.visual.action.SelectProvider;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ * Selection action that acts on double-click only. Does not support aiming.
+ *
+ * @author Peter Hofer
+ */
+public class DoubleClickSelectAction extends WidgetAction.LockedAdapter {
+
+    private final SelectProvider provider;
+
+    public DoubleClickSelectAction(SelectProvider provider) {
+        this.provider = provider;
+    }
+
+    protected boolean isLocked() {
+        return false;
+    }
+
+    @Override
+    public State mousePressed(Widget widget, WidgetMouseEvent event) {
+        if (event.getClickCount() >= 2 && (event.getButton() == MouseEvent.BUTTON1 || event.getButton() == MouseEvent.BUTTON2)) {
+            boolean invert = (event.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0;
+            Point point = event.getPoint();
+            if (provider.isSelectionAllowed(widget, point, invert)) {
+                provider.select(widget, point, invert);
+                return State.CHAIN_ONLY;
+            }
+        }
+        return State.REJECTED;
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/HierarchicalGraphLayout.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/HierarchicalGraphLayout.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -76,6 +76,10 @@
         public void setControlPoints(List<Point> list) {
         // Do nothing for now
         }
+
+        public boolean isVIP() {
+            return false;
+        }
     }
 
     private class VertexWrapper implements Vertex {
@@ -127,6 +131,7 @@
         }
 
         public int compareTo(Vertex o) {
+            @SuppressWarnings("unchecked")
             VertexWrapper vw = (VertexWrapper) o;
             return node.toString().compareTo(vw.node.toString());
         }
@@ -138,8 +143,8 @@
 
     protected void performGraphLayout(UniversalGraph<N, E> graph) {
 
-        Set<LinkWrapper> links = new HashSet<LinkWrapper>();
-        Set<VertexWrapper> vertices = new HashSet<VertexWrapper>();
+        Set<LinkWrapper> links = new LinkedHashSet<LinkWrapper>();
+        Set<VertexWrapper> vertices = new LinkedHashSet<VertexWrapper>();
         Map<N, VertexWrapper> vertexMap = new HashMap<N, VertexWrapper>();
 
         for (N node : graph.getNodes()) {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -1,126 +1,142 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://www.netbeans.org/ns/project/1">
-    <type>org.netbeans.modules.apisupport.project</type>
-    <configuration>
-        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
-            <code-name-base>com.sun.hotspot.igv.coordinator</code-name-base>
-            <suite-component/>
-            <module-dependencies>
-                <dependency>
-                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.0</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>com.sun.hotspot.igv.difference</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.0</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>com.sun.hotspot.igv.settings</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.0</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.0</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.netbeans.api.progress</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <release-version>1</release-version>
-                        <specification-version>1.10.0.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.actions</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.6.1.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.awt</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.dialogs</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>7.5.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.explorer</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.11</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.filesystems</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>7.3</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.loaders</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.7</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.nodes</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.util</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.windows</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.16</specification-version>
-                    </run-dependency>
-                </dependency>
-            </module-dependencies>
-            <public-packages/>
-        </data>
-    </configuration>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.coordinator</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.connection</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.difference</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.settings</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.23.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.actions</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.21.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.30.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.18.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.explorer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.34.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.20.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.20.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.39.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupOrganizer	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-com.sun.hotspot.igv.coordinator.StandardGroupOrganizer
-com.sun.hotspot.igv.coordinator.GraphCountGroupOrganizer
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,7 +1,6 @@
-
-AdvancedOption_DisplayName_Coordinator=Settings
-AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
-CTL_OutlineTopComponent=Outline Window
-CTL_SomeAction=test
-HINT_OutlineTopComponent=This is a Outline window
-OpenIDE-Module-Name=Coordinator
+AdvancedOption_DisplayName_Coordinator=Settings
+AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
+CTL_OutlineTopComponent=Outline
+CTL_SomeAction=test
+HINT_OutlineTopComponent=Displays loaded groups of graphs.
+OpenIDE-Module-Name=Coordinator
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,18 +24,15 @@
 package com.sun.hotspot.igv.coordinator;
 
 import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.data.*;
+import com.sun.hotspot.igv.util.PropertiesSheet;
 import java.awt.Image;
-import java.util.ArrayList;
 import java.util.List;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Utilities;
+import org.openide.nodes.Sheet;
+import org.openide.util.ImageUtilities;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 
@@ -45,107 +42,82 @@
  */
 public class FolderNode extends AbstractNode {
 
-    private GroupOrganizer organizer;
     private InstanceContent content;
-    private List<Pair<String, List<Group>>> structure;
-    private List<String> subFolders;
     private FolderChildren children;
 
-    private static class FolderChildren extends Children.Keys implements ChangedListener<Group> {
+    private static class FolderChildren extends Children.Keys<FolderElement> implements ChangedListener {
+
+        private final Folder folder;
 
-        private FolderNode parent;
-        private List<Group> registeredGroups;
-
-        public void setParent(FolderNode parent) {
-            this.parent = parent;
-            this.registeredGroups = new ArrayList<Group>();
+        public FolderChildren(Folder folder) {
+            this.folder = folder;
+            folder.getChangedEvent().addListener(this);
         }
 
         @Override
-        protected Node[] createNodes(Object arg0) {
-
-            for(Group g : registeredGroups) {
-                g.getChangedEvent().removeListener(this);
-            }
-            registeredGroups.clear();
-
-            Pair<String, List<Group>> p = (Pair<String, List<Group>>) arg0;
-            if (p.getLeft().length() == 0) {
-
-                List<Node> curNodes = new ArrayList<Node>();
-                for (Group g : p.getRight()) {
-                    for (InputGraph graph : g.getGraphs()) {
-                        curNodes.add(new GraphNode(graph));
-                    }
-                    g.getChangedEvent().addListener(this);
-                    registeredGroups.add(g);
-                }
-
-                Node[] result = new Node[curNodes.size()];
-                for (int i = 0; i < curNodes.size(); i++) {
-                    result[i] = curNodes.get(i);
-                }
-                return result;
-
-            } else {
-                return new Node[]{new FolderNode(p.getLeft(), parent.organizer, parent.subFolders, p.getRight())};
+        protected Node[] createNodes(FolderElement e) {
+             if (e instanceof InputGraph) {
+                return new Node[]{new GraphNode((InputGraph) e)};
+            } else if (e instanceof Folder) {
+                 return new Node[]{new FolderNode((Folder) e)};
+             } else {
+                return null;
             }
         }
 
         @Override
         public void addNotify() {
-            this.setKeys(parent.structure);
+            this.setKeys(folder.getElements());
         }
 
-        public void changed(Group source) {
-            List<Pair<String, List<Group>>> newStructure = new ArrayList<Pair<String, List<Group>>>();
-            for(Pair<String, List<Group>> p : parent.structure) {
-                refreshKey(p);
-            }
-        }
+        @Override
+        public void changed(Object source) {
+            addNotify();
+         }
     }
 
-    protected InstanceContent getContent() {
-        return content;
+    @Override
+    protected Sheet createSheet() {
+        Sheet s = super.createSheet();
+        if (children.folder instanceof Properties.Entity) {
+            Properties.Entity p = (Properties.Entity) children.folder;
+            PropertiesSheet.initializeSheet(p.getProperties(), s);
+        }
+        return s;
     }
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.png");
     }
 
-    protected FolderNode(String name, GroupOrganizer organizer, List<String> subFolders, List<Group> groups) {
-        this(name, organizer, subFolders, groups, new FolderChildren(), new InstanceContent());
+    protected FolderNode(Folder folder) {
+        this(folder, new FolderChildren(folder), new InstanceContent());
     }
 
-    private FolderNode(String name, GroupOrganizer organizer, List<String> oldSubFolders, final List<Group> groups, FolderChildren children, InstanceContent content) {
+    private FolderNode(final Folder folder, FolderChildren children, InstanceContent content) {
         super(children, new AbstractLookup(content));
-        children.setParent(this);
         this.content = content;
         this.children = children;
-        content.add(new RemoveCookie() {
-
-            public void remove() {
-                for (Group g : groups) {
-                    if (g.getDocument() != null) {
-                        g.getDocument().removeGroup(g);
-                    }
+        if (folder instanceof FolderElement) {
+            final FolderElement folderElement = (FolderElement) folder;
+            this.setDisplayName(folderElement.getName());
+            content.add(new RemoveCookie() {
+                @Override
+                public void remove() {
+                    folderElement.getParent().removeElement(folderElement);
                 }
-            }
-        });
-        init(name, organizer, oldSubFolders, groups);
+            });
+        }
     }
 
-    public void init(String name, GroupOrganizer organizer, List<String> oldSubFolders, List<Group> groups) {
+    public void init(String name, List<Group> groups) {
         this.setDisplayName(name);
-        this.organizer = organizer;
-        this.subFolders = new ArrayList<String>(oldSubFolders);
-        if (name.length() > 0) {
-            this.subFolders.add(name);
+        children.addNotify();
+
+        for (Group g : groups) {
+            content.add(g);
         }
-        structure = organizer.organize(subFolders, groups);
-        assert structure != null;
-        children.addNotify();
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphCountGroupOrganizer.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +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.coordinator;
-
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.Pair;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class GraphCountGroupOrganizer implements GroupOrganizer {
-
-    public String getName() {
-        return "Graph count structure";
-    }
-
-    public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
-
-        List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
-
-        if (subFolders.size() == 0) {
-            Map<Integer, List<Group>> map = new HashMap<Integer, List<Group>>();
-            for (Group g : groups) {
-                Integer cur = g.getGraphs().size();
-                if (!map.containsKey(cur)) {
-                    map.put(cur, new ArrayList<Group>());
-                }
-                map.get(cur).add(g);
-            }
-
-            SortedSet<Integer> keys = new TreeSet<Integer>(map.keySet());
-            for (Integer i : keys) {
-                result.add(new Pair<String, List<Group>>("Graph count " + i, map.get(i)));
-            }
-
-        } else if (subFolders.size() == 1) {
-            for (Group g : groups) {
-                List<Group> children = new ArrayList<Group>();
-                children.add(g);
-                Pair<String, List<Group>> p = new Pair<String, List<Group>>();
-                p.setLeft(g.getName());
-                p.setRight(children);
-                result.add(p);
-            }
-        } else if (subFolders.size() == 2) {
-            result.add(new Pair<String, List<Group>>("", groups));
-        }
-
-        return result;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,23 +23,27 @@
  */
 package com.sun.hotspot.igv.coordinator;
 
+import com.sun.hotspot.igv.coordinator.actions.CloneGraphAction;
 import com.sun.hotspot.igv.coordinator.actions.DiffGraphAction;
 import com.sun.hotspot.igv.coordinator.actions.DiffGraphCookie;
-import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphCloneCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphOpenCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphRemoveCookie;
 import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.services.GraphViewer;
-import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.util.PropertiesSheet;
 import java.awt.Image;
 import javax.swing.Action;
 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.nodes.NodeAdapter;
+import org.openide.nodes.NodeEvent;
+import org.openide.nodes.NodeMemberEvent;
 import org.openide.nodes.Sheet;
+import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
-import org.openide.util.Utilities;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 
@@ -48,7 +52,6 @@
  * @author Thomas Wuerthinger
  */
 public class GraphNode extends AbstractNode {
-
     private InputGraph graph;
 
     /** Creates a new instance of GraphNode */
@@ -56,7 +59,7 @@
         this(graph, new InstanceContent());
     }
 
-    private GraphNode(final InputGraph graph, InstanceContent content) {
+    private GraphNode(InputGraph graph, InstanceContent content) {
         super(Children.LEAF, new AbstractLookup(content));
         this.graph = graph;
         this.setDisplayName(graph.getName());
@@ -66,19 +69,22 @@
 
         if (viewer != null) {
             // Action for opening the graph
-            content.add(new OpenCookie() {
-
-                public void open() {
-                    viewer.view(graph);
-                }
-            });
+            content.add(new GraphOpenCookie(viewer, graph));
         }
 
         // Action for removing a graph
-        content.add(new RemoveCookie() {
+        content.add(new GraphRemoveCookie(graph));
+
+        // Action for diffing to the current graph
+        content.add(new DiffGraphCookie(graph));
 
-            public void remove() {
-                graph.getGroup().removeGraph(graph);
+        // Action for cloning to the current graph
+        content.add(new GraphCloneCookie(viewer, graph));
+
+        this.addNodeListener(new NodeAdapter() {
+            @Override
+            public void childrenRemoved(NodeMemberEvent ev) {
+                GraphNode.this.graph = null;
             }
         });
     }
@@ -86,13 +92,17 @@
     @Override
     protected Sheet createSheet() {
         Sheet s = super.createSheet();
-        PropertiesSheet.initializeSheet(graph.getProperties(), s);
+        Properties p = new Properties();
+        p.add(graph.getProperties());
+        p.setProperty("nodeCount", Integer.toString(graph.getNodes().size()));
+        p.setProperty("edgeCount", Integer.toString(graph.getEdges().size()));
+        PropertiesSheet.initializeSheet(p, s);
         return s;
     }
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/graph.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/graph.png");
     }
 
     @Override
@@ -101,30 +111,28 @@
     }
 
     @Override
-    public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
-        if (aClass == DiffGraphCookie.class) {
-            InputGraphProvider graphProvider = Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
-
-            InputGraph graphA = null;
-            if (graphProvider != null) {
-                graphA = graphProvider.getGraph();
-            }
-
-            if (graphA != null && !graphA.isDifferenceGraph()) {
-                return (T) new DiffGraphCookie(graphA, graph);
-            }
-        }
-
-        return super.getCookie(aClass);
-    }
-
-    @Override
     public Action[] getActions(boolean b) {
-        return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
+        return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) CloneGraphAction.findObject(CloneGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
     }
 
     @Override
     public Action getPreferredAction() {
         return (Action) OpenAction.findObject(OpenAction.class, true);
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof GraphNode) {
+            return (graph == ((GraphNode) obj).graph);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return graph.hashCode();
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.form	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.form	Mon Feb 06 17:18:57 2017 +0100
@@ -3,6 +3,8 @@
 <Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
@@ -14,28 +16,17 @@
 
   <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
   <SubComponents>
-    <Container class="javax.swing.JPanel" name="jPanel2">
+    <Container class="javax.swing.JScrollPane" name="treeView">
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
+      </AuxValues>
       <Constraints>
         <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
           <BorderConstraints direction="Center"/>
         </Constraint>
       </Constraints>
 
-      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
-      <SubComponents>
-        <Container class="javax.swing.JScrollPane" name="jScrollPane1">
-          <AuxValues>
-            <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
-              <BorderConstraints direction="Center"/>
-            </Constraint>
-          </Constraints>
-
-          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
-        </Container>
-      </SubComponents>
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
     </Container>
   </SubComponents>
 </Form>
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,37 +23,25 @@
  */
 package com.sun.hotspot.igv.coordinator;
 
-import com.sun.hotspot.igv.coordinator.actions.ImportAction;
-import com.sun.hotspot.igv.coordinator.actions.RemoveAction;
-import com.sun.hotspot.igv.coordinator.actions.RemoveAllAction;
-import com.sun.hotspot.igv.coordinator.actions.SaveAllAction;
-import com.sun.hotspot.igv.coordinator.actions.SaveAsAction;
-import com.sun.hotspot.igv.coordinator.actions.StructuredViewAction;
+import com.sun.hotspot.igv.connection.Server;
+import com.sun.hotspot.igv.coordinator.actions.*;
 import com.sun.hotspot.igv.data.GraphDocument;
-import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.data.Group;
 import com.sun.hotspot.igv.data.services.GroupCallback;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import com.sun.hotspot.igv.data.services.GroupReceiver;
 import java.awt.BorderLayout;
-import java.awt.Component;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import javax.swing.BoxLayout;
-import javax.swing.JPanel;
 import javax.swing.UIManager;
 import javax.swing.border.Border;
 import org.openide.ErrorManager;
+import org.openide.actions.GarbageCollectAction;
 import org.openide.awt.Toolbar;
 import org.openide.awt.ToolbarPool;
 import org.openide.explorer.ExplorerManager;
 import org.openide.explorer.ExplorerUtils;
 import org.openide.explorer.view.BeanTreeView;
-import org.openide.util.Lookup;
 import org.openide.util.LookupEvent;
 import org.openide.util.LookupListener;
 import org.openide.util.NbBundle;
@@ -72,7 +60,8 @@
     private ExplorerManager manager;
     private GraphDocument document;
     private FolderNode root;
-    private GroupOrganizer organizer;
+    private Server server;
+    private Server binaryServer;
 
     private OutlineTopComponent() {
         initComponents();
@@ -88,17 +77,9 @@
 
     private void initListView() {
         manager = new ExplorerManager();
-        organizer = new StandardGroupOrganizer();
-        root = new FolderNode("", organizer, new ArrayList<String>(), document.getGroups());
+        root = new FolderNode(document);
         manager.setRootContext(root);
-        ((BeanTreeView) this.jScrollPane1).setRootVisible(false);
-
-        document.getChangedEvent().addListener(new ChangedListener<GraphDocument>() {
-
-            public void changed(GraphDocument document) {
-                updateStructure();
-            }
-        });
+        ((BeanTreeView) this.treeView).setRootVisible(false);
 
         associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
     }
@@ -111,61 +92,43 @@
         this.add(toolbar, BorderLayout.NORTH);
 
         toolbar.add(ImportAction.get(ImportAction.class));
-        toolbar.add(((NodeAction) RemoveAction.get(RemoveAction.class)).createContextAwareInstance(this.getLookup()));
-        toolbar.add(RemoveAllAction.get(RemoveAllAction.class));
 
         toolbar.add(((NodeAction) SaveAsAction.get(SaveAsAction.class)).createContextAwareInstance(this.getLookup()));
         toolbar.add(SaveAllAction.get(SaveAllAction.class));
 
-        toolbar.add(StructuredViewAction.get(StructuredViewAction.class).getToolbarPresenter());
+        toolbar.add(((NodeAction) RemoveAction.get(RemoveAction.class)).createContextAwareInstance(this.getLookup()));
+        toolbar.add(RemoveAllAction.get(RemoveAllAction.class));
+
+        toolbar.add(GarbageCollectAction.get(GarbageCollectAction.class).getToolbarPresenter());
 
         for (Toolbar tb : ToolbarPool.getDefault().getToolbars()) {
             tb.setVisible(false);
         }
-
-        initOrganizers();
-    }
-
-    public void setOrganizer(GroupOrganizer organizer) {
-        this.organizer = organizer;
-        updateStructure();
-    }
-
-    private void initOrganizers() {
-
     }
 
     private void initReceivers() {
 
         final GroupCallback callback = new GroupCallback() {
 
+            @Override
             public void started(Group g) {
-                getDocument().addGroup(g);
+                synchronized(OutlineTopComponent.this) {
+                    getDocument().addElement(g);
+                }
             }
         };
 
-        Collection<? extends GroupReceiver> receivers = Lookup.getDefault().lookupAll(GroupReceiver.class);
-        if (receivers.size() > 0) {
-            JPanel panel = new JPanel();
-            panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
-
-            for (GroupReceiver r : receivers) {
-                Component c = r.init(callback);
-                panel.add(c);
-            }
-
-            jPanel2.add(panel, BorderLayout.PAGE_START);
-        }
-    }
-
-    private void updateStructure() {
-        root.init("", organizer, new ArrayList<String>(), document.getGroups());
+        server = new Server(getDocument(), callback, false);
+        binaryServer = new Server(getDocument(), callback, true);
     }
 
     public void clear() {
         document.clear();
+        root = new FolderNode(document);
+        manager.setRootContext(root);
     }
 
+    @Override
     public ExplorerManager getExplorerManager() {
         return manager;
     }
@@ -221,6 +184,25 @@
         return PREFERRED_ID;
     }
 
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        treeView.requestFocus();
+    }
+
+    @Override
+    public boolean requestFocus(boolean temporary) {
+        treeView.requestFocus();
+        return super.requestFocus(temporary);
+    }
+
+    @Override
+    protected boolean requestFocusInWindow(boolean temporary) {
+        treeView.requestFocus();
+        return super.requestFocusInWindow(temporary);
+    }
+
+    @Override
     public void resultChanged(LookupEvent lookupEvent) {
     }
 
@@ -228,7 +210,7 @@
     public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
         // Not called when user starts application for the first time
         super.readExternal(objectInput);
-        ((BeanTreeView) this.jScrollPane1).setRootVisible(false);
+        ((BeanTreeView) this.treeView).setRootVisible(false);
     }
 
     @Override
@@ -253,19 +235,13 @@
     // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
     private void initComponents() {
 
-        jPanel2 = new javax.swing.JPanel();
-        jScrollPane1 = new BeanTreeView();
+        treeView = new BeanTreeView();
 
         setLayout(new java.awt.BorderLayout());
-
-        jPanel2.setLayout(new java.awt.BorderLayout());
-        jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
-
-        add(jPanel2, java.awt.BorderLayout.CENTER);
+        add(treeView, java.awt.BorderLayout.CENTER);
     }// </editor-fold>//GEN-END:initComponents
 
     // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JPanel jPanel2;
-    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JScrollPane treeView;
     // End of variables declaration//GEN-END:variables
 }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -4,7 +4,7 @@
     <Row>
         <Toolbar name="Edit" position="1" visible="false"/>
         <Toolbar name="File" position="1" visible="false" />
-        <Toolbar name="Memory" position="1" visible="false" />
+        <Toolbar name="Memory" position="1" visible="true" />
     </Row>
     <Row>
         <Toolbar name="WorkspaceSwitcher" />
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +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.coordinator;
-
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import com.sun.hotspot.igv.data.Pair;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class StandardGroupOrganizer implements GroupOrganizer {
-
-    public String getName() {
-        return "-- None --";
-    }
-
-    public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
-
-        List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
-
-        if (groups.size() == 1 && subFolders.size() > 0) {
-            result.add(new Pair<String, List<Group>>("", groups));
-        } else {
-            for (Group g : groups) {
-                List<Group> children = new ArrayList<Group>();
-                children.add(g);
-                Pair<String, List<Group>> p = new Pair<String, List<Group>>();
-                p.setLeft(g.getName());
-                p.setRight(children);
-                result.add(p);
-            }
-        }
-
-        return result;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,18 +1,10 @@
-CTL_EditFilterAction=Edit...
 CTL_ImportAction=Open...
 CTL_OpenGraphAction=View graph
 CTL_DiffGraphAction=Difference to current graph
-CTL_RemoveAction=Remove methods
-CTL_ApplyFilterAction=Apply
-CTL_FilterAction=Open Filter Window
-CTL_AppliedFilterAction=Open AppliedFilter Window
-CTL_OutlineAction=Open Outline Window
-CTL_MoveFilterUpAction=Move upwards
-CTL_MoveFilterDownAction=Move downwards
-CTL_RemoveFilterAction=Remove
-CTL_RemoveFilterSettingsAction=Remove filter setting
-CTL_SaveAsAction=Save selected methods...
-CTL_SaveAllAction=Save all...
-CTL_SaveFilterSettingsAction=Save filter settings...
-CTL_PropertiesAction=Open Properties Window
+CTL_RemoveAction=Remove selected graphs and groups
+CTL_RemoveAllAction=Remove all graphs and groups
+CTL_OutlineAction=Outline
+CTL_SaveAsAction=Save selected groups...
+CTL_SaveAllAction=Save all groups...
+CTL_PropertiesAction=Open Properties Window 
 CTL_NewFilterAction=New filter...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/CloneGraphAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.coordinator.actions;
+
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.CookieAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class CloneGraphAction extends CookieAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        GraphCloneCookie c = activatedNodes[0].getCookie(GraphCloneCookie.class);
+        assert c != null;
+        c.openClone();
+    }
+
+    @Override
+    protected int mode() {
+        return CookieAction.MODE_EXACTLY_ONE;
+    }
+
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        boolean b = super.enable(activatedNodes);
+        if (b) {
+            assert activatedNodes.length == 1;
+            GraphCloneCookie c = activatedNodes[0].getCookie(GraphCloneCookie.class);
+            assert c != null;
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public String getName() {
+        return "Open clone";
+    }
+
+    @Override
+    protected Class<?>[] cookieClasses() {
+        return new Class<?>[]{
+            GraphCloneCookie.class
+        };
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/coordinator/images/graph.png";
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
+
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,30 +35,49 @@
  */
 public final class DiffGraphAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         DiffGraphCookie c = activatedNodes[0].getCookie(DiffGraphCookie.class);
+        assert c != null;
         c.openDiff();
     }
 
+    @Override
     protected int mode() {
         return CookieAction.MODE_EXACTLY_ONE;
     }
 
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        boolean b = super.enable(activatedNodes);
+        if (b) {
+            assert activatedNodes.length == 1;
+            DiffGraphCookie c = activatedNodes[0].getCookie(DiffGraphCookie.class);
+            assert c != null;
+            return c.isPossible();
+        }
+
+        return false;
+    }
+
+    @Override
     public String getName() {
         return NbBundle.getMessage(DiffGraphAction.class, "CTL_DiffGraphAction");
     }
 
-    protected Class[] cookieClasses() {
-        return new Class[]{
+    @Override
+    protected Class<?>[] cookieClasses() {
+        return new Class<?>[]{
             DiffGraphCookie.class
         };
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/diff.gif";
+        return "com/sun/hotspot/igv/coordinator/images/diff.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -68,3 +87,4 @@
         return false;
     }
 }
+
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,12 +21,13 @@
  * questions.
  *
  */
-
 package com.sun.hotspot.igv.coordinator.actions;
 
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.GraphViewer;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.difference.Difference;
+import com.sun.hotspot.igv.util.LookupHistory;
 import org.openide.nodes.Node;
 import org.openide.util.Lookup;
 
@@ -36,21 +37,30 @@
  */
 public class DiffGraphCookie implements Node.Cookie {
 
-    private InputGraph a;
-    private InputGraph b;
+    private InputGraph graph;
+
+    public DiffGraphCookie(InputGraph graph) {
+        this.graph = graph;
+    }
 
-    public DiffGraphCookie(InputGraph a, InputGraph b) {
-        this.a = a;
-        this.b = b;
+    private InputGraph getCurrentGraph() {
+        InputGraphProvider graphProvider = LookupHistory.getLast(InputGraphProvider.class);
+        if (graphProvider != null) {
+            return graphProvider.getGraph();
+        }
+        return null;
+    }
+
+    public boolean isPossible() {
+        return getCurrentGraph() != null;
     }
 
     public void openDiff() {
-
+        InputGraph other = getCurrentGraph();
         final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class);
-
-        if(viewer != null) {
-            InputGraph diffGraph = Difference.createDiffGraph(a, b);
-            viewer.view(diffGraph);
+        if (viewer != null) {
+            InputGraph diffGraph = Difference.createDiffGraph(other, graph);
+            viewer.view(diffGraph, true);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphCloneCookie.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.GraphViewer;
+import org.openide.nodes.Node;
+
+public class GraphCloneCookie implements Node.Cookie {
+
+    private final GraphViewer viewer;
+    private final InputGraph graph;
+
+    public GraphCloneCookie(GraphViewer viewer, InputGraph graph) {
+        this.viewer = viewer;
+        this.graph = graph;
+    }
+
+    public void openClone() {
+        viewer.view(graph, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.GraphViewer;
+import org.openide.cookies.OpenCookie;
+
+public class GraphOpenCookie implements OpenCookie {
+
+    private final GraphViewer viewer;
+    private final InputGraph graph;
+
+    public GraphOpenCookie(GraphViewer viewer, InputGraph graph) {
+        this.viewer = viewer;
+        this.graph = graph;
+    }
+
+    @Override
+    public void open() {
+        viewer.view(graph, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphRemoveCookie.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+
+public class GraphRemoveCookie implements RemoveCookie {
+    private final InputGraph graph;
+
+    public GraphRemoveCookie(InputGraph graph) {
+        this.graph = graph;
+    }
+
+    @Override
+    public void remove() {
+        graph.getGroup().removeElement(graph);
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,150 +26,157 @@
 
 import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
 import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.serialization.BinaryParser;
+import com.sun.hotspot.igv.data.serialization.GraphParser;
+import com.sun.hotspot.igv.data.serialization.ParseMonitor;
 import com.sun.hotspot.igv.data.serialization.Parser;
 import com.sun.hotspot.igv.settings.Settings;
-import com.sun.hotspot.igv.data.serialization.XMLParser;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
+import java.awt.event.ActionEvent;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import javax.swing.Action;
+import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import javax.swing.JFileChooser;
-import javax.swing.KeyStroke;
+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.util.Exceptions;
+import org.openide.util.RequestProcessor;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
 import org.openide.util.HelpCtx;
 import org.openide.util.NbBundle;
-import org.openide.util.RequestProcessor;
-import org.openide.util.actions.CallableSystemAction;
-import org.openide.xml.XMLUtil;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
+import org.openide.util.actions.SystemAction;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public final class ImportAction extends CallableSystemAction {
+
+@ActionID(
+        category = "File",
+        id = "com.sun.hotspot.igv.coordinator.actions.ImportAction"
+)
+@ActionRegistration(
+        iconBase = "com/sun/hotspot/igv/coordinator/images/import.png",
+        displayName = "#CTL_ImportAction"
+)
+@ActionReferences({
+    @ActionReference(path = "Menu/File", position = 0),
+    @ActionReference(path = "Shortcuts", name = "C-O")
+})
+public final class ImportAction extends SystemAction {
+    private static final int WORKUNITS = 10000;
 
     public static FileFilter getFileFilter() {
         return new FileFilter() {
 
+            @Override
             public boolean accept(File f) {
-                return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory();
+                return f.getName().toLowerCase().endsWith(".xml") || f.getName().toLowerCase().endsWith(".bgv") || f.isDirectory();
             }
 
+            @Override
             public String getDescription() {
-                return "XML files (*.xml)";
+                return "Graph files (*.xml, *.bgv)";
             }
         };
     }
 
-    public void performAction() {
-
+    @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)));
+        fc.setMultiSelectionEnabled(true);
 
         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 XMLReader reader = XMLUtil.createXMLReader();
-                final FileInputStream inputStream = new FileInputStream(file);
-                final InputSource is = new InputSource(inputStream);
+            for (final File file : fc.getSelectedFiles()) {
+                File dir = file;
+                if (!dir.isDirectory()) {
+                    dir = dir.getParentFile();
+                }
 
-                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() {
-
-                    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) {
-                        }
-                    }
-
-                    public void setState(String state) {
-                        setProgress(0.0);
-                        handle.progress(state);
+                Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
+                try {
+                    final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
+                    final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName());
+                    handle.start(WORKUNITS);
+                    final long startTime = System.currentTimeMillis();
+                    final long start = channel.size();
+                    ParseMonitor monitor = new ParseMonitor() {
+                            @Override
+                            public void updateProgress() {
+                                try {
+                                    int prog = (int) (WORKUNITS * (double) channel.position() / (double) start);
+                                    handle.progress(prog);
+                                } catch (IOException ex) {
+                                }
+                            }
+                            @Override
+                            public void setState(String state) {
+                                updateProgress();
+                                handle.progress(state);
+                            }
+                        };
+                    final GraphParser parser;
+                    final OutlineTopComponent component = OutlineTopComponent.findInstance();
+                    if (file.getName().endsWith(".xml")) {
+                        parser = new Parser(channel, monitor, null);
+                    } else if (file.getName().endsWith(".bgv")) {
+                        parser = new BinaryParser(channel, monitor, component.getDocument(), null);
+                    } else {
+                        parser = null;
                     }
-                };
-                final Parser parser = new Parser();
-                final OutlineTopComponent component = OutlineTopComponent.findInstance();
-
-                component.requestActive();
-
-                RequestProcessor.getDefault().post(new Runnable() {
-
-                    public void run() {
-                        GraphDocument document = null;
-                        try {
-                            document = parser.parse(reader, is, parseMonitor);
-                            parseMonitor.setState("Finishing");
-                            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() + "\"";
+                    RequestProcessor.getDefault().post(new Runnable() {
+                            @Override
+                            public void run() {
+                                try {
+                                    final GraphDocument document = parser.parse();
+                                    if (document != null) {
+                                        SwingUtilities.invokeLater(new Runnable(){
+                                                @Override
+                                                public void run() {
+                                                    component.requestActive();
+                                                    component.getDocument().addGraphDocument(document);
+                                                }
+                                            });
+                                    }
+                                } catch (IOException ex) {
+                                    Exceptions.printStackTrace(ex);
+                                }
+                                handle.finish();
+                                long stop = System.currentTimeMillis();
+                                Logger.getLogger(getClass().getName()).log(Level.INFO, "Loaded in " + file + " in " + ((stop - startTime) / 1000.0) + " seconds");
                             }
-                            ex.printStackTrace();
-                            NotifyDescriptor d = new NotifyDescriptor.Message(s, NotifyDescriptor.ERROR_MESSAGE);
-                            DialogDisplayer.getDefault().notify(d);
-                        }
-                        handle.finish();
-                    }
-                });
-
-            } catch (SAXException ex) {
-                ex.printStackTrace();
-            } catch (FileNotFoundException ex) {
-                ex.printStackTrace();
-            } catch (IOException ex) {
-                ex.printStackTrace();
+                        });
+                } catch (FileNotFoundException ex) {
+                    Exceptions.printStackTrace(ex);
+                } catch (IOException ex) {
+                    Exceptions.printStackTrace(ex);
+                }
             }
         }
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(ImportAction.class, "CTL_ImportAction");
     }
 
-    public ImportAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Open an XML graph document");
-        putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
-    }
-
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/import.gif";
+        return "com/sun/hotspot/igv/coordinator/images/import.png";
     }
-
+    
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
-
-    @Override
-    protected boolean asynchronous() {
-        return false;
-    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/OutlineAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/OutlineAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
 
 package com.sun.hotspot.igv.coordinator.actions;
 
-import com.sun.hotspot.igv.coordinator.*;
+import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
 import java.awt.event.ActionEvent;
 import javax.swing.AbstractAction;
 import org.openide.util.NbBundle;
@@ -40,6 +40,7 @@
         super(NbBundle.getMessage(OutlineAction.class, "CTL_OutlineAction"));
     }
 
+    @Override
     public void actionPerformed(ActionEvent evt) {
         TopComponent win = OutlineTopComponent.findInstance();
         win.open();
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
  */
 public final class RemoveAction extends NodeAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         for (Node n : activatedNodes) {
             RemoveCookie removeCookie = n.getCookie(RemoveCookie.class);
@@ -46,18 +47,20 @@
     }
 
     public RemoveAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Remove");
+        putValue(Action.SHORT_DESCRIPTION, "Remove selected graphs and groups");
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(RemoveAction.class, "CTL_RemoveAction");
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/remove.gif";
+        return "com/sun/hotspot/igv/coordinator/images/remove.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -67,6 +70,7 @@
         return false;
     }
 
+    @Override
     protected boolean enable(Node[] nodes) {
         return nodes.length > 0;
     }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,20 +40,22 @@
 public final class RemoveAllAction extends CallableSystemAction {
 
 
+    @Override
     public String getName() {
-        return NbBundle.getMessage(RemoveAllAction.class, "CTL_ImportAction");
+        return NbBundle.getMessage(RemoveAllAction.class, "CTL_RemoveAllAction");
     }
 
     public RemoveAllAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Remove all methods");
+        putValue(Action.SHORT_DESCRIPTION, "Remove all graphs and groups");
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SHIFT, InputEvent.CTRL_MASK));
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/removeall.gif";
+        return "com/sun/hotspot/igv/coordinator/images/removeall.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveCookie.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveCookie.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,27 +29,45 @@
 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.ActionReferences;
+import org.openide.awt.ActionRegistration;
 import org.openide.util.HelpCtx;
 import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
 import org.openide.util.actions.CallableSystemAction;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
+@ActionID(
+        category = "File",
+        id = "com.sun.hotspot.igv.coordinator.actions.SaveAllAction"
+)
+@ActionRegistration(
+        displayName = "#CTL_SaveAllAction"
+)
+@ActionReferences({
+    @ActionReference(path = "Menu/File", position = 0),
+    @ActionReference(path = "Shortcuts", name = "C-S")
+})
 public final class SaveAllAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         final OutlineTopComponent component = OutlineTopComponent.findInstance();
         SaveAsAction.save(component.getDocument());
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(SaveAllAction.class, "CTL_SaveAllAction");
     }
 
     public SaveAllAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Save all methods to XML file");
+        putValue(Action.SHORT_DESCRIPTION, "Save all groups to XML file...");
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK));
     }
 
@@ -58,6 +76,7 @@
         return "com/sun/hotspot/igv/coordinator/images/saveall.gif";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,8 @@
 import com.sun.hotspot.igv.data.Group;
 import com.sun.hotspot.igv.data.serialization.Printer;
 import com.sun.hotspot.igv.settings.Settings;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
+import java.io.*;
+import javax.swing.Action;
 import javax.swing.JFileChooser;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
@@ -47,12 +43,17 @@
  */
 public final class SaveAsAction extends NodeAction {
 
+    public SaveAsAction() {
+        putValue(Action.SHORT_DESCRIPTION, "Save selected groups to XML file...");
+    }
+
+    @Override
     protected void performAction(Node[] activatedNodes) {
 
         GraphDocument doc = new GraphDocument();
         for (Node n : activatedNodes) {
             Group group = n.getLookup().lookup(Group.class);
-            doc.addGroup(group);
+            doc.addElement(group);
         }
 
         save(doc);
@@ -75,10 +76,10 @@
             }
             Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
             try {
-                Writer writer = new OutputStreamWriter(new FileOutputStream(file));
-                Printer p = new Printer();
-                p.export(writer, doc);
-                writer.close();
+                try (Writer writer = new OutputStreamWriter(new FileOutputStream(file))) {
+                    Printer p = new Printer();
+                    p.export(writer, doc);
+                }
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             } catch (IOException e) {
@@ -92,15 +93,17 @@
         return CookieAction.MODE_SOME;
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(SaveAsAction.class, "CTL_SaveAsAction");
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/save.gif";
+        return "com/sun/hotspot/igv/coordinator/images/save.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -110,6 +113,7 @@
         return false;
     }
 
+    @Override
     protected boolean enable(Node[] nodes) {
 
         int cnt = 0;
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/StructuredViewAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +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.coordinator.actions;
-
-import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import java.awt.Component;
-import java.awt.Image;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.swing.Action;
-import javax.swing.ButtonGroup;
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JMenuItem;
-import javax.swing.JPopupMenu;
-import javax.swing.event.PopupMenuEvent;
-import javax.swing.event.PopupMenuListener;
-import org.openide.awt.DropDownButtonFactory;
-import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
-import org.openide.util.Utilities;
-import org.openide.util.actions.CallableSystemAction;
-
-public class StructuredViewAction extends CallableSystemAction {
-
-    private static JButton dropDownButton;
-    private static ButtonGroup buttonGroup;
-    private static JPopupMenu popup;
-    private MyMenuItemListener menuItemListener;
-    private Map<JMenuItem, GroupOrganizer> map;
-
-    public StructuredViewAction() {
-
-        putValue(Action.SHORT_DESCRIPTION, "Cluster nodes into blocks");
-    }
-
-    @Override
-    public Component getToolbarPresenter() {
-
-        Image iconImage = Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/structure.gif");
-        ImageIcon icon = new ImageIcon(iconImage);
-
-        popup = new JPopupMenu();
-
-        menuItemListener = new MyMenuItemListener();
-
-        buttonGroup = new ButtonGroup();
-
-        Collection<? extends GroupOrganizer> organizersCollection = Lookup.getDefault().lookupAll(GroupOrganizer.class);
-
-        List<GroupOrganizer> organizers = new ArrayList<GroupOrganizer>(organizersCollection);
-        Collections.sort(organizers, new Comparator<GroupOrganizer>() {
-            public int compare(GroupOrganizer a, GroupOrganizer b) {
-                return a.getName().compareTo(b.getName());
-            }
-        });
-
-        map = new HashMap<JMenuItem, GroupOrganizer>();
-
-        boolean first = true;
-        for(GroupOrganizer organizer : organizers) {
-            JCheckBoxMenuItem item = new JCheckBoxMenuItem(organizer.getName());
-            map.put(item, organizer);
-            item.addActionListener(menuItemListener);
-            buttonGroup.add(item);
-            popup.add(item);
-            if(first) {
-                item.setSelected(true);
-                first = false;
-            }
-        }
-
-        dropDownButton = DropDownButtonFactory.createDropDownButton(
-                new ImageIcon(
-                new BufferedImage(32, 32, BufferedImage.TYPE_BYTE_GRAY)),
-                popup);
-
-        dropDownButton.setIcon(icon);
-
-        dropDownButton.setToolTipText("Insert Layer Registration");
-
-        dropDownButton.addItemListener(new ItemListener() {
-
-            public void itemStateChanged(ItemEvent e) {
-                int state = e.getStateChange();
-                if (state == ItemEvent.SELECTED) {
-                    performAction();
-                }
-            }
-        });
-
-        dropDownButton.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                performAction();
-            }
-        });
-
-        popup.addPopupMenuListener(new PopupMenuListener() {
-
-            public void popupMenuCanceled(PopupMenuEvent e) {
-                dropDownButton.setSelected(false);
-            }
-
-            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
-                dropDownButton.setSelected(false);
-            }
-
-            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
-                dropDownButton.setSelected(true);
-            }
-        });
-
-        return dropDownButton;
-
-    }
-
-    private class MyMenuItemListener implements ActionListener {
-
-        public void actionPerformed(ActionEvent ev) {
-            JMenuItem item = (JMenuItem) ev.getSource();
-            GroupOrganizer organizer = map.get(item);
-            assert organizer != null : "Organizer must exist!";
-            OutlineTopComponent.findInstance().setOrganizer(organizer);
-        }
-    }
-
-
-    @Override
-    public void performAction() {
-        popup.show(dropDownButton, 0, dropDownButton.getHeight());
-    }
-
-    public String getName() {
-        return "Structured View";
-    }
-
-    public HelpCtx getHelpCtx() {
-        return HelpCtx.DEFAULT_HELP;
-    }
-
-    @Override
-    protected boolean asynchronous() {
-        return false;
-    }
-
-}
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/customLeftWsmode.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/customLeftWsmode.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -4,12 +4,8 @@
     <kind type="view" />
     <state type="joined" />
     <constraints>
-        <path orientation="horizontal" number="0" weight="0.779245283018868"/>
-        <path orientation="vertical" number="0" weight="0.7511825922421949"/>
-        <path orientation="horizontal" number="0" weight="0.5"/>
-        <path orientation="vertical" number="20" weight="0.7"/>
-        <path orientation="horizontal" number="40" weight="0.55"/>
-        <path orientation="horizontal" number="0" weight="0.2711864406779661"/>
+        <path orientation="horizontal" number="0" weight="0.2"/>
+        <path orientation="vertical" number="0" weight="0.75"/>
     </constraints>
     <bounds x="0" y="0" width="0" height="0" />
     <frame state="0"/>
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/diff.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/diff.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/folder.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/folder.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/graph.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/graph.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/saveall.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/structure.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/structure.png has changed
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -1,110 +1,196 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
 <filesystem>
-    <attr name="Actions\Edit\com-sun-hotspot-igv-bytecodes-SelectBytecodesAction.instance\position" intvalue="200"/>
-    <attr name="Actions\Edit\org-netbeans-core-ui-sysopen-SystemOpenAction.instance\position" intvalue="100"/>
-    <attr name="Actions\Edit\org-openide-actions-CopyAction.instance\position" intvalue="1300"/>
-    <attr name="Actions\Edit\org-openide-actions-CutAction.instance\position" intvalue="1400"/>
-    <attr name="Actions\Edit\org-openide-actions-DeleteAction.instance\position" intvalue="1500"/>
-    <attr name="Actions\Edit\org-openide-actions-FindAction.instance\position" intvalue="1600"/>
-    <attr name="Actions\Edit\org-openide-actions-GotoAction.instance\position" intvalue="1700"/>
-    <attr name="Actions\Edit\org-openide-actions-PasteAction.instance\position" intvalue="1800"/>
-    <attr name="Actions\Edit\org-openide-actions-RedoAction.instance\position" intvalue="1900"/>
-    <attr name="Actions\Edit\org-openide-actions-ReplaceAction.instance\position" intvalue="2000"/>
-    <attr name="Actions\Edit\org-openide-actions-UndoAction.instance\position" intvalue="2100"/>
-
     <folder name="Actions">
         <folder name="File">
-            <file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance">
-                <attr name="position" intvalue="700"/>
-            </file>
-            <file name="com-sun-hotspot-igv-coordinator-actions-SaveAllAction.instance">
-                <attr name="position" intvalue="800"/>
-            </file>
-            <file name="com-sun-hotspot-igv-coordinator-actions-ImportAction.instance">
-                <attr name="position" intvalue="1000"/>
-            </file>
+            <file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance"/>
+            <file name="com-sun-hotspot-igv-coordinator-actions-SaveAllAction.instance"/>
+            <file name="com-sun-hotspot-igv-coordinator-actions-ImportAction.instance"/>
         </folder>
         <folder name="Edit">
-
-            <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAction.instance">
-                <attr name="position" intvalue="1200"/>
-            </file>
+            <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAction.instance"/>
+            <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAllAction.instance"/>
         </folder>
         <folder name="Window">
             <file name="com-sun-hotspot-igv-coordinator-actions-OutlineAction.instance"/>
         </folder>
     </folder>
+    
     <folder name="Menu">
         <folder name="File">
+            <file name="Export_hidden"/>
+            <file name="Import_hidden"/>
+            <file name="Separator2.instance_hidden"/>
+            <file name="Separator3.instance_hidden"/>
+            <file name="SeparatorOpen.instance_hidden"/>
             <file name="com-sun-hotspot-igv-coordinator-actions-ImportAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-ImportAction.instance"/>
                 <attr name="position" intvalue="100"/>
             </file>
-            <file name="MySeparator2.instance">
+            <file name="SeparatorSave.instance">
                 <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
-                <attr name="position" intvalue="300"/>
+                <attr name="position" intvalue="150"/>
             </file>
             <file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance"/>
-                <attr name="position" intvalue="300"/>
+                <attr name="position" intvalue="200"/>
             </file>
             <file name="com-sun-hotspot-igv-coordinator-actions-SaveAllAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-SaveAllAction.instance"/>
-                <attr name="position" intvalue="400"/>
-            </file>
-            <file name="MySeparator3.instance">
-                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
-                <attr name="position" intvalue="500"/>
+                <attr name="position" intvalue="300"/>
             </file>
-
-            <file name="org-netbeans-modules-openfile-OpenFileAction.instance_hidden"/>
-            <file name="org-openide-actions-PageSetupAction.instance_hidden"/>
-            <file name="org-openide-actions-PrintAction.instance_hidden"/>
-            <file name="org-openide-actions-SaveAction.instance_hidden"/>
-            <file name="org-openide-actions-SaveAllAction.instance_hidden"/>
-            <file name="org-openide-actions-SaveAsAction.shadow_hidden"/>
-        </folder>
-        <folder name="Edit">
-            <file name="com-sun-hotspot-igv-coordinator-actions-SaveFilterSettingsAction.shadow">
-                <attr name="originalFile" stringvalue="Actions/Edit/com-sun-hotspot-igv-coordinator-actions-SaveFilterSettingsAction.instance"/>
+            <file name="SeparatorRemove.instance">
+                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                <attr name="position" intvalue="350"/>
             </file>
             <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/Edit/com-sun-hotspot-igv-coordinator-actions-RemoveAction.instance"/>
+                <attr name="position" intvalue="400"/>
             </file>
-            <file name="org-netbeans-core-actions-JumpNextAction.shadow_hidden"/>
-            <file name="org-netbeans-core-actions-JumpPrevAction.shadow_hidden"/>
-            <file name="org-openide-actions-CutAction.instance_hidden"/>
-            <file name="org-openide-actions-CopyAction.instance_hidden"/>
-            <file name="org-openide-actions-PasteAction.instance_hidden"/>
-            <file name="org-openide-actions-DeleteAction.instance_hidden"/>
-            <file name="org-openide-actions-FindAction.instance_hidden"/>
-            <file name="org-openide-actions-ReplaceAction.instance_hidden"/>
-            <file name="org-openide-actions-JumpNextAction.shadow_hidden"/>
-            <file name="org-openide-actions-JumpPrevAction.shadow_hidden"/>
+            <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAllAction.shadow">
+                <attr name="originalFile" stringvalue="Actions/Edit/com-sun-hotspot-igv-coordinator-actions-RemoveAllAction.instance"/>
+                <attr name="position" intvalue="500"/>
+            </file>
+            
+            <!-- Hidden menu entries from other modules -->
+            <file name="org-netbeans-modules-editor-ExportHtmlAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-openfile-OpenFileAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-openfile-RecentFileAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-print-action-PageSetupAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-print-action-PrintAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-CloseProject.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-CustomizeProject.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-NewFile.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-NewProject.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-OpenProject.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-RecentProjects.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-groups-GroupsMenu.shadow_hidden"/>
+            <file name="org-openide-actions-SaveAction.shadow_hidden"/>
+            <file name="org-openide-actions-SaveAllAction.shadow_hidden"/>
+            <file name="org-openide-actions-SaveAsAction.shadow_hidden"/>
         </folder>
-        <file name="GoTo_hidden"/>
-        <folder name="View">
+        
+        <folder name="Edit">
+            <!-- Hidden menu entries from other modules -->
             <file name="Separator1.instance_hidden"/>
             <file name="Separator2.instance_hidden"/>
-            <file name="org-netbeans-core-actions-HTMLViewAction.instance_hidden"/>
-            <file name="org-netbeans-core-actions-LogAction.instance_hidden"/>
+            <file name="SeparatorAfterFindPrevious.instance_hidden"/>
+            <file name="SeparatorAfterProjectsSearch.instance_hidden"/>
+            <file name="WhereUsedAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$FindNextAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$FindPreviousAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$FindSelectionAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$PasteFormattedAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$SelectAllAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$SelectIdentifierAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$StartMacroRecordingAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$StopMacroRecordingAction.instance_hidden"/>
+            <file name="org-netbeans-modules-search-FindInFilesAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-search-ReplaceInFilesAction.shadow_hidden"/>
+            <file name="org-openide-actions-CopyAction.shadow_hidden"/>
+            <file name="org-openide-actions-CutAction.shadow_hidden"/>
+            <file name="org-openide-actions-DeleteAction.shadow_hidden"/>
+            <file name="org-openide-actions-FindAction.shadow_hidden"/>
+            <file name="org-openide-actions-PasteAction.shadow_hidden"/>
+            <file name="org-openide-actions-ReplaceAction.shadow_hidden"/>
+            <file name="sep-before-reposearch.instance_hidden"/>
+        </folder>
+        
+        <folder name="View">
+            <!-- Hidden menu entries from other modules -->
+            <file name="Separator1.instance_hidden"/>
+            <file name="Separator2.instance_hidden"/>
+            <file name="org-netbeans-core-actions-HTMLViewAction.shadow_hidden"/>
+            <file name="org-netbeans-core-actions-LogAction.shadow_hidden"/>
+            <file name="org-netbeans-core-multiview-EditorsAction.instance_hidden"/>
             <file name="org-netbeans-core-windows-actions-ToolbarsListAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-NbCodeFoldingAction.instance_hidden"/>
+            <file name="org-netbeans-modules-project-ui-SyncEditorWithViewsAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-versioning-ShowTextAnnotationsAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-versioning-diff-ShowDiffSidebarAction.shadow_hidden"/>
+            <file name="toggle-line-numbers.shadow_hidden"/>
+            <file name="toggle-non-printable-characters.shadow_hidden"/>
+            <file name="toggle-toolbar.shadow_hidden"/>
         </folder>
+        
+        <!-- Hidden menus -->
+        <folder name="GoTo_hidden"/>
+        <folder name="Source_hidden"/>
+        <folder name="Refactoring_hidden"/>
+        <folder name="BuildProject_hidden"/>
+        <folder name="RunProject_hidden"/>
+        <folder name="Versioning_hidden"/>
+        
+        <folder name="Tools">
+            <!-- Hidden menu entries from other modules -->
+            <file name="LibrariesCustomizerAction.shadow_hidden"/>
+            <file name="PaletteManager_hidden"/>
+            <file name="Separator1.instance_hidden"/>
+            <file name="Separator2.instance_hidden"/>
+            <file name="ServerManagerAction3.shadow_hidden"/>
+            <file name="VariablesCustomizerAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-autoupdate-ui-actions-PluginManagerAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-favorites-templates-TemplatesAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-options-OptionsWindowAction-separatorBefore.instance_hidden"/>
+            <file name="org-netbeans-modules-xml-catalog-CatalogAction.shadow_hidden"/>
+            <file name="org-openide-actions-ToolsAction.shadow_hidden"/>
+        </folder>
+        
         <folder name="Window">
             <file name="OutlineAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-coordinator-actions-OutlineAction.instance"/>
             </file>
+            
+            <!-- Hidden menu entries from other modules -->
+            <file name="Debug_hidden"/>
+            <file name="Navigator_hidden"/>
+            <file name="Other_hidden"/>
+            <file name="Output_hidden"/>
+            <file name="ProgressListAction.shadow_hidden"/>
+            <file name="ShowPaletteAction.shadow_hidden"/>
+            <file name="SwitchToRecentDocumentAction.shadow_hidden"/>
+            <file name="Versioning_hidden"/>
+            <file name="org-netbeans-core-ide-ServicesTabAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-favorites-View.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-logical-tab-action.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-physical-tab-action.shadow_hidden"/>
+            <file name="org-netbeans-modules-tasklist-ui-TaskListAction.shadow_hidden"/>
+            <file name="CloneDocumentAction.shadow_hidden"/>
+        </folder>
+
+        <folder name="Help">
+            <!-- Hidden menu entries from other modules -->
+            <file name="Separator1.instance_hidden"/>
+            <file name="netbeans-kb.url_hidden"/>
+            <file name="org-netbeans-modules-autoupdate-ui-actions-CheckForUpdatesAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-bugzilla-ReportNBIssueAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-usersguide-master.xml_hidden"/>
+            <file name="shortcuts.xml_hidden"/>
         </folder>
     </folder>
-    <folder name="Toolbars">
-        <file name="Standard.xml" url="StandardConfiguration.xml"/>
+
+    <folder name="OptionsDialog">
+        <!-- Hidden option tabs from other modules -->
+        <file name="Editor.instance_hidden"/>
+        <file name="FontsAndColors.instance_hidden"/>
+        <file name="General.instance_hidden"/>
+        <file name="Keymaps.instance_hidden"/>
+        <folder name="Advanced">
+            <file name="Files.instance_hidden"/>
+            <file name="IssueTracking.instance_hidden"/>
+            <file name="JavaScript.instance_hidden"/>
+            <file name="Spellchecker.instance_hidden"/>
+            <file name="TermAdvancedOption.instance_hidden"/>
+            <file name="ToDo.instance_hidden"/>
+            <file name="Versioning.instance_hidden"/>
+        </folder>
     </folder>
+    
     <folder name="Windows2">
         <folder name="Components">
             <file name="OutlineTopComponent.settings" url="OutlineTopComponentSettings.xml"/>
         </folder>
-        <folder name="Modes">
+        <folder name="Modes">  
             <file name="customLeft.wsmode" url="customLeftWsmode.xml"/>
             <folder name="customLeft">
                 <file name="OutlineTopComponent.wstcref" url="OutlineTopComponentWstcref.xml"/>
--- a/src/share/tools/IdealGraphVisualizer/Data/manifest.mf	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/manifest.mf	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
-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
-
+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
+
--- a/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,8 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+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
--- a/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -6,6 +6,19 @@
             <code-name-base>com.sun.hotspot.igv.data</code-name-base>
             <suite-component/>
             <module-dependencies/>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.util</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.data</package>
                 <package>com.sun.hotspot.igv.data.serialization</package>
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,20 +24,22 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Class representing a generic changed event.
  * @author Thomas Wuerthinger
+ * @param <T>
  */
 public class ChangedEvent<T> extends Event<ChangedListener<T>> {
 
     private T object;
 
-    public ChangedEvent() {
-    }
-
+    /**
+     * Creates a new event with the specific object as the one for which the event gets fired.
+     */
     public ChangedEvent(T object) {
         this.object = object;
     }
 
+    @Override
     protected void fire(ChangedListener<T> l) {
         l.changed(object);
     }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,14 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Provides a changed event object.
  * @author Thomas Wuerthinger
+ * @param <T> Class for which the changed event fires.
  */
 public interface ChangedEventProvider<T> {
 
-    public ChangedEvent<T> getChangedEvent();
+    /**
+     * Returns the changed event object. Should always return the same instance.
+     */
+    ChangedEvent<T> getChangedEvent();
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,15 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Listens to changed events.
  * @author Thomas Wuerthinger
+ * @param <T> Class for which the changed event fires.
  */
 public interface ChangedListener<T> {
 
-    public void changed(T source);
+    /**
+     * This method is called everytime a changed event is fired.
+     * @param source Object that has changed.
+     */
+    void changed(T source);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ControllableChangedListener.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.data;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public abstract class ControllableChangedListener<T> implements ChangedListener<T>{
+
+    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);
+}
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Event.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Event.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,23 +33,48 @@
 public abstract class Event<L> {
 
     private List<L> listener;
+    private boolean fireEvents;
+    private boolean eventWasFired;
 
     public Event() {
-        listener = new ArrayList<L>();
+        listener = new ArrayList<>();
+        fireEvents = true;
     }
 
     public void addListener(L l) {
         listener.add(l);
     }
 
-    public void removeListener(L l) {
+    /**
+     * Remove listener
+     * @param l
+     */
+    public void removeListener(final L l) {
         listener.remove(l);
     }
 
     public void fire() {
-        List<L> tmpList = new ArrayList<L>(listener);
-        for (L l : tmpList) {
-            fire(l);
+        if(fireEvents) {
+            List<L> 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();
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Folder.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.data;
+
+import java.util.List;
+
+public interface Folder {
+    List<? extends FolderElement> getElements();
+    void removeElement(FolderElement element);
+    void addElement(FolderElement group);
+    ChangedEvent<? extends Folder> getChangedEvent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/FolderElement.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.data;
+
+public interface FolderElement {
+
+    Folder getParent();
+    String getName();
+    void setParent(Folder parent);
+}
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,55 +24,40 @@
 package com.sun.hotspot.igv.data;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class GraphDocument extends Properties.Entity implements ChangedEventProvider<GraphDocument> {
+public class GraphDocument extends Properties.Entity implements ChangedEventProvider<GraphDocument>, Folder {
 
-    private List<Group> groups;
+    private List<FolderElement> elements;
     private ChangedEvent<GraphDocument> changedEvent;
 
     public GraphDocument() {
-        groups = new ArrayList<Group>();
-        changedEvent = new ChangedEvent<GraphDocument>(this);
+        elements = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
     }
 
     public void clear() {
-        groups.clear();
+        elements.clear();
         getChangedEvent().fire();
     }
 
+    @Override
     public ChangedEvent<GraphDocument> getChangedEvent() {
         return changedEvent;
     }
 
-    public List<Group> getGroups() {
-        return Collections.unmodifiableList(groups);
-    }
-
-    public void addGroup(Group group) {
-        group.setDocument(this);
-        groups.add(group);
-        getChangedEvent().fire();
-    }
-
-    public void removeGroup(Group group) {
-        if (groups.contains(group)) {
-            group.setDocument(null);
-            groups.remove(group);
-            getChangedEvent().fire();
+    public void addGraphDocument(GraphDocument document) {
+        if (document != this) {
+            for (FolderElement e : document.elements) {
+                e.setParent(this);
+                this.addElement(e);
+            }
+            document.clear();
         }
-    }
-
-    public void addGraphDocument(GraphDocument document) {
-        for (Group g : document.groups) {
-            this.addGroup(g);
-        }
-        document.clear();
         getChangedEvent().fire();
     }
 
@@ -80,12 +65,30 @@
     public String toString() {
         StringBuilder sb = new StringBuilder();
 
-        sb.append("GraphDocument: " + getProperties().toString() + " \n\n");
-        for (Group g : getGroups()) {
+        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<? extends FolderElement> getElements() {
+        return elements;
+    }
+
+    @Override
+    public void removeElement(FolderElement element) {
+        if (elements.remove(element)) {
+            getChangedEvent().fire();
+        }
+    }
+
+    @Override
+    public void addElement(FolderElement element) {
+        elements.add(element);
+        getChangedEvent().fire();
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,49 +23,36 @@
  */
 package com.sun.hotspot.igv.data;
 
-import com.sun.hotspot.igv.data.ChangedEvent;
-import com.sun.hotspot.igv.data.ChangedEventProvider;
-import com.sun.hotspot.igv.data.Properties;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class Group extends Properties.Entity implements ChangedEventProvider<Group> {
+public class Group extends Properties.Entity implements ChangedEventProvider<Group>, Folder, FolderElement {
 
-    private List<InputGraph> graphs;
+    private final List<FolderElement> elements;
+    private final List<InputGraph> graphs;
+
+    private InputMethod method;
     private transient ChangedEvent<Group> changedEvent;
-    private GraphDocument document;
-    private InputMethod method;
-    private String assembly;
+    private Folder parent;
 
-    public Group() {
-        graphs = new ArrayList<InputGraph>();
-        init();
-    }
+    public Group(Folder parent) {
+        elements = new ArrayList<>();
+        graphs = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
+        this.parent = parent;
 
-    private void init() {
-        changedEvent = new ChangedEvent<Group>(this);
+        // Ensure that name and type are never null
+        getProperties().setProperty("name", "");
+        getProperties().setProperty("type", "");
     }
 
     public void fireChangedEvent() {
         changedEvent.fire();
     }
 
-    public void setAssembly(String s) {
-        this.assembly = s;
-    }
-
-    public String getAssembly() {
-        return assembly;
-    }
-
     public void setMethod(InputMethod method) {
         this.method = method;
     }
@@ -74,68 +61,120 @@
         return method;
     }
 
-    void setDocument(GraphDocument document) {
-        this.document = document;
-    }
-
-    public GraphDocument getDocument() {
-        return document;
-    }
-
+    @Override
     public ChangedEvent<Group> getChangedEvent() {
         return changedEvent;
     }
 
-    public List<InputGraph> getGraphs() {
-        return Collections.unmodifiableList(graphs);
+    @Override
+    public List<FolderElement> getElements() {
+        return Collections.unmodifiableList(elements);
+    }
+
+    public int getGraphsCount() {
+        return elements.size();
     }
 
-    public void addGraph(InputGraph g) {
-        assert g != null;
-        assert !graphs.contains(g);
-        graphs.add(g);
+    @Override
+    public void addElement(FolderElement element) {
+        elements.add(element);
+        if (element instanceof InputGraph) {
+            graphs.add((InputGraph) element);
+        } else {
+
+        }
+        element.setParent(this);
         changedEvent.fire();
     }
 
-    public void removeGraph(InputGraph g) {
-        int index = graphs.indexOf(g);
-        if (index != -1) {
-            graphs.remove(g);
-            changedEvent.fire();
-        }
-    }
-
     public Set<Integer> getAllNodes() {
-        Set<Integer> result = new HashSet<Integer>();
-        for (InputGraph g : graphs) {
-            Set<Integer> ids = g.getNodesAsSet();
-            result.addAll(g.getNodesAsSet());
-            for (Integer i : ids) {
-                result.add(-i);
+        Set<Integer> result = new HashSet<>();
+        for (FolderElement e : elements) {
+            if (e instanceof InputGraph) {
+                InputGraph g = (InputGraph) e;
+                result.addAll(g.getNodesAsSet());
             }
         }
         return result;
     }
 
-    public InputGraph getLastAdded() {
-        if (graphs.size() == 0) {
-            return null;
-        }
-        return graphs.get(graphs.size() - 1);
-    }
-
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("Group " + getProperties().toString() + "\n");
-        for (InputGraph g : graphs) {
+        sb.append("Group ").append(getProperties()).append("\n");
+        for (FolderElement g : elements) {
             sb.append(g.toString());
-            sb.append("\n");
+            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<InputGraph> getGraphs() {
+        return graphs;
+    }
+
+    @Override
+    public void setParent(Folder parent) {
+        this.parent = parent;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,12 +23,7 @@
  */
 package com.sun.hotspot.igv.data;
 
-import java.awt.Rectangle;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  *
@@ -37,104 +32,83 @@
 public class InputBlock {
 
     private List<InputNode> nodes;
-    private List<String> successorNames;
     private String name;
     private InputGraph graph;
-    private Rectangle bounds;
     private Set<InputBlock> successors;
-    private Set<InputBlock> predecessors;
-    private Set<InputBlockEdge> inputs;
-    private Set<InputBlockEdge> outputs;
+
+    @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;
+        }
 
-    public InputBlock(InputGraph graph, String name) {
+        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<String> 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<InputNode>();
-        successorNames = new ArrayList<String>();
-        successors = new HashSet<InputBlock>();
-        predecessors = new HashSet<InputBlock>();
-        inputs = new HashSet<InputBlockEdge>();
-        outputs = new HashSet<InputBlockEdge>();
-    }
-
-    public void removeSuccessor(InputBlock b) {
-        if (successors.contains(b)) {
-            successors.remove(b);
-            b.predecessors.remove(this);
-            InputBlockEdge e = new InputBlockEdge(this, b);
-            assert outputs.contains(e);
-            outputs.remove(e);
-            assert b.inputs.contains(e);
-            b.inputs.remove(e);
-        }
+        nodes = new ArrayList<>();
+        successors = new LinkedHashSet<>(2);
     }
 
     public String getName() {
         return name;
     }
 
-    public void setName(String s) {
-        name = s;
-    }
-
     public List<InputNode> getNodes() {
         return Collections.unmodifiableList(nodes);
     }
 
     public void addNode(int id) {
-        InputNode n = graph.getNode(id);
-        assert n != null;
-        graph.setBlock(n, this);
-        addNode(graph.getNode(id));
-    }
-
-    public void addNode(InputNode node) {
-        assert !nodes.contains(node);
+        InputNode node = graph.getNode(id);
+        assert node != null;
+        // nodes.contains(node) is too expensive for large graphs so
+        // just make sure the Graph doesn't know it yet.
+        assert graph.getBlock(id) == null : "duplicate : " + node;
+        graph.setBlock(node, this);
         nodes.add(node);
     }
 
-    public Set<InputBlock> getPredecessors() {
-        return Collections.unmodifiableSet(predecessors);
-    }
-
     public Set<InputBlock> getSuccessors() {
         return Collections.unmodifiableSet(successors);
     }
 
-    public Set<InputBlockEdge> getInputs() {
-        return Collections.unmodifiableSet(inputs);
-    }
-
-    public Set<InputBlockEdge> getOutputs() {
-        return Collections.unmodifiableSet(outputs);
-    }
-
-    // resolveBlockLinks must be called afterwards
-    public void addSuccessor(String name) {
-        successorNames.add(name);
+    @Override
+    public String toString() {
+        return "Block " + this.getName();
     }
 
-    public void resolveBlockLinks() {
-        for (String s : successorNames) {
-            InputBlock b = graph.getBlock(s);
-            addSuccessor(b);
-        }
-
-        successorNames.clear();
-    }
-
-    public void addSuccessor(InputBlock b) {
+    void addSuccessor(InputBlock b) {
         if (!successors.contains(b)) {
             successors.add(b);
-            b.predecessors.add(this);
-            InputBlockEdge e = new InputBlockEdge(this, b);
-            outputs.add(e);
-            b.inputs.add(e);
         }
     }
-
-    @Override
-    public String toString() {
-        return this.getName();
-    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,15 @@
  */
 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;
@@ -47,13 +54,21 @@
         return to;
     }
 
+    public State getState() {
+        return state;
+    }
+
+    public void setState(State state) {
+        this.state = state;
+    }
+
     @Override
     public boolean equals(Object obj) {
-        if (obj instanceof InputBlockEdge && obj != null) {
+        if (obj != null && obj instanceof InputBlockEdge) {
             InputBlockEdge e = (InputBlockEdge) obj;
             return e.from.equals(from) && e.to.equals(to);
         }
-        return super.equals(obj);
+        return false;
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,11 +31,15 @@
 
     private int bci;
     private String name;
+    private String operands;
+    private String comment;
     private InputMethod inlined;
 
-    public InputBytecode(int bci, String name) {
+    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() {
@@ -53,4 +57,12 @@
     public String getName() {
         return name;
     }
+
+    public String getOperands() {
+        return operands;
+    }
+
+    public String getComment() {
+        return comment;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,10 @@
  */
 package com.sun.hotspot.igv.data;
 
+import java.util.Comparator;
+import java.util.WeakHashMap;
+import java.lang.ref.WeakReference;
+
 /**
  *
  * @author Thomas Wuerthinger
@@ -30,21 +34,83 @@
 public class InputEdge {
 
     public enum State {
-
+        IMMUTABLE,
         SAME,
         NEW,
         DELETED
     }
-    private char toIndex;
-    private int from;
-    private int to;
+
+    public static final Comparator<InputEdge> OUTGOING_COMPARATOR = new Comparator<InputEdge>(){
+
+        @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<InputEdge> INGOING_COMPARATOR = new Comparator<InputEdge>(){
+
+        @Override
+            public int compare(InputEdge o1, InputEdge o2) {
+                if(o1.getToIndex() == o2.getToIndex()) {
+                    return o1.getFrom() - o2.getFrom();
+                }
+                return o1.getToIndex() - o2.getToIndex();
+            }
+    };
+
+    private final char toIndex;
+    private final char fromIndex;
+    private final int from;
+    private final int to;
+    private final String label;
+    private final String type;
     private State state;
 
     public InputEdge(char toIndex, int from, int to) {
+        this((char) 0, toIndex, from, to, null, null);
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to) {
+        this(fromIndex, toIndex, from, to, null, null);
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to, String label, String type) {
         this.toIndex = toIndex;
+        this.fromIndex = fromIndex;
         this.from = from;
         this.to = to;
         this.state = State.SAME;
+        this.label = label;
+        this.type = type.intern();
+    }
+
+    static WeakHashMap<InputEdge, WeakReference<InputEdge>> immutableCache = new WeakHashMap<>();
+
+    public static synchronized InputEdge createImmutable(char fromIndex, char toIndex, int from, int to, String label, String type) {
+        InputEdge edge = new InputEdge(fromIndex, toIndex, from, to, label, type, State.IMMUTABLE);
+        WeakReference<InputEdge> result = immutableCache.get(edge);
+        if (result != null) {
+            InputEdge edge2 = result.get();
+            if (edge2 != null) {
+                return edge2;
+            }
+        }
+        immutableCache.put(edge, new WeakReference<>(edge));
+        return edge;
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to, String label, String type, State state) {
+        this.toIndex = toIndex;
+        this.fromIndex = fromIndex;
+        this.from = from;
+        this.to = to;
+        this.state = state;
+        this.label = label;
+        this.type = type;
     }
 
     public State getState() {
@@ -52,6 +118,9 @@
     }
 
     public void setState(State x) {
+        if (state == State.IMMUTABLE) {
+            throw new InternalError("Can't change immutable instances");
+        }
         this.state = x;
     }
 
@@ -59,6 +128,10 @@
         return toIndex;
     }
 
+    public char getFromIndex() {
+        return fromIndex;
+    }
+
     public String getName() {
         return "in" + toIndex;
     }
@@ -71,22 +144,35 @@
         return to;
     }
 
+    public String getLabel() {
+        return label;
+    }
+
+    public String getType() {
+        return type;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (o == null || !(o instanceof InputEdge)) {
             return false;
         }
         InputEdge conn2 = (InputEdge) o;
-        return conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
+        boolean result = conn2.fromIndex == fromIndex && conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
+        if (result && (state == State.IMMUTABLE || conn2.state == State.IMMUTABLE)) {
+            // Immutable instances must be exactly the same
+            return conn2.label == label && conn2.state == state;
+        }
+        return result;
     }
 
     @Override
     public String toString() {
-        return "Edge from " + from + " to " + to + "(" + (int) toIndex + ") ";
+        return "Edge from " + from + " to " + to + "(" + (int) fromIndex + ", " + (int) toIndex + ") ";
     }
 
     @Override
     public int hashCode() {
-        return (from << 20 | to << 8 | toIndex);
+        return (from << 20 | to << 8 | toIndex << 4 | fromIndex);
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,65 +23,141 @@
  */
 package com.sun.hotspot.igv.data;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class InputGraph extends Properties.Entity {
+public class InputGraph extends Properties.Entity implements FolderElement {
+
+    private Map<Integer, InputNode> nodes;
+    private List<InputEdge> edges;
+    private Folder parent;
+    private Group parentGroup;
+    private Map<String, InputBlock> blocks;
+    private List<InputBlockEdge> blockEdges;
+    private Map<Integer, InputBlock> nodeToBlock;
+
+    public InputGraph(String name) {
+        setName(name);
+        nodes = new LinkedHashMap<>();
+        edges = new ArrayList<>();
+        blocks = new LinkedHashMap<>();
+        blockEdges = new ArrayList<>();
+        nodeToBlock = new LinkedHashMap<>();
+    }
 
-    private HashMap<Integer, InputNode> nodes;
-    private ArrayList<InputEdge> edges;
-    private Group parent;
-    private HashMap<String, InputBlock> blocks;
-    private HashMap<Integer, InputBlock> nodeToBlock;
-    private boolean isDifferenceGraph;
+    @Override
+    public void setParent(Folder parent) {
+        this.parent = parent;
+        if (parent instanceof Group) {
+            assert this.parentGroup == null;
+            this.parentGroup = (Group) parent;
+        }
+    }
 
-    public InputGraph(Group parent) {
-        this(parent, null);
+    public InputBlockEdge addBlockEdge(InputBlock left, InputBlock right) {
+        InputBlockEdge edge = new InputBlockEdge(left, right);
+        blockEdges.add(edge);
+        left.addSuccessor(right);
+        return edge;
+    }
+
+    public List<InputNode> findRootNodes() {
+        List<InputNode> result = new ArrayList<>();
+        Set<Integer> 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 InputGraph(Group parent, InputGraph last) {
-        this(parent, last, "");
+    public Map<InputNode, List<InputEdge>> findAllOutgoingEdges() {
+        Map<InputNode, List<InputEdge>> result = new HashMap<>(getNodes().size());
+        for(InputNode n : this.getNodes()) {
+            result.put(n, new ArrayList<InputEdge>());
+        }
+
+        for(InputEdge e : this.edges) {
+            int from = e.getFrom();
+            InputNode fromNode = this.getNode(from);
+            List<InputEdge> fromList = result.get(fromNode);
+            assert fromList != null;
+            fromList.add(e);
+        }
+
+        for(InputNode n : this.getNodes()) {
+            List<InputEdge> list = result.get(n);
+            Collections.sort(list, InputEdge.OUTGOING_COMPARATOR);
+        }
+
+        return result;
     }
 
-    private void clearBlocks() {
+    public Map<InputNode, List<InputEdge>> findAllIngoingEdges() {
+        Map<InputNode, List<InputEdge>> result = new HashMap<>(getNodes().size());
+        for(InputNode n : this.getNodes()) {
+            result.put(n, new ArrayList<InputEdge>());
+        }
+
+        for(InputEdge e : this.edges) {
+            int to = e.getTo();
+            InputNode toNode = this.getNode(to);
+            List<InputEdge> toList = result.get(toNode);
+            assert toList != null;
+            toList.add(e);
+        }
+
+        for(InputNode n : this.getNodes()) {
+            List<InputEdge> list = result.get(n);
+            Collections.sort(list, InputEdge.INGOING_COMPARATOR);
+        }
+
+        return result;
+    }
+
+    public List<InputEdge> findOutgoingEdges(InputNode n) {
+        List<InputEdge> 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 InputGraph(Group parent, InputGraph last, String name) {
-        this.parent = parent;
-        setName(name);
-        nodes = new HashMap<Integer, InputNode>();
-        edges = new ArrayList<InputEdge>();
-        blocks = new HashMap<String, InputBlock>();
-        nodeToBlock = new HashMap<Integer, InputBlock>();
-        if (last != null) {
+    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";
 
-            for (InputNode n : last.getNodes()) {
-                addNode(n);
-            }
-
-            for (InputEdge c : last.getEdges()) {
-                addEdge(c);
-            }
+        InputEdge edge = new InputEdge((char)fromIndex, (char)toIndex, from, to);
+        if(!this.getEdges().contains(edge)) {
+            this.addEdge(edge);
         }
     }
 
-    public void schedule(Collection<InputBlock> newBlocks) {
-        clearBlocks();
-        InputBlock noBlock = new InputBlock(this, "no block");
-        Set<InputNode> scheduledNodes = new HashSet<InputNode>();
+    public void ensureNodesInBlocks() {
+        InputBlock noBlock = null;
+        Set<InputNode> scheduledNodes = new HashSet<>();
 
-        for (InputBlock b : newBlocks) {
+        for (InputBlock b : getBlocks()) {
             for (InputNode n : b.getNodes()) {
                 assert !scheduledNodes.contains(n);
                 scheduledNodes.add(n);
@@ -91,18 +167,11 @@
         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());
             }
-        }
-
-        if (noBlock.getNodes().size() != 0) {
-            newBlocks.add(noBlock);
-        }
-        for (InputBlock b : newBlocks) {
-            addBlock(b);
-        }
-
-        for (InputNode n : this.getNodes()) {
             assert this.getBlock(n) != null;
         }
     }
@@ -116,45 +185,26 @@
     }
 
     public InputBlock getBlock(InputNode node) {
+        assert nodes.containsKey(node.getId());
+        assert nodes.get(node.getId()).equals(node);
         return getBlock(node.getId());
     }
 
     public InputGraph getNext() {
-        List<InputGraph> list = parent.getGraphs();
-        if (!list.contains(this)) {
-            return null;
-        }
-        int index = list.indexOf(this);
-        if (index == list.size() - 1) {
-            return null;
-        } else {
-            return list.get(index + 1);
-        }
+        return parentGroup.getNext(this);
     }
 
     public InputGraph getPrev() {
-        List<InputGraph> list = parent.getGraphs();
-        if (!list.contains(this)) {
-            return null;
-        }
-        int index = list.indexOf(this);
-        if (index == 0) {
-            return null;
-        } else {
-            return list.get(index - 1);
-        }
+        return parentGroup.getPrev(this);
     }
 
-    public String getName() {
-        return getProperties().get("name");
+    private void setName(String name) {
+        this.getProperties().setProperty("name", name);
     }
 
-    public String getAbsoluteName() {
-        String result = getName();
-        if (this.parent != null) {
-            result = parent.getName() + ": " + result;
-        }
-        return result;
+    @Override
+    public String getName() {
+        return getProperties().get("name");
     }
 
     public Collection<InputNode> getNodes() {
@@ -186,25 +236,22 @@
     }
 
     public void removeEdge(InputEdge c) {
-        assert edges.contains(c);
-        edges.remove(c);
-        assert !edges.contains(c);
+        boolean removed = edges.remove(c);
+        assert removed;
     }
 
     public void addEdge(InputEdge c) {
-        assert !edges.contains(c);
         edges.add(c);
-        assert edges.contains(c);
     }
 
     public Group getGroup() {
-        return parent;
+        return parentGroup;
     }
 
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("Graph " + getName() + " " + getProperties().toString() + "\n");
+        sb.append("Graph ").append(getName()).append(" ").append(getProperties().toString()).append("\n");
         for (InputNode n : nodes.values()) {
             sb.append(n.toString());
             sb.append("\n");
@@ -214,35 +261,31 @@
             sb.append(c.toString());
             sb.append("\n");
         }
+
+        for (InputBlock b : getBlocks()) {
+            sb.append(b.toString());
+            sb.append("\n");
+        }
+
         return sb.toString();
     }
 
-    public void addBlock(InputBlock b) {
+    public InputBlock addBlock(String name) {
+        final InputBlock b = new InputBlock(this, name);
         blocks.put(b.getName(), b);
-        for (InputNode n : b.getNodes()) {
-            this.nodeToBlock.put(n.getId(), b);
-        }
-    }
-
-    public void resolveBlockLinks() {
-        for (InputBlock b : blocks.values()) {
-            b.resolveBlockLinks();
-        }
-    }
-
-    public void setName(String s) {
-        getProperties().setProperty("name", s);
+        return b;
     }
 
     public InputBlock getBlock(String s) {
         return blocks.get(s);
     }
 
-    public boolean isDifferenceGraph() {
-        return this.isDifferenceGraph;
+    public Collection<InputBlockEdge> getBlockEdges() {
+        return Collections.unmodifiableList(blockEdges);
     }
 
-    public void setIsDifferenceGraph(boolean b) {
-        isDifferenceGraph = b;
+    @Override
+    public Folder getParent() {
+        return parent;
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,10 +23,13 @@
  */
 package com.sun.hotspot.igv.data;
 
-import com.sun.hotspot.igv.data.Properties;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  *
@@ -42,14 +45,37 @@
     private Group group;
     private List<InputBytecode> 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<InputMethod>();
-        bytecodes = new ArrayList<InputBytecode>();
+        inlined = new ArrayList<>();
+        bytecodes = new ArrayList<>();
     }
 
     public List<InputBytecode> getBytecodes() {
@@ -87,31 +113,42 @@
     }
 
     public void setBytecodes(String text) {
-
+        Pattern instruction = Pattern.compile("\\s*(\\d+)\\s*:?\\s*(\\w+)\\s*(.*)(?://(.*))?");
         String[] strings = text.split("\n");
-        int oldNumber = -1;
+        int oldBci = -1;
         for (String s : strings) {
-
-            if (s.length() > 0 && Character.isDigit(s.charAt(0))) {
-                s = s.trim();
-                int spaceIndex = s.indexOf(' ');
-                String numberString = s.substring(0, spaceIndex);
-                String tmpName = s.substring(spaceIndex + 1, s.length());
+            if (s.startsWith(" ")) {
+                // indented lines are extra textual information
+                continue;
+            }
+            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 number = -1;
-                number = Integer.parseInt(numberString);
+                    int bci = Integer.parseInt(bciString);
 
-                // assert correct order of bytecodes
-                assert number > oldNumber;
+                    // assert correct order of bytecodes
+                    assert bci > oldBci;
+
+                    InputBytecode bc = new InputBytecode(bci, opcode, operands, comment);
+                    bytecodes.add(bc);
 
-                InputBytecode bc = new InputBytecode(number, tmpName);
-                bytecodes.add(bc);
-
-                for (InputMethod m : inlined) {
-                    if (m.getBci() == number) {
-                        bc.setInlined(m);
-                        break;
+                    for (InputMethod m : inlined) {
+                        if (m.getBci() == bci) {
+                            bc.setInlined(m);
+                            break;
+                        }
                     }
+                } else {
+                    Logger.getLogger(getClass().getName()).log(Level.INFO, "Unparseable bytecode: " + s);
                 }
             }
         }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,10 @@
  */
 package com.sun.hotspot.igv.data;
 
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
 /**
  *
  * @author Thomas Wuerthinger
@@ -30,6 +34,37 @@
 public class InputNode extends Properties.Entity {
 
     private int id;
+    private List<InputGraph> subgraphs;
+
+    public static final Comparator<InputNode> COMPARATOR = new Comparator<InputNode>() {
+        @Override
+        public int compare(InputNode o1, InputNode o2) {
+            return o1.getId() - o2.getId();
+        }
+    };
+
+    public static Comparator<InputNode> getPropertyComparator(final String propertyName) {
+        return new Comparator<InputNode>() {
+
+            @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);
@@ -49,21 +84,29 @@
         return id;
     }
 
+    public void addSubgraph(InputGraph graph) {
+        if (subgraphs == null) {
+            subgraphs = new ArrayList<>();
+        }
+        subgraphs.add(graph);
+    }
+
+    public List<InputGraph> getSubgraphs() {
+        return subgraphs;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (!(o instanceof InputNode)) {
             return false;
         }
         InputNode n = (InputNode) o;
-        if (n.id != id) {
-            return false;
-        }
-        return getProperties().equals(n.getProperties());
+        return n.id == id;
     }
 
     @Override
     public int hashCode() {
-        return id;
+        return id * 13;
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Pair.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Pair.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,15 +58,30 @@
 
     @Override
     public boolean equals(Object o) {
-        if (!(o instanceof Pair)) {
+        if (o == null || !(o instanceof Pair)) {
             return false;
         }
-        Pair obj = (Pair) o;
-        return l.equals(obj.l) && r.equals(obj.r);
+        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.hashCode() * 71 + r.hashCode();
+        return ((l == null) ? 0 : l.hashCode()) * 71 + ((r == null) ? 0 : r.hashCode());
+    }
+
+    @Override
+    public String toString() {
+        return "[" + l + "/" + r + "]";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,13 +24,12 @@
 package com.sun.hotspot.igv.data;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
+import java.util.regex.PatternSyntaxException;
 
 /**
  *
@@ -39,7 +38,7 @@
 public class Properties implements Serializable, Iterable<Property> {
 
     public static final long serialVersionUID = 1L;
-    private String[] map = new String[4];
+    protected String[] map = new String[4];
 
     public Properties() {
     }
@@ -58,13 +57,30 @@
                 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;
-        hash = 83 * hash + (this.map != null ? this.map.hashCode() : 0);
+
+        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;
     }
 
@@ -85,7 +101,60 @@
 
     public Properties(Properties p) {
         map = new String[p.map.length];
-        System.arraycopy(map, 0, p.map, 0, p.map.length);
+        System.arraycopy(p.map, 0, map, 0, p.map.length);
+    }
+    
+    protected Properties(String[] map) {
+        this.map = map;
+    }
+    
+    static class SharedProperties extends Properties {
+        int hashCode;
+
+        SharedProperties(String[] map) {
+            super(map);
+            this.hashCode = Arrays.hashCode(map);
+        }
+        
+        @Override
+        protected void setPropertyInternal(String name, String value) {
+            throw new UnsupportedOperationException();
+        }
+        
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (!(other instanceof SharedProperties)) {
+                return super.equals(other);
+            }
+            SharedProperties props2 = (SharedProperties) other;
+            return Arrays.equals(map, props2.map);
+        }
+        
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+    }
+    
+    private static class PropertyCache {
+        static WeakHashMap<SharedProperties, WeakReference<SharedProperties>> immutableCache = new WeakHashMap<>();
+
+        static synchronized SharedProperties intern(Properties properties) {
+            String[] map = properties.map;
+            SharedProperties key = new SharedProperties(map);
+            WeakReference<SharedProperties> entry = immutableCache.get(key);
+            if (entry != null) {
+                SharedProperties props = entry.get();
+                if (props != null) {
+                    return props;
+                }
+            }
+            immutableCache.put(key, new WeakReference<>(key));
+            return key;
+        }
     }
 
     public static class Entity implements Provider {
@@ -100,17 +169,14 @@
             properties = new Properties(object.getProperties());
         }
 
+        @Override
         public Properties getProperties() {
             return properties;
         }
-    }
-
-    private String getProperty(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 internProperties() {
+            properties = PropertyCache.intern(properties);
+        }
     }
 
     public interface PropertyMatcher {
@@ -128,11 +194,16 @@
             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);
         }
     }
@@ -143,15 +214,26 @@
         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);
         }
     }
@@ -162,30 +244,55 @@
         private Pattern valuePattern;
 
         public RegexpPropertyMatcher(String name, String value) {
-            this.name = name;
-            valuePattern = Pattern.compile(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 && matcher.getName().equals(map[i]))  {
+            if (map[i] != null && name.equals(map[i])) {
                 value = map[i + 1];
                 break;
             }
         }
         if (value != null && matcher.match(value)) {
-            return new Property(matcher.getName(), value);
+            return new Property(name, value);
         } else {
             return null;
         }
@@ -198,13 +305,32 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("[");
+        List<String[]> pairs = new ArrayList<>();
         for (int i = 0; i < map.length; i += 2) {
             if (map[i + 1] != null) {
-                String p = map[i + 1];
-                sb.append(map[i] + " = " + map[i + 1] + "; ");
+                pairs.add(new String[]{map[i], map[i + 1]});
+            }
+        }
+
+        Collections.sort(pairs, new Comparator<String[]>() {
+            @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]).append("=").append(p[1]);
         }
         return sb.append("]").toString();
     }
@@ -217,10 +343,6 @@
             this.objects = objects;
         }
 
-        public T selectSingle(final String name, final String value) {
-            return selectSingle(new StringPropertyMatcher(name, value));
-        }
-
         public T selectSingle(PropertyMatcher matcher) {
 
             for (T t : objects) {
@@ -233,18 +355,16 @@
             return null;
         }
 
-        public List<T> selectMultiple(final String name, final String value) {
-            return selectMultiple(new StringPropertyMatcher(name, value));
-        }
+        public List<T> selectMultiple(PropertyMatcher matcher) {
+            List<T> result = new ArrayList<>();
 
-        public List<T> selectMultiple(PropertyMatcher matcher) {
-            List<T> result = new ArrayList<T>();
             for (T t : objects) {
                 Property p = t.getProperties().selectSingle(matcher);
                 if (p != null) {
                     result.add(t);
                 }
             }
+
             return result;
         }
     }
@@ -259,6 +379,10 @@
     }
 
     public void setProperty(String name, String value) {
+        setPropertyInternal(name.intern(), value != null ? value.intern() : null);
+    }
+
+    protected void setPropertyInternal(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];
@@ -289,34 +413,26 @@
         map = newMap;
     }
 
-    public  Iterator<Property> getProperties() {
-        return iterator();
-    }
-
     public void add(Properties properties) {
         for (Property p : properties) {
-            add(p);
+            // Already interned
+            setPropertyInternal(p.getName(), p.getValue());
         }
     }
 
-    public void add(Property property) {
-        assert property.getName() != null;
-        assert property.getValue() != null;
-        setProperty(property.getName(), property.getValue());
-    }
-    class PropertiesIterator implements Iterator<Property>, Iterable<Property> {
-        public Iterator<Property> iterator() {
-                return this;
-        }
+    private class PropertiesIterator implements Iterator<Property> {
 
         int index;
 
+        @Override
         public boolean hasNext() {
-            while (index < map.length && map[index + 1] == null)
+            while (index < map.length && map[index + 1] == null) {
                 index += 2;
+            }
             return index < map.length;
         }
 
+        @Override
         public Property next() {
             if (index < map.length) {
                 index += 2;
@@ -325,11 +441,13 @@
             return null;
         }
 
+        @Override
         public void remove() {
             throw new UnsupportedOperationException("Not supported yet.");
         }
+    }
 
-    }
+    @Override
     public Iterator<Property> iterator() {
         return new PropertiesIterator();
     }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,25 +32,20 @@
 public class Property implements Serializable {
 
     public static final long serialVersionUID = 1L;
-
     private String name;
     private String value;
 
-    private Property() {
-        this(null, null);
-    }
-
-    private Property(Property p) {
-        this(p.getName(), p.getValue());
-    }
-
-    private Property(String name) {
-        this(name, null);
-    }
-
-    public Property(String name, 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() {
@@ -63,17 +58,20 @@
 
     @Override
     public String toString() {
-        return name + " = " + value + "; ";
+        return name + "=" + value;
     }
 
     @Override
     public boolean equals(Object o) {
-        if (!(o instanceof Property)) return false;
-        Property p2 = (Property)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() + value == null ? 0 : value.hashCode();
+        return name.hashCode() * 13 + value.hashCode();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Source.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.data;
+
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Source {
+
+    private List<InputNode> sourceNodes;
+    private Set<Integer> set;
+
+    public Source() {
+        sourceNodes = new ArrayList<>(1);
+        set = new LinkedHashSet<>(1);
+    }
+
+    public List<InputNode> getSourceNodes() {
+        return Collections.unmodifiableList(sourceNodes);
+    }
+
+    public Set<Integer> 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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1011 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.services.GroupCallback;
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.Charset;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.SwingUtilities;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class BinaryParser implements GraphParser {
+    private static final int BEGIN_GROUP = 0x00;
+    private static final int BEGIN_GRAPH = 0x01;
+    private static final int CLOSE_GROUP = 0x02;
+
+    private static final int POOL_NEW = 0x00;
+    private static final int POOL_STRING = 0x01;
+    private static final int POOL_ENUM = 0x02;
+    private static final int POOL_CLASS = 0x03;
+    private static final int POOL_METHOD = 0x04;
+    private static final int POOL_NULL = 0x05;
+    private static final int POOL_NODE_CLASS = 0x06;
+    private static final int POOL_FIELD = 0x07;
+    private static final int POOL_SIGNATURE = 0x08;
+
+    private static final int KLASS = 0x00;
+    private static final int ENUM_KLASS = 0x01;
+
+    private static final int PROPERTY_POOL = 0x00;
+    private static final int PROPERTY_INT = 0x01;
+    private static final int PROPERTY_LONG = 0x02;
+    private static final int PROPERTY_DOUBLE = 0x03;
+    private static final int PROPERTY_FLOAT = 0x04;
+    private static final int PROPERTY_TRUE = 0x05;
+    private static final int PROPERTY_FALSE = 0x06;
+    private static final int PROPERTY_ARRAY = 0x07;
+    private static final int PROPERTY_SUBGRAPH = 0x08;
+
+    private static final String NO_BLOCK = "noBlock";
+
+    private static final Charset utf8 = Charset.forName("UTF-8");
+    private static final Charset utf16 = Charset.forName("UTF-16");
+
+    private final GroupCallback callback;
+    private final List<Object> constantPool;
+    private final ByteBuffer buffer;
+    private final ReadableByteChannel channel;
+    private final GraphDocument rootDocument;
+    private final Deque<Folder> folderStack;
+    private final Deque<byte[]> hashStack;
+    private final ParseMonitor monitor;
+
+    private MessageDigest digest;
+
+    private Charset stringCharset;
+
+    private int majorVersion;
+    private int minorVersion;
+
+    static final int CURRENT_MAJOR_VERSION = 1;
+    static final int CURRENT_MINOR_VERSION = 0;
+    static final String CURRENT_VERSION = versionPair(CURRENT_MAJOR_VERSION, CURRENT_MINOR_VERSION);
+
+    static class VersionMismatchException extends RuntimeException {
+        VersionMismatchException(String message) {
+            super(message);
+        }
+    }
+
+    static final byte[] MAGIC_BYTES = { 'B', 'I', 'G', 'V' };
+
+    private static String versionPair(int major, int minor) {
+        return major + "." + minor;
+    }
+
+    private void setVersion(int newMajorVersion, int newMinorVersion) {
+        if (newMajorVersion > CURRENT_MAJOR_VERSION || (newMajorVersion == CURRENT_MAJOR_VERSION && newMinorVersion > CURRENT_MINOR_VERSION)) {
+            throw new VersionMismatchException("File format version " + versionPair(newMajorVersion, newMinorVersion) + " unsupported.  Current version is " + CURRENT_VERSION);
+        }
+
+        majorVersion = newMajorVersion;
+        minorVersion = newMinorVersion;
+        stringCharset = utf8;
+    }
+
+    private enum Length {
+        S,
+        M,
+        L
+    }
+
+    private interface LengthToString {
+        String toString(Length l);
+    }
+
+    private static abstract class Member implements LengthToString {
+        public final Klass holder;
+        public final int accessFlags;
+        public final String name;
+        public Member(Klass holder, String name, int accessFlags) {
+            this.holder = holder;
+            this.accessFlags = accessFlags;
+            this.name = name;
+        }
+    }
+
+    private static class Method extends Member {
+        public final Signature signature;
+        public final byte[] code;
+        public Method(String name, Signature signature, byte[] code, Klass holder, int accessFlags) {
+            super(holder, name, accessFlags);
+            this.signature = signature;
+            this.code = code;
+        }
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(holder).append('.').append(name).append('(');
+            for (int i = 0; i < signature.argTypes.length; i++) {
+                if (i > 0) {
+                    sb.append(", ");
+                }
+                sb.append(signature.argTypes[i]);
+            }
+            sb.append(')');
+            return sb.toString();
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case M:
+                    return holder.toString(Length.L) + "." + name;
+                case S:
+                    return holder.toString(Length.S) + "." + name;
+                default:
+                case L:
+                    return toString();
+            }
+        }
+    }
+
+    private static class Signature {
+        public final String returnType;
+        public final String[] argTypes;
+        public Signature(String returnType, String[] argTypes) {
+            this.returnType = returnType;
+            this.argTypes = argTypes;
+        }
+    }
+
+    private static class Field extends Member {
+        public final String type;
+        public Field(String type, Klass holder, String name, int accessFlags) {
+            super(holder, name, accessFlags);
+            this.type = type;
+        }
+        @Override
+        public String toString() {
+            return holder + "." + name;
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case M:
+                    return holder.toString(Length.L) + "." + name;
+                case S:
+                    return holder.toString(Length.S) + "." + name;
+                default:
+                case L:
+                    return toString();
+            }
+        }
+    }
+
+    private static class Klass implements LengthToString {
+        public final String name;
+        public final String simpleName;
+        public Klass(String name) {
+            this.name = name;
+            String simple;
+            try {
+                simple = name.substring(name.lastIndexOf('.') + 1);
+            } catch (IndexOutOfBoundsException ioobe) {
+                simple = name;
+            }
+            this.simpleName = simple;
+        }
+        @Override
+        public String toString() {
+            return name;
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case S:
+                    return simpleName;
+                default:
+                case L:
+                case M:
+                    return toString();
+            }
+        }
+    }
+
+    private static class EnumKlass extends Klass {
+        public final String[] values;
+        public EnumKlass(String name, String[] values) {
+            super(name);
+            this.values = values;
+        }
+    }
+
+    private static class Port {
+        public final boolean isList;
+        public final String name;
+        private Port(boolean isList, String name) {
+            this.isList = isList;
+            this.name = name;
+        }
+    }
+
+    private static class TypedPort extends Port {
+        public final EnumValue type;
+        private TypedPort(boolean isList, String name, EnumValue type) {
+            super(isList, name);
+            this.type = type;
+        }
+    }
+
+    private static class NodeClass {
+        public final String className;
+        public final String nameTemplate;
+        public final List<TypedPort> inputs;
+        public final List<Port> sux;
+        private NodeClass(String className, String nameTemplate, List<TypedPort> inputs, List<Port> sux) {
+            this.className = className;
+            this.nameTemplate = nameTemplate;
+            this.inputs = inputs;
+            this.sux = sux;
+        }
+        @Override
+        public String toString() {
+            return className;
+        }
+    }
+
+    private static class EnumValue implements LengthToString {
+        public EnumKlass enumKlass;
+        public int ordinal;
+        public EnumValue(EnumKlass enumKlass, int ordinal) {
+            this.enumKlass = enumKlass;
+            this.ordinal = ordinal;
+        }
+        @Override
+        public String toString() {
+            return enumKlass.simpleName + "." + enumKlass.values[ordinal];
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case S:
+                    return enumKlass.values[ordinal];
+                default:
+                case M:
+                case L:
+                    return toString();
+            }
+        }
+    }
+
+    public BinaryParser(ReadableByteChannel channel, ParseMonitor monitor, GraphDocument rootDocument, GroupCallback callback) {
+        this.callback = callback;
+        constantPool = new ArrayList<>();
+        buffer = ByteBuffer.allocateDirect(256 * 1024);
+        buffer.flip();
+        this.channel = channel;
+        this.rootDocument = rootDocument;
+        folderStack = new LinkedList<>();
+        hashStack = new LinkedList<>();
+        this.monitor = monitor;
+        try {
+            this.digest = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e) {
+        }
+    }
+
+    private void fill() throws IOException {
+        // All the data between lastPosition and position has been
+        // used so add it to the digest.
+        int position = buffer.position();
+        buffer.position(lastPosition);
+        byte[] remaining = new byte[position - buffer.position()];
+        buffer.get(remaining);
+        digest.update(remaining);
+        assert position == buffer.position();
+
+        buffer.compact();
+        if (channel.read(buffer) < 0) {
+            throw new EOFException();
+        }
+        buffer.flip();
+        lastPosition = buffer.position();
+    }
+
+    private void ensureAvailable(int i) throws IOException {
+        if (i > buffer.capacity()) {
+            throw new IllegalArgumentException(String.format("Can not request %d bytes: buffer capacity is %d", i, buffer.capacity()));
+        }
+        while (buffer.remaining() < i) {
+            fill();
+        }
+    }
+
+    private int readByte() throws IOException {
+        ensureAvailable(1);
+        return ((int)buffer.get()) & 0xff;
+    }
+
+    private int readInt() throws IOException {
+        ensureAvailable(4);
+        return buffer.getInt();
+    }
+
+    private char readShort() throws IOException {
+        ensureAvailable(2);
+        return buffer.getChar();
+    }
+
+    private long readLong() throws IOException {
+        ensureAvailable(8);
+        return buffer.getLong();
+    }
+
+    private double readDouble() throws IOException {
+        ensureAvailable(8);
+        return buffer.getDouble();
+    }
+
+    private float readFloat() throws IOException {
+        ensureAvailable(4);
+        return buffer.getFloat();
+    }
+
+    private String readString() throws IOException {
+        if (stringCharset == utf8) {
+                return new String(readBytes(), utf8).intern();
+        } else if (stringCharset == utf16) {
+                int len = readInt();
+                byte[] b = readBytes(len * 2);
+                return new String(b, utf16).intern();
+        }
+        int len = readInt();
+        // Backwards compatibility
+        if (len == 0) {
+            return "";
+        }
+        byte[] b = peekBytes(1);
+        if (b[0] == '\0') {
+            // Assume UTF16 encoding
+            stringCharset = utf16;
+            return new String(readBytes(len * 2), utf16).intern();
+        } else {
+            setVersion(1, 0);
+            return new String(readBytes(len), utf8).intern();
+        }
+    }
+
+    private byte[] readBytes() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return null;
+        }
+        return readBytes(len);
+    }
+
+    private byte[] readBytes(int len) throws IOException {
+        byte[] b = new byte[len];
+        int bytesRead = 0;
+        while (bytesRead < b.length) {
+            int toRead = Math.min(b.length - bytesRead, buffer.capacity());
+            ensureAvailable(toRead);
+            buffer.get(b, bytesRead, toRead);
+            bytesRead += toRead;
+        }
+        return b;
+    }
+
+    private byte[] peekBytes(int len) throws IOException {
+        ensureAvailable(len);
+        byte[] b = new byte[len];
+        buffer.mark();
+        buffer.get(b);
+        buffer.reset();
+        return b;
+    }
+
+    private String readIntsToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        ensureAvailable(len * 4);
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(buffer.getInt());
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString().intern();
+    }
+
+    private String readDoublesToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        ensureAvailable(len * 8);
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(buffer.getDouble());
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString().intern();
+    }
+
+    private String readPoolObjectsToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(readPoolObject(Object.class));
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString().intern();
+    }
+
+    private <T> T readPoolObject(Class<T> klass) throws IOException {
+        int type = readByte();
+        if (type == POOL_NULL) {
+            return null;
+        }
+        if (type == POOL_NEW) {
+            return (T) addPoolEntry(klass);
+        }
+        assert assertObjectType(klass, type);
+        char index = readShort();
+        if (index < 0 || index >= constantPool.size()) {
+            throw new IOException("Invalid constant pool index : " + index);
+        }
+        Object obj = constantPool.get(index);
+        return (T) obj;
+    }
+
+    private boolean assertObjectType(Class<?> klass, int type) {
+        switch(type) {
+            case POOL_CLASS:
+                return klass.isAssignableFrom(EnumKlass.class);
+            case POOL_ENUM:
+                return klass.isAssignableFrom(EnumValue.class);
+            case POOL_METHOD:
+                return klass.isAssignableFrom(Method.class);
+            case POOL_STRING:
+                return klass.isAssignableFrom(String.class);
+            case POOL_NODE_CLASS:
+                return klass.isAssignableFrom(NodeClass.class);
+            case POOL_FIELD:
+                return klass.isAssignableFrom(Field.class);
+            case POOL_SIGNATURE:
+                return klass.isAssignableFrom(Signature.class);
+            case POOL_NULL:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private Object addPoolEntry(Class<?> klass) throws IOException {
+        char index = readShort();
+        int type = readByte();
+        assert assertObjectType(klass, type) : "Wrong object type : " + klass + " != " + type;
+        Object obj;
+        switch(type) {
+            case POOL_CLASS: {
+                String name = readString();
+                int klasstype = readByte();
+                if (klasstype == ENUM_KLASS) {
+                    int len = readInt();
+                    String[] values = new String[len];
+                    for (int i = 0; i < len; i++) {
+                        values[i] = readPoolObject(String.class);
+                    }
+                    obj = new EnumKlass(name, values);
+                } else if (klasstype == KLASS) {
+                    obj = new Klass(name);
+                } else {
+                    throw new IOException("unknown klass type : " + klasstype);
+                }
+                break;
+            }
+            case POOL_ENUM: {
+                EnumKlass enumClass = readPoolObject(EnumKlass.class);
+                int ordinal = readInt();
+                obj = new EnumValue(enumClass, ordinal);
+                break;
+            }
+            case POOL_NODE_CLASS: {
+                String className = readString();
+                String nameTemplate = readString();
+                int inputCount = readShort();
+                List<TypedPort> inputs = new ArrayList<>(inputCount);
+                for (int i = 0; i < inputCount; i++) {
+                    boolean isList = readByte() != 0;
+                    String name = readPoolObject(String.class);
+                    EnumValue inputType = readPoolObject(EnumValue.class);
+                    inputs.add(new TypedPort(isList, name, inputType));
+                }
+                int suxCount = readShort();
+                List<Port> sux = new ArrayList<>(suxCount);
+                for (int i = 0; i < suxCount; i++) {
+                    boolean isList = readByte() != 0;
+                    String name = readPoolObject(String.class);
+                    sux.add(new Port(isList, name));
+                }
+                obj = new NodeClass(className, nameTemplate, inputs, sux);
+                break;
+            }
+            case POOL_METHOD: {
+                Klass holder = readPoolObject(Klass.class);
+                String name = readPoolObject(String.class);
+                Signature sign = readPoolObject(Signature.class);
+                int flags = readInt();
+                byte[] code = readBytes();
+                obj = new Method(name, sign, code, holder, flags);
+                break;
+            }
+            case POOL_FIELD: {
+                Klass holder = readPoolObject(Klass.class);
+                String name = readPoolObject(String.class);
+                String fType = readPoolObject(String.class);
+                int flags = readInt();
+                obj = new Field(fType, holder, name, flags);
+                break;
+            }
+            case POOL_SIGNATURE: {
+                int argc = readShort();
+                String[] args = new String[argc];
+                for (int i = 0; i < argc; i++) {
+                    args[i] = readPoolObject(String.class);
+                }
+                String returnType = readPoolObject(String.class);
+                obj = new Signature(returnType, args);
+                break;
+            }
+            case POOL_STRING: {
+                obj = readString();
+                break;
+            }
+            default:
+                throw new IOException("unknown pool type");
+        }
+        while (constantPool.size() <= index) {
+            constantPool.add(null);
+        }
+        constantPool.set(index, obj);
+        return obj;
+    }
+
+    private Object readPropertyObject() throws IOException {
+        int type = readByte();
+        switch (type) {
+            case PROPERTY_INT:
+                return readInt();
+            case PROPERTY_LONG:
+                return readLong();
+            case PROPERTY_FLOAT:
+                return readFloat();
+            case PROPERTY_DOUBLE:
+                return readDouble();
+            case PROPERTY_TRUE:
+                return Boolean.TRUE;
+            case PROPERTY_FALSE:
+                return Boolean.FALSE;
+            case PROPERTY_POOL:
+                return readPoolObject(Object.class);
+            case PROPERTY_ARRAY:
+                int subType = readByte();
+                switch(subType) {
+                    case PROPERTY_INT:
+                        return readIntsToString();
+                    case PROPERTY_DOUBLE:
+                        return readDoublesToString();
+                    case PROPERTY_POOL:
+                        return readPoolObjectsToString();
+                    default:
+                        throw new IOException("Unknown type");
+                }
+            case PROPERTY_SUBGRAPH:
+                InputGraph graph = parseGraph("");
+                new Group(null).addElement(graph);
+                return graph;
+            default:
+                throw new IOException("Unknown type");
+        }
+    }
+
+    @Override
+    public GraphDocument parse() throws IOException {
+        folderStack.push(rootDocument);
+        hashStack.push(null);
+        if (monitor != null) {
+            monitor.setState("Starting parsing");
+        }
+        try {
+            // Check for a version specification
+            byte[] magic = peekBytes(MAGIC_BYTES.length);
+            if (Arrays.equals(MAGIC_BYTES, magic)) {
+                // Consume the bytes for real
+                readBytes(MAGIC_BYTES.length);
+                setVersion(readByte(), readByte());
+            }
+            while(true) {
+                parseRoot();
+            }
+        } catch (EOFException e) {
+
+        }
+        if (monitor != null) {
+            monitor.setState("Finished parsing");
+        }
+        return rootDocument;
+    }
+
+    private void parseRoot() throws IOException {
+        int type = readByte();
+        switch(type) {
+            case BEGIN_GRAPH: {
+                final Folder parent = folderStack.peek();
+                final InputGraph graph = parseGraph();
+                SwingUtilities.invokeLater(new Runnable(){
+                    @Override
+                    public void run() {
+                        parent.addElement(graph);
+                    }
+                });
+                break;
+            }
+            case BEGIN_GROUP: {
+                final Folder parent = folderStack.peek();
+                final Group group = parseGroup(parent);
+                if (callback == null || parent instanceof Group) {
+                    SwingUtilities.invokeLater(new Runnable(){
+                        @Override
+                        public void run() {
+                            parent.addElement(group);
+                        }
+                    });
+                }
+                folderStack.push(group);
+                hashStack.push(null);
+                if (callback != null && parent instanceof GraphDocument) {
+                    callback.started(group);
+                }
+                break;
+            }
+            case CLOSE_GROUP: {
+                if (folderStack.isEmpty()) {
+                    throw new IOException("Unbalanced groups");
+                }
+                folderStack.pop();
+                hashStack.pop();
+                break;
+            }
+            default:
+                throw new IOException("unknown root : " + type);
+        }
+    }
+
+    private Group parseGroup(Folder parent) throws IOException {
+        String name = readPoolObject(String.class);
+        String shortName = readPoolObject(String.class);
+        if (monitor != null) {
+            monitor.setState(shortName);
+        }
+        Method method = readPoolObject(Method.class);
+        int bci = readInt();
+        Group group = new Group(parent);
+        group.getProperties().setProperty("name", name);
+        parseProperties(group.getProperties());
+        if (method != null) {
+            InputMethod inMethod = new InputMethod(group, method.name, shortName, bci);
+            // TODO
+            inMethod.setBytecodes("");
+            group.setMethod(inMethod);
+        }
+        return group;
+    }
+
+    int lastPosition = 0;
+
+    private InputGraph parseGraph() throws IOException {
+        if (monitor != null) {
+            monitor.updateProgress();
+        }
+        String title = readPoolObject(String.class);
+        digest.reset();
+        lastPosition = buffer.position();
+        InputGraph graph = parseGraph(title);
+
+        int position = buffer.position();
+        buffer.position(lastPosition);
+        byte[] remaining = new byte[position - buffer.position()];
+        buffer.get(remaining);
+        digest.update(remaining);
+        assert position == buffer.position();
+        lastPosition = buffer.position();
+
+        byte[] d = digest.digest();
+        byte[] hash = hashStack.peek();
+        if (hash != null && Arrays.equals(hash, d)) {
+            graph.getProperties().setProperty("_isDuplicate", "true");
+        } else {
+            hashStack.pop();
+            hashStack.push(d);
+        }
+        return graph;
+    }
+
+    private void parseProperties(Properties properties) throws IOException {
+        int propCount = readShort();
+        for (int j = 0; j < propCount; j++) {
+            String key = readPoolObject(String.class);
+            Object value = readPropertyObject();
+            properties.setProperty(key, value != null ? value.toString() : "null");
+        }
+    }
+
+    private InputGraph parseGraph(String title) throws IOException {
+        InputGraph graph = new InputGraph(title);
+        parseProperties(graph.getProperties());
+        parseNodes(graph);
+        parseBlocks(graph);
+        graph.ensureNodesInBlocks();
+        for (InputNode node : graph.getNodes()) {
+            node.internProperties();
+        }
+        return graph;
+    }
+
+    private void parseBlocks(InputGraph graph) throws IOException {
+        int blockCount = readInt();
+        List<Edge> edges = new LinkedList<>();
+        for (int i = 0; i < blockCount; i++) {
+            int id = readInt();
+            String name = id >= 0 ? Integer.toString(id) : NO_BLOCK;
+            InputBlock block = graph.addBlock(name);
+            int nodeCount = readInt();
+            for (int j = 0; j < nodeCount; j++) {
+                int nodeId = readInt();
+                if (nodeId < 0) {
+                    continue;
+                }
+                final Properties properties = graph.getNode(nodeId).getProperties();
+                final String oldBlock = properties.get("block");
+                if(oldBlock != null) {
+                    properties.setProperty("block", oldBlock + ", " + name);
+                } else {
+                    block.addNode(nodeId);
+                    properties.setProperty("block", name);
+                }
+            }
+            int edgeCount = readInt();
+            for (int j = 0; j < edgeCount; j++) {
+                int to = readInt();
+                edges.add(new Edge(id, to));
+            }
+        }
+        for (Edge e : edges) {
+            String fromName = e.from >= 0 ? Integer.toString(e.from) : NO_BLOCK;
+            String toName = e.to >= 0 ? Integer.toString(e.to) : NO_BLOCK;
+            graph.addBlockEdge(graph.getBlock(fromName), graph.getBlock(toName));
+        }
+    }
+
+    private void parseNodes(InputGraph graph) throws IOException {
+        int count = readInt();
+        Map<String, Object> props = new HashMap<>();
+        List<Edge> inputEdges = new ArrayList<>(count);
+        List<Edge> succEdges = new ArrayList<>(count);
+        for (int i = 0; i < count; i++) {
+            int id = readInt();
+            InputNode node = new InputNode(id);
+            final Properties properties = node.getProperties();
+            NodeClass nodeClass = readPoolObject(NodeClass.class);
+            int preds = readByte();
+            if (preds > 0) {
+                properties.setProperty("hasPredecessor", "true");
+            }
+            properties.setProperty("idx", Integer.toString(id));
+            int propCount = readShort();
+            for (int j = 0; j < propCount; j++) {
+                String key = readPoolObject(String.class);
+                if (key.equals("hasPredecessor") || key.equals("name") || key.equals("class") || key.equals("id") || key.equals("idx")) {
+                    key = "!data." + key;
+                }
+                Object value = readPropertyObject();
+                if (value instanceof InputGraph) {
+                    InputGraph subgraph = (InputGraph) value;
+                    subgraph.getProperties().setProperty("name", node.getId() + ":" + key);
+                    node.addSubgraph((InputGraph) value);
+                } else {
+                    properties.setProperty(key, value != null ? value.toString() : "null");
+                    props.put(key, value);
+                }
+            }
+            ArrayList<Edge> currentEdges = new ArrayList<>();
+            int portNum = 0;
+            for (TypedPort p : nodeClass.inputs) {
+                if (p.isList) {
+                    int size = readShort();
+                    for (int j = 0; j < size; j++) {
+                        int in = readInt();
+                        if (in >= 0) {
+                            Edge e = new Edge(in, id, (char) (preds + portNum), p.name + "[" + j + "]", p.type.toString(Length.S), true);
+                            currentEdges.add(e);
+                            inputEdges.add(e);
+                            portNum++;
+                        }
+                    }
+                } else {
+                    int in = readInt();
+                    if (in >= 0) {
+                        Edge e = new Edge(in, id, (char) (preds + portNum), p.name, p.type.toString(Length.S), true);
+                        currentEdges.add(e);
+                        inputEdges.add(e);
+                        portNum++;
+                    }
+                }
+
+            }
+            portNum = 0;
+            for (Port p : nodeClass.sux) {
+                if (p.isList) {
+                    int size = readShort();
+                    for (int j = 0; j < size; j++) {
+                        int sux = readInt();
+                        if (sux >= 0) {
+                            Edge e = new Edge(id, sux, (char) portNum, p.name + "[" + j + "]", "Successor", false);
+                            currentEdges.add(e);
+                            succEdges.add(e);
+                            portNum++;
+                        }
+                    }
+                } else {
+                    int sux = readInt();
+                    if (sux >= 0) {
+                        Edge e = new Edge(id, sux, (char) portNum, p.name, "Successor", false);
+                        currentEdges.add(e);
+                        succEdges.add(e);
+                        portNum++;
+                    }
+                }
+            }
+            properties.setProperty("name", createName(currentEdges, props, nodeClass.nameTemplate));
+            properties.setProperty("class", nodeClass.className);
+            switch (nodeClass.className) {
+                case "BeginNode":
+                    properties.setProperty("shortName", "B");
+                    break;
+                case "EndNode":
+                    properties.setProperty("shortName", "E");
+                    break;
+            }
+            graph.addNode(node);
+            props.clear();
+        }
+
+        Set<InputNode> nodesWithSuccessor = new HashSet<>();
+
+        for (Edge e : succEdges) {
+            assert !e.input;
+            char fromIndex = e.num;
+            nodesWithSuccessor.add(graph.getNode(e.from));
+            char toIndex = 0;
+            graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label, e.type));
+        }
+        for (Edge e : inputEdges) {
+            assert e.input;
+            char fromIndex = (char) (nodesWithSuccessor.contains(graph.getNode(e.from)) ? 1 : 0);
+            char toIndex = e.num;
+            graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label, e.type));
+        }
+    }
+
+    static final Pattern templatePattern = Pattern.compile("\\{(p|i)#([a-zA-Z0-9$_]+)(/(l|m|s))?\\}");
+
+    private String createName(List<Edge> edges, Map<String, Object> properties, String template) {
+        Matcher m = templatePattern.matcher(template);
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            String name = m.group(2);
+            String type = m.group(1);
+            String result;
+            switch (type) {
+                case "i":
+                    StringBuilder inputString = new StringBuilder();
+                    for(Edge edge : edges) {
+                        if (edge.label.startsWith(name) && (name.length() == edge.label.length() || edge.label.charAt(name.length()) == '[')) {
+                            if (inputString.length() > 0) {
+                                inputString.append(", ");
+                            }
+                            inputString.append(edge.from);
+                        }
+                    }
+                    result = inputString.toString();
+                    break;
+                case "p":
+                    Object prop = properties.get(name);
+                    String length = m.group(4);
+                    if (prop == null) {
+                        result = "?";
+                    } else if (length != null && prop instanceof LengthToString) {
+                        LengthToString lengthProp = (LengthToString) prop;
+                        switch(length) {
+                            default:
+                            case "l":
+                                result = lengthProp.toString(Length.L);
+                                break;
+                            case "m":
+                                result = lengthProp.toString(Length.M);
+                                break;
+                            case "s":
+                                result = lengthProp.toString(Length.S);
+                                break;
+                        }
+                    } else {
+                        result = prop.toString();
+                    }
+                    break;
+                default:
+                    result = "#?#";
+                    break;
+            }
+            result = result.replace("\\", "\\\\");
+            result = result.replace("$", "\\$");
+            m.appendReplacement(sb, result);
+        }
+        m.appendTail(sb);
+        return sb.toString().intern();
+    }
+
+    private static class Edge {
+        final int from;
+        final int to;
+        final char num;
+        final String label;
+        final String type;
+        final boolean input;
+        public Edge(int from, int to) {
+            this(from, to, (char) 0, null, null, false);
+        }
+        public Edge(int from, int to, char num, String label, String type, boolean input) {
+            this.from = from;
+            this.to = to;
+            this.label = label != null ? label.intern() : label;
+            this.type = type != null ? type.intern() : type;
+            this.num = num;
+            this.input = input;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/GraphParser.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.hotspot.igv.data.serialization;
+
+import com.sun.hotspot.igv.data.GraphDocument;
+import java.io.IOException;
+
+public interface GraphParser {
+    public GraphDocument parse() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/ParseMonitor.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.hotspot.igv.data.serialization;
+
+public interface ParseMonitor {
+
+    public void updateProgress();
+
+    public void setState(String state);
+
+}
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,31 +23,34 @@
  */
 package com.sun.hotspot.igv.data.serialization;
 
-import com.sun.hotspot.igv.data.GraphDocument;
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.InputBlock;
-import com.sun.hotspot.igv.data.InputEdge;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.InputMethod;
-import com.sun.hotspot.igv.data.InputNode;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Property;
-import com.sun.hotspot.igv.data.services.GroupCallback;
+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.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+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.SAXParseException;
 import org.xml.sax.XMLReader;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class Parser {
+public class Parser implements GraphParser {
 
     public static final String INDENT = "  ";
     public static final String TOP_ELEMENT = "graphDocument";
@@ -63,6 +66,7 @@
     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";
@@ -71,9 +75,13 @@
     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 TYPE_PROPERTY = "type";
     public static final String PROPERTY_NAME_PROPERTY = "name";
     public static final String GRAPH_NAME_PROPERTY = "name";
-    public static final String TO_INDEX_PROPERTY = "index";
+    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";
@@ -86,13 +94,23 @@
     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 boolean difference;
+    private TopElementHandler<GraphDocument> xmlDocument = new TopElementHandler<>();
+    private Map<Group, Boolean> differenceEncoding = new HashMap<>();
+    private Map<Group, InputGraph> lastParsedGraph = new HashMap<>();
     private GroupCallback groupCallback;
-    private HashMap<String, Integer> idCache = new HashMap<String, Integer>();
+    private HashMap<String, Integer> idCache = new HashMap<>();
+    private ArrayList<Pair<String, String>> blockConnections = new ArrayList<>();
     private int maxId = 0;
+    private GraphDocument graphDocument;
+    private final ParseMonitor monitor;
+    private final ReadableByteChannel channel;
 
     private int lookupID(String i) {
+        try {
+            return Integer.parseInt(i);
+        } catch (NumberFormatException nfe) {
+            // ignore
+        }
         Integer id = idCache.get(i);
         if (id == null) {
             id = maxId++;
@@ -106,41 +124,40 @@
 
         @Override
         protected GraphDocument start() throws SAXException {
-            return new GraphDocument();
+            graphDocument = new GraphDocument();
+            return graphDocument;
         }
     };
     // <group>
-    private ElementHandler<Group, GraphDocument> groupHandler = new XMLParser.ElementHandler<Group, GraphDocument>(GROUP_ELEMENT) {
+    private ElementHandler<Group, Folder> groupHandler = new XMLParser.ElementHandler<Group, Folder>(GROUP_ELEMENT) {
 
         @Override
         protected Group start() throws SAXException {
-            Group group = new Group();
-            Parser.this.difference = false;
+            final Group group = new Group(this.getParentObject());
+
             String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
-            if (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))) {
-                Parser.this.difference = true;
-            }
+            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 {
-            if (groupCallback == null) {
-                getParentObject().addGroup(getObject());
-            }
-        }
-    };
-    private HandoverElementHandler<Group> assemblyHandler = new XMLParser.HandoverElementHandler<Group>(ASSEMBLY_ELEMENT, true) {
-
-        @Override
-        protected void end(String text) throws SAXException {
-            getParentObject().setAssembly(text);
         }
     };
     // <method>
@@ -155,7 +172,7 @@
         }
     };
 
-    private InputMethod parseMethod(XMLParser.ElementHandler handler, Group group) throws SAXException {
+    private InputMethod parseMethod(XMLParser.ElementHandler<?,?> handler, Group group) throws SAXException {
         String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY);
         int bci = 0;
         try {
@@ -175,7 +192,7 @@
         }
     };
     // <inlined>
-    private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<InputMethod>(INLINE_ELEMENT);
+    private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT);
     // <inlined><method>
     private ElementHandler<InputMethod, InputMethod> inlinedMethodHandler = new XMLParser.ElementHandler<InputMethod, InputMethod>(METHOD_ELEMENT) {
 
@@ -189,45 +206,110 @@
     // <graph>
     private ElementHandler<InputGraph, Group> graphHandler = new XMLParser.ElementHandler<InputGraph, Group>(GRAPH_ELEMENT) {
 
-        private InputGraph graph;
-
         @Override
         protected InputGraph start() throws SAXException {
-
             String name = readAttribute(GRAPH_NAME_PROPERTY);
-            InputGraph previous = getParentObject().getLastAdded();
-            if (!difference) {
-                previous = null;
+            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);
+                    }
+                }
             }
-            InputGraph curGraph = new InputGraph(getParentObject(), previous, name);
-            this.graph = curGraph;
+            ParseMonitor monitor = getMonitor();
+            if (monitor != null) {
+                monitor.updateProgress();
+            }
             return curGraph;
         }
 
         @Override
         protected void end(String text) throws SAXException {
-            getParentObject().addGraph(graph);
-            graph.resolveBlockLinks();
+            // 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<String, String> 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);
+                }
+            });
         }
     };
     // <nodes>
-    private HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<InputGraph>(NODES_ELEMENT);
+    private HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
     // <controlFlow>
-    private HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<InputGraph>(CONTROL_FLOW_ELEMENT);
+    private HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT);
     // <block>
     private ElementHandler<InputBlock, InputGraph> blockHandler = new ElementHandler<InputBlock, InputGraph>(BLOCK_ELEMENT) {
 
         @Override
         protected InputBlock start() throws SAXException {
             InputGraph graph = getParentObject();
-            String name = readRequiredAttribute(BLOCK_NAME_PROPERTY).intern();
-            InputBlock b = new InputBlock(getParentObject(), name);
-            graph.addBlock(b);
+            String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
+            InputBlock b = graph.addBlock(name);
+            for (InputNode n : b.getNodes()) {
+                assert graph.getBlock(n).equals(b);
+            }
             return b;
         }
     };
     // <nodes>
-    private HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<InputBlock>(NODES_ELEMENT);
+    private HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
     // <node>
     private ElementHandler<InputBlock, InputBlock> blockNodeHandler = new ElementHandler<InputBlock, InputBlock>(NODE_ELEMENT) {
 
@@ -246,14 +328,14 @@
         }
     };
     // <successors>
-    private HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<InputBlock>(SUCCESSORS_ELEMENT);
+    private HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT);
     // <successor>
     private ElementHandler<InputBlock, InputBlock> successorHandler = new ElementHandler<InputBlock, InputBlock>(SUCCESSOR_ELEMENT) {
 
         @Override
         protected InputBlock start() throws SAXException {
             String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
-            getParentObject().addSuccessor(name);
+            blockConnections.add(new Pair<>(getParentObject().getName(), name));
             return getParentObject();
         }
     };
@@ -290,7 +372,7 @@
         }
     };
     // <graph>
-    private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<InputGraph>(EDGES_ELEMENT);
+    private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT);
 
     // Local class for edge elements
     private class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> {
@@ -301,24 +383,37 @@
 
         @Override
         protected InputEdge start() throws SAXException {
+            int fromIndex = 0;
             int toIndex = 0;
             int from = -1;
             int to = -1;
+            String label = null;
+            String type = 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);
+                type = readAttribute(TYPE_PROPERTY);
+
                 from = lookupID(readRequiredAttribute(FROM_PROPERTY));
                 to = lookupID(readRequiredAttribute(TO_PROPERTY));
             } catch (NumberFormatException e) {
                 throw new SAXException(e);
             }
 
-
-            InputEdge conn = new InputEdge((char) toIndex, from, to);
+            InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label, type == null ? "" : type);
             return start(conn);
         }
 
@@ -345,14 +440,20 @@
         }
     };
     // <properties>
-    private HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<Properties.Provider>(PROPERTIES_ELEMENT);
+    private HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT);
     // <properties>
     private HandoverElementHandler<Group> groupPropertiesHandler = new HandoverElementHandler<Group>(PROPERTIES_ELEMENT) {
 
         @Override
         public void end(String text) throws SAXException {
-            if (groupCallback != null) {
-                groupCallback.started(getParentObject());
+            if (groupCallback != null && getParentObject().getParent() instanceof GraphDocument) {
+                final Group group = getParentObject();
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        groupCallback.started(group);
+                    }
+                });
             }
         }
     };
@@ -361,30 +462,32 @@
 
         @Override
         public String start() throws SAXException {
-            return readRequiredAttribute(PROPERTY_NAME_PROPERTY).intern();
-        }
+            return readRequiredAttribute(PROPERTY_NAME_PROPERTY);
+         }
 
         @Override
         public void end(String text) {
-            getParentObject().getProperties().setProperty(getObject(), text.trim().intern());
+            getParentObject().getProperties().setProperty(getObject(), text.trim());
         }
     };
 
-    public Parser() {
-        this(null);
+    public Parser(ReadableByteChannel channel) {
+        this(channel, null, null);
     }
 
-    public Parser(GroupCallback groupCallback) {
+    public Parser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback groupCallback) {
 
         this.groupCallback = groupCallback;
+        this.monitor = monitor;
+        this.channel = channel;
 
         // Initialize dependencies
         xmlDocument.addChild(topHandler);
         topHandler.addChild(groupHandler);
 
         groupHandler.addChild(methodHandler);
-        groupHandler.addChild(assemblyHandler);
         groupHandler.addChild(graphHandler);
+        groupHandler.addChild(groupHandler);
 
         methodHandler.addChild(inlinedHandler);
         methodHandler.addChild(bytecodesHandler);
@@ -420,14 +523,41 @@
     }
 
     // Returns a new GraphDocument object deserialized from an XML input source.
-    public GraphDocument parse(XMLReader reader, InputSource source, XMLParser.ParseMonitor monitor) throws SAXException {
-        reader.setContentHandler(new XMLParser(xmlDocument, monitor));
+    @Override
+    public GraphDocument parse() throws IOException {
+        if (monitor != null) {
+            monitor.setState("Starting parsing");
+        }
         try {
-            reader.parse(source);
-        } catch (IOException ex) {
+            XMLReader reader = createReader();
+            reader.setContentHandler(new XMLParser(xmlDocument, monitor));
+            reader.parse(new InputSource(Channels.newInputStream(channel)));
+        } catch (SAXException ex) {
+            if (!(ex instanceof SAXParseException) || !"XML document structures must start and end within the same entity.".equals(ex.getMessage())) {
+                throw new IOException(ex);
+            }
+        }
+        if (monitor != null) {
+            monitor.setState("Finished parsing");
+        }
+        return graphDocument;
+    }
+
+    private XMLReader createReader() throws SAXException {
+        try {
+            SAXParserFactory pfactory = SAXParserFactory.newInstance();
+            // Don't bother enabling validation since we don't have an error handler.
+            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);
         }
-
-        return topHandler.getObject();
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,17 +23,9 @@
  */
 package com.sun.hotspot.igv.data.serialization;
 
-import com.sun.hotspot.igv.data.GraphDocument;
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.InputBlock;
-import com.sun.hotspot.igv.data.InputBytecode;
-import com.sun.hotspot.igv.data.InputEdge;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.InputMethod;
-import com.sun.hotspot.igv.data.InputNode;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Property;
+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;
@@ -44,6 +36,16 @@
  */
 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);
@@ -57,8 +59,12 @@
     private void export(XMLWriter xmlWriter, GraphDocument document) throws IOException {
         xmlWriter.startTag(Parser.ROOT_ELEMENT);
         xmlWriter.writeProperties(document.getProperties());
-        for (Group g : document.getGroups()) {
-            export(xmlWriter, g);
+        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();
@@ -71,14 +77,29 @@
         writer.startTag(Parser.GROUP_ELEMENT, attributes);
         writer.writeProperties(g.getProperties());
 
-        if (g.getMethod() != null) {
-            export(writer, g.getMethod());
+        boolean shouldExport = true;
+        if (in != null) {
+            char c = (char) in.read();
+            if (c != 'y') {
+                shouldExport = false;
+            }
         }
 
-        InputGraph previous = null;
-        for (InputGraph graph : g.getGraphs()) {
-            export(writer, graph, previous, true);
-            previous = graph;
+        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();
@@ -90,8 +111,8 @@
         writer.writeProperties(graph.getProperties());
         writer.startTag(Parser.NODES_ELEMENT);
 
-        Set<InputNode> removed = new HashSet<InputNode>();
-        Set<InputNode> equal = new HashSet<InputNode>();
+        Set<InputNode> removed = new HashSet<>();
+        Set<InputNode> equal = new HashSet<>();
 
         if (previous != null) {
             for (InputNode n : previous.getNodes()) {
@@ -122,8 +143,8 @@
         writer.endTag();
 
         writer.startTag(Parser.EDGES_ELEMENT);
-        Set<InputEdge> removedEdges = new HashSet<InputEdge>();
-        Set<InputEdge> equalEdges = new HashSet<InputEdge>();
+        Set<InputEdge> removedEdges = new HashSet<>();
+        Set<InputEdge> equalEdges = new HashSet<>();
 
         if (previous != null) {
             for (InputEdge e : previous.getEdges()) {
@@ -153,23 +174,25 @@
 
         writer.startTag(Parser.CONTROL_FLOW_ELEMENT);
         for (InputBlock b : graph.getBlocks()) {
-
             writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.getName()));
 
-            writer.startTag(Parser.SUCCESSORS_ELEMENT);
-            for (InputBlock s : b.getSuccessors()) {
-                writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.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();
             }
-            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() + ""));
+                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();
@@ -199,8 +222,8 @@
             b.append(" ");
             b.append(code.getName());
             b.append("\n");
+        }
 
-        }
         b.append("]]>");
         w.write(b.toString());
         w.endTag();
@@ -209,9 +232,15 @@
 
     private Properties createProperties(InputEdge edge) {
         Properties p = new Properties();
-        p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex()));
+        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()));
+        p.setProperty(Parser.TYPE_PROPERTY, edge.getType());
         return p;
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
  */
 package com.sun.hotspot.igv.data.serialization;
 
-import com.sun.hotspot.igv.data.Property;
 import com.sun.hotspot.igv.data.Properties;
 import java.util.HashMap;
 import java.util.Stack;
@@ -38,13 +37,6 @@
  */
 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;
@@ -85,24 +77,25 @@
     public static class ElementHandler<T, P> {
 
         private String name;
-        private T object;
+        private Stack<T> object = new Stack<>();
         private Attributes attr;
         private StringBuilder currentText;
         private ParseMonitor monitor;
         private HashMap<String, ElementHandler<?, ? super T>> hashtable;
         private boolean needsText;
-        private ElementHandler<P, ?> parentElement;
+        private Stack<ElementHandler<P, ?>> parentElement = new Stack<>();
+        private Stack<P> parentObject = new Stack<>();
 
         public ElementHandler(String name) {
             this(name, false);
         }
 
         public ElementHandler<P, ?> getParentElement() {
-            return parentElement;
+            return parentElement.peek();
         }
 
         public P getParentObject() {
-            return getParentElement().getObject();
+            return parentObject.peek();
         }
 
         protected boolean needsText() {
@@ -110,7 +103,7 @@
         }
 
         public ElementHandler(String name, boolean needsText) {
-            this.hashtable = new HashMap<String, ElementHandler<?, ? super T>>();
+            this.hashtable = new HashMap<>();
             this.name = name;
             this.needsText = needsText;
         }
@@ -133,7 +126,7 @@
         }
 
         public T getObject() {
-            return object;
+            return object.size() == 0 ? null : object.peek();
         }
 
         public String readAttribute(String name) {
@@ -151,8 +144,8 @@
         public void processAttributesAsProperties(Properties p) {
             int length = attr.getLength();
             for (int i = 0; i < length; i++) {
-                String val = attr.getValue(i).intern();
-                String localName = attr.getLocalName(i).intern();
+                String val = attr.getValue(i);
+                String localName = attr.getLocalName(i);
                 p.setProperty(val, localName);
             }
         }
@@ -161,8 +154,9 @@
             this.currentText = new StringBuilder();
             this.attr = attr;
             this.monitor = monitor;
-            this.parentElement = parentElement;
-            object = start();
+            this.parentElement.push(parentElement);
+            parentObject.push(parentElement.getObject());
+            object.push(start());
         }
 
         protected T start() throws SAXException {
@@ -175,6 +169,9 @@
 
         public void endElement() throws SAXException {
             end(currentText.toString());
+            object.pop();
+            parentElement.pop();
+            parentObject.pop();
         }
 
         protected void text(char[] c, int start, int length) {
@@ -186,32 +183,37 @@
     private ParseMonitor monitor;
 
     public XMLParser(TopElementHandler rootHandler, ParseMonitor monitor) {
-        this.stack = new Stack<ElementHandler>();
+        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();
 
-        assert !stack.isEmpty();
         ElementHandler parent = stack.peek();
         if (parent != null) {
             ElementHandler child = parent.getChild(qName);
@@ -225,6 +227,7 @@
         stack.push(null);
     }
 
+    @Override
     public void endElement(String uri, String localName, String qName) throws SAXException {
         ElementHandler handler = stack.pop();
         if (handler != null) {
@@ -232,6 +235,7 @@
         }
     }
 
+    @Override
     public void characters(char[] ch, int start, int length) throws SAXException {
 
         assert !stack.isEmpty();
@@ -243,12 +247,15 @@
         }
     }
 
+    @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 {
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
 
     public XMLWriter(Writer inner) {
         this.inner = inner;
-        elementStack = new Stack<String>();
+        elementStack = new Stack<>();
     }
 
     @Override
@@ -49,6 +49,7 @@
         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];
@@ -64,10 +65,12 @@
         }
     }
 
+    @Override
     public void flush() throws IOException {
         inner.flush();
     }
 
+    @Override
     public void close() throws IOException {
         inner.close();
     }
@@ -111,7 +114,7 @@
     }
 
     public void writeProperties(Properties props) throws IOException {
-        if (props.getProperties().hasNext() == false) {
+        if (props.iterator().hasNext() == false) {
             return;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/graphdocument.xsd	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+    
+    <xsd:element name="graphDocument">
+        <xsd:complexType>
+            <xsd:sequence>
+                <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+                <xsd:element name="group" type="groupType" minOccurs="0" maxOccurs="unbounded" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+
+    <xsd:complexType name="groupType">
+        <xsd:sequence>
+            <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+            <xsd:element name="assembly" type="assemblyType" minOccurs="0" maxOccurs="1" />
+            <xsd:element name="method" type="methodType" minOccurs="0" maxOccurs="1" />
+            <xsd:choice minOccurs="0" maxOccurs="unbounded" >
+                <xsd:element name="graph" type="graphType" />
+                <xsd:element name="group" type="groupType" />
+            </xsd:choice>
+        </xsd:sequence>
+        <xsd:attribute name="difference" use="optional" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="propertiesType">
+        <xsd:sequence>
+            <xsd:element name="p" minOccurs="0" maxOccurs="unbounded">
+                <xsd:complexType>
+                    <xsd:simpleContent>
+                        <xsd:extension base="xsd:string">
+                            <xsd:attribute name="name" use="required" />
+                        </xsd:extension>
+                    </xsd:simpleContent>
+                </xsd:complexType>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    
+    <xsd:simpleType name="assemblyType">
+        <xsd:restriction base="xsd:string" />
+    </xsd:simpleType>
+    
+    <xsd:complexType name="methodType">
+        <xsd:all>
+            <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+            <xsd:element name="bytecodes" minOccurs="0" maxOccurs="1">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:string" />
+                </xsd:simpleType>
+            </xsd:element>
+            <xsd:element name="inlined" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="method" type="methodType" minOccurs="0" maxOccurs="unbounded" />
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+        </xsd:all>
+        <xsd:attribute name="bci" type="xsd:int" use="required" />
+        <xsd:attribute name="shortName" type="xsd:string" use="required" />
+        <xsd:attribute name="name" type="xsd:string" use="required" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="graphType">
+        <xsd:sequence>
+            <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+            
+            <xsd:element name="nodes" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                            <xsd:element name="node" type="nodeType" />
+                            <xsd:element name="removeNode" type="nodeRefType" />
+                        </xsd:choice>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+            
+            <xsd:element name="edges" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                            <xsd:element name="edge" type="edgeType" />
+                            <xsd:element name="removeEdge" type="edgeType" />
+                        </xsd:choice>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+            
+            <xsd:element name="controlFlow" type="controlFlowType" minOccurs="0" maxOccurs="1" />
+        </xsd:sequence>
+        
+        <xsd:attribute name="name" use="optional" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="nodeType">
+        <xsd:sequence>
+            <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+        </xsd:sequence>
+        <xsd:attribute name="id" type="xsd:int" use="required" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="nodeRefType">
+        <xsd:attribute name="id" type="xsd:int" use="required" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="edgeType">
+        <xsd:attribute name="from" type="xsd:int" use="required" />
+        <xsd:attribute name="to" type="xsd:int" use="required" />
+        <xsd:attribute name="label" type="xsd:string" use="optional" />
+        <xsd:attribute name="type" type="xsd:string" use="optional" />
+        <xsd:attribute name="fromIndex" type="xsd:int" use="optional" />
+        
+        <!-- These are aliases and should be mutually exclusive -->
+        <xsd:attribute name="toIndex" type="xsd:int" use="optional" />
+        <xsd:attribute name="index" type="xsd:int" use="optional" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="controlFlowType">
+        <xsd:sequence>
+            <xsd:element name="block" type="blockType" minOccurs="0" maxOccurs="unbounded" />
+        </xsd:sequence>
+    </xsd:complexType>
+    
+    <xsd:complexType name="blockType">
+        <xsd:all>
+            <xsd:element name="successors" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="successor" minOccurs="0" maxOccurs="unbounded">
+                            <xsd:complexType>
+                                <xsd:attribute name="name" type="xsd:string" use="required" />
+                            </xsd:complexType>
+                        </xsd:element>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+            <xsd:element name="nodes" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="node" type="nodeRefType" minOccurs="0" maxOccurs="unbounded" />
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>    
+        </xsd:all>
+        
+        <xsd:attribute name="name" type="xsd:string" use="required" />
+    </xsd:complexType>
+</xsd:schema>
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,5 +31,5 @@
  */
 public interface GraphViewer {
 
-    public void view(InputGraph graph);
+    public void view(InputGraph graph, boolean clone);
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupCallback.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupCallback.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupOrganizer.java	Mon Dec 05 13:09:39 2016 -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.data.services;
-
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.Pair;
-import java.util.List;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public interface GroupOrganizer {
-
-    public String getName();
-
-    public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups);
-}
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupReceiver.java	Mon Dec 05 13:09:39 2016 -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 java.awt.Component;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public interface GroupReceiver {
-
-    public Component init(GroupCallback callback);
-}
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,4 +37,14 @@
     InputGraph getGraph();
 
     void setSelectedNodes(Set<InputNode> nodes);
+    
+    /**
+     * @return an iterator walking forward through the {@link InputGraph}s following the {@link #getGraph()}
+     */
+    Iterable<InputGraph> searchForward();
+    
+    /**
+     * @return an iterator walking backward through the {@link InputGraph}s preceeding the {@link #getGraph()}
+     */
+    Iterable<InputGraph> searchBackward();
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/Scheduler.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/Scheduler.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ChangedEventTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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<Integer> e = new ChangedEvent<>(5);
+        final int[] fireCount = new int[1];
+
+        e.addListener(new ChangedListener<Integer>() {
+            @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]);
+
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ControllableChangedListenerTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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<Integer> l = new ControllableChangedListener<Integer>() {
+
+            @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]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/GroupTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputGraphTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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<InputNode> 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<InputNode, List<InputEdge>> 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<InputNode, List<InputEdge>> 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());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputMethodTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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());
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PairTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package 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<Integer, Integer> 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));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertiesTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package 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<Property> 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<Properties.Entity> 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<Properties.Entity> 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(), "[]");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertyTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package 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());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/SourceTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/Util.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package 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));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.hotspot.igv.data.serialization;
+
+import com.sun.hotspot.igv.data.*;
+import java.io.*;
+import java.nio.channels.Channels;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.*;
+import org.openide.util.Exceptions;
+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) {
+        try {
+            InputStream in = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
+            try {
+                Parser parser = new Parser(Channels.newChannel(in));
+                final GraphDocument parsedDocument = parser.parse();
+                Util.assertGraphDocumentEquals(document, parsedDocument);
+            } catch (SAXException ex) {
+                fail(ex.toString());
+            }
+        } catch (UnsupportedEncodingException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+
+    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(), "<graphDocument></graphDocument>");
+    }
+
+}
--- a/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -14,6 +14,14 @@
                         <specification-version>1.0</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.difference</package>
--- a/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,16 +24,11 @@
  */
 package com.sun.hotspot.igv.difference;
 
-import com.sun.hotspot.igv.data.Group;
-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.Property;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+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;
 
 /**
  *
@@ -46,7 +41,7 @@
     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 NEW_PREFIX = "NEW_";
     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"};
@@ -60,14 +55,14 @@
     }
 
     private static InputGraph createDiffSameGroup(InputGraph a, InputGraph b) {
-        Map<Integer, InputNode> keyMapB = new HashMap<Integer, InputNode>();
+        Map<Integer, InputNode> keyMapB = new HashMap<>(b.getNodes().size());
         for (InputNode n : b.getNodes()) {
             Integer key = n.getId();
             assert !keyMapB.containsKey(key);
             keyMapB.put(key, n);
         }
 
-        Set<Pair> pairs = new HashSet<Pair>();
+        Set<NodePair> pairs = new HashSet<>();
 
         for (InputNode n : a.getNodes()) {
             Integer key = n.getId();
@@ -75,30 +70,92 @@
 
             if (keyMapB.containsKey(key)) {
                 InputNode nB = keyMapB.get(key);
-                pairs.add(new Pair(n, nB));
+                pairs.add(new NodePair(n, nB));
             }
         }
 
         return createDiff(a, b, pairs);
     }
 
-    private static InputGraph createDiff(InputGraph a, InputGraph b, Set<Pair> pairs) {
-        Group g = new Group();
+    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<NodePair> pairs) {
+        ensureScheduled(a);
+        ensureScheduled(b);
+
+        Group g = new Group(null);
         g.setMethod(a.getGroup().getMethod());
-        g.setAssembly(a.getGroup().getAssembly());
+        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(g, null);
-        graph.setName(a.getName() + ", " + b.getName());
-        graph.setIsDifferenceGraph(true);
+        InputGraph graph = new InputGraph(a.getName() + ", " + b.getName());
+        g.addElement(graph);
 
-        Set<InputNode> nodesA = new HashSet<InputNode>(a.getNodes());
-        Set<InputNode> nodesB = new HashSet<InputNode>(b.getNodes());
+        Map<InputBlock, InputBlock> 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);
+        }
 
-        Map<InputNode, InputNode> inputNodeMap = new HashMap<InputNode, InputNode>();
-        for (Pair p : pairs) {
-            InputNode n = p.getN1();
+        // Difference between block edges
+        Set<Pair<String, String>> 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<String, String> 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<String, String> 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<InputNode> nodesA = new HashSet<>(a.getNodes());
+        Set<InputNode> nodesB = new HashSet<>(b.getNodes());
+
+        Map<InputNode, InputNode> inputNodeMap = new HashMap<>(pairs.size());
+        for (NodePair p : pairs) {
+            InputNode n = p.getLeft();
             assert nodesA.contains(n);
-            InputNode nB = p.getN2();
+            InputNode nB = p.getRight();
             assert nodesB.contains(nB);
 
             nodesA.remove(n);
@@ -107,41 +164,59 @@
             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);
-            markAsNew(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);
-            n2.setId(-n2.getId());
+
+            // 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);
-            markAsDeleted(n2);
+            InputBlock block = blocksMap.get(b.getBlock(n));
+            block.addNode(n2.getId());
+            markAsNew(n2);
             inputNodeMap.put(n, n2);
         }
 
         Collection<InputEdge> edgesA = a.getEdges();
         Collection<InputEdge> edgesB = b.getEdges();
 
-        Set<InputEdge> newEdges = new HashSet<InputEdge>();
+        Set<InputEdge> 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 index = e.getToIndex();
+            char fromIndex = e.getFromIndex();
+            char toIndex = e.getToIndex();
 
-            InputEdge newEdge = new InputEdge(index, nodeFrom.getId(), nodeTo.getId());
-            if (!newEdges.contains(newEdge)) {
-                markAsNew(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+            if (nodeFrom == null || nodeTo == null) {
+                System.out.println("Unexpected edge : " + from + " -> " + to);
+            } else {
+                InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId(), e.getLabel(), e.getType());
+                if (!newEdges.contains(newEdge)) {
+                    markAsDeleted(newEdge);
+                    newEdges.add(newEdge);
+                    graph.addEdge(newEdge);
+                }
             }
         }
 
@@ -150,40 +225,41 @@
             int to = e.getTo();
             InputNode nodeFrom = inputNodeMap.get(b.getNode(from));
             InputNode nodeTo = inputNodeMap.get(b.getNode(to));
-            char index = e.getToIndex();
+            char fromIndex = e.getFromIndex();
+            char toIndex = e.getToIndex();
 
-            InputEdge newEdge = new InputEdge(index, nodeFrom.getId(), nodeTo.getId());
-            if (!newEdges.contains(newEdge)) {
-                markAsDeleted(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+            if (nodeFrom == null || nodeTo == null) {
+                System.out.println("Unexpected edge : " + from + " -> " + to);
             } else {
-                newEdges.remove(newEdge);
-                graph.removeEdge(newEdge);
-                markAsSame(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+                InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId(), e.getLabel(), e.getType());
+                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);
+                }
             }
         }
 
-        g.addGraph(graph);
         return graph;
     }
 
-    private static class Pair {
+    private static class NodePair extends Pair<InputNode, InputNode> {
+
 
-        private InputNode n1;
-        private InputNode n2;
-
-        public Pair(InputNode n1, InputNode n2) {
-            this.n1 = n1;
-            this.n2 = n2;
+        public NodePair(InputNode n1, InputNode n2) {
+            super(n1, n2);
         }
 
         public double getValue() {
 
             double result = 0.0;
-            for (Property p : n1.getProperties()) {
+            for (Property p : getLeft().getProperties()) {
                 double faktor = 1.0;
                 for (String forbidden : IGNORE_PROPERTIES) {
                     if (p.getName().equals(forbidden)) {
@@ -191,7 +267,7 @@
                         break;
                     }
                 }
-                String p2 = n2.getProperties().get(p.getName());
+                String p2 = getRight().getProperties().get(p.getName());
                 result += evaluate(p.getValue(), p2) * faktor;
             }
 
@@ -208,21 +284,13 @@
                 return (double) (Math.abs(p.length() - p2.length())) / p.length() + 0.5;
             }
         }
-
-        public InputNode getN1() {
-            return n1;
-        }
-
-        public InputNode getN2() {
-            return n2;
-        }
     }
 
     private static InputGraph createDiff(InputGraph a, InputGraph b) {
 
-        Set<InputNode> matched = new HashSet<InputNode>();
+        Set<InputNode> matched = new HashSet<>();
 
-        Set<Pair> pairs = new HashSet<Pair>();
+        Set<NodePair> pairs = new HashSet<>();
         for (InputNode n : a.getNodes()) {
             String s = n.getProperties().get(MAIN_PROPERTY);
             if (s == null) {
@@ -235,18 +303,18 @@
                 }
 
                 if (s.equals(s2)) {
-                    Pair p = new Pair(n, n2);
+                    NodePair p = new NodePair(n, n2);
                     pairs.add(p);
                 }
             }
         }
 
-        Set<Pair> selectedPairs = new HashSet<Pair>();
+        Set<NodePair> selectedPairs = new HashSet<>();
         while (pairs.size() > 0) {
 
             double min = Double.MAX_VALUE;
-            Pair minPair = null;
-            for (Pair p : pairs) {
+            NodePair minPair = null;
+            for (NodePair p : pairs) {
                 double cur = p.getValue();
                 if (cur < min) {
                     minPair = p;
@@ -259,9 +327,9 @@
             } else {
                 selectedPairs.add(minPair);
 
-                Set<Pair> toRemove = new HashSet<Pair>();
-                for (Pair p : pairs) {
-                    if (p.getN1() == minPair.getN1() || p.getN2() == minPair.getN2()) {
+                Set<NodePair> toRemove = new HashSet<>();
+                for (NodePair p : pairs) {
+                    if (p.getLeft() == minPair.getLeft() || p.getRight() == minPair.getRight()) {
                         toRemove.add(p);
                     }
                 }
@@ -292,7 +360,7 @@
             String s = firstNode.getProperties().get(p.getName());
             if (!p.getValue().equals(s)) {
                 difference = true;
-                n.getProperties().setProperty(OLD_PREFIX + p.getName(), p.getValue());
+                n.getProperties().setProperty(NEW_PREFIX + p.getName(), p.getValue());
             }
         }
 
@@ -300,7 +368,7 @@
             String s = otherNode.getProperties().get(p.getName());
             if (s == null && p.getValue().length() > 0) {
                 difference = true;
-                n.getProperties().setProperty(OLD_PREFIX + p.getName(), "");
+                n.getProperties().setProperty(NEW_PREFIX + p.getName(), "");
             }
         }
 
--- a/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -23,12 +23,28 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.layout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.jdesktop.layout</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4.1</specification-version>
+                        <specification-version>1.16.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -36,7 +52,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -44,7 +60,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.3</specification-version>
+                        <specification-version>7.46.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +68,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -60,7 +76,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -68,7 +92,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.filter.JavaSE6ScriptEngine
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/AbstractFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/AbstractFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,14 +42,17 @@
         properties = new Properties();
     }
 
+    @Override
     public Properties getProperties() {
         return properties;
     }
 
+    @Override
     public OpenCookie getEditor() {
         return null;
     }
 
+    @Override
     public ChangedEvent<Filter> getChangedEvent() {
         return changedEvent;
     }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ColorFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ColorFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,9 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Connection;
+import com.sun.hotspot.igv.data.Properties;
 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.OutputSlot;
-import com.sun.hotspot.igv.graph.Selector;
-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;
@@ -45,16 +41,18 @@
 
     public ColorFilter(String name) {
         this.name = name;
-        colorRules = new ArrayList<ColorRule>();
+        colorRules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(diagram.getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
         for (ColorRule rule : colorRules) {
             if (rule.getSelector() != null) {
                 List<Figure> figures = rule.getSelector().selected(diagram);
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,9 @@
  */
 package com.sun.hotspot.igv.filter;
 
-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 com.sun.hotspot.igv.graph.OutputSlot;
 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;
@@ -46,23 +42,25 @@
 
     public CombineFilter(String name) {
         this.name = name;
-        rules = new ArrayList<CombineRule>();
+        rules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(diagram.getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
         for (CombineRule r : rules) {
 
             List<Figure> list = selector.selectMultiple(r.getFirstMatcher());
-            Set<Figure> figuresToRemove = new HashSet<Figure>();
+            Set<Figure> figuresToRemove = new HashSet<>();
             for (Figure f : list) {
 
-                List<Figure> successors = new ArrayList<Figure>(f.getSuccessors());
+                List<Figure> successors = new ArrayList<>(f.getSuccessors());
                 if (r.isReversed()) {
                     if (successors.size() == 1) {
                         Figure succ = successors.get(0);
@@ -76,21 +74,30 @@
                             }
                         }
 
-                        assert slot != null;
-                        slot.setName(f.getProperties().get("dump_spec"));
-                        if (f.getProperties().get("short_name") != null) {
-                            slot.setShortName(f.getProperties().get("short_name"));
+                        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 {
-                            String s = f.getProperties().get("dump_spec");
-                            if (s != null && s.length() <= 5) {
-                                slot.setShortName(s);
+                            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());
+                                Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel(), c.getType());
                                 newConn.setColor(c.getColor());
                                 newConn.setStyle(c.getStyle());
                             }
@@ -101,7 +108,7 @@
                 } else {
 
                     for (Figure succ : successors) {
-                        if (succ.getPredecessors().size() == 1) {
+                        if (succ.getPredecessors().size() == 1 && succ.getInputSlots().size() == 1) {
                             if (succ.getProperties().selectSingle(r.getSecondMatcher()) != null && succ.getOutputSlots().size() == 1) {
 
 
@@ -122,22 +129,32 @@
                                     pos = Integer.parseInt(succ.getProperties().get("con"));
                                 }
                                 OutputSlot slot = f.createOutputSlot(pos);
-                                slot.setName(succ.getProperties().get("dump_spec"));
-                                if (succ.getProperties().get("short_name") != null) {
-                                    slot.setShortName(succ.getProperties().get("short_name"));
+                                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 {
-                                    String s = succ.getProperties().get("dump_spec");
-                                    if (s != null && s.length() <= 2) {
-                                        slot.setShortName(s);
+                                    slot.setText(succ.getProperties().get("dump_spec"));
+                                    if (succ.getProperties().get("short_name") != null) {
+                                        slot.setShortName(succ.getProperties().get("short_name"));
                                     } else {
-                                        String tmpName = succ.getProperties().get("name");
-                                        if (tmpName != null && tmpName.length() > 0) {
-                                            slot.setShortName(tmpName.substring(0, 1));
+                                        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);
+                                    Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel(), c.getType());
                                     newConn.setColor(c.getColor());
                                     newConn.setStyle(c.getStyle());
                                 }
@@ -167,6 +184,7 @@
         private PropertyMatcher first;
         private PropertyMatcher second;
         private boolean reversed;
+        private String shortProperty;
 
         public CombineRule(PropertyMatcher first, PropertyMatcher second) {
             this(first, second, false);
@@ -174,9 +192,14 @@
         }
 
         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() {
@@ -190,5 +213,9 @@
         public PropertyMatcher getSecondMatcher() {
             return second;
         }
+
+        public String getShortProperty() {
+            return shortProperty;
+        }
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,12 +23,8 @@
  */
 package com.sun.hotspot.igv.filter;
 
-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.OutputSlot;
-import com.sun.hotspot.igv.graph.Selector;
 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;
@@ -44,16 +40,18 @@
 
     public ConnectionFilter(String name) {
         this.name = name;
-        connectionStyleRules = new ArrayList<ConnectionStyleRule>();
+        connectionStyleRules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(diagram.getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
         for (ConnectionStyleRule rule : connectionStyleRules) {
             List<Figure> figures = null;
             if (rule.getSelector() != null) {
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,17 +29,13 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.util.Collection;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
+import javax.script.*;
 import org.openide.cookies.OpenCookie;
-import org.openide.filesystems.Repository;
-import org.openide.filesystems.FileSystem;
 import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
 import org.openide.util.Exceptions;
-import org.openide.util.Lookup;
 
 /**
  *
@@ -48,7 +44,6 @@
 public class CustomFilter extends AbstractFilter {
 
     public static final String JAVASCRIPT_HELPER_ID = "JavaScriptHelper";
-    private static ScriptEngineAbstraction engine;
     private String code;
     private String name;
 
@@ -58,6 +53,7 @@
         getProperties().setProperty("name", name);
     }
 
+    @Override
     public String getName() {
         return name;
     }
@@ -80,6 +76,7 @@
     public OpenCookie getEditor() {
         return new OpenCookie() {
 
+            @Override
             public void open() {
                 openInEditor();
             }
@@ -89,7 +86,9 @@
     public boolean openInEditor() {
         EditFilterDialog dialog = new EditFilterDialog(CustomFilter.this);
         dialog.setVisible(true);
-        return dialog.wasAccepted();
+        boolean result = dialog.wasAccepted();
+        this.getChangedEvent().fire();
+        return result;
     }
 
     @Override
@@ -97,41 +96,16 @@
         return getName();
     }
 
-    public static ScriptEngineAbstraction getEngine() {
-        if (engine == null) {
-
-            ScriptEngineAbstraction chosen = null;
-            try {
-                Collection<? extends ScriptEngineAbstraction> list = Lookup.getDefault().lookupAll(ScriptEngineAbstraction.class);
-                for (ScriptEngineAbstraction s : list) {
-                    if (s.initialize(getJsHelperText())) {
-                        if (chosen == null || !(chosen instanceof JavaSE6ScriptEngine)) {
-                            chosen = s;
-                        }
-                    }
-                }
-            } catch (NoClassDefFoundError ncdfe) {
-                Logger.getLogger("global").log(Level.SEVERE, null, ncdfe);
-            }
-
-            if (chosen == null) {
-                NotifyDescriptor message = new NotifyDescriptor.Message("Could not find a scripting engine. Please make sure that the Rhino scripting engine is available. Otherwise filter cannot be used.", NotifyDescriptor.ERROR_MESSAGE);
-                DialogDisplayer.getDefault().notifyLater(message);
-                chosen = new NullScriptEngine();
-            }
-
-            engine = chosen;
-        }
-
-        return engine;
-    }
-
     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);");
+        StringBuilder sb = new StringBuilder("if (typeof importPackage === 'undefined') { try { load('nashorn:mozilla_compat.js'); } catch (e) {} }"
+                + "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 {
-            FileSystem fs = Repository.getDefault().getDefaultFileSystem();
-            FileObject fo = fs.getRoot().getFileObject(JAVASCRIPT_HELPER_ID);
+            FileObject fo = FileUtil.getConfigRoot().getFileObject(JAVASCRIPT_HELPER_ID);
             is = fo.getInputStream();
             BufferedReader r = new BufferedReader(new InputStreamReader(is));
             String s;
@@ -152,7 +126,18 @@
         return sb.toString();
     }
 
+    @Override
     public void apply(Diagram d) {
-        getEngine().execute(d, code);
+        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);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/EdgeColorIndexFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            Slot[] slots;
+            if (applyTo.equals(INPUTS)) {
+                List<InputSlot> inputSlots = f.getInputSlots();
+                slots = inputSlots.toArray(new Slot[inputSlots.size()]);
+            } else {
+                List<OutputSlot> 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++;
+            }
+
+        }
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -137,14 +137,14 @@
     }// </editor-fold>//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);
+    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);
+    setVisible(false);
 }//GEN-LAST:event_cancelButtonClicked
 
 
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/Filter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/Filter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,5 +41,6 @@
 
     OpenCookie getEditor();
 
+    @Override
     ChangedEvent<Filter> getChangedEvent();
 }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,9 +23,10 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Diagram;
 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;
@@ -38,20 +39,25 @@
 
     private List<Filter> filters;
     private transient ChangedEvent<FilterChain> changedEvent;
-    private boolean fireEvents;
+
+    private ChangedListener<Filter> changedListener = new ChangedListener<Filter>() {
+        @Override
+        public void changed(Filter source) {
+            changedEvent.fire();
+        }
+    };
 
     public FilterChain() {
-        filters = new ArrayList<Filter>();
-        changedEvent = new ChangedEvent<FilterChain>(this);
-        this.fireEvents = true;
+        filters = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
     }
 
     public FilterChain(FilterChain f) {
-        this.filters = new ArrayList<Filter>(f.filters);
-        changedEvent = new ChangedEvent<FilterChain>(this);
-        this.fireEvents = true;
+        this.filters = new ArrayList<>(f.filters);
+        changedEvent = new ChangedEvent<>(this);
     }
 
+    @Override
     public ChangedEvent<FilterChain> getChangedEvent() {
         return changedEvent;
     }
@@ -68,7 +74,7 @@
     }
 
     public void apply(Diagram d, FilterChain sequence) {
-        List<Filter> applied = new ArrayList<Filter>();
+        List<Filter> applied = new ArrayList<>();
         for (Filter f : sequence.getFilters()) {
             if (filters.contains(f)) {
                 f.apply(d);
@@ -84,29 +90,12 @@
         }
     }
 
-    public void beginAtomic() {
-        this.fireEvents = false;
-    }
-
-    public void endAtomic() {
-        this.fireEvents = true;
-        changedEvent.fire();
-    }
 
     public void addFilter(Filter filter) {
         assert filter != null;
         filters.add(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
-    }
-
-    public void addFilterSameSequence(Filter filter) {
-        assert filter != null;
-        filters.add(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        filter.getChangedEvent().addListener(changedListener);
+        changedEvent.fire();
     }
 
     public boolean containsFilter(Filter filter) {
@@ -116,9 +105,8 @@
     public void removeFilter(Filter filter) {
         assert filters.contains(filter);
         filters.remove(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        filter.getChangedEvent().removeListener(changedListener);
+        changedEvent.fire();
     }
 
     public void moveFilterUp(Filter filter) {
@@ -128,9 +116,7 @@
             filters.remove(index);
             filters.add(index - 1, filter);
         }
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        changedEvent.fire();
     }
 
     public void moveFilterDown(Filter filter) {
@@ -140,16 +126,10 @@
             filters.remove(index);
             filters.add(index + 1, filter);
         }
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        changedEvent.fire();
     }
 
     public List<Filter> getFilters() {
         return Collections.unmodifiableList(filters);
     }
-
-    public void clear() {
-        filters.clear();
-    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChainProvider.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChainProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterSetting.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterSetting.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
 
     public FilterSetting(String name) {
         this.name = name;
-        filters = new HashSet<Filter>();
+        filters = new HashSet<>();
     }
 
     public Set<Filter> getFilters() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/GradientColorFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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<Figure> 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;
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/JavaSE6ScriptEngine.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +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.graph.Diagram;
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import org.openide.util.Exceptions;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class JavaSE6ScriptEngine implements ScriptEngineAbstraction {
-
-    private ScriptEngine engine;
-    private Bindings bindings;
-
-    public boolean initialize(String jsHelperText) {
-        try {
-            ScriptEngineManager sem = new ScriptEngineManager();
-            ScriptEngine e = sem.getEngineByName("ECMAScript");
-            engine = e;
-            e.eval(jsHelperText);
-            Bindings b = e.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
-            b.put("IO", System.out);
-            bindings = b;
-            return true;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    public void execute(Diagram d, String code) {
-        try {
-            Bindings b = bindings;
-            b.put("graph", d);
-            engine.eval(code, b);
-        } catch (ScriptException ex) {
-            Exceptions.printStackTrace(ex);
-        }
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/NullScriptEngine.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +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;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class NullScriptEngine implements ScriptEngineAbstraction {
-
-    public boolean initialize(String jsHelperText) {
-        return true;
-    }
-
-    public void execute(Diagram d, String code) {
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,7 @@
 
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.graph.Selector;
-import com.sun.hotspot.igv.data.Properties;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -44,56 +42,36 @@
 
     public RemoveFilter(String name) {
         this.name = name;
-        rules = new ArrayList<RemoveRule>();
+        rules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
-
         for (RemoveRule r : rules) {
+            List<Figure> selected = r.getSelector().selected(diagram);
+            Set<Figure> toRemove = new HashSet<>(selected);
 
-            List<Figure> list = r.getSelector().selected(diagram);
-            Set<Figure> figuresToRemove = new HashSet<Figure>();
-
-            List<Figure> protectedFigures = null;
-            if (r.getRemoveAllWithoutPredecessor()) {
-                protectedFigures = diagram.getRootFigures();
+            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);
             }
 
-            for (Figure f : list) {
-                if (r.getRemoveOnlyInputs()) {
-                    List<InputSlot> inputSlots = new ArrayList<InputSlot>();
-                    for (InputSlot is : f.getInputSlots()) {
-                        inputSlots.add(is);
-                    }
-                    for (InputSlot is : inputSlots) {
-                        f.removeSlot(is);
-                    }
-
-                    f.createInputSlot();
-                } else {
-                    figuresToRemove.add(f);
-                }
-            }
-
-            if (r.getRemoveAllWithoutPredecessor()) {
-                boolean progress = true;
-                while (progress) {
-                    List<Figure> rootFigures = diagram.getRootFigures();
-                    progress = false;
-                    for (Figure f : rootFigures) {
-                        if (!protectedFigures.contains(f)) {
-                            figuresToRemove.add(f);
-                            progress = true;
-                        }
-                    }
-                }
-            }
-
-            diagram.removeAllFigures(figuresToRemove);
+            diagram.removeAllFigures(toRemove);
         }
     }
 
@@ -104,29 +82,23 @@
     public static class RemoveRule {
 
         private Selector selector;
-        private boolean removeAllWithoutPredecessor;
-        private boolean removeOnlyInputs;
+        private boolean removeOrphans;
 
-        public RemoveRule(Selector selector, boolean b) {
-            this(selector, b, false);
+        public RemoveRule(Selector selector) {
+            this(selector, false);
         }
 
-        public RemoveRule(Selector selector, boolean removeAllWithoutPredecessor, boolean removeOnlyInputs) {
+        public RemoveRule(Selector selector, boolean removeOrphans) {
             this.selector = selector;
-            this.removeOnlyInputs = removeOnlyInputs;
-            this.removeAllWithoutPredecessor = removeAllWithoutPredecessor;
+            this.removeOrphans = removeOrphans;
         }
 
         public Selector getSelector() {
             return selector;
         }
 
-        public boolean getRemoveOnlyInputs() {
-            return removeOnlyInputs;
-        }
-
-        public boolean getRemoveAllWithoutPredecessor() {
-            return removeAllWithoutPredecessor;
+        public boolean getRemoveOrphans() {
+            return removeOrphans;
         }
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,12 +23,7 @@
  */
 package com.sun.hotspot.igv.filter;
 
-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 com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Selector;
+import com.sun.hotspot.igv.graph.*;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -43,13 +38,15 @@
 
     public RemoveInputsFilter(String name) {
         this.name = name;
-        rules = new ArrayList<RemoveInputsRule>();
+        rules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
 
         for (RemoveInputsRule r : rules) {
@@ -57,7 +54,7 @@
             List<Figure> list = r.getSelector().selected(diagram);
             for (Figure f : list) {
                 int z = 0;
-                List<InputSlot> last = new ArrayList<InputSlot>();
+                List<InputSlot> last = new ArrayList<>();
                 for (InputSlot is : f.getInputSlots()) {
                     if (z >= r.getStartingIndex() && z <= r.getEndIndex() && is.getConnections().size() > 0) {
                         StringBuilder sb = new StringBuilder();
@@ -73,7 +70,7 @@
                         }
                         is.removeAllConnections();
                         is.setShortName("X");
-                        is.setName(sb.toString());
+                        is.setText(sb.toString());
                         last.add(is);
                     } else {
                         last.clear();
@@ -91,10 +88,10 @@
                         if (i != 0) {
                             sb.append("<BR>");
                         }
-                        sb.append(is2.getName());
+                        sb.append(is2.getText());
                     }
 
-                    first.setName(sb.toString());
+                    first.setText(sb.toString());
 
                     for (int i = 1; i < last.size(); i++) {
                         f.removeSlot(last.get(i));
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,7 @@
  */
 package com.sun.hotspot.igv.filter;
 
-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 com.sun.hotspot.igv.graph.OutputSlot;
+import com.sun.hotspot.igv.graph.*;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -44,17 +40,19 @@
         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<Connection> toRemove = new ArrayList<Connection>();
+                List<Connection> toRemove = new ArrayList<>();
                 for (Connection c : is.getConnections()) {
 
                     if (c.getOutputSlot().getFigure() == f) {
@@ -72,7 +70,7 @@
                     }
 
                     c.getInputSlot().setShortName("O");
-                    c.getInputSlot().setName("Self Loop");
+                    c.getInputSlot().setText("Self Loop");
                 }
             }
         }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ScriptEngineAbstraction.java	Mon Dec 05 13:09:39 2016 -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.filter;
-
-import com.sun.hotspot.igv.graph.Diagram;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public interface ScriptEngineAbstraction {
-
-    public boolean initialize(String jsHelperText);
-
-    public void execute(Diagram d, String code);
-}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,12 +23,7 @@
  */
 package com.sun.hotspot.igv.filter;
 
-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 com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Selector;
+import com.sun.hotspot.igv.graph.*;
 import java.util.List;
 
 /**
@@ -39,25 +34,52 @@
 
     private String name;
     private Selector selector;
+    private String propertyName;
 
-    public SplitFilter(String name, Selector selector) {
+    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<Figure> 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();
-                    is.setName(f.getProperties().get("dump_spec"));
-                    String s = f.getProperties().get("short_name");
+                    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);
                     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/UnconnectedSlotFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            List<Slot> 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);
+            }
+        }
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js	Mon Feb 06 17:18:57 2017 +0100
@@ -21,26 +21,35 @@
  * 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);
+    f.apply(graph); 
 }
 
 function remove(property, regexp) {
     var f = new RemoveFilter("");
-    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), false, false));
+    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp))));
     f.apply(graph);
 }
 
-function split(property, regexp) {
-    var f = new SplitFilter("", new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)));
+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);
 }
 
@@ -56,6 +65,40 @@
     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;
@@ -68,4 +111,4 @@
 var pink = Color.pink
 var red = Color.red;
 var yellow = Color.yellow;
-var white = Color.white;
+var white = Color.white;
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/build-impl.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/build-impl.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="com.sun.hotspot.igv.filterwindow-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/suite-private.properties"/>
     <property file="nbproject/suite.properties"/>
     <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
@@ -16,13 +23,21 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
             </not>
         </condition>
     </fail>
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=401b2654
-build.xml.script.CRC32=9c158403
-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=401b2654
-nbproject/build-impl.xml.script.CRC32=19fb08e0
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.data.CRC32=5b8e8a60
+nbproject/build-impl.xml.script.CRC32=e4293f0e
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -43,7 +43,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.6.1.1</specification-version>
+                        <specification-version>6.21.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.39.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -51,7 +59,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -59,7 +67,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.12.1</specification-version>
+                        <specification-version>6.34.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -67,7 +75,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.3.1</specification-version>
+                        <specification-version>7.46.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -75,7 +83,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.7.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -83,7 +91,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -91,7 +99,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -99,7 +115,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.18.1</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,3 +1,3 @@
 OpenIDE-Module-Name=FilterWindow
-CTL_FilterTopComponent=Filter Window
-HINT_FilterTopComponent=This is a Filter window
+CTL_FilterTopComponent=Filters
+HINT_FilterTopComponent=Allows to choose active filters and modify them.
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckListView.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckListView.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,8 +44,8 @@
     }
 
     @Override
-    protected JList createList() {
-        JList tmpList = super.createList();
+    protected JList<Object> createList() {
+        JList<Object> tmpList = super.createList();
         tmpList.setCellRenderer(new CheckRenderer(tmpList));
         return tmpList;
     }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,7 @@
 
     public CheckNode(Children c, Lookup lookup) {
         super(c, lookup);
-        selectionChangedEvent = new ChangedEvent<CheckNode>(this);
+        selectionChangedEvent = new ChangedEvent<>(this);
         selected = false;
         enabled = true;
     }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
 package com.sun.hotspot.igv.filterwindow;
 
 import org.openide.explorer.view.NodeListModel;
-import org.openide.nodes.Node;
+import org.openide.explorer.view.Visualizer;
 
 /**
  *
@@ -32,15 +32,11 @@
  */
 public class CheckNodeListModel extends NodeListModel {
 
-    private Node rootNode;
-
-    @Override
-    public void setNode(Node rootNode) {
-        this.rootNode = rootNode;
-        super.setNode(rootNode);
-    }
-
     public CheckNode getCheckNodeAt(int index) {
-        return (CheckNode) rootNode.getChildren().getNodes()[index];
+        Object item = getElementAt(index);
+        if (item != null) {
+            return (CheckNode) Visualizer.findNode(item);
+        }
+        return null;
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckRenderer.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckRenderer.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,7 @@
  */
 package com.sun.hotspot.igv.filterwindow;
 
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
+import java.awt.*;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import javax.swing.JCheckBox;
@@ -37,12 +33,12 @@
 /**
  * @author Thomas Wuerthinger
  */
-public class CheckRenderer extends JCheckBox implements ListCellRenderer {
+public class CheckRenderer extends JCheckBox implements ListCellRenderer<Object> {
 
-    private JList list;
+    private JList<Object> list;
     private Color startBackground;
 
-    public CheckRenderer(final JList list) {
+    public CheckRenderer(final JList<Object> list) {
         this.list = list;
         list.addMouseListener(
                 new MouseAdapter() {
@@ -65,7 +61,8 @@
         startBackground = this.getBackground();
     }
 
-    public Component getListCellRendererComponent(final JList list, Object value, final int index, boolean isSelected, boolean cellHasFocus) {
+    @Override
+    public Component getListCellRendererComponent(final JList<? extends Object> list, Object value, final int index, boolean isSelected, boolean cellHasFocus) {
         setText(value.toString());
         CheckNode node = ((CheckNodeListModel) list.getModel()).getCheckNodeAt(index);
         this.setSelected(node.isSelected());
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterChainProviderImplementation.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterChainProviderImplementation.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,10 +32,12 @@
  */
 public class FilterChainProviderImplementation implements FilterChainProvider {
 
+    @Override
     public FilterChain getFilterChain() {
         return FilterTopComponent.findInstance().getFilterChain();
     }
 
+    @Override
     public FilterChain getSequence() {
         return FilterTopComponent.findInstance().getSequence();
     }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,12 +23,12 @@
  */
 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.filter.Filter;
-import com.sun.hotspot.igv.filter.FilterChain;
-import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.util.PropertiesSheet;
 import javax.swing.Action;
 import org.openide.actions.OpenAction;
@@ -48,7 +48,7 @@
 public class FilterNode extends CheckNode implements LookupListener, ChangedListener<FilterTopComponent> {
 
     private Filter filter;
-    private Lookup.Result result;
+    private Lookup.Result<FilterChain> result;
 
     public FilterNode(Filter filter) {
         this(filter, new InstanceContent());
@@ -62,6 +62,7 @@
         this.filter = filter;
         filter.getChangedEvent().addListener(new ChangedListener<Filter>() {
 
+            @Override
             public void changed(Filter source) {
                 update();
             }
@@ -69,12 +70,14 @@
 
         update();
 
-        Lookup.Template<FilterChain> tpl = new Lookup.Template<FilterChain>(FilterChain.class);
+        Lookup.Template<FilterChain> 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() {
@@ -102,10 +105,12 @@
         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));
     }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form	Mon Feb 06 17:18:57 2017 +0100
@@ -3,6 +3,8 @@
 <Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,65 +23,38 @@
  */
 package com.sun.hotspot.igv.filterwindow;
 
-import com.sun.hotspot.igv.filterwindow.actions.MoveFilterDownAction;
-import com.sun.hotspot.igv.filterwindow.actions.MoveFilterUpAction;
-import com.sun.hotspot.igv.filterwindow.actions.NewFilterAction;
-import com.sun.hotspot.igv.filterwindow.actions.RemoveFilterAction;
-import com.sun.hotspot.igv.filterwindow.actions.RemoveFilterSettingsAction;
-import com.sun.hotspot.igv.filterwindow.actions.SaveFilterSettingsAction;
+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.data.ChangedEvent;
-import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.filterwindow.actions.*;
 import java.awt.BorderLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Serializable;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+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.Exceptions;
-import org.openide.util.Lookup;
-import org.openide.util.LookupEvent;
-import org.openide.util.LookupListener;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
-import org.openide.awt.Toolbar;
-import org.openide.filesystems.FileLock;
+import org.openide.util.*;
 import org.openide.util.actions.SystemAction;
 import org.openide.windows.TopComponent;
 import org.openide.windows.WindowManager;
-import org.openide.filesystems.Repository;
-import org.openide.filesystems.FileSystem;
-import org.openide.filesystems.FileObject;
 
 /**
  *
@@ -98,13 +71,14 @@
     private ExplorerManager manager;
     private FilterChain filterChain;
     private FilterChain sequence;
-    private Lookup.Result result;
+    private Lookup.Result<FilterChain> result;
     private JComboBox comboBox;
     private List<FilterSetting> filterSettings;
     private FilterSetting customFilterSetting = new FilterSetting("-- Custom --");
     private ChangedEvent<FilterTopComponent> filterSettingsChangedEvent;
     private ActionListener comboBoxActionListener = new ActionListener() {
 
+        @Override
         public void actionPerformed(ActionEvent e) {
             comboBoxSelectionChanged();
         }
@@ -139,8 +113,8 @@
 
         if (s != customFilterSetting) {
             FilterChain chain = getFilterChain();
-            chain.beginAtomic();
-            List<Filter> toRemove = new ArrayList<Filter>();
+            chain.getChangedEvent().beginAtomic();
+            List<Filter> toRemove = new ArrayList<>();
             for (Filter f : chain.getFilters()) {
                 if (!s.containsFilter(f)) {
                     toRemove.add(f);
@@ -156,7 +130,7 @@
                 }
             }
 
-            chain.endAtomic();
+            chain.getChangedEvent().endAtomic();
             filterSettingsChangedEvent.fire();
         } else {
             this.updateComboBoxSelection();
@@ -177,14 +151,14 @@
     }
 
     public void addFilterSetting() {
-        NotifyDescriptor.InputLine l = new NotifyDescriptor.InputLine("Enter a name:", "Filter");
+        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 \"" + name + "\" already exists, to you want to overwrite?", "Filter");
+                    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;
@@ -203,6 +177,7 @@
             // Sort alphabetically
             Collections.sort(filterSettings, new Comparator<FilterSetting>() {
 
+                @Override
                 public int compare(FilterSetting o1, FilterSetting o2) {
                     return o1.getName().compareTo(o2.getName());
                 }
@@ -223,7 +198,7 @@
             FilterSetting f = (FilterSetting) o;
             assert f != customFilterSetting;
             assert filterSettings.contains(f);
-            NotifyDescriptor.Confirmation l = new NotifyDescriptor.Confirmation("Do you really want to remove filter \"" + f + "\"?", "Filter");
+            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();
@@ -267,28 +242,26 @@
         }
     }
 
-    private class FilterChildren extends Children.Keys implements ChangedListener<CheckNode> {
+    private class FilterChildren extends Children.Keys<Filter> implements ChangedListener<CheckNode> {
+
+        private HashMap<Filter, Node> nodeHash = new HashMap<>();
 
-        //private Node[] oldSelection;
-        //private ArrayList<Node> newSelection;
-        private HashMap<Object, Node> nodeHash = new HashMap<Object, Node>();
-
-        protected Node[] createNodes(Object object) {
-            if (nodeHash.containsKey(object)) {
-                return new Node[]{nodeHash.get(object)};
+        @Override
+        protected Node[] createNodes(Filter filter) {
+            if (nodeHash.containsKey(filter)) {
+                return new Node[]{nodeHash.get(filter)};
             }
 
-            assert object instanceof Filter;
-            Filter filter = (Filter) object;
-            com.sun.hotspot.igv.filterwindow.FilterNode node = new com.sun.hotspot.igv.filterwindow.FilterNode(filter);
+            FilterNode node = new FilterNode(filter);
             node.getSelectionChangedEvent().addListener(this);
-            nodeHash.put(object, node);
+            nodeHash.put(filter, node);
             return new Node[]{node};
         }
 
         public FilterChildren() {
             sequence.getChangedEvent().addListener(new ChangedListener<FilterChain>() {
 
+                @Override
                 public void changed(FilterChain source) {
                     addNotify();
                 }
@@ -297,11 +270,13 @@
             setBefore(false);
         }
 
+        @Override
         protected void addNotify() {
             setKeys(sequence.getFilters());
             updateSelection();
         }
 
+        @Override
         public void changed(CheckNode source) {
             FilterNode node = (FilterNode) source;
             Filter f = node.getFilter();
@@ -322,16 +297,11 @@
     }
 
     public FilterChain getFilterChain() {
-        return filterChain;/*
-    EditorTopComponent tc = EditorTopComponent.getActive();
-    if (tc == null) {
-    return filterChain;
-    }
-    return tc.getFilterChain();*/
+        return filterChain;
     }
 
     private FilterTopComponent() {
-        filterSettingsChangedEvent = new ChangedEvent<FilterTopComponent>(this);
+        filterSettingsChangedEvent = new ChangedEvent<>(this);
         initComponents();
         setName(NbBundle.getMessage(FilterTopComponent.class, "CTL_FilterTopComponent"));
         setToolTipText(NbBundle.getMessage(FilterTopComponent.class, "HINT_FilterTopComponent"));
@@ -355,13 +325,13 @@
         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()));
-        toolBar.add(RemoveFilterAction.get(RemoveFilterAction.class).createContextAwareInstance(this.getLookup()));
-        toolBar.add(NewFilterAction.get(NewFilterAction.class));
         this.add(view, BorderLayout.CENTER);
 
-        filterSettings = new ArrayList<FilterSetting>();
+        filterSettings = new ArrayList<>();
         updateComboBox();
 
         comboBox.addActionListener(comboBoxActionListener);
@@ -401,6 +371,7 @@
             filter = cf;
         }
 
+        @Override
         public void changed(Filter source) {
             try {
                 if (!fileObject.getName().equals(filter.getName())) {
@@ -409,15 +380,14 @@
                     lock.releaseLock();
                     FileObject newFileObject = fileObject.getParent().getFileObject(filter.getName());
                     fileObject = newFileObject;
-
                 }
 
                 FileLock lock = fileObject.lock();
                 OutputStream os = fileObject.getOutputStream(lock);
-                Writer w = new OutputStreamWriter(os);
-                String s = filter.getCode();
-                w.write(s);
-                w.close();
+                try (Writer w = new OutputStreamWriter(os)) {
+                    String s = filter.getCode();
+                    w.write(s);
+                }
                 lock.releaseLock();
 
             } catch (IOException ex) {
@@ -427,15 +397,13 @@
     }
 
     public void initFilters() {
-
-        FileSystem fs = Repository.getDefault().getDefaultFileSystem();
-        FileObject folder = fs.getRoot().getFileObject(FOLDER_ID);
+        FileObject folder = FileUtil.getConfigRoot().getFileObject(FOLDER_ID);
         FileObject[] children = folder.getChildren();
 
-        List<CustomFilter> customFilters = new ArrayList<CustomFilter>();
-        HashMap<CustomFilter, String> afterMap = new HashMap<CustomFilter, String>();
-        Set<CustomFilter> enabledSet = new HashSet<CustomFilter>();
-        HashMap<String, CustomFilter> map = new HashMap<String, CustomFilter>();
+        List<CustomFilter> customFilters = new ArrayList<>();
+        HashMap<CustomFilter, String> afterMap = new HashMap<>();
+        Set<CustomFilter> enabledSet = new HashSet<>();
+        HashMap<String, CustomFilter> map = new HashMap<>();
 
         for (final FileObject fo : children) {
             InputStream is = null;
@@ -447,13 +415,12 @@
                 is = fo.getInputStream();
                 BufferedReader r = new BufferedReader(new InputStreamReader(is));
                 String s;
-                StringBuffer sb = new StringBuffer();
+                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) {
@@ -488,7 +455,7 @@
 
         for (int j = 0; j < customFilters.size(); j++) {
             for (int i = 0; i < customFilters.size(); i++) {
-                List<CustomFilter> copiedList = new ArrayList<CustomFilter>(customFilters);
+                List<CustomFilter> copiedList = new ArrayList<>(customFilters);
                 for (CustomFilter cf : copiedList) {
 
                     String after = afterMap.get(cf);
@@ -573,7 +540,7 @@
 
     @Override
     public void componentOpened() {
-        Lookup.Template<FilterChain> tpl = new Lookup.Template<FilterChain>(FilterChain.class);
+        Lookup.Template<FilterChain> tpl = new Lookup.Template<>(FilterChain.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
     }
@@ -584,13 +551,9 @@
         result = null;
     }
 
+    @Override
     public void resultChanged(LookupEvent lookupEvent) {
         setChain(Utilities.actionsGlobalContext().lookup(FilterChain.class));
-    /*
-    EditorTopComponent tc = EditorTopComponent.getActive();
-    if (tc != null) {
-    setChain(tc.getFilterChain());
-    }*/
     }
 
     public void setChain(FilterChain chain) {
@@ -598,10 +561,10 @@
     }
 
     private FileObject getFileObject(CustomFilter cf) {
-        FileObject fo = Repository.getDefault().getDefaultFileSystem().getRoot().getFileObject(FOLDER_ID + "/" + cf.getName());
+        FileObject fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID + "/" + cf.getName());
         if (fo == null) {
             try {
-                fo = org.openide.filesystems.Repository.getDefault().getDefaultFileSystem().getRoot().getFileObject(FOLDER_ID).createData(cf.getName());
+                fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID).createData(cf.getName());
             } catch (IOException ex) {
                 Exceptions.printStackTrace(ex);
             }
@@ -610,6 +573,24 @@
     }
 
     @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);
 
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,10 +1,7 @@
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
-
-CTL_FilterAction=Open Filter Window
+CTL_FilterAction=Filters
+CTL_MoveFilterUpAction=Move upwards
 CTL_MoveFilterDownAction=Move downwards
-CTL_MoveFilterUpAction=Move upwards
-CTL_NewFilterAction=New filter...
 CTL_RemoveFilterAction=Remove
 CTL_RemoveFilterSettingsAction=Remove filter setting
-CTL_SaveFilterSettingsAction=Save filter settings...
+CTL_SaveFilterSettingsAction=Create filter profile...
+CTL_NewFilterAction=New filter...
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/FilterAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/FilterAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
  */
 package com.sun.hotspot.igv.filterwindow.actions;
 
-import com.sun.hotspot.igv.filterwindow.*;
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
 import java.awt.event.ActionEvent;
 import javax.swing.AbstractAction;
 import org.openide.util.NbBundle;
@@ -39,6 +39,7 @@
         super(NbBundle.getMessage(FilterAction.class, "CTL_FilterAction"));
     }
 
+    @Override
     public void actionPerformed(ActionEvent evt) {
         TopComponent win = FilterTopComponent.findInstance();
         win.open();
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,8 @@
  */
 package com.sun.hotspot.igv.filterwindow.actions;
 
+import com.sun.hotspot.igv.filter.Filter;
 import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
-import com.sun.hotspot.igv.filter.Filter;
 import javax.swing.Action;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
@@ -37,6 +37,7 @@
  */
 public final class MoveFilterDownAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         for (Node n : activatedNodes) {
             Filter c = n.getLookup().lookup(Filter.class);
@@ -44,19 +45,22 @@
         }
     }
 
+    @Override
     protected int mode() {
         return CookieAction.MODE_EXACTLY_ONE;
     }
 
     public MoveFilterDownAction() {
 
-        putValue(Action.SHORT_DESCRIPTION, "Move filter downwards");
+        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
@@ -65,7 +69,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/down.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/down.png";
     }
 
     @Override
@@ -74,6 +78,7 @@
         putValue("noIconInMenu", Boolean.TRUE);
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,8 @@
  */
 package com.sun.hotspot.igv.filterwindow.actions;
 
+import com.sun.hotspot.igv.filter.Filter;
 import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
-import com.sun.hotspot.igv.filter.Filter;
 import javax.swing.Action;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
@@ -37,6 +37,7 @@
  */
 public final class MoveFilterUpAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         for (Node n : activatedNodes) {
             Filter c = n.getLookup().lookup(Filter.class);
@@ -44,18 +45,21 @@
         }
     }
 
+    @Override
     protected int mode() {
         return CookieAction.MODE_EXACTLY_ONE;
     }
 
     public MoveFilterUpAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Move filter upwards");
+        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
@@ -64,7 +68,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/up.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/up.png";
     }
 
     @Override
@@ -73,6 +77,7 @@
         putValue("noIconInMenu", Boolean.TRUE);
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,10 +39,12 @@
         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");
     }
@@ -52,6 +54,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -63,6 +66,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/plus.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/plus.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,8 @@
  */
 package com.sun.hotspot.igv.filterwindow.actions;
 
+import com.sun.hotspot.igv.filter.Filter;
 import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
-import com.sun.hotspot.igv.filter.Filter;
 import javax.swing.Action;
 import javax.swing.JOptionPane;
 import org.openide.nodes.Node;
@@ -39,13 +39,14 @@
  */
 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?",
+                "Do you really want to delete " + activatedNodes.length + " filter(s)?", "Delete Filters",
                 JOptionPane.YES_NO_CANCEL_OPTION,
                 JOptionPane.QUESTION_MESSAGE,
                 null,
@@ -59,18 +60,21 @@
         }
     }
 
+    @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 filter");
+        putValue(Action.SHORT_DESCRIPTION, "Remove selected filter");
     }
 
+    @Override
     protected Class[] cookieClasses() {
         return new Class[]{
             Filter.class
@@ -85,9 +89,10 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/minus.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/minus.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,16 +35,18 @@
  */
 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, "Remove filter profile");
+        putValue(Action.SHORT_DESCRIPTION, "Delete current filter profile");
     }
 
     @Override
@@ -52,6 +54,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -63,6 +66,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/delete.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/delete.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,10 +35,12 @@
  */
 public final class SaveFilterSettingsAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         FilterTopComponent.findInstance().addFilterSetting();
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(SaveFilterSettingsAction.class, "CTL_SaveFilterSettingsAction");
     }
@@ -49,9 +51,10 @@
     }
 
     public SaveFilterSettingsAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Create new filter profile");
+        putValue(Action.SHORT_DESCRIPTION, "Save filter configuration as profile...");
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -63,6 +66,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/add.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/add.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -4,8 +4,8 @@
     <kind type="view" />
     <state type="joined" />
     <constraints>
-        <path orientation="horizontal" number="45" weight="0.21761006289308177"/>
-        <path orientation="vertical" number="0" weight="0.2510122989593188"/>
+        <path orientation="horizontal" number="90" weight="0.2"/>
+        <path orientation="vertical" number="0" weight="0.75"/>
     </constraints>
     <bounds x="0" y="0" width="0" height="0" />
     <frame state="0"/>
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.png has changed
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -18,8 +18,11 @@
             <attr name="position" intvalue="900"/>
         </file>
     </folder>
-    <folder name="Window">
-        <file name="com-sun-hotspot-igv-coordinator-actions-FilterAction.instance"/>
+    
+    <folder name="Actions">
+        <folder name="Window">
+            <file name="com-sun-hotspot-igv-filterwindow-actions-FilterAction.instance"/>
+        </folder>
     </folder>
     <folder name="Menu">
         <folder name="Window">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/build.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.graal" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.graal.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/manifest.mf	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,6 @@
+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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/build-impl.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.graal-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/genfiles.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=92ea213f
+build.xml.script.CRC32=3534d355
+build.xml.stylesheet.CRC32=a56c6a5b@2.67.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=92ea213f
+nbproject/build-impl.xml.script.CRC32=2867f2d5
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.graal</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.filter</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.layout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/suite.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Graal Compiler Support
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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 com.sun.hotspot.igv.graph.OutputSlot;
+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<Connection> connectionsToRemove = new HashSet<>();
+
+        for (Figure f : d.getFigures()) {
+            Properties p = f.getProperties();
+            int predCount;
+            String predCountString = p.get("predecessorCount");
+            if (predCountString != null) {
+                predCount = Integer.parseInt(predCountString);
+            } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) {
+                predCount = 1;
+            } else {
+                predCount = 0;
+            }
+            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();
+        }
+
+        Set<Figure> figuresToRemove = new HashSet<>();
+        next: for (Figure f : d.getFigures()) {
+            for (InputSlot is : f.getInputSlots()) {
+                if (!is.getConnections().isEmpty()) {
+                    continue next;
+                }
+            }
+            for (OutputSlot os : f.getOutputSlots()) {
+                if (!os.getConnections().isEmpty()) {
+                    continue next;
+                }
+            }
+            figuresToRemove.add(f);
+        }
+        d.removeAllFigures(figuresToRemove);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalColoringFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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<Figure> 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
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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.HashMap;
+import java.util.List;
+
+/**
+ * Filter that colors usage and successor edges differently.
+ *
+ * @author Peter Hofer
+ */
+public class GraalEdgeColorFilter extends AbstractFilter {
+
+    private final HashMap<String,Color> usageColor = new HashMap<>();
+    private Color otherUsageColor = Color.BLACK;
+
+    public GraalEdgeColorFilter() {
+    }
+
+    @Override
+    public String getName() {
+        return "Graal Edge Color Filter";
+    }
+
+    @Override
+    public void apply(Diagram d) {
+        List<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            for (InputSlot is : f.getInputSlots()) {
+                for (Connection c : is.getConnections()) {
+                    String type = c.getType();
+                    if (type == "Association" && "EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) {
+                        type = "Successor";
+                    }
+
+                    if (type != null) {
+                        Color typeColor = usageColor.get(type);
+                        if (typeColor == null) {
+                            c.setColor(otherUsageColor);
+                        } else {
+                            c.setColor(typeColor);
+                        }
+                        if (c.getStyle() != ConnectionStyle.DASHED && type == "Successor") {
+                            c.setStyle(ConnectionStyle.BOLD);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public Color getUsageColor(String type) {
+        return usageColor.get(type);
+    }
+
+    public void setUsageColor(String type, Color usageColor) {
+        this.usageColor.put(type, usageColor);
+    }
+
+    public Color getOtherUsageColor() {
+        return otherUsageColor;
+    }
+
+    public void setOtherUsageColor(Color otherUsageColor) {
+        this.otherUsageColor = otherUsageColor;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,4 @@
+colorize("name", "<init>.*", yellow);
+colorize("name", "<clinit>.*", pink);
+colorize("leaf", "1", lightGray);
+colorize("cutoff", "1", red);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,31 @@
+var red =  new java.awt.Color(240, 59, 32);
+var orange = new java.awt.Color(254, 178, 76);
+var yellow = new java.awt.Color(255, 237, 160);
+var middleBlue = new java.awt.Color(100, 147, 224);
+var lightGreen = new java.awt.Color(173, 221, 142);
+var lightBlue = new java.awt.Color(200, 200, 250);
+var gray = new java.awt.Color(220, 220, 220);
+var violet = new java.awt.Color(201, 148, 199);
+var black = new java.awt.Color(0, 0, 0);
+
+colorize("category", "controlSink", red);
+colorize("category", "controlSplit", red);
+colorize("category", "merge", red);
+colorize("category", "begin", orange);
+colorize("category", "end", orange);
+colorize("category", "fixed", yellow);
+colorize("category", "state", lightGreen);
+colorize("category", "phi", middleBlue);
+colorize("category", "proxy", middleBlue);
+colorize("category", "floating", lightBlue);
+colorize("class", "ConstantLocationNode", gray);
+colorize("class", "ParameterNode", gray);
+colorize("class", "ConstantNode", gray);
+colorize("class", "GuardNode", violet);
+colorize("class", "BlackholeNode", black);
+
+var f = new com.sun.hotspot.igv.graal.filters.GraalEdgeColorFilter();
+f.setUsageColor("Successor", red);
+f.setUsageColor("Value", blue);
+f.setUsageColor("Memory", new Color(0.0, 0.5, 0.0));
+f.apply(graph);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/probability.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,3 @@
+colorizeGradientWithMode("probability", 0, 500, "logarithmic");
+
+// more parameters: colorizeGradientCustom("probability", 0, 500, "logarithmic", [blue, yellow, red], [0, 0.5, 1], 16);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/reduceEdges.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,3 @@
+split("class", "ConstantLocationNode");
+split("class", "ParameterNode");
+split("class", "ConstantNode");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/removeFloating.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,4 @@
+remove("category", "floating");
+remove("category", "state");
+remove("category", "phi");
+remove("category", "proxy");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/removeState.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+remove("category", "state");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/stampColor.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,16 @@
+var red =  new java.awt.Color(240, 59, 32);
+var orange = new java.awt.Color(254, 178, 76);
+var yellow = new java.awt.Color(255, 237, 160);
+var middleBlue = new java.awt.Color(100, 147, 224);
+var lightGreen = new java.awt.Color(173, 221, 142);
+var lightBlue = new java.awt.Color(200, 200, 250);
+var gray = new java.awt.Color(220, 220, 220);
+var violet = new java.awt.Color(201, 148, 199);
+
+colorize("stamp", ".*", white);
+colorize("stamp", "void", gray);
+colorize("stamp", "a.*", yellow);
+colorize("stamp", "a#.*", orange);
+colorize("stamp", "a!.*", red);
+colorize("stamp", "i.*", middleBlue);
+colorize("stamp", "f.*", lightGreen);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+    <folder name="Filters">
+        <file name="Coloring" url="filters/color.filter">
+            <attr name="enabled" boolvalue="true"/>
+        </file>
+        
+        
+        <file name="Stamp Coloring" url="filters/stampColor.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+      
+        <file name="Probability Coloring" url="filters/probability.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Call Graph Coloring" url="filters/callgraph.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Reduce Edges" url="filters/reduceEdges.filter">
+            <attr name="enabled" boolvalue="true"/>
+        </file>
+        
+        <file name="Remove State" url="filters/removeState.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Remove Floating" url="filters/removeFloating.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+    </folder>
+</filesystem>
--- a/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -22,9 +22,18 @@
                         <specification-version>1.0</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.graph</package>
+                <package>com.sun.hotspot.igv.graph.services</package>
             </public-packages>
         </data>
     </configuration>
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/AndSelector.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/AndSelector.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,11 @@
         this.selector2 = s2;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
         List<Figure> l1 = selector1.selected(d);
         List<Figure> l2 = selector2.selected(d);
-        List<Figure> result = new ArrayList<Figure>();
+        List<Figure> result = new ArrayList<>();
         for (Figure f : l2) {
             if (l1.contains(f)) {
                 result.add(f);
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,14 +60,6 @@
         return succs;
     }
 
-    public Set<? extends Cluster> getPredecessors() {
-        Set<Block> succs = new HashSet<Block>();
-        for (InputBlock b : inputBlock.getPredecessors()) {
-            succs.add(diagram.getBlock(b));
-        }
-        return succs;
-    }
-
     public void setBounds(Rectangle r) {
         this.bounds = r;
     }
@@ -79,4 +71,10 @@
     public int compareTo(Cluster o) {
         return toString().compareTo(o.toString());
     }
+
+    @Override
+    public String toString() {
+        return inputBlock.getName();
+    }
 }
+
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 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;
@@ -36,6 +37,11 @@
  */
 public class Connection implements Source.Provider, Link {
 
+    @Override
+    public boolean isVIP() {
+        return style == ConnectionStyle.BOLD;
+    }
+
     public enum ConnectionStyle {
 
         NORMAL,
@@ -48,13 +54,17 @@
     private Color color;
     private ConnectionStyle style;
     private List<Point> controlPoints;
+    private String label;
+    private String type;
 
-    protected Connection(InputSlot inputSlot, OutputSlot outputSlot) {
+    protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) {
         this.inputSlot = inputSlot;
         this.outputSlot = outputSlot;
+        this.label = label;
+        this.type = type;
         this.inputSlot.connections.add(this);
         this.outputSlot.connections.add(this);
-        controlPoints = new ArrayList<Point>();
+        controlPoints = new ArrayList<>();
         Figure sourceFigure = this.outputSlot.getFigure();
         Figure destFigure = this.inputSlot.getFigure();
         sourceFigure.addSuccessor(destFigure);
@@ -89,10 +99,19 @@
         style = s;
     }
 
+    @Override
     public Source getSource() {
         return source;
     }
 
+    public String getLabel() {
+        return label;
+    }
+
+    public String getType() {
+        return type;
+    }
+
     public void remove() {
         inputSlot.getFigure().removePredecessor(outputSlot.getFigure());
         inputSlot.connections.remove(this);
@@ -100,24 +119,44 @@
         outputSlot.connections.remove(this);
     }
 
+    public String getToolTipText() {
+        StringBuilder builder = new StringBuilder();
+        if (label != null) {
+            builder.append(label).append(": ");
+        }
+        if (type != null) {
+            builder.append(type).append(" ");
+        }
+        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(" + getFrom().getVertex() + " to " + getTo().getVertex() + ")";
+        return "Connection('" + label + "', " + getFrom().getVertex() + " to " + getTo().getVertex() + ")";
     }
 
+    @Override
     public Port getFrom() {
         return outputSlot;
     }
 
+    @Override
     public Port getTo() {
         return inputSlot;
     }
 
+    @Override
     public List<Point> getControlPoints() {
         return controlPoints;
     }
 
+    @Override
     public void setControlPoints(List<Point> list) {
         controlPoints = list;
     }
 }
+
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,17 +28,9 @@
 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.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  *
@@ -51,20 +43,33 @@
     private InputGraph graph;
     private int curId;
     private String nodeText;
-    private Font font;
+    private final Font font;
+    private final Font slotFont;
+    private final Font boldFont;
 
     public Font getFont() {
         return font;
     }
 
+    public Font getSlotFont() {
+        return slotFont;
+    }
+
+    public Font getBoldFont() {
+        return boldFont;
+    }
+
     private Diagram() {
-        figures = new ArrayList<Figure>();
-        blocks = new HashMap<InputBlock, Block>();
+        figures = new ArrayList<>();
+        blocks = new LinkedHashMap<>(8);
         this.nodeText = "";
-        this.font = new Font("Serif", Font.PLAIN, 14);
+        this.font = new Font("Arial", Font.PLAIN, 12);
+        this.slotFont = new Font("Arial", Font.PLAIN, 10);
+        this.boldFont = this.font.deriveFont(Font.BOLD);
     }
 
     public Block getBlock(InputBlock b) {
+        assert blocks.containsKey(b);
         return blocks.get(b);
     }
 
@@ -72,12 +77,7 @@
         return nodeText;
     }
 
-    public void schedule(Collection<InputBlock> newBlocks) {
-        graph.schedule(newBlocks);
-        updateBlocks();
-    }
-
-    private void updateBlocks() {
+    public void updateBlocks() {
         blocks.clear();
         for (InputBlock b : graph.getBlocks()) {
             Block curBlock = new Block(b, this);
@@ -108,10 +108,26 @@
         return f;
     }
 
-    public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot) {
+    public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) {
         assert inputSlot.getFigure().getDiagram() == this;
         assert outputSlot.getFigure().getDiagram() == this;
-        return new Connection(inputSlot, outputSlot);
+        return new Connection(inputSlot, outputSlot, label, type);
+    }
+
+    public Map<InputNode, Set<Figure>> calcSourceToFigureRelation() {
+        Map<InputNode, Set<Figure>> map = new HashMap<>();
+
+        for(InputNode node : this.getGraph().getNodes()) {
+            map.put(node, new HashSet<Figure>());
+        }
+
+        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) {
@@ -126,11 +142,12 @@
         d.updateBlocks();
 
         Collection<InputNode> nodes = graph.getNodes();
-        HashMap<Integer, Figure> figureHash = new HashMap<Integer, Figure>();
+        Hashtable<Integer, Figure> figureHash = new Hashtable<>();
         for (InputNode n : nodes) {
             Figure f = d.createFigure();
             f.getSource().addSourceNode(n);
             f.getProperties().add(n.getProperties());
+            f.setSubgraphs(n.getSubgraphs());
             figureHash.put(n.getId(), f);
         }
 
@@ -140,23 +157,23 @@
             int to = e.getTo();
             Figure fromFigure = figureHash.get(from);
             Figure toFigure = figureHash.get(to);
+
+            if(fromFigure == null || toFigure == null) continue;
             assert fromFigure != null && toFigure != null;
 
+            int fromIndex = e.getFromIndex();
+            while (fromFigure.getOutputSlots().size() <= fromIndex) {
+                fromFigure.createOutputSlot();
+            }
+            OutputSlot outputSlot = fromFigure.getOutputSlots().get(fromIndex);
+
             int toIndex = e.getToIndex();
-
-            while (fromFigure.getOutputSlots().size() <= 0) {
-                fromFigure.createOutputSlot();
-            }
-
-            OutputSlot outputSlot = fromFigure.getOutputSlots().get(0);
-
             while (toFigure.getInputSlots().size() <= toIndex) {
                 toFigure.createInputSlot();
             }
-
             InputSlot inputSlot = toFigure.getInputSlots().get(toIndex);
 
-            Connection c = d.createConnection(inputSlot, outputSlot);
+            Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel(), e.getType());
 
             if (e.getState() == InputEdge.State.NEW) {
                 c.setStyle(Connection.ConnectionStyle.BOLD);
@@ -174,7 +191,7 @@
             freeFigure(f);
         }
 
-        ArrayList<Figure> newFigures = new ArrayList<Figure>();
+        ArrayList<Figure> newFigures = new ArrayList<>();
         for (Figure f : this.figures) {
             if (!figuresToRemove.contains(f)) {
                 newFigures.add(f);
@@ -185,12 +202,12 @@
 
     private void freeFigure(Figure succ) {
 
-        List<InputSlot> inputSlots = new ArrayList<InputSlot>(succ.getInputSlots());
+        List<InputSlot> inputSlots = new ArrayList<>(succ.getInputSlots());
         for (InputSlot s : inputSlots) {
             succ.removeInputSlot(s);
         }
 
-        List<OutputSlot> outputSlots = new ArrayList<OutputSlot>(succ.getOutputSlots());
+        List<OutputSlot> outputSlots = new ArrayList<>(succ.getOutputSlots());
         for (OutputSlot s : outputSlots) {
             succ.removeOutputSlot(s);
         }
@@ -219,7 +236,7 @@
 
     public Set<Connection> getConnections() {
 
-        Set<Connection> connections = new HashSet<Connection>();
+        Set<Connection> connections = new HashSet<>();
         for (Figure f : figures) {
 
             for (InputSlot s : f.getInputSlots()) {
@@ -231,10 +248,10 @@
     }
 
     public Figure getRootFigure() {
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(figures);
-        Figure root = selector.selectSingle("name", "Root");
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(figures);
+        Figure root = selector.selectSingle(new StringPropertyMatcher("name", "Root"));
         if (root == null) {
-            root = selector.selectSingle("name", "Start");
+            root = selector.selectSingle(new StringPropertyMatcher("name", "Start"));
         }
         if (root == null) {
             List<Figure> rootFigures = getRootFigures();
@@ -258,9 +275,10 @@
         System.out.println("Number of figures: " + tmpFigures.size());
         System.out.println("Number of connections: " + connections.size());
 
-        List<Figure> figuresSorted = new ArrayList<Figure>(tmpFigures);
+        List<Figure> figuresSorted = new ArrayList<>(tmpFigures);
         Collections.sort(figuresSorted, new Comparator<Figure>() {
 
+            @Override
             public int compare(Figure a, Figure b) {
                 return b.getPredecessors().size() + b.getSuccessors().size() - a.getPredecessors().size() - a.getSuccessors().size();
             }
@@ -283,7 +301,7 @@
     }
 
     public List<Figure> getRootFigures() {
-        ArrayList<Figure> rootFigures = new ArrayList<Figure>();
+        ArrayList<Figure> rootFigures = new ArrayList<>();
         for (Figure f : figures) {
             if (f.getPredecessors().size() == 0) {
                 rootFigures.add(f);
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,30 +23,25 @@
  */
 package com.sun.hotspot.igv.graph;
 
+import com.sun.hotspot.igv.data.InputBlock;
+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.Source;
 import com.sun.hotspot.igv.layout.Cluster;
 import com.sun.hotspot.igv.layout.Vertex;
-import com.sun.hotspot.igv.data.Properties;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Point;
+import java.awt.*;
 import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
+import java.util.*;
 
-/**
- *
- * @author Thomas Wuerthinger
- */
 public class Figure extends Properties.Entity implements Source.Provider, Vertex {
 
-    public static final int INSET = 6;
-    public static final int SLOT_WIDTH = 10;
-    public static final int SLOT_START = 3;
+    public static final int INSET = 8;
+    public static int SLOT_WIDTH = 10;
+    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<InputSlot> inputSlots;
     protected List<OutputSlot> outputSlots;
@@ -55,6 +50,7 @@
     private Point position;
     private List<Figure> predecessors;
     private List<Figure> successors;
+    private List<InputGraph> subgraphs;
     private Color color;
     private int id;
     private String idString;
@@ -66,7 +62,7 @@
         if (heightCash == -1) {
             BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
             Graphics g = image.getGraphics();
-            g.setFont(diagram.getFont());
+            g.setFont(diagram.getFont().deriveFont(Font.BOLD));
             FontMetrics metrics = g.getFontMetrics();
             String nodeText = diagram.getNodeText();
             heightCash = nodeText.split("\n").length * metrics.getHeight() + INSET;
@@ -74,20 +70,41 @@
         return heightCash;
     }
 
+    public static <T> List<T> getAllBefore(List<T> inputList, T tIn) {
+        List<T> result = new ArrayList<>();
+        for(T t : inputList) {
+            if(t.equals(tIn)) {
+                break;
+            }
+            result.add(t);
+        }
+        return result;
+    }
+
+    public static int getSlotsWidth(Collection<? extends Slot> 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());
+            g.setFont(diagram.getFont().deriveFont(Font.BOLD));
             FontMetrics metrics = g.getFontMetrics();
-            for (String s : lines) {
+            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;
     }
@@ -95,10 +112,10 @@
     protected Figure(Diagram diagram, int id) {
         this.diagram = diagram;
         this.source = new Source();
-        inputSlots = new ArrayList<InputSlot>(5);
-        outputSlots = new ArrayList<OutputSlot>(1);
-        predecessors = new ArrayList<Figure>(6);
-        successors = new ArrayList<Figure>(6);
+        inputSlots = new ArrayList<>(5);
+        outputSlots = new ArrayList<>(1);
+        predecessors = new ArrayList<>(6);
+        successors = new ArrayList<>(6);
         this.id = id;
         idString = Integer.toString(id);
 
@@ -123,7 +140,7 @@
     }
 
     public Set<Figure> getPredecessorSet() {
-        Set<Figure> result = new HashSet<Figure>();
+        Set<Figure> result = new HashSet<>();
         for (Figure f : getPredecessors()) {
             result.add(f);
         }
@@ -131,7 +148,7 @@
     }
 
     public Set<Figure> getSuccessorSet() {
-        Set<Figure> result = new HashSet<Figure>();
+        Set<Figure> result = new HashSet<>();
         for (Figure f : getSuccessors()) {
             result.add(f);
         }
@@ -160,10 +177,20 @@
         successors.remove(f);
     }
 
+    public List<InputGraph> getSubgraphs() {
+        return subgraphs;
+    }
+
+    public void setSubgraphs(List<InputGraph> subgraphs) {
+        this.subgraphs = subgraphs;
+    }
+
+    @Override
     public void setPosition(Point p) {
         this.position = p;
     }
 
+    @Override
     public Point getPosition() {
         return position;
     }
@@ -172,6 +199,7 @@
         return diagram;
     }
 
+    @Override
     public Source getSource() {
         return source;
     }
@@ -193,7 +221,7 @@
 
         assert inputSlots.contains(s) || outputSlots.contains(s);
 
-        List<Connection> connections = new ArrayList<Connection>(s.getConnections());
+        List<Connection> connections = new ArrayList<>(s.getConnections());
         for (Connection c : connections) {
             c.remove();
         }
@@ -222,6 +250,13 @@
         return Collections.unmodifiableList(inputSlots);
     }
 
+    public Set<Slot> getSlots() {
+        Set<Slot> result = new HashSet<>();
+        result.addAll(getInputSlots());
+        result.addAll(getOutputSlots());
+        return result;
+    }
+
     public List<OutputSlot> getOutputSlots() {
         return Collections.unmodifiableList(outputSlots);
     }
@@ -248,13 +283,13 @@
         String[] result = new String[strings.length];
 
         for (int i = 0; i < strings.length; i++) {
-            result[i] = resolveString(strings[i]);
+            result[i] = resolveString(strings[i], getProperties());
         }
 
         lines = result;
     }
 
-    private String resolveString(String string) {
+    public static final String resolveString(String string, Properties properties) {
 
         StringBuilder sb = new StringBuilder();
         boolean inBrackets = false;
@@ -264,7 +299,7 @@
             char c = string.charAt(i);
             if (inBrackets) {
                 if (c == ']') {
-                    String value = getProperties().get(curIdent.toString());
+                    String value = properties.get(curIdent.toString());
                     if (value == null) {
                         value = "";
                     }
@@ -286,13 +321,16 @@
         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;
+            int height = getHeight() + 2 * Figure.SLOT_WIDTH - 2 * Figure.OVERLAPPING;
+
+
             return new Dimension(width, height);
         } else {
-            int width = getWidth() + 2 * Figure.SLOT_WIDTH;
+            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);
         }
@@ -308,21 +346,31 @@
             assert false : "Should never reach here, every figure must have at least one source node!";
             return null;
         } else {
-            Cluster result = diagram.getBlock(diagram.getGraph().getBlock(getSource().getSourceNodes().get(0)));
+            final InputBlock inputBlock = diagram.getGraph().getBlock(getSource().getSourceNodes().get(0));
+            assert inputBlock != null;
+            Cluster result = diagram.getBlock(inputBlock);
             assert result != null;
             return result;
         }
     }
 
+    @Override
     public boolean isRoot() {
-        if (source.getSourceNodes().size() > 0 && source.getSourceNodes().get(0).getProperties().get("name").equals("Root")) {
-            return true;
+
+        List<InputNode> 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()));
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,18 +36,24 @@
         super(figure, wantedIndex);
     }
 
+    @Override
     public int getPosition() {
         return getFigure().getInputSlots().indexOf(this);
     }
 
+    @Override
     public void setPosition(int position) {
         List<InputSlot> inputSlots = getFigure().inputSlots;
         InputSlot s = inputSlots.remove(position);
         inputSlots.add(position, s);
     }
-
+    @Override
     public Point getRelativePosition() {
-        return new Point(getFigure().getWidth() * (getPosition() + 1) / (getFigure().getInputSlots().size() + 1), Figure.SLOT_WIDTH - Figure.SLOT_START);
+        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
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InvertSelector.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InvertSelector.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,9 +38,10 @@
         this.selector = selector;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
 
-        List<Figure> result = new ArrayList<Figure>();
+        List<Figure> result = new ArrayList<>();
         List<Figure> otherResult = selector.selected(d);
         for (Figure f : d.getFigures()) {
             if (!otherResult.contains(f)) {
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/MatcherSelector.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/MatcherSelector.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,9 @@
         this.matcher = matcher;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(d.getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(d.getFigures());
         List<Figure> list = selector.selectMultiple(matcher);
         return list;
     }
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OrSelector.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OrSelector.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
         this.selector2 = s2;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
 
         List<Figure> l1 = selector1.selected(d);
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,17 +35,26 @@
         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() {
-        return new Point(getFigure().getWidth() * (getPosition() + 1) / (getFigure().getOutputSlots().size() + 1), getFigure().getSize().height - Figure.SLOT_WIDTH + Figure.SLOT_START);
+        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
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/PredecessorSelector.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/PredecessorSelector.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,9 +38,10 @@
         this.innerSelector = innerSelector;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
         List<Figure> inner = innerSelector.selected(d);
-        List<Figure> result = new ArrayList<Figure>();
+        List<Figure> result = new ArrayList<>();
         for (Figure f : d.getFigures()) {
             boolean saved = false;
             for (Figure f2 : f.getSuccessors()) {
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Selector.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Selector.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,63 +23,112 @@
  */
 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 com.sun.hotspot.igv.util.StringUtils;
+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;
-import java.util.Comparator;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public abstract class Slot implements Port, Source.Provider {
+public abstract class Slot implements Port, Source.Provider, Properties.Provider {
 
     private int wantedIndex;
-    private String name;
-    private String shortName; // 1 - 2 characters
     private Source source;
     protected List<Connection> 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<Connection>(2);
+        connections = new ArrayList<>(2);
         source = new Source();
         this.wantedIndex = wantedIndex;
-        name = "";
+        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<Slot> slotIndexComparator = new Comparator<Slot>() {
 
+        @Override
         public int compare(Slot o1, Slot o2) {
             return o1.wantedIndex - o2.wantedIndex;
         }
     };
     public static final Comparator<Slot> slotFigureComparator = new Comparator<Slot>() {
 
+        @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 getName() {
-        return name;
+    public String getText() {
+        return text;
     }
 
     public void setShortName(String s) {
         assert s != null;
-        assert s.length() <= 2;
+//        assert s.length() <= 2;
         this.shortName = s;
 
     }
@@ -88,15 +137,27 @@
         return shortName;
     }
 
-    public boolean getShowName() {
+    public String getToolTipText() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(text);
+
+        for (InputNode n : getSource().getSourceNodes()) {
+            sb.append(StringUtils.escapeHTML("Node (ID=" + n.getId() + "): " + n.getProperties().get("name")));
+            sb.append("<br>");
+        }
+
+        return sb.toString();
+    }
+
+    public boolean shouldShowName() {
         return getShortName() != null && getShortName().length() > 0;
     }
 
-    public void setName(String s) {
+    public void setText(String s) {
         if (s == null) {
             s = "";
         }
-        this.name = s;
+        this.text = s;
     }
 
     public Figure getFigure() {
@@ -104,17 +165,26 @@
         return figure;
     }
 
+    public Color getColor() {
+        return this.color;
+    }
+
+    public void setColor(Color c) {
+        color = c;
+    }
+
     public List<Connection> getConnections() {
         return Collections.unmodifiableList(connections);
     }
 
     public void removeAllConnections() {
-        List<Connection> connectionsCopy = new ArrayList<Connection>(this.connections);
+        List<Connection> connectionsCopy = new ArrayList<>(this.connections);
         for (Connection c : connectionsCopy) {
             c.remove();
         }
     }
 
+    @Override
     public Vertex getVertex() {
         return figure;
     }
@@ -123,3 +193,4 @@
 
     public abstract void setPosition(int position);
 }
+
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Source.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +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.InputBlock;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.InputNode;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class Source {
-
-    private List<InputNode> sourceNodes;
-    private Set<Integer> set;
-
-    public Source() {
-        sourceNodes = new ArrayList<InputNode>(1);
-    }
-
-    public List<InputNode> getSourceNodes() {
-        return Collections.unmodifiableList(sourceNodes);
-    }
-
-    public Set<Integer> getSourceNodesAsSet() {
-        if (set == null) {
-            set = new HashSet<Integer>();
-            for (InputNode n : sourceNodes) {
-                int id = n.getId();
-                //if(id < 0) id = -id;
-                set.add(id);
-            }
-        }
-        return set;
-    }
-
-    public void addSourceNode(InputNode n) {
-        sourceNodes.add(n);
-        set = null;
-    }
-
-    public void removeSourceNode(InputNode n) {
-        sourceNodes.remove(n);
-        set = null;
-    }
-
-    public interface Provider {
-
-        public Source getSource();
-    }
-
-    public void setSourceNodes(List<InputNode> sourceNodes) {
-        this.sourceNodes = sourceNodes;
-        set = null;
-    }
-
-    public void addSourceNodes(Source s) {
-        for (InputNode n : s.getSourceNodes()) {
-            sourceNodes.add(n);
-        }
-        set = null;
-    }
-
-    public boolean isInBlock(InputGraph g, InputBlock blockNode) {
-
-        for (InputNode n : this.getSourceNodes()) {
-            if (g.getBlock(n) == blockNode) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/SuccessorSelector.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/SuccessorSelector.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,9 +38,10 @@
         this.innerSelector = innerSelector;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
         List<Figure> inner = innerSelector.selected(d);
-        List<Figure> result = new ArrayList<Figure>();
+        List<Figure> result = new ArrayList<>();
         for (Figure f : d.getFigures()) {
             boolean saved = false;
             for (Figure f2 : f.getPredecessors()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/services/DiagramProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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<DiagramProvider> getChangedEvent();
+
+}
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterEdge.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterEdge.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,4 +60,8 @@
     public List<Point> getControlPoints() {
         return points;
     }
+
+    public boolean isVIP() {
+        return false;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterIngoingConnection.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterIngoingConnection.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,4 +73,8 @@
     public List<Point> getControlPoints() {
         return controlPoints;
     }
+
+    public boolean isVIP() {
+        return false;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterInputSlotNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterInputSlotNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,7 +93,7 @@
         outputSlot = new Port() {
 
             public Point getRelativePosition() {
-                return new Point(size.width / 2, size.height);
+                return new Point(size.width / 2, 0);//size.height);
             }
 
             public Vertex getVertex() {
@@ -183,7 +183,7 @@
 
         for (Link e : subEdges) {
             List<Point> arr = e.getControlPoints();
-            ArrayList<Point> newArr = new ArrayList<Point>();
+            ArrayList<Point> newArr = new ArrayList<Point>(arr.size());
             for (Point p : arr) {
                 if (p != null) {
                     Point p2 = new Point(p);
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutgoingConnection.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutgoingConnection.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,4 +65,8 @@
     public List<Point> getControlPoints() {
         return intermediatePoints;
     }
+
+    public boolean isVIP() {
+        return false;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutputSlotNode.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutputSlotNode.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -88,7 +88,7 @@
             public Point getRelativePosition() {
                 Point p = new Point(thisNode.getPosition());
                 p.x += ClusterNode.BORDER;
-                p.y = thisBlockNode.getSize().height;
+                p.y = 0;//thisBlockNode.getSize().height;
                 return p;
             }
 
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Edge.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Edge.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,7 @@
         dest.addInEdge(this);
     }
 
+    @Override
     public String toString() {
         return "Edge (" + source + " -- " + dest + "): " + data;
     }
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,7 @@
  */
 package com.sun.hotspot.igv.hierarchicallayout;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
+import java.util.*;
 
 /**
  *
@@ -42,13 +36,13 @@
     private List<Node<N, E>> nodeList;
 
     public Graph() {
-        nodes = new HashMap<Object, Node<N, E>>();
-        edges = new HashMap<Object, Edge<N, E>>();
-        nodeList = new ArrayList<Node<N, E>>();
+        nodes = new HashMap<>();
+        edges = new HashMap<>();
+        nodeList = new ArrayList<>();
     }
 
     public Node<N, E> createNode(N data, Object key) {
-        Node<N, E> n = new Node<N, E>(this, data);
+        Node<N, E> n = new Node<>(this, data);
         assert key == null || !nodes.containsKey(key);
         if (key != null) {
             nodes.put(key, n);
@@ -58,7 +52,7 @@
     }
 
     public Edge<N, E> createEdge(Node<N, E> source, Node<N, E> dest, E data, Object key) {
-        Edge<N, E> e = new Edge<N, E>(this, source, dest, data);
+        Edge<N, E> e = new Edge<>(this, source, dest, data);
         source.addOutEdge(e);
         dest.addInEdge(e);
         if (key != null) {
@@ -114,7 +108,7 @@
 
     public List<Node<N, E>> getNodesWithInDegree(int x, boolean countSelfLoops) {
 
-        List<Node<N, E>> result = new ArrayList<Node<N, E>>();
+        List<Node<N, E>> result = new ArrayList<>();
         for (Node<N, E> n : getNodes()) {
             if (n.getInDegree(countSelfLoops) == x) {
                 result.add(n);
@@ -126,7 +120,7 @@
     }
 
     private void markReachable(Node<N, E> startingNode) {
-        ArrayList<Node<N, E>> arr = new ArrayList<Node<N, E>>();
+        ArrayList<Node<N, E>> arr = new ArrayList<>();
         arr.add(startingNode);
         for (Node<N, E> n : getNodes()) {
             n.setReachable(false);
@@ -151,7 +145,7 @@
             n.setActive(false);
         }
 
-        Queue<Node<N, E>> queue = new LinkedList<Node<N, E>>();
+        Queue<Node<N, E>> queue = new LinkedList<>();
         queue.add(startingNode);
         startingNode.setVisited(true);
         int layer = 0;
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,12 +44,12 @@
  */
 public class HierarchicalClusterLayoutManager implements LayoutManager {
 
-    private OldHierarchicalLayoutManager.Combine combine;
-    private LayoutManager subManager = new OldHierarchicalLayoutManager(combine);
-    private LayoutManager manager = new OldHierarchicalLayoutManager(combine, 150);
+    private HierarchicalLayoutManager.Combine combine;
+    private LayoutManager subManager = new HierarchicalLayoutManager(combine);
+    private LayoutManager manager = new HierarchicalLayoutManager(combine);
     private static final boolean TRACE = false;
 
-    public HierarchicalClusterLayoutManager(OldHierarchicalLayoutManager.Combine combine) {
+    public HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine combine) {
         this.combine = combine;
     }
 
@@ -57,6 +57,10 @@
         doLayout(graph, new HashSet<Vertex>(), new HashSet<Vertex>(), new HashSet<Link>());
     }
 
+    public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks) {
+        doLayout(graph);
+    }
+
     public void setSubManager(LayoutManager manager) {
         this.subManager = manager;
     }
@@ -116,7 +120,7 @@
 
         for (Vertex v : graph.getVertices()) {
             Cluster c = v.getCluster();
-            assert c != null;
+            assert c != null : "Cluster of vertex " + v + " is null!";
             clusterNodes.get(c).addSubNode(v);
         }
 
@@ -130,9 +134,9 @@
             Cluster toCluster = toVertex.getCluster();
 
             Port samePort = null;
-            if (combine == OldHierarchicalLayoutManager.Combine.SAME_INPUTS) {
+            if (combine == HierarchicalLayoutManager.Combine.SAME_INPUTS) {
                 samePort = toPort;
-            } else if (combine == OldHierarchicalLayoutManager.Combine.SAME_OUTPUTS) {
+            } else if (combine == HierarchicalLayoutManager.Combine.SAME_OUTPUTS) {
                 samePort = fromPort;
             }
 
@@ -196,7 +200,7 @@
 
         for (Cluster c : cluster) {
             ClusterNode n = clusterNodes.get(c);
-            subManager.doLayout(new LayoutGraph(n.getSubEdges(), n.getSubNodes()), clusterInputSlotSet.get(c), clusterOutputSlotSet.get(c), new HashSet<Link>());
+            subManager.doLayout(new LayoutGraph(n.getSubEdges(), n.getSubNodes()), new HashSet<Link>());
             n.updateSize();
         }
 
@@ -206,7 +210,7 @@
             ((ClusterNode) v).setRoot(true);
         }
 
-        manager.doLayout(new LayoutGraph(clusterEdges, clusterNodeSet), new HashSet<Vertex>(), new HashSet<Vertex>(), interClusterEdges);
+        manager.doLayout(new LayoutGraph(clusterEdges, clusterNodeSet), interClusterEdges);
 
         for (Cluster c : cluster) {
             ClusterNode n = clusterNodes.get(c);
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,18 +29,7 @@
 import com.sun.hotspot.igv.layout.Vertex;
 import java.awt.Dimension;
 import java.awt.Point;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.Stack;
-import java.util.TreeSet;
+import java.util.*;
 
 /**
  *
@@ -54,10 +43,11 @@
     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 X_OFFSET = 8;
+    public static final int LAYER_OFFSET = 8;
     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 {
 
@@ -85,8 +75,6 @@
     private LayoutGraph graph;
     private List<LayoutNode>[] layers;
     private int layerCount;
-    private Set<? extends Vertex> firstLayerHint;
-    private Set<? extends Vertex> lastLayerHint;
     private Set<? extends Link> importantLinks;
     private Set<Link> linksToFollow;
 
@@ -101,11 +89,13 @@
         public int yOffset;
         public int bottomYOffset;
         public Vertex vertex; // Only used for non-dummy nodes, otherwise null
-        public List<LayoutEdge> preds = new ArrayList<LayoutEdge>();
-        public List<LayoutEdge> succs = new ArrayList<LayoutEdge>();
-        public HashMap<Integer, Integer> outOffsets = new HashMap<Integer, Integer>();
-        public HashMap<Integer, Integer> inOffsets = new HashMap<Integer, Integer>();
+
+        public List<LayoutEdge> preds = new ArrayList<>();
+        public List<LayoutEdge> succs = new ArrayList<>();
+        public HashMap<Integer, Integer> outOffsets = new HashMap<>();
+        public HashMap<Integer, Integer> inOffsets = new HashMap<>();
         public int pos = -1; // Position within layer
+
         public int crossingNumber;
 
         @Override
@@ -121,6 +111,7 @@
         public int relativeFrom;
         public int relativeTo;
         public Link link;
+        public boolean vip;
     }
 
     private abstract class AlgorithmPart {
@@ -171,7 +162,7 @@
         this.layerOffset = LAYER_OFFSET;
         this.maxLayerLength = MAX_LAYER_LENGTH;
         this.minLayerDifference = MIN_LAYER_DIFFERENCE;
-        this.linksToFollow = new HashSet<Link>();
+        this.linksToFollow = new HashSet<>();
     }
 
     public int getMaxLayerLength() {
@@ -186,26 +177,26 @@
         minLayerDifference = v;
     }
 
+    @Override
     public void doLayout(LayoutGraph graph) {
-        doLayout(graph, new HashSet<Vertex>(), new HashSet<Vertex>(), new HashSet<Link>());
+        doLayout(graph, new HashSet<Link>());
 
     }
 
-    public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks) {
+    @Override
+    public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks) {
 
         this.importantLinks = importantLinks;
         this.graph = graph;
-        this.firstLayerHint = firstLayerHint;
-        this.lastLayerHint = lastLayerHint;
 
-        vertexToLayoutNode = new HashMap<Vertex, LayoutNode>();
-        reversedLinks = new HashSet<Link>();
-        reversedLinkStartPoints = new HashMap<Link, List<Point>>();
-        reversedLinkEndPoints = new HashMap<Link, List<Point>>();
-        bottomEdgeHash = new HashMap<LayoutEdge, LayoutEdge>();
-        nodes = new ArrayList<LayoutNode>();
-        splitStartPoints = new HashMap<Link, List<Point>>();
-        splitEndPoints = new HashMap<Link, List<Point>>();
+        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
@@ -216,7 +207,7 @@
         new ReverseEdges().start();
 
         for (LayoutNode n : nodes) {
-            ArrayList<LayoutEdge> tmpArr = new ArrayList<LayoutEdge>();
+            ArrayList<LayoutEdge> tmpArr = new ArrayList<>();
             for (LayoutEdge e : n.succs) {
                 if (importantLinks.contains(e.link)) {
                     tmpArr.add(e);
@@ -224,7 +215,6 @@
             }
 
             for (LayoutEdge e : tmpArr) {
-                //System.out.println("Removed " + e);
                 e.from.succs.remove(e);
                 e.to.preds.remove(e);
             }
@@ -244,8 +234,7 @@
 
         // #############################################################
         // STEP 7: Assign X coordinates
-        //new AssignXCoordinates().start();
-        new AssignXCoordinates2().start();
+        new AssignXCoordinates().start();
 
         // #############################################################
         // STEP 6: Assign Y coordinates
@@ -260,10 +249,11 @@
 
         private int pointCount;
 
+        @Override
         protected void run() {
 
-            HashMap<Vertex, Point> vertexPositions = new HashMap<Vertex, Point>();
-            HashMap<Link, List<Point>> linkPositions = new HashMap<Link, List<Point>>();
+            HashMap<Vertex, Point> vertexPositions = new HashMap<>();
+            HashMap<Link, List<Point>> linkPositions = new HashMap<>();
             for (Vertex v : graph.getVertices()) {
                 LayoutNode n = vertexToLayoutNode.get(v);
                 assert !vertexPositions.containsKey(v);
@@ -274,12 +264,12 @@
 
                 for (LayoutEdge e : n.preds) {
                     if (e.link != null) {
-                        ArrayList<Point> points = new ArrayList<Point>();
+                        ArrayList<Point> points = new ArrayList<>();
 
-                        Point p = new Point(e.to.x + e.relativeTo, e.to.y + e.to.yOffset);
+                        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)));
+                            points.add(new Point(p.x, p.y + e.to.inOffsets.get(e.relativeTo) + e.link.getTo().getRelativePosition().y));
                         }
 
                         LayoutNode cur = e.from;
@@ -299,16 +289,14 @@
                             cur = curEdge.from;
                         }
 
-                        p = new Point(cur.x + curEdge.relativeFrom, cur.y + cur.height - cur.bottomYOffset);
+                        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)));
+                            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)) {
@@ -359,17 +347,17 @@
 
                 for (LayoutEdge e : n.succs) {
                     if (e.link != null) {
-                        ArrayList<Point> points = new ArrayList<Point>();
-                        Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset);
+                        ArrayList<Point> 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)));
+                            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) {
+                        while (cur.vertex == null && !cur.succs.isEmpty()) {
                             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);
                             }
@@ -378,7 +366,7 @@
                                 points.remove(points.size() - 1);
                             }
                             points.add(new Point(cur.x + cur.width / 2, cur.y + cur.height));
-                            if (cur.succs.size() == 0) {
+                            if (cur.succs.isEmpty()) {
                                 break;
                             }
                             assert cur.succs.size() == 1;
@@ -386,15 +374,13 @@
                             cur = curEdge.to;
                         }
 
-
-                        p = new Point(cur.x + curEdge.relativeTo, cur.y + cur.yOffset);
+                        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)));
+                            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 (cur.succs.isEmpty() && 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));
@@ -495,13 +481,14 @@
 
         public float d;
         public int orderNumber = -1;
-        public ArrayList<LayoutNode> nodes = new ArrayList<LayoutNode>();
-        public HashSet<Segment> succs = new HashSet<Segment>();
-        public HashSet<Segment> preds = new HashSet<Segment>();
+        public ArrayList<LayoutNode> nodes = new ArrayList<>();
+        public HashSet<Segment> succs = new HashSet<>();
+        public HashSet<Segment> preds = new HashSet<>();
         public Region region;
     }
     private static final Comparator<Segment> segmentComparator = new Comparator<Segment>() {
 
+        @Override
         public int compare(Segment s1, Segment s2) {
             return s1.orderNumber - s2.orderNumber;
         }
@@ -511,26 +498,46 @@
 
         public float d;
         public int minOrderNumber;
-        public SortedSet<Segment> segments = new TreeSet<Segment>(segmentComparator);
-        public HashSet<Region> succs = new HashSet<Region>(4);
-        public HashSet<Region> preds = new HashSet<Region>(4);
+        public SortedSet<Segment> segments = new TreeSet<>(segmentComparator);
+        public HashSet<Region> succs = new HashSet<>(4);
+        public HashSet<Region> preds = new HashSet<>(4);
     }
     private static final Comparator<Region> regionComparator = new Comparator<Region>() {
 
+        @Override
         public int compare(Region r1, Region r2) {
             return r1.minOrderNumber - r2.minOrderNumber;
         }
     };
     private static final Comparator<LayoutNode> nodePositionComparator = new Comparator<LayoutNode>() {
 
+        @Override
         public int compare(LayoutNode n1, LayoutNode n2) {
             return n1.pos - n2.pos;
         }
     };
     private static final Comparator<LayoutNode> nodeProcessingDownComparator = new Comparator<LayoutNode>() {
-
+        @Override
         public int compare(LayoutNode n1, LayoutNode n2) {
+            int n1VIP = 0;
+            for (LayoutEdge e : n1.preds) {
+                if (e.vip) {
+                    n1VIP++;
+                }
+            }
+            int n2VIP = 0;
+            for (LayoutEdge e : n2.preds) {
+                if (e.vip) {
+                    n2VIP++;
+                }
+            }
+            if (n1VIP != n2VIP) {
+                return n2VIP - n1VIP;
+            }
             if (n1.vertex == null) {
+                if (n2.vertex == null) {
+                    return 0;
+                }
                 return -1;
             }
             if (n2.vertex == null) {
@@ -541,8 +548,27 @@
     };
     private static final Comparator<LayoutNode> nodeProcessingUpComparator = new Comparator<LayoutNode>() {
 
+        @Override
         public int compare(LayoutNode n1, LayoutNode n2) {
+            int n1VIP = 0;
+            for (LayoutEdge e : n1.succs) {
+                if (e.vip) {
+                    n1VIP++;
+                }
+            }
+            int n2VIP = 0;
+            for (LayoutEdge e : n2.succs) {
+                if (e.vip) {
+                    n2VIP++;
+                }
+            }
+            if (n1VIP != n2VIP) {
+                return n2VIP - n1VIP;
+            }
             if (n1.vertex == null) {
+                if (n2.vertex == null) {
+                    return 0;
+                }
                 return -1;
             }
             if (n2.vertex == null) {
@@ -552,7 +578,7 @@
         }
     };
 
-    private class AssignXCoordinates2 extends AlgorithmPart {
+    private class AssignXCoordinates extends AlgorithmPart {
 
         private ArrayList<Integer>[] space;
         private ArrayList<LayoutNode>[] downProcessingOrder;
@@ -564,16 +590,21 @@
             }
         }
 
-        protected void run() {
-
+        @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<Integer>();
-                downProcessingOrder[i] = new ArrayList<LayoutNode>();
-                upProcessingOrder[i] = new ArrayList<LayoutNode>();
+                space[i] = new ArrayList<>();
+                downProcessingOrder[i] = new ArrayList<>();
+                upProcessingOrder[i] = new ArrayList<>();
 
                 int curX = 0;
                 for (LayoutNode n : layers[i]) {
@@ -590,72 +621,106 @@
             initialPositions();
             for (int i = 0; i < SWEEP_ITERATIONS; i++) {
                 sweepDown();
-                sweepUp();
+                adjustSpace();
+                sweepUp(false);
+                adjustSpace();
             }
 
-            for (int i = 0; i < SWEEP_ITERATIONS; i++) {
-                doubleSweep();
+            sweepDown();
+            adjustSpace();
+            sweepUp(true);
+        }
+
+        private void adjustSpace() {
+            for (int i = 0; i < layers.length; i++) {
+                //               space[i] = new ArrayList<>();
+                int curX = 0;
+                for (LayoutNode n : layers[i]) {
+                    space[i].add(n.x);
+//                    curX += n.width + xOffset;
+                }
             }
         }
 
         private int calculateOptimalDown(LayoutNode n) {
-
-            List<Integer> values = new ArrayList<Integer>();
-            if (n.preds.size() == 0) {
+            int size = n.preds.size();
+            if (size == 0) {
                 return n.x;
             }
+            int vipCount = 0;
             for (LayoutEdge e : n.preds) {
-                int cur = e.from.x + e.relativeFrom - e.relativeTo;
-                values.add(cur);
+                if (e.vip) {
+                    vipCount++;
+                }
             }
-            return median(values);
+
+            if (vipCount == 0) {
+                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;
+                }
+                return median(values);
+            } else {
+                int z = 0;
+                int[] values = new int[vipCount];
+                for (int i = 0; i < size; i++) {
+                    LayoutEdge e = n.preds.get(i);
+                    if (e.vip) {
+                        values[z++] = e.from.x + e.relativeFrom - e.relativeTo;
+                    }
+                }
+                return median(values);
+            }
         }
 
         private int calculateOptimalBoth(LayoutNode n) {
-
-            List<Integer> values = new ArrayList<Integer>();
-            if (n.preds.size() == 0 + n.succs.size()) {
+            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) {
-                int cur = e.from.x + e.relativeFrom - e.relativeTo;
-                values.add(cur);
+                values[i] = e.from.x + e.relativeFrom - e.relativeTo;
+                i++;
             }
 
             for (LayoutEdge e : n.succs) {
-                int cur = e.to.x + e.relativeTo - e.relativeFrom;
-                values.add(cur);
+                values[i] = e.to.x + e.relativeTo - e.relativeFrom;
+                i++;
             }
 
             return median(values);
         }
 
         private int calculateOptimalUp(LayoutNode n) {
-
-            //List<Integer> values = new ArrayList<Integer>();
             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 {
-                int result = 0;
-                for (LayoutEdge e : n.succs) {
-                    int cur = e.to.x + e.relativeTo - e.relativeFrom;
-                    result += cur;
-                }
-                return result / size; //median(values);
+                return values[values.length / 2];
             }
         }
 
-        private int median(List<Integer> values) {
-            Collections.sort(values);
-            if (values.size() % 2 == 0) {
-                return (values.get(values.size() / 2 - 1) + values.get(values.size() / 2)) / 2;
-            } else {
-                return values.get(values.size() / 2);
-            }
-        }
-
-        private void sweepUp() {
+        private void sweepUp(boolean onlyDummies) {
             for (int i = layers.length - 1; i >= 0; i--) {
                 NodeRow r = new NodeRow(space[i]);
                 for (LayoutNode n : upProcessingOrder[i]) {
@@ -663,14 +728,6 @@
                     r.insert(n, optimal);
                 }
             }
-        /*
-        for(int i=0; i<layers.length; i++) {
-        NodeRow r = new NodeRow(space[i]);
-        for(LayoutNode n : upProcessingOrder[i]) {
-        int optimal = calculateOptimalUp(n);
-        r.insert(n, optimal);
-        }
-        }*/
         }
 
         private void doubleSweep() {
@@ -700,7 +757,7 @@
         private ArrayList<Integer> space;
 
         public NodeRow(ArrayList<Integer> space) {
-            treeSet = new TreeSet<LayoutNode>(nodePositionComparator);
+            treeSet = new TreeSet<>(nodePositionComparator);
             this.space = space;
         }
 
@@ -739,357 +796,15 @@
                     n.x = pos;
                 }
 
-                assert minX <= maxX;
+                assert minX <= maxX : minX + " vs " + maxX;
             }
 
             treeSet.add(n);
         }
     }
-
-    private class AssignXCoordinates extends AlgorithmPart {
-
-        HashMap<LayoutNode, Segment> hashMap = new HashMap<LayoutNode, Segment>();
-        ArrayList<Segment> segments = new ArrayList<Segment>();
-
-        private void generateSegments() {
-
-            for (int i = 0; i < layerCount; i++) {
-                for (LayoutNode n : layers[i]) {
-                    if (!hashMap.containsKey(n)) {
-                        Segment s = new Segment();
-                        segments.add(s);
-                        LayoutNode curNode = n;
-
-                        int maxLength = 0;
-                        while (curNode.succs.size() == 1 && curNode.preds.size() == 1) {
-                            s.nodes.add(curNode);
-                            assert !hashMap.containsKey(curNode);
-                            hashMap.put(curNode, s);
-                            curNode = curNode.succs.get(0).to;
-                            maxLength++;
-                        //if(maxLength > 10) break;
-                        }
-
-                        if (s.nodes.size() > 0 && curNode.preds.size() == 1 && curNode.vertex == null) {
-                            s.nodes.add(curNode);
-                            assert !hashMap.containsKey(curNode);
-                            hashMap.put(curNode, s);
-                        }
-
-                        if (s.nodes.size() == 0) {
-                            // Simple segment with a single node
-                            s.nodes.add(n);
-                            hashMap.put(n, s);
-                        }
-                    }
-                }
-            }
-        }
-
-        private void addEdges() {
-
-            for (int i = 0; i < layerCount; i++) {
-                LayoutNode prev = null;
-                for (LayoutNode n : layers[i]) {
-
-                    if (prev != null) {
-                        Segment s1 = hashMap.get(prev);
-                        Segment s2 = hashMap.get(n);
-
-                        if (s1 != s2) {
-                            s1.succs.add(s2);
-                            s2.preds.add(s1);
-                        }
-                    }
-                    prev = n;
-
-                }
-            }
-        }
-
-        private void topologicalSorting() {
-
-            Queue<Segment> queue = new LinkedList<Segment>();
-
-            int index = 0;
-            ArrayList<Segment> newList = new ArrayList<Segment>();
-            for (Segment s : segments) {
-                if (s.preds.size() == 0) {
-                    s.orderNumber = index;
-                    newList.add(s);
-                    index++;
-                    queue.add(s);
-                }
-            }
-
-            while (!queue.isEmpty()) {
-                Segment s = queue.remove();
-
-                for (Segment succ : s.succs) {
-                    succ.preds.remove(s);
-                    if (succ.preds.size() == 0) {
-                        queue.add(succ);
-                        succ.orderNumber = index;
-                        newList.add(succ);
-                        index++;
-                    }
-                }
-            }
-
-            segments = newList;
-        }
-
-        private void initialPositions() {
-
-            int[] minPos = new int[layers.length];
-
-            for (Segment s : segments) {
-                int max = 0;
-                for (LayoutNode n : s.nodes) {
-                    int x = minPos[n.layer];
-                    if (x > max) {
-                        max = x;
-                    }
-                }
-
-                for (LayoutNode n : s.nodes) {
-                    minPos[n.layer] = max + n.width + xOffset;
-                    n.x = max;
-                }
-            }
-        }
-
-        private int predSum(LayoutNode n) {
-            int sum = 0;
-            for (LayoutEdge e : n.preds) {
-                assert e.to == n;
-                //sum += (e.from.x + e.relativeFrom + (int)hashMap.get(e.from).d) - (e.to.x + e.relativeTo + (int)hashMap.get(e.to).d);
-                sum += (e.from.x + e.relativeFrom) - (e.to.x + e.relativeTo);
-            }
-
-            return sum;
-        }
-
-        private int succSum(LayoutNode n) {
-            int sum = 0;
-            for (LayoutEdge e : n.succs) {
-
-                assert e.from == n;
-                sum += (e.to.x + e.relativeTo) - (e.from.x + e.relativeFrom);
-            //sum += (e.to.x + e.relativeTo + (int)hashMap.get(e.to).d) - (e.from.x + e.relativeFrom + (int)hashMap.get(e.from).d);
-            }
-
-            return sum;
-
-        }
-
-        private void downValues() {
-
-            for (Segment s : segments) {
-                downValues(s);
-
-            }
-
-        }
-
-        private void downValues(Segment s) {
-            LayoutNode n = s.nodes.get(0); // Only first node needed, all other have same coordinate
-
-            if (n.preds.size() == 0) {
-                // Value is 0.0;
-                if (n.succs.size() == 0) {
-                    s.d = 0.0f;
-                } else {
-                    s.d = (((float) succSum(n) / (float) n.succs.size())) / 2;
-                }
-            } else {
-                s.d = (float) predSum(n) / (float) n.preds.size();
-            }
-        }
-
-        private void upValues() {
-            for (Segment s : segments) {
-                upValues(s);
-            }
-        }
-
-        private void upValues(Segment s) {
-            LayoutNode n = s.nodes.get(0); // Only first node needed, all other have same coordinate
-
-            if (n.succs.size() == 0) {
-                // Value is 0.0;
-                if (n.preds.size() == 0) {
-                    s.d = 0.0f;
-                } else {
-                    s.d = (float) predSum(n) / (float) n.preds.size();
-                }
-            } else {
-                s.d = ((float) succSum(n) / (float) n.succs.size()) / 2;
-            }
-        }
-
-        private void sweep(boolean down) {
-
-            if (down) {
-                downValues();
-            } else {
-                upValues();
-            }
-
-            SortedSet<Region> regions = new TreeSet<Region>(regionComparator);
-            for (Segment s : segments) {
-                s.region = new Region();
-                s.region.minOrderNumber = s.orderNumber;
-                s.region.segments.add(s);
-                s.region.d = s.d;
-                regions.add(s.region);
-            }
-
-            for (Segment s : segments) {
-                for (LayoutNode n : s.nodes) {
-                    if (n.pos != 0) {
-                        LayoutNode prevNode = layers[n.layer].get(n.pos - 1);
-                        if (prevNode.x + prevNode.width + xOffset == n.x) {
-                            Segment other = hashMap.get(prevNode);
-                            Region r1 = s.region;
-                            Region r2 = other.region;
-                            // They are close together
-                            if (r1 != r2 && r2.d >= r1.d) {
-
-                                if (r2.segments.size() < r1.segments.size()) {
-
-                                    r1.d = (r1.d * r1.segments.size() + r2.d * r2.segments.size()) / (r1.segments.size() + r2.segments.size());
-
-                                    for (Segment tempS : r2.segments) {
-                                        r1.segments.add(tempS);
-                                        tempS.region = r1;
-                                        r1.minOrderNumber = Math.min(r1.minOrderNumber, tempS.orderNumber);
-                                    }
-
-                                    regions.remove(r2);
-                                } else {
-
-                                    r2.d = (r1.d * r1.segments.size() + r2.d * r2.segments.size()) / (r1.segments.size() + r2.segments.size());
-
-                                    for (Segment tempS : r1.segments) {
-                                        r2.segments.add(tempS);
-                                        tempS.region = r2;
-                                        r2.minOrderNumber = Math.min(r2.minOrderNumber, tempS.orderNumber);
-                                    }
-
-                                    regions.remove(r1);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-
-
-            ArrayList<Region> reversedRegions = new ArrayList<Region>();
-            for (Region r : regions) {
-                if (r.d < 0) {
-                    processRegion(r, down);
-                } else {
-                    reversedRegions.add(0, r);
-                }
-            }
-
-            for (Region r : reversedRegions) {
-                processRegion(r, down);
-            }
-
-        }
-
-        private void processRegion(Region r, boolean down) {
-
-            // Do not move
-            if ((int) r.d == 0) {
-                return;
-            }
-
-            ArrayList<Segment> arr = new ArrayList<Segment>();
-            for (Segment s : r.segments) {
-                arr.add(s);
-            }
-
-            if (r.d > 0) {
-                Collections.reverse(arr);
-            }
-
-            for (Segment s : arr) {
-
-
-                int min = (int) r.d;
-                if (min < 0) {
-                    min = -min;
-                }
-
-                for (LayoutNode n : s.nodes) {
-
-                    int layer = n.layer;
-                    int pos = n.pos;
-
-
-                    if (r.d > 0) {
-
-                        if (pos != layers[layer].size() - 1) {
-
-                            int off = layers[layer].get(pos + 1).x - n.x - xOffset - n.width;
-                            assert off >= 0;
-                            if (off < min) {
-                                min = off;
-                            }
-                        }
-
-                    } else {
-
-                        if (pos != 0) {
-
-                            int off = n.x - xOffset - layers[layer].get(pos - 1).x - layers[layer].get(pos - 1).width;
-                            assert off >= 0;
-                            if (off < min) {
-                                min = off;
-                            }
-                        }
-                    }
-                }
-
-                assert min >= 0;
-                if (min != 0) {
-                    for (LayoutNode n : s.nodes) {
-                        if (r.d > 0) {
-                            n.x += min;
-                        } else {
-                            n.x -= min;
-                        }
-
-                    }
-                }
-            }
-        }
-
-        protected void run() {
-
-            generateSegments();
-            addEdges();
-            topologicalSorting();
-            initialPositions();
-            for (int i = 0; i < SWEEP_ITERATIONS; i++) {
-
-                sweep(true);
-                sweep(true);
-                sweep(false);
-                sweep(false);
-            }
-
-            sweep(true);
-            sweep(true);
-        }
-    }
     private static Comparator<LayoutNode> crossingNodeComparator = new Comparator<LayoutNode>() {
 
+        @Override
         public int compare(LayoutNode n1, LayoutNode n2) {
             return n1.crossingNumber - n2.crossingNumber;
         }
@@ -1104,22 +819,26 @@
             }
         }
 
-        protected void run() {
-
+        @SuppressWarnings("unchecked")
+        private void createLayers() {
             layers = new List[layerCount];
 
             for (int i = 0; i < layerCount; i++) {
-                layers[i] = new ArrayList<LayoutNode>();
+                layers[i] = new ArrayList<>();
             }
+        }
 
+        @Override
+        protected void run() {
+            createLayers();
 
             // Generate initial ordering
-            HashSet<LayoutNode> visited = new HashSet<LayoutNode>();
+            HashSet<LayoutNode> visited = new HashSet<>();
             for (LayoutNode n : nodes) {
                 if (n.layer == 0) {
                     layers[0].add(n);
                     visited.add(n);
-                } else if (n.preds.size() == 0) {
+                } else if (n.preds.isEmpty()) {
                     layers[n.layer].add(n);
                     visited.add(n);
                 }
@@ -1136,7 +855,6 @@
                 }
             }
 
-
             updatePositions();
 
             initX();
@@ -1146,10 +864,7 @@
                 downSweep();
                 upSweep();
             }
-
-        /*for(int i=0; i<CROSSING_ITERATIONS; i++) {
-        doubleSweep();
-        }*/
+            downSweep();
         }
 
         private void initX() {
@@ -1191,25 +906,23 @@
                 for (LayoutNode n : layers[i]) {
 
                     int sum = 0;
+                    int count = 0;
                     for (LayoutEdge e : n.preds) {
                         int cur = e.from.x + e.relativeFrom;
-
-                        /*pos;
-                        if(e.from.width != 0 && e.relativeFrom != 0) {
-                        cur += (float)e.relativeFrom / (float)(e.from.width);
-                        }*/
-
-                        sum += cur;
+                        int factor = 1;
+                        if (e.vip) {
+                            factor = VIP_BONUS;
+                        }
+                        sum += cur * factor;
+                        count += factor;
                     }
 
-                    if (n.preds.size() > 0) {
-                        sum /= n.preds.size();
+                    if (count > 0) {
+                        sum /= count;
                         n.crossingNumber = sum;
-                    //if(n.vertex == null) n.crossingNumber += layers[i].size();
                     }
                 }
 
-
                 updateCrossingNumbers(i, true);
                 Collections.sort(layers[i], crossingNodeComparator);
                 updateXOfLayer(i);
@@ -1234,9 +947,9 @@
                     next = layers[index].get(i + 1);
                 }
 
-                boolean cond = (n.succs.size() == 0);
+                boolean cond = n.succs.isEmpty();
                 if (down) {
-                    cond = (n.preds.size() == 0);
+                    cond = n.preds.isEmpty();
                 }
 
                 if (cond) {
@@ -1251,44 +964,6 @@
                 }
             }
         }
-        /*
-        private void doubleSweep() {
-        // Downsweep
-        for(int i=0; i<layerCount*2; i++) {
-        int index = i;
-        if(index >= layerCount) {
-        index = 2*layerCount - i - 1;
-        }
-        for(LayoutNode n : layers[index]) {
-        float sum = 0.0f;
-        for(LayoutEdge e : n.preds) {
-        float cur = e.from.pos;
-        if(e.from.width != 0 && e.relativeFrom != 0) {
-        cur += (float)e.relativeFrom / (float)(e.from.width);
-        }
-        sum += cur;
-        }
-        for(LayoutEdge e : n.succs) {
-        float cur = e.to.pos;
-        if(e.to.width != 0 && e.relativeTo != 0) {
-        cur += (float)e.relativeTo / (float)(e.to.width);
-        }
-        sum += cur;
-        }
-        if(n.preds.size() + n.succs.size() > 0) {
-        sum /= n.preds.size() + n.succs.size();
-        n.crossingNumber = sum;
-        }
-        }
-        Collections.sort(layers[index], crossingNodeComparator);
-        updateXOfLayer(index);
-        int z = 0;
-        for(LayoutNode n : layers[index]) {
-        n.pos = z;
-        z++;
-        }
-        }
-        }*/
 
         private void upSweep() {
             // Upsweep
@@ -1300,21 +975,21 @@
 
                 for (LayoutNode n : layers[i]) {
 
+                    int count = 0;
                     int sum = 0;
                     for (LayoutEdge e : n.succs) {
-                        int cur = e.to.x + e.relativeTo;//pos;
-                                                /*
-                        if(e.to.width != 0 && e.relativeTo != 0) {
-                        cur += (float)e.relativeTo / (float)(e.to.width);
-                        }*/
-
-                        sum += cur;
+                        int cur = e.to.x + e.relativeTo;
+                        int factor = 1;
+                        if (e.vip) {
+                            factor = VIP_BONUS;
+                        }
+                        sum += cur * factor;
+                        count += factor;
                     }
 
-                    if (n.succs.size() > 0) {
-                        sum /= n.succs.size();
+                    if (count > 0) {
+                        sum /= count;
                         n.crossingNumber = sum;
-                    //if(n.vertex == null) n.crossingNumber += layers[i].size();
                     }
 
                 }
@@ -1331,15 +1006,10 @@
             }
         }
 
-        private int evaluate() {
-            // TODO: Implement efficient evaluate / crossing min
-            return 0;
-        }
-
         @Override
         public void postCheck() {
 
-            HashSet<LayoutNode> visited = new HashSet<LayoutNode>();
+            HashSet<LayoutNode> visited = new HashSet<>();
             for (int i = 0; i < layers.length; i++) {
                 for (LayoutNode n : layers[i]) {
                     assert !visited.contains(n);
@@ -1353,9 +1023,10 @@
 
     private class AssignYCoordinates extends AlgorithmPart {
 
+        @Override
         protected void run() {
             int curY = 0;
-            //maxLayerHeight = new int[layers.length];
+
             for (int i = 0; i < layers.length; i++) {
                 int maxHeight = 0;
                 int baseLine = 0;
@@ -1383,10 +1054,8 @@
                     }
                 }
 
-                //maxLayerHeight[i] = maxHeight + baseLine + bottomBaseLine;
-
                 curY += maxHeight + baseLine + bottomBaseLine;
-                curY += layerOffset + (int) Math.sqrt(maxXOffset);
+                curY += layerOffset + ((int) (Math.sqrt(maxXOffset) * 1.5));
             }
         }
     }
@@ -1411,26 +1080,27 @@
             }
         }
 
+        @Override
         protected void run() {
             oldNodeCount = nodes.size();
 
-
             if (combine == Combine.SAME_OUTPUTS) {
 
                 Comparator<LayoutEdge> comparator = new Comparator<LayoutEdge>() {
 
+                    @Override
                     public int compare(LayoutEdge e1, LayoutEdge e2) {
                         return e1.to.layer - e2.to.layer;
                     }
                 };
-                HashMap<Integer, List<LayoutEdge>> portHash = new HashMap<Integer, List<LayoutEdge>>();
-                ArrayList<LayoutNode> currentNodes = new ArrayList<LayoutNode>(nodes);
+                HashMap<Integer, List<LayoutEdge>> portHash = new HashMap<>();
+                ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
                 for (LayoutNode n : currentNodes) {
                     portHash.clear();
 
-                    ArrayList<LayoutEdge> succs = new ArrayList<LayoutEdge>(n.succs);
-                    HashMap<Integer, LayoutNode> topNodeHash = new HashMap<Integer, LayoutNode>();
-                    HashMap<Integer, HashMap<Integer, LayoutNode>> bottomNodeHash = new HashMap<Integer, HashMap<Integer, LayoutNode>>();
+                    ArrayList<LayoutEdge> succs = new ArrayList<>(n.succs);
+                    HashMap<Integer, LayoutNode> topNodeHash = new HashMap<>();
+                    HashMap<Integer, HashMap<Integer, LayoutNode>> bottomNodeHash = new HashMap<>();
                     for (LayoutEdge e : succs) {
                         assert e.from.layer < e.to.layer;
                         if (e.from.layer != e.to.layer - 1) {
@@ -1449,6 +1119,7 @@
                                     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 {
@@ -1464,6 +1135,7 @@
                                     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);
@@ -1491,6 +1163,7 @@
                                 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);
@@ -1500,17 +1173,12 @@
                                 if (!portHash.containsKey(i)) {
                                     portHash.put(i, new ArrayList<LayoutEdge>());
                                 }
-
-                                if (n.vertex.toString().equals("1012 CastPP")) {
-                                    int x = 0;
-                                }
-
                                 portHash.get(i).add(e);
                             }
                         }
                     }
 
-                    succs = new ArrayList<LayoutEdge>(n.succs);
+                    succs = new ArrayList<>(n.succs);
                     for (LayoutEdge e : succs) {
 
                         Integer i = e.relativeFrom;
@@ -1528,13 +1196,13 @@
                                     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();
@@ -1546,6 +1214,7 @@
                                 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]);
@@ -1577,7 +1246,7 @@
             } else if (combine == Combine.SAME_INPUTS) {
                 throw new UnsupportedOperationException("Currently not supported");
             } else {
-                ArrayList<LayoutNode> currentNodes = new ArrayList<LayoutNode>(nodes);
+                ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
                 for (LayoutNode n : currentNodes) {
                     for (LayoutEdge e : n.succs) {
                         processSingleEdge(e);
@@ -1604,6 +1273,7 @@
             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;
@@ -1623,7 +1293,7 @@
 
         @Override
         public void postCheck() {
-            ArrayList<LayoutNode> currentNodes = new ArrayList<LayoutNode>(nodes);
+            ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
             for (LayoutNode n : currentNodes) {
                 for (LayoutEdge e : n.succs) {
                     assert e.from.layer == e.to.layer - 1;
@@ -1648,91 +1318,114 @@
             }
         }
 
+        @Override
         protected void run() {
-            HashSet<LayoutNode> set = new HashSet<LayoutNode>();
+            assignLayerDownwards();
+            assignLayerUpwards();
+        }
+
+        private void assignLayerDownwards() {
+            ArrayList<LayoutNode> hull = new ArrayList<>();
             for (LayoutNode n : nodes) {
-                if (n.preds.size() == 0) {
-                    set.add(n);
+                if (n.preds.isEmpty()) {
+                    hull.add(n);
                     n.layer = 0;
                 }
             }
 
             int z = minLayerDifference;
-            HashSet<LayoutNode> newSet = new HashSet<LayoutNode>();
-            HashSet<LayoutNode> failed = new HashSet<LayoutNode>();
-            while (!set.isEmpty()) {
-
-                newSet.clear();
-                failed.clear();
-
-                for (LayoutNode n : set) {
-
+            while (!hull.isEmpty()) {
+                ArrayList<LayoutNode> newSet = new ArrayList<>();
+                for (LayoutNode n : hull) {
                     for (LayoutEdge se : n.succs) {
                         LayoutNode s = se.to;
-                        if (!newSet.contains(s) && !failed.contains(s)) {
-                            boolean ok = true;
+                        if (s.layer != -1) {
+                            // This node was assigned before.
+                        } else {
+                            boolean unassignedPred = false;
                             for (LayoutEdge pe : s.preds) {
                                 LayoutNode p = pe.from;
-                                if (p.layer == -1) {
-                                    ok = false;
+                                if (p.layer == -1 || p.layer >= z) {
+                                    // This now has an unscheduled successor or a successor that was scheduled only in this round.
+                                    unassignedPred = true;
                                     break;
                                 }
                             }
 
-                            if (ok) {
+                            if (unassignedPred) {
+                                // This successor node can not yet be assigned.
+                            } else {
+                                s.layer = z;
                                 newSet.add(s);
-                            } else {
-                                failed.add(s);
                             }
                         }
                     }
-
                 }
 
-                for (LayoutNode n : newSet) {
-                    n.layer = z;
-                }
-
-                // Swap sets
-                HashSet<LayoutNode> tmp = set;
-                set = newSet;
-                newSet = tmp;
+                hull = newSet;
                 z += minLayerDifference;
             }
 
-            optimize(set);
+            layerCount = z - minLayerDifference;
+            for (LayoutNode n : nodes) {
+                n.layer = (layerCount - 1 - n.layer);
+            }
+        }
+
+        private void assignLayerUpwards() {
+            ArrayList<LayoutNode> hull = new ArrayList<>();
+            for (LayoutNode n : nodes) {
+                if (n.succs.isEmpty()) {
+                    hull.add(n);
+                } else {
+                    n.layer = -1;
+                }
+            }
+
+            int z = minLayerDifference;
+            while (!hull.isEmpty()) {
+                ArrayList<LayoutNode> newSet = new ArrayList<>();
+                for (LayoutNode n : hull) {
+                    if (n.layer < z) {
+                        for (LayoutEdge se : n.preds) {
+                            LayoutNode s = se.from;
+                            if (s.layer != -1) {
+                                // This node was assigned before.
+                            } else {
+                                boolean unassignedSucc = false;
+                                for (LayoutEdge pe : s.succs) {
+                                    LayoutNode p = pe.to;
+                                    if (p.layer == -1 || p.layer >= z) {
+                                        // This now has an unscheduled successor or a successor that was scheduled only in this round.
+                                        unassignedSucc = true;
+                                        break;
+                                    }
+                                }
+
+                                if (unassignedSucc) {
+                                    // This predecessor node can not yet be assigned.
+                                } else {
+                                    s.layer = z;
+                                    newSet.add(s);
+                                }
+                            }
+                        }
+                    } else {
+                        newSet.add(n);
+                    }
+                }
+
+                hull = newSet;
+                z += minLayerDifference;
+            }
 
             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;
-                assert n.layer == 0;
+            for (LayoutNode n : nodes) {
+                n.layer = (layerCount - 1 - n.layer);
             }
         }
 
-        public void optimize(HashSet<LayoutNode> set) {
-
-            for (LayoutNode n : set) {
-                if (n.preds.size() == 0 && n.succs.size() > 0) {
-                    int minLayer = n.succs.get(0).to.layer;
-                    for (LayoutEdge e : n.succs) {
-                        minLayer = Math.min(minLayer, e.to.layer);
-                    }
-
-                    n.layer = minLayer - 1;
-                }
-            }
-
-        }
-
         @Override
         public void postCheck() {
             for (LayoutNode n : nodes) {
@@ -1750,11 +1443,12 @@
         private HashSet<LayoutNode> visited;
         private HashSet<LayoutNode> active;
 
+        @Override
         protected void run() {
 
-            // Remove self-edges, TODO: Special treatment
+            // Remove self-edges
             for (LayoutNode node : nodes) {
-                ArrayList<LayoutEdge> succs = new ArrayList<LayoutEdge>(node.succs);
+                ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs);
                 for (LayoutEdge e : succs) {
                     assert e.from == node;
                     if (e.to == node) {
@@ -1780,18 +1474,16 @@
                 }
             }
 
-
             // Start DFS and reverse back edges
-            visited = new HashSet<LayoutNode>();
-            active = new HashSet<LayoutNode>();
+            visited = new HashSet<>();
+            active = new HashSet<>();
             for (LayoutNode node : nodes) {
                 DFS(node);
             }
 
-
             for (LayoutNode node : nodes) {
 
-                SortedSet<Integer> reversedDown = new TreeSet<Integer>();
+                SortedSet<Integer> reversedDown = new TreeSet<>();
 
                 for (LayoutEdge e : node.succs) {
                     if (reversedLinks.contains(e.link)) {
@@ -1799,12 +1491,11 @@
                     }
                 }
 
-
                 SortedSet<Integer> reversedUp = null;
                 if (reversedDown.size() == 0) {
-                    reversedUp = new TreeSet<Integer>(Collections.reverseOrder());
+                    reversedUp = new TreeSet<>(Collections.reverseOrder());
                 } else {
-                    reversedUp = new TreeSet<Integer>();
+                    reversedUp = new TreeSet<>();
                 }
 
                 for (LayoutEdge e : node.preds) {
@@ -1818,7 +1509,7 @@
                 int curX = 0;
                 int curWidth = node.width + reversedDown.size() * offset;
                 for (int pos : reversedDown) {
-                    ArrayList<LayoutEdge> reversedSuccs = new ArrayList<LayoutEdge>();
+                    ArrayList<LayoutEdge> reversedSuccs = new ArrayList<>();
                     for (LayoutEdge e : node.succs) {
                         if (e.relativeFrom == pos && reversedLinks.contains(e.link)) {
                             reversedSuccs.add(e);
@@ -1826,7 +1517,7 @@
                         }
                     }
 
-                    ArrayList<Point> startPoints = new ArrayList<Point>();
+                    ArrayList<Point> startPoints = new ArrayList<>();
                     startPoints.add(new Point(curWidth, curX));
                     startPoints.add(new Point(pos, curX));
                     startPoints.add(new Point(pos, reversedDown.size() * offset));
@@ -1856,7 +1547,7 @@
 
                 int oldNodeHeight = node.height;
                 for (int pos : reversedUp) {
-                    ArrayList<LayoutEdge> reversedPreds = new ArrayList<LayoutEdge>();
+                    ArrayList<LayoutEdge> reversedPreds = new ArrayList<>();
                     for (LayoutEdge e : node.preds) {
                         if (e.relativeTo == pos && reversedLinks.contains(e.link)) {
                             if (reversedDown.size() == 0) {
@@ -1869,7 +1560,7 @@
                         }
                     }
                     node.height += offset;
-                    ArrayList<Point> endPoints = new ArrayList<Point>();
+                    ArrayList<Point> endPoints = new ArrayList<>();
 
                     if (reversedDown.size() == 0) {
 
@@ -1887,7 +1578,6 @@
                     curX += offset;
                     node.bottomYOffset += offset;
 
-
                     endPoints.add(new Point(pos, node.height));
                     endPoints.add(new Point(pos, oldNodeHeight));
                     for (LayoutEdge e : reversedPreds) {
@@ -1895,7 +1585,6 @@
                     }
                 }
 
-
                 if (minX < 0) {
                     for (LayoutEdge e : node.preds) {
                         e.relativeTo -= minX;
@@ -1917,7 +1606,7 @@
                 return;
             }
 
-            Stack<LayoutNode> stack = new Stack<LayoutNode>();
+            Stack<LayoutNode> stack = new Stack<>();
             stack.push(startNode);
 
             while (!stack.empty()) {
@@ -1934,7 +1623,7 @@
                 visited.add(node);
                 active.add(node);
 
-                ArrayList<LayoutEdge> succs = new ArrayList<LayoutEdge>(node.succs);
+                ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs);
                 for (LayoutEdge e : succs) {
                     if (active.contains(e.to)) {
                         assert visited.contains(e.to);
@@ -1989,8 +1678,8 @@
 
             for (LayoutNode n : nodes) {
 
-                HashSet<LayoutNode> curVisited = new HashSet<LayoutNode>();
-                Queue<LayoutNode> queue = new LinkedList<LayoutNode>();
+                HashSet<LayoutNode> curVisited = new HashSet<>();
+                Queue<LayoutNode> queue = new LinkedList<>();
                 for (LayoutEdge e : n.succs) {
                     LayoutNode s = e.to;
                     queue.add(s);
@@ -2013,7 +1702,15 @@
     }
     private Comparator<Link> linkComparator = new Comparator<Link>() {
 
+        @Override
         public int compare(Link l1, Link l2) {
+            if (l1.isVIP() && !l2.isVIP()) {
+                return -1;
+            }
+
+            if (!l1.isVIP() && l2.isVIP()) {
+                return 1;
+            }
 
             int result = l1.getFrom().getVertex().compareTo(l2.getFrom().getVertex());
             if (result != 0) {
@@ -2034,9 +1731,10 @@
 
     private class BuildDatastructure extends AlgorithmPart {
 
+        @Override
         protected void run() {
             // Set up nodes
-            List<Vertex> vertices = new ArrayList<Vertex>(graph.getVertices());
+            List<Vertex> vertices = new ArrayList<>(graph.getVertices());
             Collections.sort(vertices);
 
             for (Vertex v : vertices) {
@@ -2050,7 +1748,7 @@
             }
 
             // Set up edges
-            List<Link> links = new ArrayList<Link>(graph.getLinks());
+            List<Link> links = new ArrayList<>(graph.getLinks());
             Collections.sort(links, linkComparator);
             for (Link l : links) {
                 LayoutEdge edge = new LayoutEdge();
@@ -2061,14 +1759,15 @@
                 edge.relativeFrom = l.getFrom().getRelativePosition().x;
                 edge.relativeTo = l.getTo().getRelativePosition().x;
                 edge.link = l;
+                edge.vip = l.isVIP();
                 edge.from.succs.add(edge);
                 edge.to.preds.add(edge);
-            //assert edge.from != edge.to; // No self-loops allowed
+                //assert edge.from != edge.to; // No self-loops allowed
             }
 
             for (Link l : importantLinks) {
-                if (!vertexToLayoutNode.containsKey(l.getFrom().getVertex()) ||
-                        vertexToLayoutNode.containsKey(l.getTo().getVertex())) {
+                if (!vertexToLayoutNode.containsKey(l.getFrom().getVertex())
+                        || vertexToLayoutNode.containsKey(l.getTo().getVertex())) {
                     continue;
                 }
                 LayoutNode from = vertexToLayoutNode.get(l.getFrom().getVertex());
@@ -2104,7 +1803,8 @@
         }
     }
 
+    @Override
     public void doRouting(LayoutGraph graph) {
-    // Do nothing for now
+        // Do nothing for now
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/InterClusterConnection.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/InterClusterConnection.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,4 +73,8 @@
     public String toString() {
         return "InterClusterConnection[from=" + getFrom() + ", to=" + getTo() + "]";
     }
+
+    public boolean isVIP() {
+        return false;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Node.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Node.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -90,8 +90,8 @@
     protected Node(Graph<N, E> graph, N data) {
         setData(data);
         this.graph = graph;
-        inEdges = new ArrayList<Edge<N, E>>();
-        outEdges = new ArrayList<Edge<N, E>>();
+        inEdges = new ArrayList<>();
+        outEdges = new ArrayList<>();
     }
 
     protected void addInEdge(Edge<N, E> e) {
@@ -125,7 +125,7 @@
     }
 
     public List<Node<N, E>> getSuccessors() {
-        ArrayList<Node<N, E>> succ = new ArrayList<Node<N, E>>();
+        ArrayList<Node<N, E>> succ = new ArrayList<>();
         for (Edge<N, E> e : getOutEdges()) {
             Node<N, E> n = e.getDest();
             if (!succ.contains(n)) {
@@ -136,7 +136,7 @@
     }
 
     public List<Node<N, E>> getPredecessors() {
-        ArrayList<Node<N, E>> pred = new ArrayList<Node<N, E>>();
+        ArrayList<Node<N, E>> pred = new ArrayList<>();
         for (Edge<N, E> e : getInEdges()) {
             Node<N, E> n = e.getSource();
             if (!pred.contains(n)) {
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/OldHierarchicalLayoutManager.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1222 +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.awt.Point;
-import java.util.ArrayList;
-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 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.Port;
-import com.sun.hotspot.igv.layout.Vertex;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class OldHierarchicalLayoutManager implements LayoutManager {
-
-    public static final int DUMMY_WIDTH = 0;
-    public static final int DUMMY_HEIGHT = 0;
-    public static final int LAYER_OFFSET = 50;
-    public static final int OFFSET = 8;
-    public static final boolean VERTICAL_LAYOUT = true;
-    public static final boolean ASSERT = false;
-    public static final boolean TRACE = false;
-    public static final Timing initTiming = new Timing("init");
-    public static final Timing removeCyclesTiming = new Timing("removeCycles");
-    public static final Timing reversedEdgesTiming = new Timing("reversedEdges");
-    public static final Timing assignLayersTiming = new Timing("assignLayers");
-    public static final Timing dummyNodesTiming = new Timing("dummyNodes");
-    public static final Timing crossingReductionTiming = new Timing("crossingReduction");
-    public static final Timing assignCoordinatesTiming = new Timing("assignCoordinates");
-    public static final Timing assignRealTiming = new Timing("assignReal");
-    public static final Timing rootVertexTiming = new Timing("rootVertex");
-    public static final Timing createEdgesTiming = new Timing("createEdges");
-    public static final Timing optimizeMedianTiming = new Timing("optimizeMedian");
-    private Combine combine;
-
-    public enum Combine {
-
-        NONE,
-        SAME_INPUTS,
-        SAME_OUTPUTS
-    }
-
-    private class NodeData {
-
-        private Map<Port, Integer> reversePositions;
-        private Vertex node;
-        private Link edge;
-        private int layer;
-        private int x;
-        private int y;
-        private int width;
-
-        public NodeData(Vertex node) {
-            reversePositions = new HashMap<Port, Integer>();
-            layer = -1;
-            this.node = node;
-            assert node != null;
-
-            if (VERTICAL_LAYOUT) {
-                width = node.getSize().width;
-            } else {
-                width = node.getSize().height;
-            }
-        }
-
-        public NodeData(Link edge) {
-            layer = -1;
-            this.edge = edge;
-            assert edge != null;
-
-            if (VERTICAL_LAYOUT) {
-                width = DUMMY_WIDTH;
-            } else {
-                width = DUMMY_HEIGHT;
-            }
-        }
-
-        public Vertex getNode() {
-            return node;
-        }
-
-        public Link getEdge() {
-            return edge;
-        }
-
-        public int getCoordinate() {
-            return x;
-        }
-
-        public void setCoordinate(int x) {
-            this.x = x;
-        }
-
-        public int getX() {
-            if (VERTICAL_LAYOUT) {
-                return x;
-            } else {
-                return y;
-            }
-        }
-
-        public int getY() {
-            if (VERTICAL_LAYOUT) {
-                return y;
-            } else {
-                return x;
-            }
-        }
-
-        public void setLayerCoordinate(int y) {
-            this.y = y;
-        }
-
-        public void setLayer(int x) {
-            layer = x;
-        }
-
-        public int getLayer() {
-            return layer;
-        }
-
-        public boolean isDummy() {
-            return edge != null;
-        }
-
-        public int getWidth() {
-            return width;
-        }
-
-        public void addReversedStartEdge(Edge<NodeData, EdgeData> e) {
-            assert e.getData().isReversed();
-            Port port = e.getData().getEdge().getTo();
-            int pos = addReversedPort(port);
-            Point start = e.getData().getRelativeStart();
-            e.getData().addStartPoint(start);
-            int yCoord = node.getSize().height + width - node.getSize().width;
-            e.getData().addStartPoint(new Point(start.x, yCoord));
-            e.getData().addStartPoint(new Point(pos, yCoord));
-            e.getData().setRelativeStart(new Point(pos, 0));
-        }
-
-        private int addReversedPort(Port p) {
-            if (reversePositions.containsKey(p)) {
-                return reversePositions.get(p);
-            } else {
-                width += OFFSET;
-                reversePositions.put(p, width);
-                return width;
-            }
-        }
-
-        public void addReversedEndEdge(Edge<NodeData, EdgeData> e) {
-            assert e.getData().isReversed();
-            int pos = addReversedPort(e.getData().getEdge().getFrom());
-            Point end = e.getData().getRelativeEnd();
-            e.getData().setRelativeEnd(new Point(pos, node.getSize().height));
-            int yCoord = 0 - width + node.getSize().width;
-            e.getData().addEndPoint(new Point(pos, yCoord));
-            e.getData().addEndPoint(new Point(end.x, yCoord));
-            e.getData().addEndPoint(end);
-        }
-
-        public int getHeight() {
-            if (isDummy()) {
-                if (VERTICAL_LAYOUT) {
-                    return DUMMY_HEIGHT;
-                } else {
-                    return DUMMY_WIDTH;
-                }
-
-            } else {
-                if (VERTICAL_LAYOUT) {
-                    return node.getSize().height;
-                } else {
-                    return node.getSize().width;
-                }
-            }
-        }
-
-        @Override
-        public String toString() {
-            if (isDummy()) {
-                return edge.toString() + "(layer=" + layer + ")";
-            } else {
-                return node.toString() + "(layer=" + layer + ")";
-            }
-        }
-    }
-
-    private class EdgeData {
-
-        private Point relativeEnd;
-        private Point relativeStart;
-        private List<Point> startPoints;
-        private List<Point> endPoints;
-        private boolean important;
-        private boolean reversed;
-        private Link edge;
-
-        public EdgeData(Link edge) {
-            this(edge, false);
-        }
-
-        public EdgeData(Link edge, boolean rev) {
-            this.edge = edge;
-            reversed = rev;
-            relativeStart = edge.getFrom().getRelativePosition();
-            relativeEnd = edge.getTo().getRelativePosition();
-            assert relativeStart.x >= 0 && relativeStart.x <= edge.getFrom().getVertex().getSize().width;
-            assert relativeStart.y >= 0 && relativeStart.y <= edge.getFrom().getVertex().getSize().height;
-            assert relativeEnd.x >= 0 && relativeEnd.x <= edge.getTo().getVertex().getSize().width;
-            assert relativeEnd.y >= 0 && relativeEnd.y <= edge.getTo().getVertex().getSize().height;
-            startPoints = new ArrayList<Point>();
-            endPoints = new ArrayList<Point>();
-            this.important = true;
-        }
-
-        public boolean isImportant() {
-            return important;
-        }
-
-        public void setImportant(boolean b) {
-            this.important = b;
-        }
-
-        public List<Point> getStartPoints() {
-            return startPoints;
-        }
-
-        public List<Point> getEndPoints() {
-            return endPoints;
-        }
-
-        public List<Point> getAbsoluteEndPoints() {
-            if (endPoints.size() == 0) {
-                return endPoints;
-            }
-
-            List<Point> result = new ArrayList<Point>();
-            Point point = edge.getTo().getVertex().getPosition();
-            for (Point p : endPoints) {
-                Point p2 = new Point(p.x + point.x, p.y + point.y);
-                result.add(p2);
-            }
-
-            return result;
-        }
-
-        public List<Point> getAbsoluteStartPoints() {
-            if (startPoints.size() == 0) {
-                return startPoints;
-            }
-
-            List<Point> result = new ArrayList<Point>();
-            Point point = edge.getFrom().getVertex().getPosition();
-            for (Point p : startPoints) {
-                Point p2 = new Point(p.x + point.x, p.y + point.y);
-                result.add(p2);
-            }
-
-            return result;
-        }
-
-        public void addEndPoint(Point p) {
-            endPoints.add(p);
-        }
-
-        public void addStartPoint(Point p) {
-            startPoints.add(p);
-        }
-
-        public Link getEdge() {
-            return edge;
-        }
-
-        public void setRelativeEnd(Point p) {
-            relativeEnd = p;
-        }
-
-        public void setRelativeStart(Point p) {
-            relativeStart = p;
-        }
-
-        public Point getRelativeEnd() {
-            return relativeEnd;
-        }
-
-        public Point getRelativeStart() {
-            return relativeStart;
-        }
-
-        public boolean isReversed() {
-            return reversed;
-        }
-
-        public void setReversed(boolean b) {
-            reversed = b;
-        }
-
-        @Override
-        public String toString() {
-            return "EdgeData[reversed=" + reversed + "]";
-        }
-    }
-    private Graph<NodeData, EdgeData> graph;
-    private Map<Vertex, Node<NodeData, EdgeData>> nodeMap;
-    private int layerOffset;
-
-    /** Creates a new instance of HierarchicalPositionManager */
-    public OldHierarchicalLayoutManager(Combine combine) {
-        this(combine, LAYER_OFFSET);
-    }
-
-    public OldHierarchicalLayoutManager(Combine combine, int layerOffset) {
-        this.combine = combine;
-        this.layerOffset = layerOffset;
-    }
-
-    public void doRouting(LayoutGraph graph) {
-    }
-
-    //public void setPositions(PositionedNode rootNode, List<? extends PositionedNode> nodes, List<? extends PositionedEdge> edges) {
-    public void doLayout(LayoutGraph layoutGraph) {
-        doLayout(layoutGraph, new HashSet<Vertex>(), new HashSet<Vertex>());
-    }
-
-    public void doLayout(LayoutGraph layoutGraph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint) {
-        doLayout(layoutGraph, firstLayerHint, lastLayerHint, new HashSet<Link>());
-    }
-
-    public void doLayout(LayoutGraph layoutGraph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinksHint) {
-
-        if (TRACE) {
-            System.out.println("HierarchicalPositionManager.doLayout called");
-            System.out.println("Vertex count = " + layoutGraph.getVertices().size() + " Link count = " + layoutGraph.getLinks().size());
-        }
-
-        // Nothing to do => quit immediately
-        if (layoutGraph.getVertices().size() == 0) {
-            return;
-        }
-
-        initTiming.start();
-
-        // Mapping vertex to Node in graph
-        nodeMap = new HashMap<Vertex, Node<NodeData, EdgeData>>();
-
-        graph = new Graph<NodeData, EdgeData>();
-
-        Set<Node<NodeData, EdgeData>> rootNodes = new HashSet<Node<NodeData, EdgeData>>();
-        Set<Vertex> startRootVertices = new HashSet<Vertex>();
-
-        for (Vertex v : layoutGraph.getVertices()) {
-            if (v.isRoot()) {
-                startRootVertices.add(v);
-            }
-        }
-
-        rootVertexTiming.start();
-        Set<Vertex> rootVertices = layoutGraph.findRootVertices(startRootVertices);
-        rootVertexTiming.stop();
-
-
-        for (Vertex node : layoutGraph.getVertices()) {
-
-            NodeData data = new NodeData(node);
-            Node<NodeData, EdgeData> n = graph.createNode(data, node);
-            nodeMap.put(node, n);
-
-            if (rootVertices.contains(node)) {
-                rootNodes.add(n);
-            }
-        }
-
-        Set<? extends Link> links = layoutGraph.getLinks();
-        Link[] linkArr = new Link[links.size()];
-        links.toArray(linkArr);
-
-        List<Link> linkList = new ArrayList<Link>();
-        for (Link l : linkArr) {
-            linkList.add(l);
-        }
-
-        createEdgesTiming.start();
-        Collections.sort(linkList, new Comparator<Link>() {
-
-            public int compare(Link o1, Link o2) {
-                int result = o1.getFrom().getVertex().compareTo(o2.getFrom().getVertex());
-                if (result == 0) {
-                    return o1.getTo().getVertex().compareTo(o2.getTo().getVertex());
-                } else {
-                    return result;
-                }
-            }
-        });
-
-        for (Link edge : linkList) {
-            EdgeData data = new EdgeData(edge);
-            graph.createEdge(graph.getNode(edge.getFrom().getVertex()), graph.getNode(edge.getTo().getVertex()), data, data);
-            if (importantLinksHint.size() > 0 && !importantLinksHint.contains(edge)) {
-                data.setImportant(false);
-            }
-        }
-        createEdgesTiming.stop();
-
-        initTiming.stop();
-
-        removeCyclesTiming.start();
-
-        // STEP 1: Remove cycles!
-        removeCycles(rootNodes);
-        if (ASSERT) {
-            assert checkRemoveCycles();
-        }
-
-        removeCyclesTiming.stop();
-
-        reversedEdgesTiming.start();
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            List<Edge<NodeData, EdgeData>> edges = new ArrayList<Edge<NodeData, EdgeData>>(n.getOutEdges());
-            Collections.sort(edges, new Comparator<Edge<NodeData, EdgeData>>() {
-
-                public int compare(Edge<NodeData, EdgeData> o1, Edge<NodeData, EdgeData> o2) {
-                    return o2.getData().getRelativeEnd().x - o1.getData().getRelativeEnd().x;
-                }
-            });
-
-
-            for (Edge<NodeData, EdgeData> e : edges) {
-
-                if (e.getData().isReversed()) {
-                    e.getSource().getData().addReversedEndEdge(e);
-                }
-            }
-        }
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            List<Edge<NodeData, EdgeData>> edges = new ArrayList<Edge<NodeData, EdgeData>>(n.getInEdges());
-            Collections.sort(edges, new Comparator<Edge<NodeData, EdgeData>>() {
-
-                public int compare(Edge<NodeData, EdgeData> o1, Edge<NodeData, EdgeData> o2) {
-                    return o2.getData().getRelativeStart().x - o1.getData().getRelativeStart().x;
-                }
-            });
-
-
-            for (Edge<NodeData, EdgeData> e : edges) {
-                if (e.getData().isReversed()) {
-                    e.getDest().getData().addReversedStartEdge(e);
-                }
-            }
-        }
-
-        reversedEdgesTiming.stop();
-
-        assignLayersTiming.start();
-        // STEP 2: Assign layers!
-        int maxLayer = assignLayers(rootNodes, firstLayerHint, lastLayerHint);
-        if (ASSERT) {
-            assert checkAssignLayers();
-        }
-
-        // Put into layer array
-        //int maxLayer = 0;
-        //for(Node<NodeData, EdgeData> n : graph.getNodes()) {
-        //    maxLayer = Math.max(maxLayer, n.getData().getLayer());
-        //}
-
-
-        ArrayList<Node<NodeData, EdgeData>> layers[] = new ArrayList[maxLayer + 1];
-        int layerSizes[] = new int[maxLayer + 1];
-        for (int i = 0; i < maxLayer + 1; i++) {
-            layers[i] = new ArrayList<Node<NodeData, EdgeData>>();
-        }
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            int curLayer = n.getData().getLayer();
-            layers[curLayer].add(n);
-        }
-
-        assignLayersTiming.stop();
-
-        // STEP 3: Insert dummy nodes!
-        dummyNodesTiming.start();
-        insertDummyNodes(layers);
-        if (ASSERT) {
-            assert checkDummyNodes();
-        }
-        dummyNodesTiming.stop();
-
-        crossingReductionTiming.start();
-        // STEP 4: Assign Y coordinates
-        assignLayerCoordinates(layers, layerSizes);
-
-        // STEP 5: Crossing reduction
-        crossingReduction(layers);
-        crossingReductionTiming.stop();
-
-        // STEP 6: Assign Y coordinates
-        assignCoordinatesTiming.start();
-        assignCoordinates(layers);
-        assignCoordinatesTiming.stop();
-
-        assignRealTiming.start();
-
-        // Assign coordinates of nodes to real objects
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            if (!n.getData().isDummy()) {
-
-                Vertex node = n.getData().getNode();
-                node.setPosition(new Point(n.getData().getX(), n.getData().getY()));
-            }
-        }
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            if (!n.getData().isDummy()) {
-
-                Vertex node = n.getData().getNode();
-
-                List<Edge<NodeData, EdgeData>> outEdges = n.getOutEdges();
-                for (Edge<NodeData, EdgeData> e : outEdges) {
-                    Node<NodeData, EdgeData> succ = e.getDest();
-                    if (succ.getData().isDummy()) {
-                        //PositionedEdge edge = succ.getData().getEdge();
-                        List<Point> points = new ArrayList<Point>();
-                        assignToRealObjects(layerSizes, succ, points);
-                    } else {
-                        List<Point> points = new ArrayList<Point>();
-
-                        EdgeData otherEdgeData = e.getData();
-                        points.addAll(otherEdgeData.getAbsoluteStartPoints());
-                        Link otherEdge = otherEdgeData.getEdge();
-                        Point relFrom = new Point(otherEdgeData.getRelativeStart());
-                        Point from = otherEdge.getFrom().getVertex().getPosition();
-                        relFrom.move(relFrom.x + from.x, relFrom.y + from.y);
-                        points.add(relFrom);
-
-                        Point relTo = new Point(otherEdgeData.getRelativeEnd());
-                        Point to = otherEdge.getTo().getVertex().getPosition();
-                        relTo.move(relTo.x + to.x, relTo.y + to.y);
-                        assert from != null;
-                        assert to != null;
-                        points.add(relTo);
-                        points.addAll(otherEdgeData.getAbsoluteEndPoints());
-                        e.getData().getEdge().setControlPoints(points);
-                    }
-                }
-            }
-        }
-
-        assignRealTiming.stop();
-
-        initTiming.print();
-        removeCyclesTiming.print();
-        reversedEdgesTiming.print();
-        assignLayersTiming.print();
-        dummyNodesTiming.print();
-        crossingReductionTiming.print();
-        assignCoordinatesTiming.print();
-        assignRealTiming.print();
-        rootVertexTiming.print();
-        createEdgesTiming.print();
-        optimizeMedianTiming.print();
-    }
-
-    public boolean onOneLine(Point p1, Point p2, Point p3) {
-        int xoff1 = p1.x - p2.x;
-        int yoff1 = p1.y - p2.y;
-        int xoff2 = p3.x - p2.x;
-        int yoff2 = p3.y - p2.x;
-
-        return (xoff1 * yoff2 - yoff1 * xoff2 == 0);
-    }
-
-    private void assignToRealObjects(int layerSizes[], Node<NodeData, EdgeData> cur, List<Point> points) {
-        assert cur.getData().isDummy();
-
-        ArrayList<Point> otherPoints = new ArrayList<Point>(points);
-
-        int size = layerSizes[cur.getData().getLayer()];
-        otherPoints.add(new Point(cur.getData().getX(), cur.getData().getY() - size / 2));
-        if (otherPoints.size() >= 3 && onOneLine(otherPoints.get(otherPoints.size() - 1), otherPoints.get(otherPoints.size() - 2), otherPoints.get(otherPoints.size() - 3))) {
-            otherPoints.remove(otherPoints.size() - 2);
-        }
-        otherPoints.add(new Point(cur.getData().getX(), cur.getData().getY() + size / 2));
-        if (otherPoints.size() >= 3 && onOneLine(otherPoints.get(otherPoints.size() - 1), otherPoints.get(otherPoints.size() - 2), otherPoints.get(otherPoints.size() - 3))) {
-            otherPoints.remove(otherPoints.size() - 2);
-        }
-
-        for (int i = 0; i < cur.getOutEdges().size(); i++) {
-            Node<NodeData, EdgeData> otherSucc = cur.getOutEdges().get(i).getDest();
-
-            if (otherSucc.getData().isDummy()) {
-                assignToRealObjects(layerSizes, otherSucc, otherPoints);
-            } else {
-                EdgeData otherEdgeData = cur.getOutEdges().get(i).getData();
-                Link otherEdge = otherEdgeData.getEdge();
-
-                List<Point> middlePoints = new ArrayList<Point>(otherPoints);
-                if (cur.getOutEdges().get(i).getData().isReversed()) {
-                    Collections.reverse(middlePoints);
-                }
-
-                ArrayList<Point> copy = new ArrayList<Point>();
-                Point relFrom = new Point(otherEdgeData.getRelativeStart());
-                Point from = otherEdge.getFrom().getVertex().getPosition();
-                //int moveUp = (size - otherEdge.getFrom().getVertex().getSize().height) / 2;
-                relFrom.move(relFrom.x + from.x, relFrom.y + from.y);
-                copy.addAll(otherEdgeData.getAbsoluteStartPoints());
-                copy.add(relFrom);
-                copy.addAll(middlePoints);
-
-                Point relTo = new Point(otherEdgeData.getRelativeEnd());
-                Point to = otherEdge.getTo().getVertex().getPosition();
-                relTo.move(relTo.x + to.x, relTo.y + to.y);
-                copy.add(relTo);
-
-                copy.addAll(otherEdgeData.getAbsoluteEndPoints());
-
-
-                otherEdge.setControlPoints(copy);
-            }
-        }
-    }
-
-    private boolean checkDummyNodes() {
-        for (Edge<NodeData, EdgeData> e : graph.getEdges()) {
-            if (e.getSource().getData().getLayer() != e.getDest().getData().getLayer() - 1) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private void insertDummyNodes(ArrayList<Node<NodeData, EdgeData>> layers[]) {
-
-        int sum = 0;
-        List<Node<NodeData, EdgeData>> nodes = new ArrayList<Node<NodeData, EdgeData>>(graph.getNodes());
-        int edgeCount = 0;
-        int innerMostLoop = 0;
-
-        for (Node<NodeData, EdgeData> n : nodes) {
-            List<Edge<NodeData, EdgeData>> edges = new ArrayList<Edge<NodeData, EdgeData>>(n.getOutEdges());
-            for (Edge<NodeData, EdgeData> e : edges) {
-
-                edgeCount++;
-                Link edge = e.getData().getEdge();
-                Node<NodeData, EdgeData> destNode = e.getDest();
-                Node<NodeData, EdgeData> lastNode = n;
-                Edge<NodeData, EdgeData> lastEdge = e;
-
-                boolean searchForNode = (combine != Combine.NONE);
-                for (int i = n.getData().getLayer() + 1; i < destNode.getData().getLayer(); i++) {
-
-                    Node<NodeData, EdgeData> foundNode = null;
-                    if (searchForNode) {
-                        for (Node<NodeData, EdgeData> sameLayerNode : layers[i]) {
-                            innerMostLoop++;
-
-                            if (combine == Combine.SAME_OUTPUTS) {
-                                if (sameLayerNode.getData().isDummy() && sameLayerNode.getData().getEdge().getFrom() == edge.getFrom()) {
-                                    foundNode = sameLayerNode;
-                                    break;
-                                }
-                            } else if (combine == Combine.SAME_INPUTS) {
-                                if (sameLayerNode.getData().isDummy() && sameLayerNode.getData().getEdge().getTo() == edge.getTo()) {
-                                    foundNode = sameLayerNode;
-                                    break;
-                                }
-                            }
-                        }
-                    }
-
-                    if (foundNode == null) {
-                        searchForNode = false;
-                        NodeData intermediateData = new NodeData(edge);
-                        Node<NodeData, EdgeData> curNode = graph.createNode(intermediateData, null);
-                        curNode.getData().setLayer(i);
-                        layers[i].add(0, curNode);
-                        sum++;
-                        lastEdge.remove();
-                        graph.createEdge(lastNode, curNode, e.getData(), null);
-                        assert lastNode.getData().getLayer() == curNode.getData().getLayer() - 1;
-                        lastEdge = graph.createEdge(curNode, destNode, e.getData(), null);
-                        lastNode = curNode;
-                    } else {
-                        lastEdge.remove();
-                        lastEdge = graph.createEdge(foundNode, destNode, e.getData(), null);
-                        lastNode = foundNode;
-                    }
-
-                }
-            }
-        }
-
-        if (TRACE) {
-            System.out.println("Number of edges: " + edgeCount);
-        }
-        if (TRACE) {
-            System.out.println("Dummy nodes inserted: " + sum);
-        }
-    }
-
-    private void assignLayerCoordinates(ArrayList<Node<NodeData, EdgeData>> layers[], int layerSizes[]) {
-        int cur = 0;
-        for (int i = 0; i < layers.length; i++) {
-            int maxHeight = 0;
-            for (Node<NodeData, EdgeData> n : layers[i]) {
-                maxHeight = Math.max(maxHeight, n.getData().getHeight());
-            }
-
-            layerSizes[i] = maxHeight;
-            for (Node<NodeData, EdgeData> n : layers[i]) {
-                int curCoordinate = cur + (maxHeight - n.getData().getHeight()) / 2;
-                n.getData().setLayerCoordinate(curCoordinate);
-            }
-            cur += maxHeight + layerOffset;
-
-        }
-    }
-
-    private void assignCoordinates(ArrayList<Node<NodeData, EdgeData>> layers[]) {
-
-        // TODO: change this
-        for (int i = 0; i < layers.length; i++) {
-            ArrayList<Node<NodeData, EdgeData>> curArray = layers[i];
-            int curY = 0;
-            for (Node<NodeData, EdgeData> n : curArray) {
-
-                n.getData().setCoordinate(curY);
-                if (!n.getData().isDummy()) {
-                    curY += n.getData().getWidth();
-                }
-                curY += OFFSET;
-
-            }
-        }
-
-        int curSol = evaluateSolution();
-        if (TRACE) {
-            System.out.println("First coordinate solution found: " + curSol);
-        }
-
-        // Sort to correct order
-        for (int i = 0; i < layers.length; i++) {
-            Collections.sort(layers[i], new Comparator<Node<NodeData, EdgeData>>() {
-
-                public int compare(Node<NodeData, EdgeData> o1, Node<NodeData, EdgeData> o2) {
-                    if (o2.getData().isDummy()) {
-                        return 1;
-                    } else if (o1.getData().isDummy()) {
-                        return -1;
-                    }
-                    return o2.getInEdges().size() + o2.getOutEdges().size() - o1.getInEdges().size() - o1.getOutEdges().size();
-                }
-            });
-        }
-
-
-        optimizeMedianTiming.start();
-        for (int i = 0; i < 2; i++) {
-            optimizeMedian(layers);
-            curSol = evaluateSolution();
-            if (TRACE) {
-                System.out.println("Current coordinate solution found: " + curSol);
-            }
-        }
-        optimizeMedianTiming.stop();
-        normalizeCoordinate();
-
-    }
-
-    private void normalizeCoordinate() {
-
-        int min = Integer.MAX_VALUE;
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            min = Math.min(min, n.getData().getCoordinate());
-        }
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            n.getData().setCoordinate(n.getData().getCoordinate() - min);
-        }
-
-    }
-
-    private void optimizeMedian(ArrayList<Node<NodeData, EdgeData>> layers[]) {
-
-        // Downsweep
-        for (int i = 1; i < layers.length; i++) {
-
-            ArrayList<Node<NodeData, EdgeData>> processingList = layers[i];
-            ArrayList<Node<NodeData, EdgeData>> alreadyAssigned = new ArrayList<Node<NodeData, EdgeData>>();
-            for (Node<NodeData, EdgeData> n : processingList) {
-
-
-                ArrayList<Node<NodeData, EdgeData>> preds = new ArrayList<Node<NodeData, EdgeData>>(n.getPredecessors());
-                int pos = n.getData().getCoordinate();
-                if (preds.size() > 0) {
-
-                    Collections.sort(preds, new Comparator<Node<NodeData, EdgeData>>() {
-
-                        public int compare(Node<NodeData, EdgeData> o1, Node<NodeData, EdgeData> o2) {
-                            return o1.getData().getCoordinate() - o2.getData().getCoordinate();
-                        }
-                    });
-
-                    if (preds.size() % 2 == 0) {
-                        assert preds.size() >= 2;
-                        pos = (preds.get(preds.size() / 2).getData().getCoordinate() - calcRelativeCoordinate(preds.get(preds.size() / 2), n) + preds.get(preds.size() / 2 - 1).getData().getCoordinate() - calcRelativeCoordinate(preds.get(preds.size() / 2 - 1), n)) / 2;
-                    } else {
-                        assert preds.size() >= 1;
-                        pos = preds.get(preds.size() / 2).getData().getCoordinate() - calcRelativeCoordinate(preds.get(preds.size() / 2), n);
-                    }
-                }
-
-                tryAdding(alreadyAssigned, n, pos);
-            }
-        }
-        // Upsweep
-        for (int i = layers.length - 2; i >= 0; i--) {
-            ArrayList<Node<NodeData, EdgeData>> processingList = layers[i];
-            ArrayList<Node<NodeData, EdgeData>> alreadyAssigned = new ArrayList<Node<NodeData, EdgeData>>();
-            for (Node<NodeData, EdgeData> n : processingList) {
-
-                ArrayList<Node<NodeData, EdgeData>> succs = new ArrayList<Node<NodeData, EdgeData>>(n.getSuccessors());
-                int pos = n.getData().getCoordinate();
-                if (succs.size() > 0) {
-
-                    Collections.sort(succs, new Comparator<Node<NodeData, EdgeData>>() {
-
-                        public int compare(Node<NodeData, EdgeData> o1, Node<NodeData, EdgeData> o2) {
-                            return o1.getData().getCoordinate() - o2.getData().getCoordinate();
-                        }
-                    });
-
-                    if (succs.size() % 2 == 0) {
-                        assert succs.size() >= 2;
-                        pos = (succs.get(succs.size() / 2).getData().getCoordinate() - calcRelativeCoordinate(n, succs.get(succs.size() / 2)) + succs.get(succs.size() / 2 - 1).getData().getCoordinate() - calcRelativeCoordinate(n, succs.get(succs.size() / 2 - 1))) / 2;
-                    } else {
-                        assert succs.size() >= 1;
-                        pos = succs.get(succs.size() / 2).getData().getCoordinate() - calcRelativeCoordinate(n, succs.get(succs.size() / 2));
-                    }
-                }
-
-                tryAdding(alreadyAssigned, n, pos);
-            }
-        }
-    }
-
-    private int median(ArrayList<Integer> arr) {
-        assert arr.size() > 0;
-        Collections.sort(arr);
-        if (arr.size() % 2 == 0) {
-            return (arr.get(arr.size() / 2) + arr.get(arr.size() / 2 - 1)) / 2;
-        } else {
-            return arr.get(arr.size() / 2);
-        }
-    }
-
-    private int calcRelativeCoordinate(Node<NodeData, EdgeData> n, Node<NodeData, EdgeData> succ) {
-
-        if (n.getData().isDummy() && succ.getData().isDummy()) {
-            return 0;
-        }
-
-        int pos = 0;
-        int pos2 = 0;
-        ArrayList<Integer> coords2 = new ArrayList<Integer>();
-        ArrayList<Integer> coords = new ArrayList<Integer>();
-        /*if(!n.getData().isDummy())*/ {
-            for (Edge<NodeData, EdgeData> e : n.getOutEdges()) {
-
-                //System.out.println("reversed: " + e.getData().isReversed());
-                if (e.getDest() == succ) {
-
-                    if (e.getData().isReversed()) {
-                        if (!n.getData().isDummy()) {
-                            coords.add(e.getData().getRelativeEnd().x);
-                        }
-
-                        if (!succ.getData().isDummy()) {
-                            coords2.add(e.getData().getRelativeStart().x);
-                        }
-                    } else {
-                        if (!n.getData().isDummy()) {
-                            coords.add(e.getData().getRelativeStart().x);
-                        }
-
-                        if (!succ.getData().isDummy()) {
-                            coords2.add(e.getData().getRelativeEnd().x);
-                        }
-                    }
-                }
-            }
-
-            // assert coords.size() > 0;
-            if (!n.getData().isDummy()) {
-                pos = median(coords);
-            }
-
-            if (!succ.getData().isDummy()) {
-                pos2 = median(coords2);
-            }
-        }
-        //System.out.println("coords=" + coords);
-        //System.out.println("coords2=" + coords2);
-
-        return pos - pos2;
-    }
-
-    private boolean intersect(int v1, int w1, int v2, int w2) {
-        if (v1 >= v2 && v1 < v2 + w2) {
-            return true;
-        }
-        if (v1 + w1 > v2 && v1 + w1 < v2 + w2) {
-            return true;
-        }
-        if (v1 < v2 && v1 + w1 > v2) {
-            return true;
-        }
-        return false;
-    }
-
-    private boolean intersect(Node<NodeData, EdgeData> n1, Node<NodeData, EdgeData> n2) {
-        return intersect(n1.getData().getCoordinate(), n1.getData().getWidth() + OFFSET, n2.getData().getCoordinate(), n2.getData().getWidth() + OFFSET);
-    }
-
-    private void tryAdding(List<Node<NodeData, EdgeData>> alreadyAssigned, Node<NodeData, EdgeData> node, int pos) {
-
-        boolean doesIntersect = false;
-        node.getData().setCoordinate(pos);
-        for (Node<NodeData, EdgeData> n : alreadyAssigned) {
-            if (n.getData().getCoordinate() + n.getData().getWidth() < pos) {
-                break;
-            } else if (intersect(node, n)) {
-                doesIntersect = true;
-                break;
-            }
-
-        }
-
-        if (!doesIntersect) {
-
-            // Everything fine, just place the node
-            int z = 0;
-            for (Node<NodeData, EdgeData> n : alreadyAssigned) {
-                if (pos > n.getData().getCoordinate()) {
-                    break;
-                }
-                z++;
-            }
-
-            if (z == -1) {
-                z = alreadyAssigned.size();
-            }
-
-
-            if (ASSERT) {
-                assert !findOverlap(alreadyAssigned, node);
-            }
-            alreadyAssigned.add(z, node);
-
-        } else {
-
-            assert alreadyAssigned.size() > 0;
-
-            // Search for alternative location
-            int minOffset = Integer.MAX_VALUE;
-            int minIndex = -1;
-            int minPos = 0;
-            int w = node.getData().getWidth() + OFFSET;
-
-            // Try top-most
-            minIndex = 0;
-            minPos = alreadyAssigned.get(0).getData().getCoordinate() + alreadyAssigned.get(0).getData().getWidth() + OFFSET;
-            minOffset = Math.abs(minPos - pos);
-
-            // Try bottom-most
-            Node<NodeData, EdgeData> lastNode = alreadyAssigned.get(alreadyAssigned.size() - 1);
-            int lastPos = lastNode.getData().getCoordinate() - w;
-            int lastOffset = Math.abs(lastPos - pos);
-            if (lastOffset < minOffset) {
-                minPos = lastPos;
-                minOffset = lastOffset;
-                minIndex = alreadyAssigned.size();
-            }
-
-            // Try between
-            for (int i = 0; i < alreadyAssigned.size() - 1; i++) {
-                Node<NodeData, EdgeData> curNode = alreadyAssigned.get(i);
-                Node<NodeData, EdgeData> nextNode = alreadyAssigned.get(i + 1);
-
-                int start = nextNode.getData().getCoordinate() + nextNode.getData().getWidth() + OFFSET;
-                int end = curNode.getData().getCoordinate() - OFFSET;
-
-                int bestPoss = end - node.getData().getWidth();
-                if (bestPoss < pos && pos - bestPoss > minOffset) {
-                    // No better solution possible => break
-                    break;
-                }
-
-                if (end - start >= node.getData().getWidth()) {
-                    // Node could fit here
-                    int cand1 = start;
-                    int cand2 = end - node.getData().getWidth();
-                    int off1 = Math.abs(cand1 - pos);
-                    int off2 = Math.abs(cand2 - pos);
-                    if (off1 < minOffset) {
-                        minPos = cand1;
-                        minOffset = off1;
-                        minIndex = i + 1;
-                    }
-
-                    if (off2 < minOffset) {
-                        minPos = cand2;
-                        minOffset = off2;
-                        minIndex = i + 1;
-                    }
-                }
-            }
-
-            assert minIndex != -1;
-            node.getData().setCoordinate(minPos);
-            if (ASSERT) {
-                assert !findOverlap(alreadyAssigned, node);
-            }
-            alreadyAssigned.add(minIndex, node);
-        }
-
-    }
-
-    private boolean findOverlap(List<Node<NodeData, EdgeData>> nodes, Node<NodeData, EdgeData> node) {
-
-        for (Node<NodeData, EdgeData> n1 : nodes) {
-            if (intersect(n1, node)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private int evaluateSolution() {
-
-        int sum = 0;
-        for (Edge<NodeData, EdgeData> e : graph.getEdges()) {
-            Node<NodeData, EdgeData> source = e.getSource();
-            Node<NodeData, EdgeData> dest = e.getDest();
-            int offset = 0;
-            offset = Math.abs(source.getData().getCoordinate() - dest.getData().getCoordinate());
-            sum += offset;
-        }
-
-        return sum;
-    }
-
-    private void crossingReduction(ArrayList<Node<NodeData, EdgeData>> layers[]) {
-
-        for (int i = 0; i < layers.length - 1; i++) {
-
-            ArrayList<Node<NodeData, EdgeData>> curNodes = layers[i];
-            ArrayList<Node<NodeData, EdgeData>> nextNodes = layers[i + 1];
-            for (Node<NodeData, EdgeData> n : curNodes) {
-                for (Node<NodeData, EdgeData> succ : n.getSuccessors()) {
-                    if (ASSERT) {
-                        assert nextNodes.contains(succ);
-                    }
-                    nextNodes.remove(succ);
-                    nextNodes.add(succ);
-                }
-            }
-
-        }
-
-    }
-
-    private void removeCycles(Set<Node<NodeData, EdgeData>> rootNodes) {
-        final List<Edge<NodeData, EdgeData>> reversedEdges = new ArrayList<Edge<NodeData, EdgeData>>();
-
-
-        int removedCount = 0;
-        int reversedCount = 0;
-
-        Graph.DFSTraversalVisitor visitor = graph.new DFSTraversalVisitor() {
-
-            @Override
-            public boolean visitEdge(Edge<NodeData, EdgeData> e, boolean backEdge) {
-                if (backEdge) {
-                    if (ASSERT) {
-                        assert !reversedEdges.contains(e);
-                    }
-                    reversedEdges.add(e);
-                    e.getData().setReversed(!e.getData().isReversed());
-                }
-
-                return e.getData().isImportant();
-            }
-        };
-        Set<Node<NodeData, EdgeData>> nodes = new HashSet<Node<NodeData, EdgeData>>();
-        nodes.addAll(rootNodes);
-
-        assert nodes.size() > 0;
-
-        this.graph.traverseDFS(nodes, visitor);
-
-        for (Edge<NodeData, EdgeData> e : reversedEdges) {
-            if (e.isSelfLoop()) {
-                e.remove();
-                removedCount++;
-            } else {
-                e.reverse();
-                reversedCount++;
-            }
-        }
-    }
-
-    private boolean checkRemoveCycles() {
-        return !graph.hasCycles();
-    }
-    // Only used by assignLayers
-    private int maxLayerTemp;
-
-    private int assignLayers(Set<Node<NodeData, EdgeData>> rootNodes, Set<? extends Vertex> firstLayerHints,
-            Set<? extends Vertex> lastLayerHints) {
-        this.maxLayerTemp = -1;
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            n.getData().setLayer(-1);
-        }
-
-        Graph.BFSTraversalVisitor traverser = graph.new BFSTraversalVisitor() {
-
-            @Override
-            public void visitNode(Node<NodeData, EdgeData> n, int depth) {
-                if (depth > n.getData().getLayer()) {
-                    n.getData().setLayer(depth);
-                    maxLayerTemp = Math.max(maxLayerTemp, depth);
-                }
-            }
-        };
-
-        for (Node<NodeData, EdgeData> n : rootNodes) {
-            if (n.getData().getLayer() == -1) {
-                this.graph.traverseBFS(n, traverser, true);
-            }
-        }
-
-        for (Vertex v : firstLayerHints) {
-            assert nodeMap.containsKey(v);
-            nodeMap.get(v).getData().setLayer(0);
-        }
-
-        for (Vertex v : lastLayerHints) {
-            assert nodeMap.containsKey(v);
-            nodeMap.get(v).getData().setLayer(maxLayerTemp);
-        }
-
-        return maxLayerTemp;
-    }
-
-    private boolean checkAssignLayers() {
-
-        for (Edge<NodeData, EdgeData> e : graph.getEdges()) {
-            Node<NodeData, EdgeData> source = e.getSource();
-            Node<NodeData, EdgeData> dest = e.getDest();
-
-
-            if (source.getData().getLayer() >= dest.getData().getLayer()) {
-                return false;
-            }
-        }
-        int maxLayer = 0;
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            assert n.getData().getLayer() >= 0;
-            if (n.getData().getLayer() > maxLayer) {
-                maxLayer = n.getData().getLayer();
-            }
-        }
-
-        int countPerLayer[] = new int[maxLayer + 1];
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            countPerLayer[n.getData().getLayer()]++;
-        }
-
-        if (TRACE) {
-            System.out.println("Number of layers: " + maxLayer);
-        }
-        return true;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Timing.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Timing.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Layout/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Layout/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Cluster.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Cluster.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,4 @@
     public void setBounds(Rectangle r);
 
     public Set<? extends Cluster> getSuccessors();
-
-    public Set<? extends Cluster> getPredecessors();
 }
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,7 @@
  */
 package com.sun.hotspot.igv.layout;
 
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
+import java.util.*;
 
 /**
  *
@@ -49,10 +45,10 @@
         this.links = links;
         assert verify();
 
-        vertices = new TreeSet<Vertex>();
-        portLinks = new HashMap<Port, Set<Link>>();
-        inputPorts = new HashMap<Vertex, Set<Port>>();
-        outputPorts = new HashMap<Vertex, Set<Port>>();
+        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();
@@ -76,7 +72,7 @@
             }
 
             if (!portLinks.containsKey(p)) {
-                HashSet<Link> hashSet = new HashSet<Link>(3);
+                HashSet<Link> hashSet = new HashSet<>(3);
                 portLinks.put(p, hashSet);
             }
 
@@ -152,7 +148,7 @@
     //   whole graph is visited.
     public Set<Vertex> findRootVertices(Set<Vertex> startingRoots) {
 
-        Set<Vertex> notRootSet = new HashSet<Vertex>();
+        Set<Vertex> notRootSet = new HashSet<>();
         for (Vertex v : startingRoots) {
             if (!notRootSet.contains(v)) {
                 markNotRoot(notRootSet, v, v);
@@ -174,7 +170,7 @@
             }
         }
 
-        Set<Vertex> result = new HashSet<Vertex>();
+        Set<Vertex> result = new HashSet<>();
         for (Vertex v : tmpVertices) {
             if (!notRootSet.contains(v)) {
                 result.add(v);
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutManager.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutManager.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
 
     public void doLayout(LayoutGraph graph);
 
-    public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks);
+    public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks);
 
     public void doRouting(LayoutGraph graph);
 }
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Link.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Link.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,8 @@
 
     public Port getTo();
 
+    public boolean isVIP();
+
     public List<Point> getControlPoints();
 
     public void setControlPoints(List<Point> list);
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Port.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Port.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,8 +32,6 @@
  */
 public interface Vertex extends Comparable<Vertex> {
 
-    public Cluster getCluster();
-
     public Dimension getSize();
 
     public Point getPosition();
@@ -41,4 +39,6 @@
     public void setPosition(Point p);
 
     public boolean isRoot();
+
+    public Cluster getCluster();
 }
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/genfiles.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/genfiles.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=f8e21cb6
-build.xml.script.CRC32=a265137e
-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=f8e21cb6
-nbproject/build-impl.xml.script.CRC32=36f3138c
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.data.CRC32=5a0e591e
+nbproject/build-impl.xml.script.CRC32=4c38ce23
+nbproject/build-impl.xml.stylesheet.CRC32=e50cf570@2.62.1
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -27,7 +27,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.1.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -35,7 +35,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -43,7 +43,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupReceiver	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.connection.Server
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,73 +24,46 @@
  */
 package com.sun.hotspot.igv.connection;
 
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.services.GroupCallback;
+import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.serialization.BinaryParser;
 import com.sun.hotspot.igv.data.serialization.Parser;
-import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
+import com.sun.hotspot.igv.data.services.GroupCallback;
 import java.io.IOException;
-import java.io.InputStream;
-import java.net.Socket;
-import javax.swing.JTextField;
+import java.nio.channels.SocketChannel;
 import org.openide.util.Exceptions;
-import org.openide.xml.XMLUtil;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
 
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class Client implements Runnable, GroupCallback {
+public class Client implements Runnable {
+    private final boolean binary;
+    private final SocketChannel socket;
+    private final GraphDocument rootDocument;
+    private final GroupCallback callback;
 
-    private Socket socket;
-    private JTextField networkTextField;
-    private GroupCallback callback;
-
-    public Client(Socket socket, JTextField networkTextField, GroupCallback callback) {
+    public Client(SocketChannel socket, GraphDocument rootDocument, GroupCallback callback, boolean  binary) {
         this.callback = callback;
         this.socket = socket;
-        this.networkTextField = networkTextField;
+        this.binary = binary;
+        this.rootDocument = rootDocument;
     }
 
+    @Override
     public void run() {
 
         try {
-            InputStream inputStream = socket.getInputStream();
-
-            if (networkTextField.isEnabled()) {
-
-                socket.getOutputStream().write('y');
-                InputSource is = new InputSource(inputStream);
-
-                try {
-                    XMLReader reader = XMLUtil.createXMLReader();
-                    Parser parser = new Parser(this);
-                    parser.parse(reader, is, null);
-                } catch (SAXException ex) {
-                    ex.printStackTrace();
-                }
+            final SocketChannel channel = socket;
+            channel.configureBlocking(true);
+            if (binary) {
+                new BinaryParser(channel, null, rootDocument, callback).parse();
             } else {
-                socket.getOutputStream().write('n');
+                new Parser(channel, null, callback).parse();
             }
-
-            socket.close();
         } catch (IOException ex) {
             Exceptions.printStackTrace(ex);
-        }
-    }
-
-    public void started(final Group g) {
-        try {
-            RegexpPropertyMatcher matcher = new RegexpPropertyMatcher("name", ".*" + networkTextField.getText() + ".*");
-            if (g.getProperties().selectSingle(matcher) != null && networkTextField.isEnabled()) {
-                socket.getOutputStream().write('y');
-                callback.started(g);
-            } else {
-                socket.getOutputStream().write('n');
+        } finally {
+            try {
+                socket.close();
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
             }
-        } catch (IOException e) {
         }
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,17 +24,15 @@
  */
 package com.sun.hotspot.igv.connection;
 
-import com.sun.hotspot.igv.data.Group;
+import com.sun.hotspot.igv.data.GraphDocument;
 import com.sun.hotspot.igv.data.services.GroupCallback;
-import com.sun.hotspot.igv.data.services.GroupReceiver;
 import com.sun.hotspot.igv.settings.Settings;
-import java.awt.Component;
 import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
+import java.net.InetSocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
 import java.util.prefs.PreferenceChangeEvent;
 import java.util.prefs.PreferenceChangeListener;
-import javax.swing.SwingUtilities;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
 import org.openide.util.RequestProcessor;
@@ -43,54 +41,26 @@
  *
  * @author Thomas Wuerthinger
  */
-public class Server implements GroupCallback, GroupReceiver, PreferenceChangeListener {
-
-    private javax.swing.JPanel jPanel1;
-    private javax.swing.JCheckBox networkCheckBox;
-    private javax.swing.JTextField networkTextField;
-    private ServerSocket serverSocket;
-    private GroupCallback callback;
+public class Server implements PreferenceChangeListener {
+    private final boolean binary;
+    private ServerSocketChannel serverSocket;
+    private final GraphDocument rootDocument;
+    private final GroupCallback callback;
     private int port;
     private Runnable serverRunnable;
 
-    public Component init(GroupCallback callback) {
-
+    public Server(GraphDocument rootDocument, GroupCallback callback, boolean binary) {
+        this.binary = binary;
+        this.rootDocument = rootDocument;
         this.callback = callback;
-
-        jPanel1 = new javax.swing.JPanel();
-        networkTextField = new javax.swing.JTextField();
-        networkCheckBox = new javax.swing.JCheckBox();
-
-
-        jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
-        jPanel1.setLayout(new java.awt.BorderLayout(10, 10));
-        jPanel1.add(networkTextField, java.awt.BorderLayout.CENTER);
-
-        networkCheckBox.setSelected(true);
-        org.openide.awt.Mnemonics.setLocalizedText(networkCheckBox, "Receive when name contains");
-        networkCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
-        networkCheckBox.setMargin(new java.awt.Insets(0, 0, 0, 0));
-        networkCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
-
-            public void stateChanged(javax.swing.event.ChangeEvent evt) {
-                networkCheckBoxChanged(evt);
-            }
-        });
-        jPanel1.add(networkCheckBox, java.awt.BorderLayout.WEST);
-        networkCheckBox.getAccessibleContext().setAccessibleName("Read from network when name contains");
-
         initializeNetwork();
         Settings.get().addPreferenceChangeListener(this);
-        return jPanel1;
     }
 
-    private void networkCheckBoxChanged(javax.swing.event.ChangeEvent evt) {
-        networkTextField.setEnabled(networkCheckBox.isSelected());
-    }
-
+    @Override
     public void preferenceChange(PreferenceChangeEvent e) {
 
-        int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
+        int curPort = Integer.parseInt(Settings.get().get(binary ? Settings.PORT_BINARY : Settings.PORT, binary ? Settings.PORT_BINARY_DEFAULT : Settings.PORT_DEFAULT));
         if (curPort != port) {
             initializeNetwork();
         }
@@ -98,30 +68,32 @@
 
     private void initializeNetwork() {
 
-        int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
+        int curPort = Integer.parseInt(Settings.get().get(binary ? Settings.PORT_BINARY : Settings.PORT, binary ? Settings.PORT_BINARY_DEFAULT : Settings.PORT_DEFAULT));
         this.port = curPort;
         try {
-            serverSocket = new java.net.ServerSocket(curPort);
-        } catch (IOException ex) {
-            NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
+            serverSocket = ServerSocketChannel.open();
+            serverSocket.bind(new InetSocketAddress(curPort));
+        } catch (Throwable ex) {
+            NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
             DialogDisplayer.getDefault().notifyLater(message);
             return;
         }
 
         Runnable runnable = new Runnable() {
 
+            @Override
             public void run() {
                 while (true) {
                     try {
-                        Socket clientSocket = serverSocket.accept();
+                        SocketChannel clientSocket = serverSocket.accept();
                         if (serverRunnable != this) {
                             clientSocket.close();
                             return;
                         }
-                        RequestProcessor.getDefault().post(new Client(clientSocket, networkTextField, Server.this), 0, Thread.MAX_PRIORITY);
+                        RequestProcessor.getDefault().post(new Client(clientSocket, rootDocument, callback, binary), 0, Thread.MAX_PRIORITY);
                     } catch (IOException ex) {
                         serverSocket = null;
-                        NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
+                        NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
                         DialogDisplayer.getDefault().notifyLater(message);
                         return;
                     }
@@ -133,13 +105,4 @@
 
         RequestProcessor.getDefault().post(runnable, 0, Thread.MAX_PRIORITY);
     }
-
-    public void started(final Group g) {
-        SwingUtilities.invokeLater(new Runnable() {
-
-            public void run() {
-                callback.started(g);
-            }
-        });
-    }
 }
--- a/src/share/tools/IdealGraphVisualizer/README	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/README	Mon Feb 06 17:18:57 2017 +0100
@@ -5,16 +5,11 @@
 was the primary target of the tool.  The tool itself is fairly general
 with only a few modules that contain C2 specific elements.
 
-The tool is built on top of the NetBeans 6.1 rich client
+The tool is built on top of the NetBeans 7 rich client
 infrastructure and so requires NetBeans to build.  It currently
 requires Java 6 to run as it needs support for JavaScript for its
 filtering mechanism and assumes it's built into the platform.  It
-should build out of the box with NetBeans 6.1 and Java 6 or later.
-It's possible to run it on 1.5 by including Rhino on the classpath
-though that currently isn't working correctly.  Support for exporting
-graphs as SVG can be enabled by adding batik to the classpath which
-isn't included by default.  It can be built on top of NetBeans 6.0 if
-you change the required modules to be platform7 instead of platform8.
+should build out of the box with NetBeans 7.0 and Java 6 or later.
 
 The JVM support is controlled by the flag -XX:PrintIdealGraphLevel=#
 where # is:
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/build.xml	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
-<!-- for some information on what you could do (e.g. targets to override). -->
-<!-- If you delete this file and reopen the project it will be recreated. -->
-<project name="com.sun.hotspot.igv.rhino" default="netbeans" basedir=".">
-    <description>Builds, tests, and runs the project com.sun.hotspot.igv.rhino.</description>
-    <import file="nbproject/build-impl.xml"/>
-</project>
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/manifest.mf	Mon Dec 05 13:09:39 2016 -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.rhino
-OpenIDE-Module-Layer: com/sun/hotspot/igv/rhino/layer.xml
-OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/rhino/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.0
-
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/build-impl.xml	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-*** GENERATED FROM project.xml - DO NOT EDIT  ***
-***         EDIT ../build.xml INSTEAD         ***
--->
-<project name="com.sun.hotspot.igv.rhino-impl" basedir="..">
-    <property file="nbproject/private/suite-private.properties"/>
-    <property file="nbproject/suite.properties"/>
-    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
-    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
-    <property file="${suite.dir}/nbproject/platform.properties"/>
-    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
-        <attribute name="name"/>
-        <attribute name="value"/>
-        <sequential>
-            <property name="@{name}" value="${@{value}}"/>
-        </sequential>
-    </macrodef>
-    <property file="${user.properties.file}"/>
-    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
-        <condition>
-            <not>
-                <available file="${harness.dir}" type="dir"/>
-            </not>
-        </condition>
-    </fail>
-    <import file="${harness.dir}/build.xml"/>
-</project>
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/genfiles.properties	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-build.xml.data.CRC32=0c3e7912
-build.xml.script.CRC32=44d0050c
-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=0c3e7912
-nbproject/build-impl.xml.script.CRC32=7aab3f52
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://www.netbeans.org/ns/project/1">
-    <type>org.netbeans.modules.apisupport.project</type>
-    <configuration>
-        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
-            <code-name-base>com.sun.hotspot.igv.rhino</code-name-base>
-            <suite-component/>
-            <module-dependencies>
-                <dependency>
-                    <code-name-base>com.sun.hotspot.igv.filter</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.0</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.0</specification-version>
-                    </run-dependency>
-                </dependency>
-            </module-dependencies>
-            <public-packages>
-                <package>com.sun.hotspot.igv.rhino</package>
-            </public-packages>
-        </data>
-    </configuration>
-</project>
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/suite.properties	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-suite.dir=${basedir}/..
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.rhino.RhinoScriptEngine
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-OpenIDE-Module-Name=RhinoScriptEngineProxy
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/RhinoScriptEngine.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +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.rhino;
-
-import com.sun.hotspot.igv.filter.ScriptEngineAbstraction;
-import com.sun.hotspot.igv.graph.Diagram;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class RhinoScriptEngine implements ScriptEngineAbstraction {
-
-    private String jsHelperText;
-    private Constructor importer;
-    private Method scope_put;
-    private Method cx_evaluateString;
-    private Method context_enter;
-    private Method context_exit;
-
-    public boolean initialize(String s) {
-        this.jsHelperText = s;
-        Class importerTopLevel = null;
-        try {
-            ClassLoader cl = RhinoScriptEngine.class.getClassLoader();
-            Class context = cl.loadClass("org.mozilla.javascript.Context");
-            Class scriptable = cl.loadClass("org.mozilla.javascript.Scriptable");
-            importerTopLevel = cl.loadClass("org.mozilla.javascript.ImporterTopLevel");
-            importer = importerTopLevel.getDeclaredConstructor(context);
-            scope_put = importerTopLevel.getMethod("put", new Class[]{String.class, scriptable, Object.class});
-            cx_evaluateString = context.getDeclaredMethod("evaluateString", new Class[]{scriptable, String.class, String.class, Integer.TYPE, Object.class});
-            context_enter = context.getDeclaredMethod("enter", new Class[0]);
-            context_exit = context.getDeclaredMethod("exit", new Class[0]);
-            return true;
-        } catch (NoSuchMethodException nsme) {
-            return false;
-        } catch (ClassNotFoundException cnfe) {
-            return false;
-        }
-    }
-
-    public void execute(Diagram d, String code) {
-        try {
-            Object cx = context_enter.invoke(null, (Object[]) null);
-            try {
-                Object scope = importer.newInstance(cx);
-                scope_put.invoke(scope, "IO", scope, System.out);
-                scope_put.invoke(scope, "graph", scope, d);
-                cx_evaluateString.invoke(cx, scope, jsHelperText, "jsHelper.js", 1, null);
-                cx_evaluateString.invoke(cx, scope, code, "<cmd>", 1, null);
-            } finally {
-                // Exit from the context.
-                context_exit.invoke(null, (Object[]) null);
-            }
-        } catch (InvocationTargetException iae) {
-        } catch (IllegalAccessException iae) {
-        } catch (InstantiationException iae) {
-        }
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/layer.xml	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
-<filesystem>
-</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/build.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.selectioncoordinator" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.selectioncoordinator.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/manifest.mf	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.selectioncoordinator
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/selectioncoordinator/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/build-impl.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.selectioncoordinator-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/genfiles.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,5 @@
+# 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=13553862
+nbproject/build-impl.xml.script.CRC32=3db87c68
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/platform.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,129 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    gsf1,\
+    harness,\
+    java2,\
+    nb6.1,\
+    profiler3
+disabled.modules=\
+    org.apache.xml.resolver,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.output2,\
+    org.netbeans.insane,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.libs.commons_logging,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jna,\
+    org.netbeans.libs.jsch,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.classfile,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    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.diff,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.errorstripe,\
+    org.netbeans.modules.editor.errorstripe.api,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.highlights,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.plain,\
+    org.netbeans.modules.editor.plain.lib,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.bat,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.sh,\
+    org.netbeans.modules.lexer.editorbridge,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.progress.ui,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    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.sendopts,\
+    org.netbeans.modules.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.templates,\
+    org.netbeans.modules.timers,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.system.cvss,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.flyingsaucer,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    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.util.enumerations
+enabled.clusters=\
+    ide9,\
+    platform8
+nbjdk.active=default
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.selectioncoordinator</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.sun.hotspot.igv.selectioncoordinator</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/suite.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=SelectionCoordinator
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/SelectionCoordinator.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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<Object> selectedObjects;
+    private Set<Object> highlightedObjects;
+    private ChangedEvent<SelectionCoordinator> selectedChangedEvent;
+    private ChangedEvent<SelectionCoordinator> 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<Object> getSelectedObjects() {
+        return Collections.unmodifiableSet(selectedObjects);
+    }
+
+    public Set<Object> getHighlightedObjects() {
+        return Collections.unmodifiableSet(highlightedObjects);
+    }
+
+    public ChangedEvent<SelectionCoordinator> getHighlightedChangedEvent() {
+        return highlightedChangedEvent;
+    }
+
+    public ChangedEvent<SelectionCoordinator> 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<? extends Object> s) {
+        int oldSize = highlightedObjects.size();
+        highlightedObjects.addAll(s);
+        if (oldSize != highlightedObjects.size()) {
+            highlightedObjectsChanged();
+        }
+    }
+
+    public void removeAllHighlighted(Set<? extends Object> s) {
+        int oldSize = highlightedObjects.size();
+        highlightedObjects.removeAll(s);
+        if (oldSize != highlightedObjects.size()) {
+            highlightedObjectsChanged();
+        }
+    }
+
+    private void highlightedObjectsChanged() {
+        highlightedChangedEvent.fire();
+
+    }
+
+    public void addAllSelected(Set<? extends Object> s) {
+        int oldSize = selectedObjects.size();
+        selectedObjects.addAll(s);
+        if (oldSize != selectedObjects.size()) {
+            selectedObjectsChanged();
+        }
+    }
+
+    public void removeAllSelected(Set<? extends Object> s) {
+        int oldSize = selectedObjects.size();
+        selectedObjects.removeAll(s);
+        if (oldSize != selectedObjects.size()) {
+            selectedObjectsChanged();
+        }
+    }
+
+    public void setSelectedObjects(Set<? extends Object> s) {
+        assert s != null;
+        selectedObjects.clear();
+        selectedObjects.addAll(s);
+        selectedObjectsChanged();
+    }
+
+    private void selectedObjectsChanged() {
+        selectedChangedEvent.fire();
+    }
+
+    public void setHighlightedObjects(Set<? extends Object> s) {
+        assert s != null;
+        this.highlightedObjects.clear();
+        this.highlightedObjects.addAll(s);
+        highlightedObjectsChanged();
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -1,21 +1,29 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://www.netbeans.org/ns/project/1">
-    <type>org.netbeans.modules.apisupport.project</type>
-    <configuration>
-        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
-            <code-name-base>com.sun.hotspot.igv.servercompiler</code-name-base>
-            <suite-component/>
-            <module-dependencies>
-                <dependency>
-                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.0</specification-version>
-                    </run-dependency>
-                </dependency>
-            </module-dependencies>
-            <public-packages/>
-        </data>
-    </configuration>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.servercompiler</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupOrganizer	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.servercompiler.JavaGroupOrganizer
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/JavaGroupOrganizer.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +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.servercompiler;
-
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import com.sun.hotspot.igv.data.Pair;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class JavaGroupOrganizer implements GroupOrganizer {
-
-    public String getName() {
-        return "Java structure";
-    }
-
-    public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
-
-        List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
-
-        if (subFolders.size() == 0) {
-            buildResult(result, groups, packageNameProvider);
-        } else if (subFolders.size() == 1) {
-            buildResult(result, groups, classNameProvider);
-        } else if (subFolders.size() == 2) {
-            for (Group g : groups) {
-                List<Group> children = new ArrayList<Group>();
-                children.add(g);
-                Pair<String, List<Group>> p = new Pair<String, List<Group>>();
-                p.setLeft(reducedNameProvider.getName(g));
-                p.setRight(children);
-                result.add(p);
-            }
-        } else {
-            result.add(new Pair<String, List<Group>>("", groups));
-        }
-
-        return result;
-    }
-
-    private void buildResult(List<Pair<String, List<Group>>> result, List<Group> groups, NameProvider provider) {
-        HashMap<String, List<Group>> map = new HashMap<String, List<Group>>();
-        for (Group g : groups) {
-            String s = provider.getName(g);
-
-            if (!map.containsKey(s)) {
-                List<Group> list = new ArrayList<Group>();
-                Pair<String, List<Group>> pair = new Pair<String, List<Group>>(s, list);
-                result.add(pair);
-                map.put(s, list);
-            }
-
-            List<Group> curList = map.get(s);
-            curList.add(g);
-        }
-
-        Collections.sort(result, new Comparator<Pair<String, List<Group>>>() {
-
-            public int compare(Pair<String, List<Group>> a, Pair<String, List<Group>> b) {
-                return a.getLeft().compareTo(b.getLeft());
-            }
-        });
-    }
-
-    private static interface NameProvider {
-
-        public String getName(Group g);
-    }
-    private NameProvider reducedNameProvider = new NameProvider() {
-
-        public String getName(Group g) {
-            String name = g.getName();
-            assert name != null : "name of group must be set!";
-            final String noReducedName = name;
-
-            int firstPoint = name.indexOf(".");
-            if (firstPoint == -1) {
-                return noReducedName;
-            }
-
-            int firstParenthese = name.indexOf("(");
-            if (firstParenthese == -1 || firstParenthese < firstPoint) {
-                return noReducedName;
-            }
-
-            int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
-                current--;
-            }
-
-            String tmp = name.substring(0, firstParenthese);
-            int lastPoint = tmp.lastIndexOf(".");
-            if (lastPoint == -1) {
-                return noReducedName;
-            }
-
-            name = name.substring(0, current + 1) + name.substring(lastPoint + 1);
-            return name;
-        }
-    };
-    private NameProvider packageNameProvider = new NameProvider() {
-
-        public String getName(Group g) {
-            String name = g.getName();
-            assert name != null : "name of group must be set!";
-            final String noPackage = "<default>";
-
-            int firstPoint = name.indexOf(".");
-            if (firstPoint == -1) {
-                return noPackage;
-            }
-
-            int firstParenthese = name.indexOf("(");
-            if (firstParenthese == -1 || firstParenthese < firstPoint) {
-                return noPackage;
-            }
-
-            int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
-                current--;
-            }
-
-            String fullClassName = name.substring(current + 1, firstParenthese);
-            int lastPoint = fullClassName.lastIndexOf(".");
-            if (lastPoint == -1) {
-                return noPackage;
-            }
-            lastPoint = fullClassName.lastIndexOf(".", lastPoint - 1);
-            if (lastPoint == -1) {
-                return noPackage;
-            }
-
-            String packageName = fullClassName.substring(0, lastPoint);
-            return packageName;
-        }
-    };
-    private NameProvider classNameProvider = new NameProvider() {
-
-        public String getName(Group g) {
-            String name = g.getName();
-            assert name != null : "name of group must be set!";
-
-            final String noClass = "<noclass>";
-
-            int firstPoint = name.indexOf(".");
-            if (firstPoint == -1) {
-                return noClass;
-            }
-
-            int firstParenthese = name.indexOf("(");
-            if (firstParenthese == -1 || firstParenthese < firstPoint) {
-                return noClass;
-            }
-
-            int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
-                current--;
-            }
-
-            String fullClassName = name.substring(current + 1, firstParenthese);
-            int lastPoint = fullClassName.lastIndexOf(".");
-            if (lastPoint == -1) {
-                return noClass;
-            }
-            int lastlastPoint = fullClassName.lastIndexOf(".", lastPoint - 1);
-
-            String className = fullClassName.substring(lastlastPoint + 1, lastPoint);
-            return className;
-        }
-    };
-}
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,17 +29,7 @@
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.data.services.Scheduler;
-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.Stack;
-import java.util.Vector;
+import java.util.*;
 
 /**
  *
@@ -50,8 +40,8 @@
     private static class Node {
 
         public InputNode inputNode;
-        public Set<Node> succs = new HashSet<Node>();
-        public List<Node> preds = new ArrayList<Node>();
+        public Set<Node> succs = new HashSet<>();
+        public List<Node> preds = new ArrayList<>();
         public InputBlock block;
         public boolean isBlockProjection;
         public boolean isBlockStart;
@@ -65,6 +55,7 @@
     private InputBlock[][] commonDominator;
     private static final Comparator<InputEdge> edgeComparator = new Comparator<InputEdge>() {
 
+        @Override
         public int compare(InputEdge o1, InputEdge o2) {
             return o1.getToIndex() - o2.getToIndex();
         }
@@ -72,13 +63,13 @@
 
     public void buildBlocks() {
 
-        blocks = new Vector<InputBlock>();
+        blocks = new Vector<>();
         Node root = findRoot();
         if (root == null) {
             return;
         }
-        Stack<Node> stack = new Stack<Node>();
-        Set<Node> visited = new HashSet<Node>();
+        Stack<Node> stack = new Stack<>();
+        Set<Node> visited = new HashSet<>();
         stack.add(root);
         int blockCount = 0;
         InputBlock rootBlock = null;
@@ -93,7 +84,7 @@
 
             if (!visited.contains(parent)) {
                 visited.add(parent);
-                InputBlock block = new InputBlock(graph, "" + blockCount);
+                InputBlock block = graph.addBlock(Integer.toString(blockCount));
                 blocks.add(block);
                 if (parent == root) {
                     rootBlock = block;
@@ -111,7 +102,12 @@
                         p = parent;
                         break;
                     }
+
                     p = p.preds.get(0);
+                    if (p == proj) {
+                        // Cycle, stop
+                        break;
+                    }
 
                     if (p.block == null) {
                         p.block = block;
@@ -125,7 +121,7 @@
                                 n = n.preds.get(0);
                             }
                             if (n.block != null) {
-                                n.block.addSuccessor(block);
+                                graph.addBlockEdge(n.block, block);
                             }
                         }
                     }
@@ -136,12 +132,12 @@
                         for (Node n2 : n.succs) {
 
                             if (n2 != parent && n2.block != null && n2.block != rootBlock) {
-                                block.addSuccessor(n2.block);
+                                graph.addBlockEdge(block, n2.block);
                             }
                         }
                     } else {
                         if (n != parent && n.block != null && n.block != rootBlock) {
-                            block.addSuccessor(n.block);
+                            graph.addBlockEdge(block, n.block);
                         }
                     }
                 }
@@ -161,7 +157,7 @@
                 }
 
                 if (pushed == 0 && p == root) {
-                // TODO: special handling when root backedges are not built yet
+                    // TODO: special handling when root backedges are not built yet
                 }
             }
         }
@@ -174,7 +170,7 @@
         }
 
         int z = 0;
-        blockIndex = new HashMap<InputBlock, Integer>();
+        blockIndex = new HashMap<>(blocks.size());
         for (InputBlock b : blocks) {
             blockIndex.put(b, z);
             z++;
@@ -185,20 +181,25 @@
         return n.getProperties().get("block");
     }
 
+    @Override
     public Collection<InputBlock> schedule(InputGraph graph) {
+        if (graph.getNodes().isEmpty()) {
+            return Collections.emptyList();
+        }
+
         if (graph.getBlocks().size() > 0) {
-            Collection<InputNode> tmpNodes = new ArrayList<InputNode>(graph.getNodes());
+            Collection<InputNode> tmpNodes = new ArrayList<>(graph.getNodes());
             for (InputNode n : tmpNodes) {
                 String block = getBlockName(n);
                 if (graph.getBlock(n) == null) {
-                    graph.getBlock(block).addNode(n);
+                    graph.getBlock(block).addNode(n.getId());
                     assert graph.getBlock(n) != null;
                 }
             }
             return graph.getBlocks();
         } else {
-            nodes = new ArrayList<Node>();
-            inputNodeToNode = new HashMap<InputNode, Node>();
+            nodes = new ArrayList<>();
+            inputNodeToNode = new HashMap<>(graph.getNodes().size());
 
             this.graph = graph;
             buildUpGraph();
@@ -207,7 +208,16 @@
             buildCommonDominators();
             scheduleLatest();
 
+            InputBlock noBlock = null;
             for (InputNode n : graph.getNodes()) {
+                if (graph.getBlock(n) == null) {
+                    if (noBlock == null) {
+                        noBlock = graph.addBlock("(no block)");
+                        blocks.add(noBlock);
+                    }
+
+                    graph.setBlock(n, noBlock);
+                }
                 assert graph.getBlock(n) != null;
             }
 
@@ -215,15 +225,17 @@
         }
     }
 
-    public void scheduleLatest() {
-
-
+    private void scheduleLatest() {
         Node root = findRoot();
+        if(root == null) {
+            assert false : "No root found!";
+            return;
+        }
 
         // Mark all nodes reachable in backward traversal from root
-        Set<Node> reachable = new HashSet<Node>();
+        Set<Node> reachable = new HashSet<>();
         reachable.add(root);
-        Stack<Node> stack = new Stack<Node>();
+        Stack<Node> stack = new Stack<>();
         stack.push(root);
         while (!stack.isEmpty()) {
             Node cur = stack.pop();
@@ -235,7 +247,7 @@
             }
         }
 
-        Set<Node> unscheduled = new HashSet<Node>();
+        Set<Node> unscheduled = new HashSet<>();
         for (Node n : this.nodes) {
             if (n.block == null && reachable.contains(n)) {
                 unscheduled.add(n);
@@ -245,7 +257,7 @@
         while (unscheduled.size() > 0) {
             boolean progress = false;
 
-            Set<Node> newUnscheduled = new HashSet<Node>();
+            Set<Node> newUnscheduled = new HashSet<>();
             for (Node n : unscheduled) {
 
                 InputBlock block = null;
@@ -285,7 +297,7 @@
             }
         }
 
-        Set<Node> curReachable = new HashSet<Node>(reachable);
+        Set<Node> curReachable = new HashSet<>(reachable);
         for (Node n : curReachable) {
             if (n.block != null) {
                 for (Node s : n.succs) {
@@ -300,7 +312,7 @@
 
     private void markWithBlock(Node n, InputBlock b, Set<Node> reachable) {
         assert !reachable.contains(n);
-        Stack<Node> stack = new Stack<Node>();
+        Stack<Node> stack = new Stack<>();
         stack.push(n);
         n.block = b;
         b.addNode(n.inputNode.getId());
@@ -356,7 +368,7 @@
         if (ba == bb) {
             return ba;
         }
-        Set<InputBlock> visited = new HashSet<InputBlock>();
+        Set<InputBlock> visited = new HashSet<>();
         while (ba != null) {
             visited.add(ba);
             ba = dominatorMap.get(ba);
@@ -374,12 +386,12 @@
     }
 
     public void buildDominators() {
-        dominatorMap = new HashMap<InputBlock, InputBlock>();
+        dominatorMap = new HashMap<>(graph.getBlocks().size());
         if (blocks.size() == 0) {
             return;
         }
-        Vector<BlockIntermediate> intermediate = new Vector<BlockIntermediate>();
-        Map<InputBlock, BlockIntermediate> map = new HashMap<InputBlock, BlockIntermediate>();
+        Vector<BlockIntermediate> intermediate = new Vector<>(graph.getBlocks().size());
+        Map<InputBlock, BlockIntermediate> map = new HashMap<>(graph.getBlocks().size());
         int z = 0;
         for (InputBlock b : blocks) {
             BlockIntermediate bi = new BlockIntermediate();
@@ -390,16 +402,16 @@
             bi.parent = -1;
             bi.label = z;
             bi.ancestor = -1;
-            bi.pred = new ArrayList<Integer>();
-            bi.bucket = new ArrayList<Integer>();
+            bi.pred = new ArrayList<>();
+            bi.bucket = new ArrayList<>();
             intermediate.add(bi);
             map.put(b, bi);
             z++;
         }
-        Stack<Integer> stack = new Stack<Integer>();
+        Stack<Integer> stack = new Stack<>();
         stack.add(0);
 
-        Vector<BlockIntermediate> array = new Vector<BlockIntermediate>();
+        Vector<BlockIntermediate> array = new Vector<>();
         intermediate.get(0).dominator = 0;
 
         int n = 0;
@@ -538,15 +550,30 @@
     }
 
     private Node findRoot() {
+        Node minNode = null;
+        Node alternativeRoot = null;
 
-        for (Node n : nodes) {
-            InputNode inputNode = n.inputNode;
-            if (inputNode.getProperties().get("name").equals("Root")) {
-                return n;
+        for (Node node : nodes) {
+            InputNode inputNode = node.inputNode;
+            String s = inputNode.getProperties().get("name");
+            if (s != null && s.equals("Root")) {
+                return node;
+            }
+
+            if (alternativeRoot == null && node.preds.isEmpty()) {
+                alternativeRoot = node;
+            }
+
+            if (minNode == null || node.inputNode.getId() < minNode.inputNode.getId()) {
+                minNode = node;
             }
         }
 
-        return null;
+        if (alternativeRoot != null) {
+            return alternativeRoot;
+        } else {
+            return minNode;
+        }
     }
 
     public void buildUpGraph() {
@@ -562,7 +589,7 @@
             inputNodeToNode.put(n, node);
         }
 
-        Map<Integer, List<InputEdge>> edgeMap = new HashMap<Integer, List<InputEdge>>();
+        Map<Integer, List<InputEdge>> edgeMap = new HashMap<>(graph.getEdges().size());
         for (InputEdge e : graph.getEdges()) {
 
             int to = e.getTo();
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,18 @@
 colorize("name", ".*", yellow);
 colorize("name", "Catch.*", blue);
-
 colorize("name", "Region|Loop|CountedLoop|Root", red);
 colorize("name", "CProj|IfFalse|IfTrue|JProj|CatchProj", magenta);
+colorize("name", "Con.*", orange);
+colorize("name", "Parm|Proj", lightGray);
+
+// Nodes with bci
+colorize("bci", "..*", magenta);
+
+// Line style
+var f = new ColorFilter("Line Style filter");
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "int:")), null, Color.BLUE, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "control")), null, Color.RED, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory")), null, Color.GREEN, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "tuple:")), null, Color.MAGENTA, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "bottom")), null, Color.LIGHT_GRAY, null));
+f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/combine.filter	Mon Dec 05 13:09:39 2016 -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("name", ".*"), new Properties.RegexpPropertyMatcher("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj")));
-f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", "Cmp.*"), new Properties.RegexpPropertyMatcher("name", "Bool")));
-f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/extendedColor.filter	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-colorize("name", "Con.*", orange);
-colorize("name", "Parm|Proj", lightGray);
-colorize("bci", "..*", magenta);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/linestyle.filter	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-var f = new ColorFilter("Line Style filter");
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "int:")), null, Color.BLUE, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "control")), null, Color.RED, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory")), null, Color.GREEN, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "tuple:")), null, Color.MAGENTA, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "bottom")), null, Color.LIGHT_GRAY, null));
-f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -20,5 +20,5 @@
     ), false
   )
 );
-f.addRule( new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher("name", "Phi|Store.")), false));
+f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher("name", "Phi|Store."))));
 f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/register.filter	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/register.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -1,4 +1,5 @@
+// Register coloring
 colorize("reg", "EAX", green);
 colorize("reg", "EFLAGS", gray);
 colorize("reg", "EBP", orange);
-colorize("reg", "ECX", cyan);
+colorize("reg", "ECX", cyan);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -1,1 +1,8 @@
-remove("dump_spec", "FramePtr|ReturnAdr|I_O"); 
\ No newline at end of file
+remove("dump_spec", "FramePtr|ReturnAdr|I_O"); 
+removeInputs("name", "Root");
+var f = new RemoveSelfLoopsFilter("Remove Self-Loops");
+f.apply(graph);
+removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5);
+removeInputs("name", "Unlock|Lock", 7);
+removeInputs("name", "Allocate", 7);
+removeInputs("name", "AllocateArray", 9);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeMemory.filter	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-
-//var f = new RemoveFilter("Remove Memory");
-//f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("dump_spec", "Memory")), false));
-//f.addRule(new RemoveFilter.RemoveRule(new AndSelector(new MatcherSelector(new Properties.StringPropertyMatcher("name", "Proj")), new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory"))), false));
-//f.apply(graph);
-
-remove("dump_spec", "Memory");
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeRootInputs.filter	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-removeInputs("name", "Root");
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSafepointInputs.filter	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5);
-removeInputs("name", "Unlock|Lock", 7);
-removeInputs("name", "Allocate", 7);
-removeInputs("name", "AllocateArray", 9);
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSelfLoops.filter	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-var f = new RemoveSelfLoopsFilter("Remove Self-Loops");
-f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/split.filter	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-split("name", "BoxLock");
-split("name", "(Con.*)|(loadCon.*)");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/structural.filter	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,6 @@
+var f = new CombineFilter("Combine Filter");
+f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", ".*"), new Properties.RegexpPropertyMatcher("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj")));
+f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", "Cmp.*"), new Properties.RegexpPropertyMatcher("name", "Bool")));
+f.apply(graph);
+split("name", "BoxLock");
+split("name", "(Con.*)|(loadCon.*)", "[dump_spec]");
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -2,60 +2,28 @@
 <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
 <filesystem>
       <folder name="Filters">
-        <file name="Basic Coloring" url="filters/color.filter">
-            <attr name="enabled" boolvalue="true"/>
-        </file>
-        <file name="Matcher Flags Coloring" url="filters/matchingFlags.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Basic Coloring"/>
-        </file>
-        <file name="Register Coloring" url="filters/register.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Matcher Flags Coloring"/>
+        <file name="C2 Basic Coloring" url="filters/color.filter">
+            <attr name="enabled" boolvalue="false"/>
         </file>
-        <file name="Extended Coloring" url="filters/extendedColor.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Register Coloring"/>
-        </file>
-        <file name="Line Coloring" url="filters/linestyle.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Extended Coloring"/>
+        <file name="C2 Matcher Flags Coloring" url="filters/matchingFlags.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Basic Coloring"/>
         </file>
-        <file name="Difference Coloring" url="filters/difference.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Line Coloring"/>
-        </file>
-        <file name="Only Control Flow" url="filters/onlyControlFlow.filter">
+        <file name="C2 Register Coloring" url="filters/register.filter">
             <attr name="enabled" boolvalue="false"/>
-            <attr name="after" stringvalue="Difference Coloring"/>
+            <attr name="after" stringvalue="C2 Matcher Flags Coloring"/>
         </file>
-        <file name="Remove FramePtr, I_O and Return Address" url="filters/remove.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Only Control Flow"/>
-        </file>
-        <file name="Remove Memory" url="filters/removeMemory.filter">
+        <file name="C2 Only Control Flow" url="filters/onlyControlFlow.filter">
             <attr name="enabled" boolvalue="false"/>
-            <attr name="after" stringvalue="Remove FramePtr, I_O and Return Address"/>
-        </file>
-        <file name="Remove Root Inputs" url="filters/removeRootInputs.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Memory"/>
+            <attr name="after" stringvalue="C2 Register Coloring"/>
         </file>
-        <file name="Remove Safepoint Inputs" url="filters/removeSafepointInputs.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Root Inputs"/>
-        </file>
-        <file name="Remove Self Loops" url="filters/removeSelfLoops.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Safepoint Inputs"/>
+        <file name="C2 Remove Filter" url="filters/remove.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Only Control Flow"/>
         </file>
-        <file name="Combine" url="filters/combine.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Self Loops"/>
+        <file name="C2 Structural" url="filters/structural.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Remove Filter"/>
         </file>
-        <file name="Split" url="filters/split.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Combine"/>
-        </file>
-    </folder>
+    </folder>	
 </filesystem>
--- a/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -12,7 +12,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -21,7 +21,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.5</specification-version>
+                        <specification-version>1.21.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -29,7 +29,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -37,7 +37,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,9 @@
     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_BINARY = "portBinary";
     public final static String PORT_DEFAULT = "4444";
+    public final static String PORT_BINARY_DEFAULT = "4445";
     public final static String DIRECTORY = "directory";
     public final static String DIRECTORY_DEFAULT = System.getProperty("user.dir");
 
--- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,8 +27,8 @@
 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;
-import org.openide.util.Utilities;
 
 /**
  *
@@ -38,17 +38,20 @@
 
     @Override
     public Icon getIcon() {
-        return new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/settings/settings.gif"));
+        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();
     }
--- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsPanelController.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsPanelController.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,40 +40,49 @@
     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);
     }
--- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -2,8 +2,10 @@
 <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
 <filesystem>
     <folder name="OptionsDialog">
-        <file name="Advanced.instance_hidden"/>
-        <file name="General.instance_hidden"/>
-        <file name="com-sun-hotspot-igv-settings-ViewOptionsCategory.instance"/>
+      <!-- <file name="Advanced.instance_hidden"/>
+        <file name="General.instance_hidden"/>-->
+        <file name="com-sun-hotspot-igv-settings-ViewOptionsCategory.instance">
+            <attr name="position" intvalue="100" />
+        </file>
     </folder>
 </filesystem>
Binary file src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/settings.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/settings.png has changed
--- a/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -19,7 +19,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>2.9</specification-version>
+                        <specification-version>2.27.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.39.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -27,7 +35,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -35,7 +43,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/BoundedZoomAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/BoundedZoomAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ColorIcon.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ColorIcon.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,21 +34,26 @@
  */
 public class ColorIcon implements Icon {
 
-    private Color color;
+    private final Color color;
 
     public ColorIcon(Color c) {
         color = c;
     }
 
+    @Override
     public void paintIcon(Component c, Graphics g, int x, int y) {
+        Color oldColor = g.getColor();
         g.setColor(color);
         g.fillRect(x, y, 16, 16);
+        g.setColor(oldColor);
     }
 
+    @Override
     public int getIconWidth() {
         return 16;
     }
 
+    @Override
     public int getIconHeight() {
         return 16;
     }
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ContextAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ContextAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,7 @@
 package com.sun.hotspot.igv.util;
 
 import java.awt.EventQueue;
-import org.openide.util.ContextAwareAction;
-import org.openide.util.Lookup;
-import org.openide.util.LookupEvent;
-import org.openide.util.LookupListener;
-import org.openide.util.Utilities;
+import org.openide.util.*;
 import org.openide.util.actions.CallableSystemAction;
 
 /**
@@ -56,6 +52,7 @@
         resultChanged(null);
     }
 
+    @Override
     public void resultChanged(LookupEvent e) {
         if (result.allItems().size() != 0) {
             update(result.allInstances().iterator().next());
@@ -71,6 +68,7 @@
         // Ensure it's AWT event thread
         EventQueue.invokeLater(new Runnable() {
 
+            @Override
             public void run() {
                 performAction(t);
             }
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickHandler.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickHandler.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSatelliteComponent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSatelliteComponent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,10 @@
  */
 package com.sun.hotspot.igv.util;
 
-import org.netbeans.api.visual.widget.Scene;
-
-import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
+import javax.swing.JComponent;
+import org.netbeans.api.visual.widget.Scene;
 
 /**
  * @author David Kaspar
@@ -118,27 +117,34 @@
         }
     }
 
+    @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) {
     }
 
@@ -170,26 +176,33 @@
 
     }
 
+    @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) {
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSelectAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSelectAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/LookupHistory.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.openide.util.Lookup.Result;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author Thomas
+ */
+public class LookupHistory {
+
+    private static Map<Class, LookupHistoryImpl> cache = new HashMap<>();
+
+    private static class LookupHistoryImpl<T> implements LookupListener {
+
+        private Class<T> klass;
+        private Result<T> result;
+        private T last;
+
+        public LookupHistoryImpl(Class<T> klass) {
+            this.klass = klass;
+            result = Utilities.actionsGlobalContext().lookupResult(klass);
+            result.addLookupListener(this);
+            last = Utilities.actionsGlobalContext().lookup(klass);
+        }
+
+        public T getLast() {
+            return last;
+        }
+
+        @Override
+        public void resultChanged(LookupEvent ev) {
+            T current = Utilities.actionsGlobalContext().lookup(klass);
+            if (current != null) {
+                last = current;
+            }
+        }
+    }
+
+    public static <T> void init(Class<T> klass) {
+        if (!cache.containsKey(klass)) {
+            cache.put(klass, new LookupHistoryImpl<>(klass));
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T getLast(Class<T> klass) {
+        init(klass);
+        assert cache.containsKey(klass);
+        return (T) cache.get(klass).getLast();
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,33 +25,27 @@
 package com.sun.hotspot.igv.util;
 
 import com.sun.hotspot.igv.data.ChangedListener;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.Dimension;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
+import java.awt.*;
+import java.awt.geom.*;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.util.List;
-import javax.swing.JComponent;
+import javax.swing.*;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class RangeSlider extends JComponent implements ChangedListener<RangeSliderModel>, MouseListener, MouseMotionListener {
+public class RangeSlider extends JComponent implements ChangedListener<RangeSliderModel>, MouseListener, MouseMotionListener, Scrollable {
 
     public static final int HEIGHT = 40;
-    public static final int BAR_HEIGHT = 22;
-    public static final int BAR_SELECTION_ENDING_HEIGHT = 16;
-    public static final int BAR_SELECTION_HEIGHT = 10;
-    public static final int BAR_THICKNESS = 2;
-    public static final int BAR_CIRCLE_SIZE = 9;
+    public static final float BAR_HEIGHT = 22;
+    public static final float BAR_SELECTION_ENDING_HEIGHT = 16;
+    public static final float BAR_SELECTION_HEIGHT = 10;
+    public static final float BAR_THICKNESS = 2;
+    public static final float BAR_CIRCLE_SIZE = 9;
+    public static final float BAR_CIRCLE_CONNECTOR_SIZE = 6;
     public static final int MOUSE_ENDING_OFFSET = 3;
     public static final Color BACKGROUND_COLOR = Color.white;
     public static final Color BAR_COLOR = Color.black;
@@ -98,14 +92,61 @@
         return model;
     }
 
+    /**
+     * Returns the preferred size of the viewport for a view component.
+     * For example, the preferred size of a <code>JList</code> component
+     * is the size required to accommodate all of the cells in its list.
+     * However, the value of <code>preferredScrollableViewportSize</code>
+     * is the size required for <code>JList.getVisibleRowCount</code> rows.
+     * A component without any properties that would affect the viewport
+     * size should just return <code>getPreferredSize</code> here.
+     *
+     * @return the preferredSize of a <code>JViewport</code> whose view
+     *    is this <code>Scrollable</code>
+     * @see JViewport#getPreferredSize
+     */
+    public Dimension getPreferredScrollableViewportSize() {
+        return getPreferredSize();
+    }
+
+    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
+        if (orientation == SwingConstants.VERTICAL) {
+            return 1;
+        }
+
+        return (int)(BAR_CIRCLE_SIZE + BAR_CIRCLE_CONNECTOR_SIZE);
+    }
+
+    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
+        return orientation == SwingConstants.VERTICAL ? visibleRect.height / 2 : visibleRect.width / 2;
+    }
+
+    public boolean getScrollableTracksViewportWidth() {
+        return false;
+    }
+
+    public boolean getScrollableTracksViewportHeight() {
+        return true;
+    }
+
     @Override
     public Dimension getPreferredSize() {
         Dimension d = super.getPreferredSize();
         d.height = HEIGHT;
+        d.width = Math.max(d.width, (int)(2 * BAR_CIRCLE_CONNECTOR_SIZE + getPaintingModel().getPositions().size() * (BAR_CIRCLE_SIZE + BAR_CIRCLE_CONNECTOR_SIZE)));
         return d;
     }
 
+    @Override
     public void changed(RangeSliderModel source) {
+        revalidate();
+
+        float barStartY = getBarStartY();
+        int circleCenterY = (int)(barStartY + BAR_HEIGHT / 2);
+        int startX = (int)getStartXPosition(model.getFirstPosition());
+        int endX = (int)getEndXPosition(model.getSecondPosition());
+        Rectangle r = new Rectangle(startX, circleCenterY, endX - startX, 1);
+        scrollRectToVisible(r);
         update();
     }
 
@@ -113,22 +154,22 @@
         this.repaint();
     }
 
-    private int getXPosition(int index) {
+    private float getXPosition(int index) {
         assert index >= 0 && index < getPaintingModel().getPositions().size();
         return getXOffset() * (index + 1);
     }
 
-    private int getXOffset() {
+    private float getXOffset() {
         int size = getPaintingModel().getPositions().size();
-        int width = getWidth();
+        float width = (float)getWidth();
         return (width / (size + 1));
     }
 
-    private int getEndXPosition(int index) {
+    private float getEndXPosition(int index) {
         return getXPosition(index) + getXOffset() / 2;
     }
 
-    private int getStartXPosition(int index) {
+    private float getStartXPosition(int index) {
         return getXPosition(index) - getXOffset() / 2;
     }
 
@@ -142,7 +183,7 @@
         int height = getHeight();
 
         g2.setColor(BACKGROUND_COLOR);
-        g2.fillRect(0, 0, width, height);
+        g2.fill(new Rectangle2D.Float(0, 0, width, height));
 
         // Nothing to paint?
         if (getPaintingModel() == null || getPaintingModel().getPositions().size() == 0) {
@@ -157,30 +198,30 @@
 
     }
 
-    private int getBarStartY() {
-        return getHeight() - BAR_HEIGHT;
+    private float getBarStartY() {
+        return getHeight() / 2 - BAR_HEIGHT / 2;
     }
 
     private void paintBar(Graphics2D g) {
         List<String> list = getPaintingModel().getPositions();
-        int barStartY = getBarStartY();
+        float barStartY = getBarStartY();
 
         g.setColor(BAR_COLOR);
-        g.fillRect(getXPosition(0), barStartY + BAR_HEIGHT / 2 - BAR_THICKNESS / 2, getXPosition(list.size() - 1) - getXPosition(0), BAR_THICKNESS);
+        g.fill(new Rectangle2D.Float(getXPosition(0), barStartY + BAR_HEIGHT / 2 - BAR_THICKNESS / 2, getXPosition(list.size() - 1) - getXPosition(0), BAR_THICKNESS));
 
-        int circleCenterY = barStartY + BAR_HEIGHT / 2;
+        float circleCenterY = barStartY + BAR_HEIGHT / 2;
         for (int i = 0; i < list.size(); i++) {
-            int curX = getXPosition(i);
+            float curX = getXPosition(i);
             g.setColor(getPaintingModel().getColors().get(i));
-            g.fillOval(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE);
+            g.fill(new Ellipse2D.Float(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE));
             g.setColor(Color.black);
-            g.drawOval(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE);
+            g.draw(new Ellipse2D.Float(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE));
 
 
             String curS = list.get(i);
             if (curS != null && curS.length() > 0) {
-                int startX = getStartXPosition(i);
-                int endX = getEndXPosition(i);
+                float startX = getStartXPosition(i);
+                float endX = getEndXPosition(i);
                 FontMetrics metrics = g.getFontMetrics();
                 Rectangle bounds = metrics.getStringBounds(curS, g).getBounds();
                 if (bounds.width < endX - startX && bounds.height < barStartY) {
@@ -194,10 +235,10 @@
 
     private void paintSelected(Graphics2D g, int start, int end) {
 
-        int startX = getStartXPosition(start);
-        int endX = getEndXPosition(end);
-        int barStartY = getBarStartY();
-        int barSelectionEndingStartY = barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_ENDING_HEIGHT / 2;
+        float startX = getStartXPosition(start);
+        float endX = getEndXPosition(end);
+        float barStartY = getBarStartY();
+        float barSelectionEndingStartY = barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_ENDING_HEIGHT / 2;
         paintSelectedEnding(g, startX, barSelectionEndingStartY);
         paintSelectedEnding(g, endX, barSelectionEndingStartY);
 
@@ -207,18 +248,18 @@
         } else if (isOverBar) {
             g.setColor(BAR_SELECTION_COLOR_ROLLOVER);
         }
-        g.fillRect(startX, barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_HEIGHT / 2, endX - startX, BAR_SELECTION_HEIGHT);
+        g.fill(new Rectangle2D.Float(startX, barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_HEIGHT / 2, endX - startX, BAR_SELECTION_HEIGHT));
     }
 
-    private void paintSelectedEnding(Graphics g, int x, int y) {
+    private void paintSelectedEnding(Graphics2D g, float x, float y) {
         g.setColor(BAR_COLOR);
-        g.fillRect(x - BAR_THICKNESS / 2, y, BAR_THICKNESS, BAR_SELECTION_ENDING_HEIGHT);
+        g.fill(new Rectangle2D.Float(x - BAR_THICKNESS / 2, y, BAR_THICKNESS, BAR_SELECTION_ENDING_HEIGHT));
     }
 
     private boolean isOverSecondPosition(Point p) {
         if (p.y >= getBarStartY()) {
-            int destX = getEndXPosition(getPaintingModel().getSecondPosition());
-            int off = Math.abs(destX - p.x);
+            float destX = getEndXPosition(getPaintingModel().getSecondPosition());
+            float off = Math.abs(destX - p.x);
             return off <= MOUSE_ENDING_OFFSET;
         }
         return false;
@@ -226,8 +267,8 @@
 
     private boolean isOverFirstPosition(Point p) {
         if (p.y >= getBarStartY()) {
-            int destX = getStartXPosition(getPaintingModel().getFirstPosition());
-            int off = Math.abs(destX - p.x);
+            float destX = getStartXPosition(getPaintingModel().getFirstPosition());
+            float off = Math.abs(destX - p.x);
             return off <= MOUSE_ENDING_OFFSET;
         }
         return false;
@@ -240,10 +281,14 @@
         return false;
     }
 
+    @Override
     public void mouseDragged(MouseEvent e) {
+        Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
+        scrollRectToVisible(r);
+
         if (state == State.DragBar) {
-            int firstX = this.getStartXPosition(model.getFirstPosition());
-            int newFirstX = firstX + e.getPoint().x - startPoint.x;
+            float firstX = this.getStartXPosition(model.getFirstPosition());
+            float newFirstX = firstX + e.getPoint().x - startPoint.x;
             int newIndex = getIndexFromPosition(newFirstX) + 1;
             if (newIndex + model.getSecondPosition() - model.getFirstPosition() >= model.getPositions().size()) {
                 newIndex = model.getPositions().size() - (model.getSecondPosition() - model.getFirstPosition()) - 1;
@@ -270,13 +315,13 @@
         }
     }
 
-    private int getIndexFromPosition(int x) {
+    private int getIndexFromPosition(float x) {
         if (x < getXPosition(0)) {
             return -1;
         }
         for (int i = 0; i < getPaintingModel().getPositions().size() - 1; i++) {
-            int startX = getXPosition(i);
-            int endX = getXPosition(i + 1);
+            float startX = getXPosition(i);
+            float endX = getXPosition(i + 1);
             if (x >= startX && x <= endX) {
                 return i;
             }
@@ -286,7 +331,7 @@
 
     private int getCircleIndexFromPosition(int x) {
         int result = 0;
-        for (int i = 1; i < getPaintingModel().getPositions().size() - 1; i++) {
+        for (int i = 1; i < getPaintingModel().getPositions().size(); i++) {
             if (x > getStartXPosition(i)) {
                 result = i;
             }
@@ -294,6 +339,7 @@
         return result;
     }
 
+    @Override
     public void mouseMoved(MouseEvent e) {
         isOverBar = false;
         if (model == null) {
@@ -313,6 +359,7 @@
         repaint();
     }
 
+    @Override
     public void mouseClicked(MouseEvent e) {
         if (e.getClickCount() > 1) {
             // Double click
@@ -321,6 +368,7 @@
         }
     }
 
+    @Override
     public void mousePressed(MouseEvent e) {
         if (model == null) {
             return;
@@ -341,6 +389,7 @@
         tempModel = model.copy();
     }
 
+    @Override
     public void mouseReleased(MouseEvent e) {
         if (model == null || tempModel == null) {
             return;
@@ -350,9 +399,11 @@
         tempModel = null;
     }
 
+    @Override
     public void mouseEntered(MouseEvent e) {
     }
 
+    @Override
     public void mouseExited(MouseEvent e) {
         isOverBar = false;
         repaint();
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,8 @@
  */
 package com.sun.hotspot.igv.util;
 
+import com.sun.hotspot.igv.data.ChangedEvent;
 import com.sun.hotspot.igv.data.ChangedEventProvider;
-import com.sun.hotspot.igv.data.ChangedEvent;
 import java.awt.Color;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -65,17 +65,19 @@
 
     public RangeSliderModel(List<String> positions) {
         assert positions.size() > 0;
-        this.changedEvent = new ChangedEvent<RangeSliderModel>(this);
-        this.colorChangedEvent = new ChangedEvent<RangeSliderModel>(this);
+        this.changedEvent = new ChangedEvent<>(this);
+        this.colorChangedEvent = new ChangedEvent<>(this);
         setPositions(positions);
     }
 
     protected void setPositions(List<String> positions) {
         this.positions = positions;
-        colors = new ArrayList<Color>();
+        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();
         colorChangedEvent.fire();
     }
@@ -91,9 +93,7 @@
 
     public RangeSliderModel copy() {
         RangeSliderModel newModel = new RangeSliderModel(positions);
-        newModel.firstPosition = firstPosition;
-        newModel.secondPosition = secondPosition;
-        newModel.colors = colors;
+        newModel.setData(this);
         return newModel;
     }
 
@@ -130,6 +130,7 @@
         return colorChangedEvent;
     }
 
+    @Override
     public ChangedEvent<RangeSliderModel> getChangedEvent() {
         return changedEvent;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/StringUtils.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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;
+
+/**
+ *
+ * @author tkrodrig
+ */
+public class StringUtils {
+
+    public static String escapeHTML(String s) {
+        StringBuilder str = null;
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            switch (c) {
+                case '&':
+                case '<':
+                case '>':
+                case '"':
+                case '\'':
+                    if (str == null) {
+                        str = new StringBuilder();
+                        str.append(s, 0, i);
+                    }
+                    switch (c) {
+                        case '&':
+                            str.append("&amp;");
+                            break;
+                        case '<':
+                            str.append("&lt;");
+                            break;
+                        case '>':
+                            str.append("&gt;");
+                            break;
+                        case '"':
+                            str.append("&quot;");
+                            break;
+                        case '\'':
+                            str.append("&apos;");
+                            break;
+                        default:
+                            assert false;
+                    }
+                    break;
+                case '\u0000':
+                case '\u0001':
+                case '\u0002':
+                case '\u0003':
+                case '\u0004':
+                case '\u0005':
+                case '\u0006':
+                case '\u0007':
+                case '\u0008':
+                case '\u000b':
+                case '\u000c':
+                case '\u000e':
+                case '\u000f':
+                case '\u0010':
+                case '\u0011':
+                case '\u0012':
+                case '\u0013':
+                case '\u0014':
+                case '\u0015':
+                case '\u0016':
+                case '\u0017':
+                case '\u0018':
+                case '\u0019':
+                case '\u001a':
+                case '\u001b':
+                case '\u001c':
+                case '\u001d':
+                case '\u001e':
+                case '\u001f':
+                    if (str == null) {
+                        str = new StringBuilder();
+                        str.append(s, 0, i);
+                    }
+                    str.append("'0x").append(Integer.toHexString(c));
+                    break;
+                default:
+                    if (str != null) {
+                        str.append(c);
+                    }
+                    break;
+            }
+        }
+        if (str == null) {
+            return s;
+        } else {
+            return str.toString();
+        }
+    }
+
+}
--- a/src/share/tools/IdealGraphVisualizer/View/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/src/share/tools/IdealGraphVisualizer/View/nbproject/project.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/nbproject/project.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -55,6 +55,14 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.selectioncoordinator</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>com.sun.hotspot.igv.settings</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
@@ -83,7 +91,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>2.9</specification-version>
+                        <specification-version>2.27.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.spi.quicksearch</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -91,7 +107,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.6.0.1</specification-version>
+                        <specification-version>6.21.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -99,7 +115,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -107,7 +123,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -115,7 +131,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.7</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -123,7 +139,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -131,7 +147,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -139,7 +163,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/View/src/META-INF/services/com.sun.hotspot.igv.data.services.InputGraphProvider	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.view.EditorInputGraphProvider
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/BoundedZoomAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/BoundedZoomAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,3 +1,3 @@
-HINT_EditorTopComponent=This is a Editor window
-OpenIDE-Module-Name=View
-CTL_EditorTopComponent=Editor Window
+HINT_EditorTopComponent=Visualizes a graph.
+OpenIDE-Module-Name=View
+CTL_EditorTopComponent=Graph
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ConnectionAnchor.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +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;
-
-import com.sun.hotspot.igv.view.widgets.SlotWidget;
-import java.awt.Point;
-import java.awt.Rectangle;
-import org.netbeans.api.visual.anchor.Anchor;
-import org.netbeans.api.visual.anchor.Anchor.Entry;
-import org.netbeans.api.visual.anchor.Anchor.Result;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class ConnectionAnchor extends Anchor {
-
-    public enum HorizontalAlignment {
-
-        Left,
-        Center,
-        Right
-    }
-    private HorizontalAlignment alignment;
-
-    public ConnectionAnchor(Widget widget) {
-        this(HorizontalAlignment.Center, widget);
-    }
-
-    public ConnectionAnchor(HorizontalAlignment alignment, Widget widget) {
-        super(widget);
-        this.alignment = alignment;
-    }
-
-    public Result compute(Entry entry) {
-        return new Result(getRelatedSceneLocation(), Anchor.DIRECTION_ANY);
-    }
-
-    @Override
-    public Point getRelatedSceneLocation() {
-        Point p = null;
-        Widget w = getRelatedWidget();
-        if (w != null) {
-            if (w instanceof SlotWidget) {
-                p = ((SlotWidget) w).getAnchorPosition();
-            } else {
-                Rectangle r = w.convertLocalToScene(w.getBounds());
-                int y = r.y + r.height / 2;
-                int x = r.x;
-                if (alignment == HorizontalAlignment.Center) {
-                    x = r.x + r.width / 2;
-                } else if (alignment == HorizontalAlignment.Right) {
-                    x = r.x + r.width;
-                }
-
-                p = new Point(x, y);
-            }
-        }
-
-        return p;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,77 +23,42 @@
  */
 package com.sun.hotspot.igv.view;
 
-import com.sun.hotspot.igv.view.widgets.BlockWidget;
-import com.sun.hotspot.igv.view.widgets.LineWidget;
-import com.sun.hotspot.igv.util.DoubleClickAction;
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.data.ControllableChangedListener;
 import com.sun.hotspot.igv.data.InputBlock;
 import com.sun.hotspot.igv.data.InputNode;
-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 com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Slot;
+import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.services.Scheduler;
+import com.sun.hotspot.igv.graph.*;
 import com.sun.hotspot.igv.hierarchicallayout.HierarchicalClusterLayoutManager;
-import com.sun.hotspot.igv.hierarchicallayout.OldHierarchicalLayoutManager;
 import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
-import com.sun.hotspot.igv.view.widgets.FigureWidget;
-import com.sun.hotspot.igv.view.widgets.InputSlotWidget;
-import com.sun.hotspot.igv.view.widgets.OutputSlotWidget;
-import com.sun.hotspot.igv.view.widgets.SlotWidget;
 import com.sun.hotspot.igv.layout.LayoutGraph;
-import com.sun.hotspot.igv.data.services.Scheduler;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.graph.Block;
+import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
 import com.sun.hotspot.igv.util.ColorIcon;
-import com.sun.hotspot.igv.util.ExtendedSelectAction;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.event.ActionEvent;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-import java.awt.event.MouseWheelEvent;
-import java.awt.event.MouseWheelListener;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.HashMap;
+import com.sun.hotspot.igv.util.DoubleClickAction;
+import com.sun.hotspot.igv.util.PropertiesSheet;
+import com.sun.hotspot.igv.view.actions.CustomizablePanAction;
+import com.sun.hotspot.igv.view.widgets.*;
+import java.awt.*;
+import java.awt.event.*;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-import javax.swing.BorderFactory;
-import javax.swing.JComponent;
-import javax.swing.JPopupMenu;
-import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
+import java.util.*;
+import javax.swing.*;
 import javax.swing.event.UndoableEditEvent;
 import javax.swing.undo.AbstractUndoableEdit;
 import javax.swing.undo.CannotRedoException;
 import javax.swing.undo.CannotUndoException;
-import org.netbeans.api.visual.action.ActionFactory;
-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.SelectProvider;
-import org.netbeans.api.visual.action.WidgetAction;
+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.widget.ConnectionWidget;
+import org.netbeans.api.visual.model.*;
 import org.netbeans.api.visual.widget.LayerWidget;
-import org.netbeans.api.visual.widget.Scene;
 import org.netbeans.api.visual.widget.Widget;
-import org.netbeans.api.visual.widget.LabelWidget;
 import org.openide.awt.UndoRedo;
+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;
@@ -102,54 +67,58 @@
  *
  * @author Thomas Wuerthinger
  */
-public class DiagramScene extends Scene implements ChangedListener<DiagramViewModel> {
+public class DiagramScene extends ObjectScene implements DiagramViewer {
 
-    private HashMap<Figure, FigureWidget> figureWidgets;
-    private HashMap<Slot, SlotWidget> slotWidgets;
-    private HashMap<Connection, ConnectionWidget> connectionWidgets;
-    private HashMap<InputBlock, BlockWidget> blockWidgets;
-    private Widget hoverWidget;
+    private CustomizablePanAction panAction;
     private WidgetAction hoverAction;
-    private List<FigureWidget> selectedWidgets;
+    private WidgetAction selectAction;
     private Lookup lookup;
     private InstanceContent content;
     private Action[] actions;
+    private Action[] actionsWithSelection;
     private LayerWidget connectionLayer;
     private JScrollPane scrollPane;
     private UndoRedo.Manager undoRedoManager;
     private LayerWidget mainLayer;
-    private LayerWidget slotLayer;
     private LayerWidget blockLayer;
-    private double realZoomFactor;
-    private BoundedZoomAction zoomAction;
-    private WidgetAction panAction;
     private Widget topLeft;
     private Widget bottomRight;
-    private LayerWidget startLayer;
-    private LabelWidget startLabel;
     private DiagramViewModel model;
     private DiagramViewModel modelCopy;
-    public static final int AFTER = 1;
-    public static final int BEFORE = 1;
+    private WidgetAction zoomAction;
+    private boolean rebuilding;
+
+    /**
+     * The alpha level of partially visible figures.
+     */
     public static final float ALPHA = 0.4f;
-    public static final int GRID_SIZE = 30;
+
+    /**
+     * 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 SLOT_OFFSET = 8;
     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));
@@ -157,8 +126,98 @@
             return widget;
         }
     };
+
+    @SuppressWarnings("unchecked")
+    public <T> T getWidget(Object o) {
+        Widget w = this.findWidget(o);
+        return (T) w;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T getWidget(Object o, Class<T> klass) {
+        Widget w = this.findWidget(o);
+        return (T) w;
+    }
+
+    private static boolean intersects(Set<? extends Object> s1, Set<? extends Object> s2) {
+        for (Object o : s1) {
+            if (s2.contains(o)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    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)));
+        }
+    }
+
+    @Override
+    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)));
+        }
+    }
+
+
+    @Override
+    public void centerFigures(List<Figure> list) {
+
+        boolean b = getUndoRedoEnabled();
+        setUndoRedoEnabled(false);
+        gotoFigures(list);
+        setUndoRedoEnabled(b);
+    }
+
+    private Set<Object> getObjectsFromIdSet(Set<Object> set) {
+        Set<Object> selectedObjects = new HashSet<>();
+        for (Figure f : getModel().getDiagramToView().getFigures()) {
+            if (intersects(f.getSource().getSourceNodesAsSet(), set)) {
+                selectedObjects.add(f);
+            }
+
+            for (Slot s : f.getSlots()) {
+                if (intersects(s.getSource().getSourceNodesAsSet(), set)) {
+                    selectedObjects.add(s);
+                }
+            }
+        }
+        return selectedObjects;
+    }
+    private ControllableChangedListener<SelectionCoordinator> highlightedCoordinatorListener = new ControllableChangedListener<SelectionCoordinator>() {
+
+        @Override
+        public void filteredChanged(SelectionCoordinator source) {
+            DiagramScene.this.setHighlightedObjects(getObjectsFromIdSet(source.getHighlightedObjects()));
+            DiagramScene.this.validate();
+        }
+    };
+    private ControllableChangedListener<SelectionCoordinator> selectedCoordinatorListener = new ControllableChangedListener<SelectionCoordinator>() {
+
+        @Override
+        public void filteredChanged(SelectionCoordinator source) {
+            DiagramScene.this.gotoSelection(source.getSelectedObjects());
+            DiagramScene.this.validate();
+        }
+    };
+
     private RectangularSelectProvider rectangularSelectProvider = new RectangularSelectProvider() {
 
+        @Override
         public void performSelection(Rectangle rectangle) {
             if (rectangle.width < 0) {
                 rectangle.x += rectangle.width;
@@ -170,168 +229,44 @@
                 rectangle.height *= -1;
             }
 
-            boolean updated = false;
+            Set<Object> selectedObjects = new HashSet<>();
             for (Figure f : getModel().getDiagramToView().getFigures()) {
-                FigureWidget w = figureWidgets.get(f);
-                Rectangle r = new Rectangle(w.getBounds());
-                r.setLocation(w.getLocation());
-                if (r.intersects(rectangle)) {
-                    if (!selectedWidgets.contains(w)) {
-                        addToSelection(w);
-                        updated = true;
+                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 {
-                    if (selectedWidgets.contains(w)) {
-                        selectedWidgets.remove(w);
-                        content.remove(w.getNode());
-                        w.setState(w.getState().deriveSelected(false));
-                        updated = true;
-                    }
-                }
-            }
-
-            if (updated) {
-                selectionUpdated();
-            }
-        }
-    };
-    private SelectProvider selectProvider = new SelectProvider() {
-
-        public boolean isAimingAllowed(Widget widget, Point point, boolean b) {
-            return false;
-        }
-
-        public boolean isSelectionAllowed(Widget widget, Point point, boolean b) {
-            return widget instanceof FigureWidget || widget == DiagramScene.this;
-        }
-
-        public void select(Widget w, Point point, boolean change) {
-
-            boolean updated = false;
-
-            if (w == DiagramScene.this) {
-                if (DiagramScene.this.selectedWidgets.size() != 0) {
-                    clearSelection();
-                    selectionUpdated();
-                }
-                return;
-            }
-
-            FigureWidget widget = (FigureWidget) w;
-
-
-            if (change) {
-                if (widget.getState().isSelected()) {
-                    assert selectedWidgets.contains(widget);
-                    widget.setState(widget.getState().deriveSelected(false));
-                    selectedWidgets.remove(widget);
-                    content.remove(widget.getNode());
-                    updated = true;
-                } else {
-                    assert !selectedWidgets.contains(widget);
-                    addToSelection(widget);
-                    updated = true;
-                    assert widget.getState().isSelected();
-                }
-            } else {
-
-                if (widget.getState().isSelected()) {
-                    assert selectedWidgets.contains(widget);
-                } else {
-
-                    assert !selectedWidgets.contains(widget);
-                    clearSelection();
-                    addToSelection(widget);
-                    updated = true;
-                    assert widget.getState().isSelected();
+                    assert false : "w should not be null here!";
                 }
             }
 
-            if (updated) {
-                selectionUpdated();
-            }
-
+            setSelectedObjects(selectedObjects);
         }
     };
 
-    private FigureWidget getFigureWidget(Figure f) {
-        return figureWidgets.get(f);
-    }
-    private FocusListener focusListener = new FocusListener() {
-
-        public void focusGained(FocusEvent e) {
-            DiagramScene.this.getView().requestFocus();
-        }
-
-        public void focusLost(FocusEvent e) {
-        }
-    };
     private MouseWheelListener mouseWheelListener = new MouseWheelListener() {
 
+        @Override
         public void mouseWheelMoved(MouseWheelEvent e) {
-            DiagramScene.this.zoomAction.mouseWheelMoved(DiagramScene.this, new WidgetAction.WidgetMouseWheelEvent(0, e));
-            DiagramScene.this.validate();
+            if (e.isControlDown()) {
+                DiagramScene.this.relayoutWithoutLayout(null);
+            }
         }
     };
-    private MouseListener mouseListener = new MouseListener() {
-
-        public void mouseClicked(MouseEvent e) {
-            DiagramScene.this.panAction.mouseClicked(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mousePressed(MouseEvent e) {
-            DiagramScene.this.panAction.mousePressed(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseReleased(MouseEvent e) {
-            DiagramScene.this.panAction.mouseReleased(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseEntered(MouseEvent e) {
-            DiagramScene.this.panAction.mouseEntered(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseExited(MouseEvent e) {
-            DiagramScene.this.panAction.mouseExited(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-    };
-    private MouseMotionListener mouseMotionListener = new MouseMotionListener() {
-
-        public void mouseDragged(MouseEvent e) {
-            DiagramScene.this.panAction.mouseDragged(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseMoved(MouseEvent e) {
-        }
-    };
-    private ScrollChangeListener scrollChangeListener = new ScrollChangeListener();
-
-    private class ScrollChangeListener implements ChangeListener {
-
-        private Map<Widget, Point> relativePositions = new HashMap<Widget, Point>();
-        private Point oldPosition;
-
-        public void register(Widget w, Point p) {
-            relativePositions.put(w, p);
-        }
-
-        public void unregister(Widget w) {
-            relativePositions.remove(w);
-        }
-
-        public void stateChanged(ChangeEvent e) {
-            Point p = DiagramScene.this.getScrollPane().getViewport().getViewPosition();
-            if (oldPosition == null || !p.equals(oldPosition)) {
-                for (Widget w : relativePositions.keySet()) {
-                    Point curPoint = relativePositions.get(w);
-                    Point newPoint = new Point(p.x + curPoint.x, p.y + curPoint.y);
-                    w.setPreferredLocation(newPoint);
-                    DiagramScene.this.validate();
-                }
-                oldPosition = p;
-            }
-        }
-    }
 
     public Point getScrollPosition() {
         return getScrollPane().getViewport().getViewPosition();
@@ -341,42 +276,138 @@
         getScrollPane().getViewport().setViewPosition(p);
     }
 
-    public DiagramScene(Action[] actions, DiagramViewModel model) {
-        this.actions = actions;
-        selectedWidgets = new ArrayList<FigureWidget>();
-        content = new InstanceContent();
-        lookup = new AbstractLookup(content);
-        this.setCheckClipping(true);
-        this.getInputBindings().setZoomActionModifiers(0);
-
+    private JScrollPane createScrollPane() {
         JComponent comp = this.createView();
         comp.setDoubleBuffered(true);
         comp.setBackground(Color.WHITE);
         comp.setOpaque(true);
-
         this.setBackground(Color.WHITE);
         this.setOpaque(true);
-        scrollPane = new JScrollPane(comp);
-        scrollPane.setBackground(Color.WHITE);
-        scrollPane.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
-        scrollPane.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
-        scrollPane.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
-        scrollPane.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
-        scrollPane.getViewport().addChangeListener(scrollChangeListener);
-        hoverAction = this.createWidgetHoverAction();
+        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<Object> oldSet, Set<Object> newSet) {
+            DiagramScene scene = (DiagramScene) e.getObjectScene();
+            if (scene.isRebuilding()) {
+                return;
+            }
+
+            content.set(newSet, null);
+
+            Set<Integer> 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);
+
+            boolean b = selectedCoordinatorListener.isEnabled();
+            selectedCoordinatorListener.setEnabled(false);
+            SelectionCoordinator.getInstance().setSelectedObjects(nodeSelection);
+            selectedCoordinatorListener.setEnabled(b);
+
+        }
+
+        @Override
+        public void highlightingChanged(ObjectSceneEvent e, Set<Object> oldSet, Set<Object> newSet) {
+            Set<Integer> 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(true);
+        }
+
+        @Override
+        public void hoverChanged(ObjectSceneEvent e, Object oldObject, Object newObject) {
+            Set<Object> 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 DiagramScene(Action[] actions, Action[] actionsWithSelection, DiagramViewModel model) {
+
+        this.actions = actions;
+        this.actionsWithSelection = actionsWithSelection;
+
+        content = new InstanceContent();
+        lookup = new AbstractLookup(content);
+
+        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 CustomizablePanAction(~0, MouseEvent.BUTTON1_DOWN_MASK);
+        this.getActions().addAction(panAction);
+
+        selectAction = createSelectAction();
+        this.getActions().addAction(selectAction);
 
         blockLayer = new LayerWidget(this);
         this.addChild(blockLayer);
 
-        startLayer = new LayerWidget(this);
-        this.addChild(startLayer);
-        // TODO: String startLabelString = "Loading graph with " + originalDiagram.getFigures().size() + " figures and " + originalDiagram.getConnections().size() + " connections...";
-        String startLabelString = "";
-        LabelWidget w = new LabelWidget(this, startLabelString);
-        scrollChangeListener.register(w, new Point(10, 10));
-        w.setAlignment(LabelWidget.Alignment.CENTER);
-        startLabel = w;
-        startLayer.addChild(w);
+        connectionLayer = new LayerWidget(this);
+        this.addChild(connectionLayer);
 
         mainLayer = new LayerWidget(this);
         this.addChild(mainLayer);
@@ -385,83 +416,53 @@
         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);
 
-        slotLayer = new LayerWidget(this);
-        this.addChild(slotLayer);
-
-        connectionLayer = new LayerWidget(this);
-        this.addChild(connectionLayer);
-
         LayerWidget selectionLayer = new LayerWidget(this);
         this.addChild(selectionLayer);
 
         this.setLayout(LayoutFactory.createAbsoluteLayout());
 
-        this.getActions().addAction(hoverAction);
-        zoomAction = new BoundedZoomAction(1.1, false);
-        zoomAction.setMaxFactor(ZOOM_MAX_FACTOR);
-        zoomAction.setMinFactor(ZOOM_MIN_FACTOR);
-        this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
-        panAction = new ExtendedPanAction();
-        this.getActions().addAction(panAction);
+        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));
 
-        blockWidgets = new HashMap<InputBlock, BlockWidget>();
-
         boolean b = this.getUndoRedoEnabled();
         this.setUndoRedoEnabled(false);
         this.setNewModel(model);
         this.setUndoRedoEnabled(b);
-    }
-
-    private void selectionUpdated() {
-        getModel().setSelectedNodes(this.getSelectedNodes());
-        addUndo();
+        this.addObjectSceneListener(selectionChangedListener, ObjectSceneEventType.OBJECT_SELECTION_CHANGED, ObjectSceneEventType.OBJECT_HIGHLIGHTING_CHANGED, ObjectSceneEventType.OBJECT_HOVER_CHANGED);
     }
 
     public DiagramViewModel getModel() {
         return model;
     }
 
-    public void setRealZoomFactor(double d) {
-        this.realZoomFactor = d;
-    }
-
-    public double getRealZoomFactor() {
-        if (realZoomFactor == 0.0) {
-            return getZoomFactor();
-        } else {
-            return realZoomFactor;
-        }
-    }
-
     public JScrollPane getScrollPane() {
         return scrollPane;
     }
 
+    @Override
+    public Component getComponent() {
+        return scrollPane;
+    }
+
     public boolean isAllVisible() {
-        return getModel().getHiddenNodes().size() == 0;
+        return getModel().getHiddenNodes().isEmpty();
     }
 
     public Action createGotoAction(final Figure f) {
         final DiagramScene diagramScene = this;
-        Action a = new AbstractAction() {
-
-            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 += " (";
@@ -469,112 +470,81 @@
         if (f.getCluster() != null) {
             name += "B" + f.getCluster().toString();
         }
-        if (!this.getFigureWidget(f).isVisible()) {
+        final boolean hidden = !this.getWidget(f, FigureWidget.class).isVisible();
+        if (hidden) {
             if (f.getCluster() != null) {
                 name += ", ";
             }
             name += "hidden";
         }
         name += ")";
-        a.putValue(Action.NAME, name);
+        Action a = new AbstractAction(name, new ColorIcon(f.getColor())) {
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                diagramScene.gotoFigure(f);
+            }
+        };
+
+        a.setEnabled(true);
         return a;
     }
 
     public void setNewModel(DiagramViewModel model) {
-        if (this.model != null) {
-            this.model.getDiagramChangedEvent().removeListener(this);
-            this.model.getViewPropertiesChangedEvent().removeListener(this);
-        }
+        assert this.model == null : "can set model only once!";
         this.model = model;
+        this.modelCopy = null;
 
-        if (this.model == null) {
-            this.modelCopy = null;
-        } else {
-            this.modelCopy = this.model.copy();
-        }
-
-        model.getDiagramChangedEvent().addListener(this);
-        model.getViewPropertiesChangedEvent().addListener(this);
-
+        model.getDiagramChangedEvent().addListener(fullChange);
+        model.getViewPropertiesChangedEvent().addListener(fullChange);
+        model.getViewChangedEvent().addListener(selectionChange);
+        model.getHiddenNodesChangedEvent().addListener(hiddenNodesChange);
         update();
     }
 
     private void update() {
-
-        /*if (startLabel != null) {
-        // Animate fade-out
-        final LabelWidget labelWidget = this.startLabel;
-        labelWidget.setVisible(true);
-        RequestProcessor.getDefault().post(new Runnable() {
-        public void run() {
-        final int Sleep = 200;
-        final int Progress = 10;
-        for (int i = 0; i < 255 / Progress + 1; i++) {
-        try {
-        SwingUtilities.invokeAndWait(new Runnable() {
-        public void run() {
-        Color c = labelWidget.getForeground();
-        int v = c.getRed();
-        v += Progress;
-        if (v > 255) {
-        v = 255;
-        }
-        labelWidget.setForeground(new Color(v, v, v, 255 - v));
-        labelWidget.getScene().validate();
-        }
-        });
-        } catch (InterruptedException ex) {
-        } catch (InvocationTargetException ex) {
-        }
-        try {
-        Thread.sleep(Sleep);
-        } catch (InterruptedException ex) {
-        }
-        }
-        labelWidget.setVisible(false);
-        DiagramScene.this.scrollChangeListener.unregister(labelWidget);
-        }
-        }, 1000);
-        startLabel = null;
-        }*/
-
-        slotLayer.removeChildren();
         mainLayer.removeChildren();
         blockLayer.removeChildren();
 
-        blockWidgets.clear();
-        figureWidgets = new HashMap<Figure, FigureWidget>();
-        slotWidgets = new HashMap<Slot, SlotWidget>();
-        connectionWidgets = new HashMap<Connection, ConnectionWidget>();
+        rebuilding = true;
 
-        WidgetAction selectAction = new ExtendedSelectAction(selectProvider);
+        Collection<Object> objects = new ArrayList<>(this.getObjects());
+        for (Object o : objects) {
+            this.removeObject(o);
+        }
+
         Diagram d = getModel().getDiagramToView();
 
-        if (getModel().getShowBlocks()) {
+        if (d.getGraph().getBlocks().isEmpty()) {
             Scheduler s = Lookup.getDefault().lookup(Scheduler.class);
-            Collection<InputBlock> newBlocks = new ArrayList<InputBlock>(s.schedule(d.getGraph()));
-            d.schedule(newBlocks);
+            d.getGraph().clearBlocks();
+            s.schedule(d.getGraph());
+            d.getGraph().ensureNodesInBlocks();
+            d.updateBlocks();
         }
 
         for (Figure f : d.getFigures()) {
-            FigureWidget w = new FigureWidget(f, this, mainLayer);
+            FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer);
+            w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
             w.getActions().addAction(selectAction);
             w.getActions().addAction(hoverAction);
-            w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
-            w.getActions().addAction(new DoubleClickAction(w));
             w.setVisible(false);
 
-            figureWidgets.put(f, w);
+            this.addObject(f, w);
 
             for (InputSlot s : f.getInputSlots()) {
-                SlotWidget sw = new InputSlotWidget(s, this, slotLayer, w);
-                slotWidgets.put(s, sw);
+                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, slotLayer, w);
-                slotWidgets.put(s, sw);
+                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);
             }
         }
@@ -583,28 +553,30 @@
             for (InputBlock bn : d.getGraph().getBlocks()) {
                 BlockWidget w = new BlockWidget(this, d, bn);
                 w.setVisible(false);
-                blockWidgets.put(bn, w);
+                this.addObject(bn, w);
                 blockLayer.addChild(w);
             }
         }
 
+        rebuilding = false;
         this.smallUpdate(true);
+    }
 
+    public boolean isRebuilding() {
+        return rebuilding;
     }
 
     private void smallUpdate(boolean relayout) {
-
         this.updateHiddenNodes(model.getHiddenNodes(), relayout);
         boolean b = this.getUndoRedoEnabled();
         this.setUndoRedoEnabled(false);
-        this.setSelection(getModel().getSelectedNodes());
         this.setUndoRedoEnabled(b);
         this.validate();
     }
 
     private boolean isVisible(Connection c) {
-        FigureWidget w1 = figureWidgets.get(c.getInputSlot().getFigure());
-        FigureWidget w2 = figureWidgets.get(c.getOutputSlot().getFigure());
+        FigureWidget w1 = getWidget(c.getInputSlot().getFigure());
+        FigureWidget w2 = getWidget(c.getOutputSlot().getFigure());
 
         if (w1.isVisible() && w2.isVisible()) {
             return true;
@@ -614,19 +586,18 @@
     }
 
     private void relayout(Set<Widget> oldVisibleWidgets) {
-
         Diagram diagram = getModel().getDiagramToView();
 
-        HashSet<Figure> figures = new HashSet<Figure>();
+        HashSet<Figure> figures = new HashSet<>();
 
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 figures.add(f);
             }
         }
 
-        HashSet<Connection> edges = new HashSet<Connection>();
+        HashSet<Connection> edges = new HashSet<>();
 
         for (Connection c : diagram.getConnections()) {
             if (isVisible(c)) {
@@ -635,24 +606,31 @@
         }
 
         if (getModel().getShowBlocks()) {
-            HierarchicalClusterLayoutManager m = new HierarchicalClusterLayoutManager(OldHierarchicalLayoutManager.Combine.SAME_OUTPUTS);
+            HierarchicalClusterLayoutManager m = new HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
             HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
             manager.setMaxLayerLength(9);
             manager.setMinLayerDifference(3);
             m.setManager(manager);
             m.setSubManager(new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS));
             m.doLayout(new LayoutGraph(edges, figures));
-
         } else {
             HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
             manager.setMaxLayerLength(10);
             manager.doLayout(new LayoutGraph(edges, figures));
         }
 
+        relayoutWithoutLayout(oldVisibleWidgets);
+    }
+    private Set<Pair<Point, Point>> lineCache = new HashSet<>();
+
+    private void relayoutWithoutLayout(Set<Widget> oldVisibleWidgets) {
+
+        Diagram diagram = getModel().getDiagramToView();
+
         int maxX = -BORDER_SIZE;
         int maxY = -BORDER_SIZE;
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 Point p = f.getPosition();
                 Dimension d = f.getSize();
@@ -663,8 +641,8 @@
 
         for (Connection c : diagram.getConnections()) {
             List<Point> points = c.getControlPoints();
-            FigureWidget w1 = figureWidgets.get((Figure) c.getTo().getVertex());
-            FigureWidget w2 = figureWidgets.get((Figure) c.getFrom().getVertex());
+            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) {
@@ -677,7 +655,7 @@
 
         if (getModel().getShowBlocks()) {
             for (Block b : diagram.getBlocks()) {
-                BlockWidget w = blockWidgets.get(b.getInputBlock());
+                BlockWidget w = getWidget(b.getInputBlock());
                 if (w != null && w.isVisible()) {
                     Rectangle r = b.getBounds();
                     maxX = Math.max(maxX, r.x + r.width);
@@ -693,6 +671,8 @@
         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;
         }
@@ -708,62 +688,61 @@
         connectionLayer.removeChildren();
         int visibleFigureCount = 0;
         for (Figure f : diagram.getFigures()) {
-            if (figureWidgets.get(f).isVisible()) {
+            if (getWidget(f, FigureWidget.class).isVisible()) {
                 visibleFigureCount++;
             }
         }
 
+
+        Set<Pair<Point, Point>> 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()) {
-            for (OutputSlot s : f.getOutputSlots()) {
-                SceneAnimator anim = animator;
-                if (visibleFigureCount > ANIMATION_LIMIT) {
-                    anim = null;
-                }
-                processOutputSlot(s, s.getConnections(), 0, null, null, offx2, offy2, anim);
-            }
-        }
-
-        for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 Point p = f.getPosition();
                 Point p2 = new Point(p.x + offx2, p.y + offy2);
-                Rectangle r = new Rectangle(p.x + offx2, p.y + offy2, f.getSize().width, f.getSize().height);
-                if (oldVisibleWidgets.contains(w)) {
-                    if (visibleFigureCount > ANIMATION_LIMIT) {
-                        w.setPreferredLocation(p2);
-                    } else {
-                        animator.animatePreferredLocation(w, p2);
-                    }
+                if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
+                    animator.animatePreferredLocation(w, p2);
                 } else {
                     w.setPreferredLocation(p2);
+                    animator.animatePreferredLocation(w, p2);
                 }
             }
         }
 
         if (getModel().getShowBlocks()) {
             for (Block b : diagram.getBlocks()) {
-                BlockWidget w = blockWidgets.get(b.getInputBlock());
+                BlockWidget w = getWidget(b.getInputBlock());
                 if (w != null && w.isVisible()) {
                     Point location = new Point(b.getBounds().x + offx2, b.getBounds().y + offy2);
                     Rectangle r = new Rectangle(location.x, location.y, b.getBounds().width, b.getBounds().height);
-                    if (oldVisibleWidgets.contains(w)) {
-                        if (visibleFigureCount > ANIMATION_LIMIT) {
-                            w.setPreferredBounds(r);
-                        } else {
-                            animator.animatePreferredBounds(w, r);
-                        }
+
+                    if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
+                        animator.animatePreferredBounds(w, r);
                     } else {
                         w.setPreferredBounds(r);
+                        animator.animatePreferredBounds(w, r);
                     }
                 }
             }
         }
+
+        this.validate();
     }
     private final Point specialNullPoint = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
 
-    private void processOutputSlot(OutputSlot s, List<Connection> connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) {
-        Map<Point, List<Connection>> pointMap = new HashMap<Point, List<Connection>>();
+    private void processOutputSlot(Set<Pair<Point, Point>> lastLineCache, OutputSlot s, List<Connection> connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) {
+        Map<Point, List<Connection>> pointMap = new HashMap<>(connections.size());
 
         for (Connection c : connections) {
 
@@ -779,16 +758,16 @@
             Point cur = controlPoints.get(controlPointIndex);
             if (cur == null) {
                 cur = specialNullPoint;
-            } else if (controlPointIndex == 0 && !s.getShowName()) {
+            } else if (controlPointIndex == 0 && !s.shouldShowName()) {
                 cur = new Point(cur.x, cur.y - SLOT_OFFSET);
-            } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().getShowName()) {
+            } 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<Connection> newList = new ArrayList<Connection>(2);
+                List<Connection> newList = new ArrayList<>(2);
                 newList.add(c);
                 pointMap.put(cur, newList);
             }
@@ -814,44 +793,70 @@
 
             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);
-                LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, animator, isBold, isDashed);
+
+                Pair<Point, Point> 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);
+                this.addObject(new ConnectionSet(connectionList), w);
                 w.getActions().addAction(hoverAction);
             }
 
-            processOutputSlot(s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator);
+            processOutputSlot(lastLineCache, s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator);
         }
     }
 
-    private void clearSelection() {
-        if (selectedWidgets.size() == 0) {
-            return;
-        }
-        for (FigureWidget w : selectedWidgets) {
-            assert w.getState().isSelected();
-            w.setState(w.getState().deriveSelected(false));
-            content.remove(w.getNode());
-        }
-        selectedWidgets.clear();
+    @Override
+    public void setInteractionMode(InteractionMode mode) {
+        panAction.setEnabled(mode == InteractionMode.PANNING);
+        // When panAction is not enabled, it does not consume the event
+        // and the selection action handles it instead
     }
 
+    private class ConnectionSet {
+
+        private Set<Connection> connections;
+
+        public ConnectionSet(Collection<Connection> connections) {
+            connections = new HashSet<>(connections);
+        }
+
+        public Set<Connection> getConnectionSet() {
+            return Collections.unmodifiableSet(connections);
+        }
+    }
+
+    @Override
     public Lookup getLookup() {
         return lookup;
     }
 
+    @Override
+    public void initialize() {
+        Figure f = getModel().getDiagramToView().getRootFigure();
+        if (f != null) {
+            setUndoRedoEnabled(false);
+            gotoFigure(f);
+            setUndoRedoEnabled(true);
+        }
+    }
+
     public void gotoFigures(final List<Figure> figures) {
         Rectangle overall = null;
-        showFigures(figures);
+        getModel().showFigures(figures);
         for (Figure f : figures) {
 
-            FigureWidget fw = getFigureWidget(f);
+            FigureWidget fw = getWidget(f);
             if (fw != null) {
                 Rectangle r = fw.getBounds();
                 Point p = fw.getLocation();
@@ -869,6 +874,54 @@
         }
     }
 
+    private Set<Object> idSetToObjectSet(Set<Object> ids) {
+
+        Set<Object> 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<Object> ids) {
+
+        Rectangle overall = null;
+        Set<Integer> hiddenNodes = new HashSet<>(this.getModel().getHiddenNodes());
+        hiddenNodes.removeAll(ids);
+        this.getModel().showNot(hiddenNodes);
+
+        Set<Object> 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());
@@ -909,63 +962,9 @@
         }
     }
 
-    private void addToSelection(Figure f) {
-        FigureWidget w = getFigureWidget(f);
-        addToSelection(w);
-    }
-
-    private void addToSelection(FigureWidget w) {
-        assert !selectedWidgets.contains(w);
-        selectedWidgets.add(w);
-        content.add(w.getNode());
-        w.setState(w.getState().deriveSelected(true));
-    }
-
-    private void setSelection(Set<Integer> nodes) {
-        clearSelection();
-        for (Figure f : getModel().getDiagramToView().getFigures()) {
-            if (doesIntersect(f.getSource().getSourceNodesAsSet(), nodes)) {
-                addToSelection(f);
-            }
-        }
-        selectionUpdated();
-        this.validate();
-    }
-
+    @Override
     public void setSelection(Collection<Figure> list) {
-        clearSelection();
-        for (Figure f : list) {
-            addToSelection(f);
-        }
-
-        selectionUpdated();
-        this.validate();
-    }
-
-    public Set<Figure> getSelectedFigures() {
-        Set<Figure> result = new HashSet<Figure>();
-        for (Widget w : selectedWidgets) {
-            if (w instanceof FigureWidget) {
-                FigureWidget fw = (FigureWidget) w;
-                if (fw.getState().isSelected()) {
-                    result.add(fw.getFigure());
-                }
-            }
-        }
-        return result;
-    }
-
-    public Set<Integer> getSelectedNodes() {
-        Set<Integer> result = new HashSet<Integer>();
-        for (Widget w : selectedWidgets) {
-            if (w instanceof FigureWidget) {
-                FigureWidget fw = (FigureWidget) w;
-                if (fw.getState().isSelected()) {
-                    result.addAll(fw.getFigure().getSource().getSourceNodesAsSet());
-                }
-            }
-        }
-        return result;
+        super.setSelectedObjects(new HashSet<>(list));
     }
 
     private UndoRedo.Manager getUndoRedoManager() {
@@ -977,6 +976,7 @@
         return undoRedoManager;
     }
 
+    @Override
     public UndoRedo getUndoRedo() {
         return getUndoRedoManager();
     }
@@ -990,9 +990,9 @@
         return true;
     }
 
-    private boolean doesIntersect(Set s1, Set s2) {
+    public static boolean doesIntersect(Set<?> s1, Set<?> s2) {
         if (s1.size() > s2.size()) {
-            Set tmp = s1;
+            Set<?> tmp = s1;
             s1 = s2;
             s2 = tmp;
         }
@@ -1006,35 +1006,36 @@
         return false;
     }
 
-    public void showNot(final Set<Integer> nodes) {
-        updateHiddenNodes(nodes, true);
+    @Override
+    public void componentHidden() {
+        SelectionCoordinator.getInstance().getHighlightedChangedEvent().removeListener(highlightedCoordinatorListener);
+        SelectionCoordinator.getInstance().getSelectedChangedEvent().removeListener(selectedCoordinatorListener);
     }
 
-    public void showOnly(final Set<Integer> nodes) {
-        HashSet<Integer> allNodes = new HashSet<Integer>(getModel().getGraphToView().getGroup().getAllNodes());
-        allNodes.removeAll(nodes);
-        updateHiddenNodes(allNodes, true);
+    @Override
+    public void componentShowing() {
+        SelectionCoordinator.getInstance().getHighlightedChangedEvent().addListener(highlightedCoordinatorListener);
+        SelectionCoordinator.getInstance().getSelectedChangedEvent().addListener(selectedCoordinatorListener);
     }
 
     private void updateHiddenNodes(Set<Integer> newHiddenNodes, boolean doRelayout) {
 
-        Set<InputBlock> visibleBlocks = new HashSet<InputBlock>();
-
         Diagram diagram = getModel().getDiagramToView();
         assert diagram != null;
 
-        Set<Widget> oldVisibleWidgets = new HashSet<Widget>();
+        Set<InputBlock> visibleBlocks = new HashSet<InputBlock>();
+        Set<Widget> oldVisibleWidgets = new HashSet<>();
 
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
-            if (w.isVisible()) {
+            FigureWidget w = getWidget(f);
+            if (w != null && w.isVisible()) {
                 oldVisibleWidgets.add(w);
             }
         }
 
         if (getModel().getShowBlocks()) {
             for (InputBlock b : diagram.getGraph().getBlocks()) {
-                BlockWidget w = blockWidgets.get(b);
+                BlockWidget w = getWidget(b);
                 if (w.isVisible()) {
                     oldVisibleWidgets.add(w);
                 }
@@ -1044,7 +1045,7 @@
         for (Figure f : diagram.getFigures()) {
             boolean hiddenAfter = doesIntersect(f.getSource().getSourceNodesAsSet(), newHiddenNodes);
 
-            FigureWidget w = this.figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             w.setBoundary(false);
             if (!hiddenAfter) {
                 // Figure is shown
@@ -1059,16 +1060,16 @@
         }
 
         if (getModel().getShowNodeHull()) {
-            List<FigureWidget> boundaries = new ArrayList<FigureWidget>();
+            List<FigureWidget> boundaries = new ArrayList<>();
             for (Figure f : diagram.getFigures()) {
-                FigureWidget w = this.figureWidgets.get(f);
+                FigureWidget w = getWidget(f);
                 if (!w.isVisible()) {
-                    Set<Figure> set = new HashSet<Figure>(f.getPredecessorSet());
+                    Set<Figure> set = new HashSet<>(f.getPredecessorSet());
                     set.addAll(f.getSuccessorSet());
 
                     boolean b = false;
                     for (Figure neighbor : set) {
-                        FigureWidget neighborWidget = figureWidgets.get(neighbor);
+                        FigureWidget neighborWidget = getWidget(neighbor);
                         if (neighborWidget.isVisible()) {
                             b = true;
                             break;
@@ -1097,7 +1098,7 @@
 
                 boolean visibleAfter = visibleBlocks.contains(b);
 
-                BlockWidget w = blockWidgets.get(b);
+                BlockWidget w = getWidget(b);
                 if (visibleAfter) {
                     // Block must be shown
                     w.setVisible(true);
@@ -1108,7 +1109,6 @@
             }
         }
 
-        getModel().setHiddenNodes(newHiddenNodes);
         if (doRelayout) {
             relayout(oldVisibleWidgets);
         }
@@ -1116,51 +1116,50 @@
         addUndo();
     }
 
-    private void showFigures(Collection<Figure> f) {
-        HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getModel().getHiddenNodes());
-        for (Figure fig : f) {
-            newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet());
-        }
-        updateHiddenNodes(newHiddenNodes, true);
-    }
-
     private void showFigure(Figure f) {
-        HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getModel().getHiddenNodes());
+        HashSet<Integer> newHiddenNodes = new HashSet<>(getModel().getHiddenNodes());
         newHiddenNodes.removeAll(f.getSource().getSourceNodesAsSet());
-        updateHiddenNodes(newHiddenNodes, true);
-    }
-
-    public void showAll(final Collection<Figure> f) {
-        showFigures(f);
-
+        this.model.setHiddenNodes(newHiddenNodes);
     }
 
     public void show(final Figure f) {
         showFigure(f);
     }
 
+    public void setSelectedObjects(Object... args) {
+        Set<Object> 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 = getFigureWidget(f);
+        FigureWidget fw = getWidget(f);
         if (fw != null) {
-            Rectangle r = fw.getBounds();
-            Point p = fw.getLocation();
-            centerRectangle(new Rectangle(p.x, p.y, r.width, r.height));
-
-            // Select figure
-            clearSelection();
-            addToSelection(fw);
-            selectionUpdated();
+            centerWidget(fw);
+            setSelection(Arrays.asList(f));
         }
     }
 
     public JPopupMenu createPopupMenu() {
         JPopupMenu menu = new JPopupMenu();
-        for (Action a : actions) {
+
+        Action[] currentActions = actionsWithSelection;
+        if (this.getSelectedObjects().isEmpty()) {
+            currentActions = actions;
+        }
+        for (Action a : currentActions) {
             if (a == null) {
                 menu.addSeparator();
             } else {
@@ -1208,6 +1207,7 @@
 
             SwingUtilities.invokeLater(new Runnable() {
 
+                @Override
                 public void run() {
                     scene.setScrollPosition(oldScrollPosition);
                 }
@@ -1216,9 +1216,10 @@
             scene.setUndoRedoEnabled(b);
         }
 
+        @Override
         public void changed(DiagramViewModel source) {
             scene.getModel().getViewChangedEvent().removeListener(this);
-            if (oldModel.getSelectedNodes().equals(newModel.getHiddenNodes())) {
+            if (oldModel.getHiddenNodes().equals(newModel.getHiddenNodes())) {
                 scene.smallUpdate(false);
             } else {
                 scene.smallUpdate(true);
@@ -1235,11 +1236,33 @@
         return undoRedoEnabled;
     }
 
-    public void changed(DiagramViewModel source) {
-        assert source == model : "Receive only changed event from current model!";
-        assert source != null;
-        update();
-    }
+    private final ChangedListener<DiagramViewModel> fullChange = new ChangedListener<DiagramViewModel>() {
+        @Override
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            update();
+        }
+    };
+
+    private final ChangedListener<DiagramViewModel> hiddenNodesChange = new ChangedListener<DiagramViewModel>() {
+        @Override
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            smallUpdate(true);
+        }
+    };
+
+    private final ChangedListener<DiagramViewModel> selectionChange = new ChangedListener<DiagramViewModel>() {
+        @Override
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            smallUpdate(false);
+        }
+    };
+
 
     private void addUndo() {
 
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,22 +24,16 @@
  */
 package com.sun.hotspot.igv.view;
 
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.InputNode;
+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.data.ChangedEvent;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.settings.Settings;
 import com.sun.hotspot.igv.util.RangeSliderModel;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.settings.Settings;
 import java.awt.Color;
+import java.util.*;
 
 /**
  *
@@ -49,20 +43,25 @@
 
     // Warning: Update setData method if fields are added
     private Group group;
+    private ArrayList<InputGraph> graphs;
     private Set<Integer> hiddenNodes;
     private Set<Integer> onScreenNodes;
     private Set<Integer> selectedNodes;
     private FilterChain filterChain;
     private FilterChain sequenceFilterChain;
     private Diagram diagram;
+    private InputGraph inputGraph;
     private ChangedEvent<DiagramViewModel> groupChangedEvent;
     private ChangedEvent<DiagramViewModel> diagramChangedEvent;
     private ChangedEvent<DiagramViewModel> viewChangedEvent;
+    private ChangedEvent<DiagramViewModel> hiddenNodesChangedEvent;
     private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent;
     private boolean showBlocks;
     private boolean showNodeHull;
+    private boolean hideDuplicates;
     private ChangedListener<FilterChain> filterChainChangedListener = new ChangedListener<FilterChain>() {
 
+        @Override
         public void changed(FilterChain source) {
             diagramChanged();
         }
@@ -75,6 +74,10 @@
         return result;
     }
 
+    public Group getGroup() {
+        return group;
+    }
+
     public void setData(DiagramViewModel newModel) {
         super.setData(newModel);
         boolean diagramChanged = false;
@@ -83,6 +86,10 @@
 
         boolean groupChanged = (group == newModel.group);
         this.group = newModel.group;
+        if (groupChanged) {
+            filterGraphs();
+        }
+
         diagramChanged |= (filterChain != newModel.filterChain);
         this.filterChain = newModel.filterChain;
         diagramChanged |= (sequenceFilterChain != newModel.sequenceFilterChain);
@@ -100,7 +107,7 @@
         viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
         this.showNodeHull = newModel.showNodeHull;
 
-        if(groupChanged) {
+        if (groupChanged) {
             groupChangedEvent.fire();
         }
 
@@ -133,53 +140,75 @@
         viewPropertiesChangedEvent.fire();
     }
 
-    public DiagramViewModel(Group g, FilterChain filterChain, FilterChain sequenceFilterChain) {
-        super(calculateStringList(g));
+    public boolean getHideDuplicates() {
+        return hideDuplicates;
+    }
 
+    public void setHideDuplicates(boolean b) {
+        System.err.println("setHideDuplicates: " + b);
+        hideDuplicates = b;
+        InputGraph currentGraph = getFirstGraph();
+        if (hideDuplicates) {
+            // Back up to the unhidden equivalent graph
+            int index = graphs.indexOf(currentGraph);
+            while (graphs.get(index).getProperties().get("_isDuplicate") != null) {
+                index--;
+            }
+            currentGraph = graphs.get(index);
+        }
+        filterGraphs();
+        selectGraph(currentGraph);
+        viewPropertiesChangedEvent.fire();
+    }
+
+    public DiagramViewModel(Group g, FilterChain filterChain, FilterChain sequenceFilterChain) {
+        super(Arrays.asList("default"));
+
+        this.showBlocks = false;
         this.showNodeHull = true;
-        this.showBlocks = true;
         this.group = g;
+        filterGraphs();
         assert filterChain != null;
         this.filterChain = filterChain;
         assert sequenceFilterChain != null;
         this.sequenceFilterChain = sequenceFilterChain;
-        hiddenNodes = new HashSet<Integer>();
-        onScreenNodes = new HashSet<Integer>();
-        selectedNodes = new HashSet<Integer>();
+        hiddenNodes = new HashSet<>();
+        onScreenNodes = new HashSet<>();
+        selectedNodes = new HashSet<>();
         super.getChangedEvent().addListener(this);
-        diagramChangedEvent = new ChangedEvent<DiagramViewModel>(this);
-        viewChangedEvent = new ChangedEvent<DiagramViewModel>(this);
-        viewPropertiesChangedEvent = new ChangedEvent<DiagramViewModel>(this);
-        groupChangedEvent = new ChangedEvent<DiagramViewModel>(this);
+        diagramChangedEvent = new ChangedEvent<>(this);
+        viewChangedEvent = new ChangedEvent<>(this);
+        hiddenNodesChangedEvent = new ChangedEvent<>(this);
+        viewPropertiesChangedEvent = new ChangedEvent<>(this);
+
+        groupChangedEvent = new ChangedEvent<>(this);
         groupChangedEvent.addListener(groupChangedListener);
         groupChangedEvent.fire();
 
         filterChain.getChangedEvent().addListener(filterChainChangedListener);
         sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener);
     }
-
     private final ChangedListener<DiagramViewModel> groupChangedListener = new ChangedListener<DiagramViewModel>() {
 
         private Group oldGroup;
 
+        @Override
         public void changed(DiagramViewModel source) {
-            if(oldGroup != null) {
+            if (oldGroup != null) {
                 oldGroup.getChangedEvent().removeListener(groupContentChangedListener);
             }
             group.getChangedEvent().addListener(groupContentChangedListener);
             oldGroup = group;
         }
     };
-
-
     private final ChangedListener<Group> groupContentChangedListener = new ChangedListener<Group>() {
 
+        @Override
         public void changed(Group source) {
             assert source == group;
-            setPositions(calculateStringList(source));
+            filterGraphs();
             setSelectedNodes(selectedNodes);
         }
-
     };
 
     public ChangedEvent<DiagramViewModel> getDiagramChangedEvent() {
@@ -190,25 +219,29 @@
         return viewChangedEvent;
     }
 
+    public ChangedEvent<DiagramViewModel> getHiddenNodesChangedEvent() {
+        return hiddenNodesChangedEvent;
+    }
+
     public ChangedEvent<DiagramViewModel> getViewPropertiesChangedEvent() {
         return viewPropertiesChangedEvent;
     }
 
     public Set<Integer> getSelectedNodes() {
-        return Collections.unmodifiableSet(selectedNodes);
+        return selectedNodes;
     }
 
     public Set<Integer> getHiddenNodes() {
-        return Collections.unmodifiableSet(hiddenNodes);
+        return hiddenNodes;
     }
 
     public Set<Integer> getOnScreenNodes() {
-        return Collections.unmodifiableSet(onScreenNodes);
+        return onScreenNodes;
     }
 
     public void setSelectedNodes(Set<Integer> nodes) {
         this.selectedNodes = nodes;
-        List<Color> colors = new ArrayList<Color>();
+        List<Color> colors = new ArrayList<>();
         for (String s : getPositions()) {
             colors.add(Color.black);
         }
@@ -219,14 +252,14 @@
                 }
                 InputNode last = null;
                 int index = 0;
-                for (InputGraph g : group.getGraphs()) {
+                for (InputGraph g : graphs) {
                     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 (last.equals(cur) && last.getProperties().equals(cur.getProperties())) {
                                 if (curColor == Color.black) {
                                     curColor = Color.white;
                                 }
@@ -242,15 +275,49 @@
                     index++;
                 }
             }
-            this.setColors(colors);
         }
         setColors(colors);
         viewChangedEvent.fire();
     }
 
+    public void showNot(final Set<Integer> nodes) {
+        setHiddenNodes(nodes);
+    }
+
+    public void showFigures(Collection<Figure> f) {
+        HashSet<Integer> newHiddenNodes = new HashSet<>(getHiddenNodes());
+        for (Figure fig : f) {
+            newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet());
+        }
+        setHiddenNodes(newHiddenNodes);
+    }
+
+
+    public Set<Figure> getSelectedFigures() {
+        Set<Figure> 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<Figure> f) {
+        showFigures(f);
+    }
+
+    public void showOnly(final Set<Integer> nodes) {
+        final HashSet<Integer> allNodes = new HashSet<>(getGraphToView().getGroup().getAllNodes());
+        allNodes.removeAll(nodes);
+        setHiddenNodes(allNodes);
+    }
+
     public void setHiddenNodes(Set<Integer> nodes) {
         this.hiddenNodes = nodes;
-        viewChangedEvent.fire();
+        hiddenNodesChangedEvent.fire();
     }
 
     public void setOnScreenNodes(Set<Integer> onScreenNodes) {
@@ -289,27 +356,44 @@
         diagramChanged();
     }
 
-    private static List<String> calculateStringList(Group g) {
-        List<String> result = new ArrayList<String>();
-        for (InputGraph graph : g.getGraphs()) {
-            result.add(graph.getName());
+    /*
+     * Select the set of graphs to be presented.
+     */
+    private void filterGraphs() {
+        ArrayList<InputGraph> result = new ArrayList<>();
+        List<String> positions = new ArrayList<>();
+        for (InputGraph graph : group.getGraphs()) {
+            String duplicate = graph.getProperties().get("_isDuplicate");
+            if (duplicate == null || !hideDuplicates) {
+                result.add(graph);
+                positions.add(graph.getName());
+            }
         }
-        return result;
+        this.graphs = result;
+        setPositions(positions);
     }
 
     public InputGraph getFirstGraph() {
-        return group.getGraphs().get(getFirstPosition());
+        if (getFirstPosition() < graphs.size()) {
+            return graphs.get(getFirstPosition());
+        }
+        return graphs.get(graphs.size() - 1);
     }
 
     public InputGraph getSecondGraph() {
-        List<InputGraph> graphs = group.getGraphs();
-        if (graphs.size() >= getSecondPosition())
-            return group.getGraphs().get(getSecondPosition());
+        if (getSecondPosition() < graphs.size()) {
+            return graphs.get(getSecondPosition());
+        }
         return getFirstGraph();
     }
 
     public void selectGraph(InputGraph g) {
-        int index = group.getGraphs().indexOf(g);
+        int index = graphs.indexOf(g);
+        if (index == -1 && hideDuplicates) {
+            // A graph was selected that's currently hidden, so unhide and select it.
+            setHideDuplicates(false);
+            index = graphs.indexOf(g);
+        }
         assert index != -1;
         setPositions(index, index);
     }
@@ -319,22 +403,90 @@
         if (diagram == null) {
             diagram = Diagram.createDiagram(getGraphToView(), Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
             getFilterChain().apply(diagram, getSequenceFilterChain());
+            if (getFirstPosition() != getSecondPosition()) {
+                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 (getFirstGraph() != getSecondGraph()) {
-            InputGraph inputGraph = Difference.createDiffGraph(getSecondGraph(), getFirstGraph());
-            return inputGraph;
-        } else {
-            InputGraph inputGraph = getFirstGraph();
-            return inputGraph;
+        if (inputGraph == null) {
+            if (getFirstGraph() != getSecondGraph()) {
+                inputGraph = Difference.createDiffGraph(getFirstGraph(), getSecondGraph());
+            } else {
+                inputGraph = getFirstGraph();
+            }
         }
+
+        return inputGraph;
+    }
+
+    @Override
+    public void changed(RangeSliderModel source) {
+        inputGraph = null;
+        diagramChanged();
+    }
+
+    void setSelectedFigures(List<Figure> list) {
+        Set<Integer> newSelectedNodes = new HashSet<>();
+        for (Figure f : list) {
+            newSelectedNodes.addAll(f.getSource().getSourceNodesAsSet());
+        }
+        this.setSelectedNodes(newSelectedNodes);
+    }
+
+    void close() {
+        filterChain.getChangedEvent().removeListener(filterChainChangedListener);
+        sequenceFilterChain.getChangedEvent().removeListener(filterChainChangedListener);
     }
 
-    public void changed(RangeSliderModel source) {
-        diagramChanged();
+    Iterable<InputGraph> getGraphsForward() {
+        return new Iterable<InputGraph>() {
+
+            @Override
+            public Iterator<InputGraph> iterator() {
+                return new Iterator<InputGraph>() {
+                    int index = getFirstPosition();
+
+                    @Override
+                    public boolean hasNext() {
+                        return index + 1 < graphs.size();
+                    }
+
+                    @Override
+                    public InputGraph next() {
+                        return graphs.get(++index);
+                    }
+                };
+            }
+        };
+    }
+
+    Iterable<InputGraph> getGraphsBackward() {
+        return new Iterable<InputGraph>() {
+            @Override
+            public Iterator<InputGraph> iterator() {
+                return new Iterator<InputGraph>() {
+                    int index = getFirstPosition();
+
+                    @Override
+                    public boolean hasNext() {
+                        return index - 1 > 0;
+                    }
+
+                    @Override
+                    public InputGraph next() {
+                        return graphs.get(--index);
+                    }
+                };
+            }
+        };
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewer.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.view;
+
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.util.Collection;
+import java.util.List;
+import javax.swing.JComponent;
+import org.openide.awt.UndoRedo;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+interface DiagramViewer {
+
+    enum InteractionMode {
+        SELECTION,
+        PANNING,
+    }
+
+    public void paint(Graphics2D svgGenerator);
+
+    public Lookup getLookup();
+
+    public JComponent createSatelliteView();
+
+    public Component getComponent();
+
+    public void zoomOut();
+
+    public void zoomIn();
+
+    public UndoRedo getUndoRedo();
+
+    public void componentHidden();
+
+    public void componentShowing();
+
+    public void initialize();
+
+    public void setSelection(Collection<Figure> list);
+
+    public void centerFigures(List<Figure> list);
+
+    public void setInteractionMode(InteractionMode mode);
+
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,8 @@
 package com.sun.hotspot.igv.view;
 
 import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
-import com.sun.hotspot.igv.data.InputNode;
 import java.util.Set;
 
 /**
@@ -35,18 +35,29 @@
  */
 public class EditorInputGraphProvider implements InputGraphProvider {
 
+    private EditorTopComponent editor;
+
+    public EditorInputGraphProvider(EditorTopComponent editor) {
+        this.editor = editor;
+    }
+
+    @Override
     public InputGraph getGraph() {
-        EditorTopComponent e = EditorTopComponent.getActive();
-        if (e == null) {
-            return null;
-        }
-        return e.getDiagramModel().getGraphToView();
+        return editor.getDiagramModel().getGraphToView();
     }
 
+    @Override
     public void setSelectedNodes(Set<InputNode> nodes) {
-        EditorTopComponent e = EditorTopComponent.getActive();
-        if (e != null) {
-            e.setSelectedNodes(nodes);
-        }
+        editor.setSelectedNodes(nodes);
+    }
+    
+    @Override
+    public Iterable<InputGraph> searchBackward() {
+        return editor.getDiagramModel().getGraphsBackward();
+    }
+    
+    @Override
+    public Iterable<InputGraph> searchForward() {
+        return editor.getDiagramModel().getGraphsForward();
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.form	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.form	Mon Feb 06 17:18:57 2017 +0100
@@ -18,6 +18,8 @@
   </NonVisualComponents>
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,62 +23,35 @@
  */
 package com.sun.hotspot.igv.view;
 
+import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.filter.FilterChain;
+import com.sun.hotspot.igv.filter.FilterChainProvider;
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.view.actions.EnableBlockLayoutAction;
-import com.sun.hotspot.igv.view.actions.ExpandPredecessorsAction;
-import com.sun.hotspot.igv.view.actions.ExpandSuccessorsAction;
-import com.sun.hotspot.igv.view.actions.ExtractAction;
-import com.sun.hotspot.igv.view.actions.HideAction;
-import com.sun.hotspot.igv.view.actions.NextDiagramAction;
-import com.sun.hotspot.igv.view.actions.NodeFindAction;
-import com.sun.hotspot.igv.view.actions.OverviewAction;
-import com.sun.hotspot.igv.view.actions.PredSuccAction;
-import com.sun.hotspot.igv.view.actions.PrevDiagramAction;
-import com.sun.hotspot.igv.view.actions.ShowAllAction;
-import com.sun.hotspot.igv.view.actions.ZoomInAction;
-import com.sun.hotspot.igv.view.actions.ZoomOutAction;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
-import com.sun.hotspot.igv.filter.FilterChainProvider;
+import com.sun.hotspot.igv.graph.services.DiagramProvider;
+import com.sun.hotspot.igv.svg.BatikSVG;
+import com.sun.hotspot.igv.util.LookupHistory;
 import com.sun.hotspot.igv.util.RangeSlider;
-import com.sun.hotspot.igv.util.RangeSliderModel;
-import com.sun.hotspot.igv.svg.BatikSVG;
-import java.awt.BorderLayout;
-import java.awt.CardLayout;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Graphics2D;
-import java.awt.Point;
+import com.sun.hotspot.igv.view.actions.*;
+import java.awt.*;
 import java.awt.event.HierarchyBoundsListener;
 import java.awt.event.HierarchyEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.HashSet;
+import java.io.*;
 import java.util.List;
-import java.util.Set;
-import javax.swing.Action;
-import javax.swing.ActionMap;
-import javax.swing.JPanel;
-import javax.swing.JToggleButton;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
+import java.util.*;
+import javax.swing.*;
 import javax.swing.border.Border;
 import org.openide.DialogDisplayer;
-import org.openide.actions.FindAction;
+import org.openide.NotifyDescriptor;
 import org.openide.actions.RedoAction;
 import org.openide.actions.UndoAction;
 import org.openide.awt.Toolbar;
@@ -86,40 +59,44 @@
 import org.openide.awt.UndoRedo;
 import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
-import org.openide.util.actions.CallbackSystemAction;
-import org.openide.util.actions.SystemAction;
+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.ProxyLookup;
 import org.openide.windows.Mode;
 import org.openide.windows.TopComponent;
 import org.openide.windows.WindowManager;
-import org.openide.NotifyDescriptor;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public final class EditorTopComponent extends TopComponent implements ChangedListener<RangeSliderModel>, PropertyChangeListener {
+public final class EditorTopComponent extends TopComponent implements PropertyChangeListener {
 
-    private DiagramScene scene;
+    private DiagramViewer scene;
     private InstanceContent content;
-    private FindPanel findPanel;
+    private InstanceContent graphContent;
     private EnableBlockLayoutAction blockLayoutAction;
     private OverviewAction overviewAction;
+    private HideDuplicatesAction hideDuplicatesAction;
     private PredSuccAction predSuccAction;
+    private SelectionModeAction selectionModeAction;
+    private PanModeAction panModeAction;
     private boolean notFirstTime;
-    private ExtendedSatelliteComponent satelliteComponent;
+    private JComponent satelliteComponent;
     private JPanel centerPanel;
     private CardLayout cardLayout;
     private RangeSlider rangeSlider;
     private JToggleButton overviewButton;
+    private JToggleButton hideDuplicatesButton;
     private static final String PREFERRED_ID = "EditorTopComponent";
     private static final String SATELLITE_STRING = "satellite";
     private static final String SCENE_STRING = "scene";
     private DiagramViewModel rangeSliderModel;
     private ExportCookie exportCookie = new ExportCookie() {
 
+        @Override
         public void export(File f) {
 
             Graphics2D svgGenerator = BatikSVG.createGraphicsObject();
@@ -152,12 +129,32 @@
         }
     };
 
+    private DiagramProvider diagramProvider = new DiagramProvider() {
+
+        @Override
+        public Diagram getDiagram() {
+            return getModel().getDiagramToView();
+        }
+
+        @Override
+        public ChangedEvent<DiagramProvider> getChangedEvent() {
+            return diagramChangedEvent;
+        }
+    };
+
+    private ChangedEvent<DiagramProvider> diagramChangedEvent = new ChangedEvent<>(diagramProvider);
+
+
     private void updateDisplayName() {
         setDisplayName(getDiagram().getName());
+        setToolTipText(getDiagram().getGraph().getGroup().getName());
     }
 
     public EditorTopComponent(Diagram diagram) {
 
+        LookupHistory.init(InputGraphProvider.class);
+        LookupHistory.init(DiagramProvider.class);
+        this.setFocusable(true);
         FilterChain filterChain = null;
         FilterChain sequence = null;
         FilterChainProvider provider = Lookup.getDefault().lookup(FilterChainProvider.class);
@@ -182,16 +179,19 @@
             null,
             ZoomInAction.get(ZoomInAction.class),
             ZoomOutAction.get(ZoomOutAction.class),
+        };
+
+
+        Action[] actionsWithSelection = new Action[]{
+            ExtractAction.get(ExtractAction.class),
+            ShowAllAction.get(HideAction.class),
             null,
             ExpandPredecessorsAction.get(ExpandPredecessorsAction.class),
             ExpandSuccessorsAction.get(ExpandSuccessorsAction.class)
         };
 
-
         initComponents();
 
-        ActionMap actionMap = getActionMap();
-
         ToolbarPool.getDefault().setPreferredIconSize(16);
         Toolbar toolBar = new Toolbar();
         Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N
@@ -202,24 +202,30 @@
         container.add(BorderLayout.NORTH, toolBar);
 
         rangeSliderModel = new DiagramViewModel(diagram.getGraph().getGroup(), filterChain, sequence);
-        rangeSliderModel.selectGraph(diagram.getGraph());
         rangeSlider = new RangeSlider();
         rangeSlider.setModel(rangeSliderModel);
-        rangeSliderModel.getChangedEvent().addListener(this);
-        container.add(BorderLayout.CENTER, rangeSlider);
+        JScrollPane pane = new JScrollPane(rangeSlider, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        container.add(BorderLayout.CENTER, pane);
 
-        scene = new DiagramScene(actions, rangeSliderModel);
+        scene = new DiagramScene(actions, actionsWithSelection, rangeSliderModel);
         content = new InstanceContent();
-        this.associateLookup(new ProxyLookup(new Lookup[]{scene.getLookup(), new AbstractLookup(content)}));
+        graphContent = new InstanceContent();
+        this.associateLookup(new ProxyLookup(new Lookup[]{scene.getLookup(), new AbstractLookup(graphContent), new AbstractLookup(content)}));
         content.add(exportCookie);
         content.add(rangeSliderModel);
+        content.add(diagramProvider);
+
+        rangeSliderModel.getDiagramChangedEvent().addListener(diagramChangedListener);
+        rangeSliderModel.selectGraph(diagram.getGraph());
+        rangeSliderModel.getViewPropertiesChangedEvent().addListener(new ChangedListener<DiagramViewModel>() {
+                @Override
+                public void changed(DiagramViewModel source) {
+                    hideDuplicatesButton.setSelected(getModel().getHideDuplicates());
+                    hideDuplicatesAction.setState(getModel().getHideDuplicates());
+                }
+            });
 
 
-        findPanel = new FindPanel(diagram.getFigures());
-        findPanel.setMaximumSize(new Dimension(200, 50));
-        toolBar.add(findPanel);
-        toolBar.add(NodeFindAction.get(NodeFindAction.class));
-        toolBar.addSeparator();
         toolBar.add(NextDiagramAction.get(NextDiagramAction.class));
         toolBar.add(PrevDiagramAction.get(PrevDiagramAction.class));
         toolBar.addSeparator();
@@ -232,7 +238,7 @@
 
         blockLayoutAction = new EnableBlockLayoutAction();
         JToggleButton button = new JToggleButton(blockLayoutAction);
-        button.setSelected(true);
+        button.setSelected(false);
         toolBar.add(button);
         blockLayoutAction.addPropertyChangeListener(this);
 
@@ -248,59 +254,94 @@
         toolBar.add(button);
         predSuccAction.addPropertyChangeListener(this);
 
+        hideDuplicatesAction = new HideDuplicatesAction();
+        hideDuplicatesButton = new JToggleButton(hideDuplicatesAction);
+        hideDuplicatesButton.setSelected(false);
+        toolBar.add(hideDuplicatesButton);
+        hideDuplicatesAction.addPropertyChangeListener(this);
+
         toolBar.addSeparator();
         toolBar.add(UndoAction.get(UndoAction.class));
         toolBar.add(RedoAction.get(RedoAction.class));
 
+        toolBar.addSeparator();
+        ButtonGroup interactionButtons = new ButtonGroup();
+
+        panModeAction = new PanModeAction();
+        panModeAction.setSelected(true);
+        button = new JToggleButton(panModeAction);
+        button.setSelected(true);
+        interactionButtons.add(button);
+        toolBar.add(button);
+        panModeAction.addPropertyChangeListener(this);
+
+        selectionModeAction = new SelectionModeAction();
+        button = new JToggleButton(selectionModeAction);
+        interactionButtons.add(button);
+        toolBar.add(button);
+        selectionModeAction.addPropertyChangeListener(this);
+
+        toolBar.add(Box.createHorizontalGlue());
+        Action action = Utilities.actionsForPath("QuickSearchShadow").get(0);
+        Component quicksearch = ((Presenter.Toolbar) action).getToolbarPresenter();
+        try {
+            // (aw) workaround for disappearing search bar due to reparenting one shared component instance.
+            quicksearch = (Component) quicksearch.getClass().getConstructor(KeyStroke.class).newInstance(new Object[]{null});
+        } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
+        }
+        Dimension preferredSize = quicksearch.getPreferredSize();
+        preferredSize = new Dimension((int) preferredSize.getWidth() * 2, (int) preferredSize.getHeight());
+        quicksearch.setMinimumSize(preferredSize); // necessary for GTK LAF
+        quicksearch.setPreferredSize(preferredSize);
+        toolBar.add(quicksearch);
+
         centerPanel = new JPanel();
         this.add(centerPanel, BorderLayout.CENTER);
         cardLayout = new CardLayout();
         centerPanel.setLayout(cardLayout);
-        centerPanel.add(SCENE_STRING, scene.getScrollPane());
+        centerPanel.add(SCENE_STRING, scene.getComponent());
         centerPanel.setBackground(Color.WHITE);
-        satelliteComponent = new ExtendedSatelliteComponent(scene);
+        satelliteComponent = scene.createSatelliteView();
         satelliteComponent.setSize(200, 200);
         centerPanel.add(SATELLITE_STRING, satelliteComponent);
 
-        CallbackSystemAction callFindAction = (CallbackSystemAction) SystemAction.get(FindAction.class);
-        NodeFindAction findAction = NodeFindAction.get(NodeFindAction.class);
-        Object key = callFindAction.getActionMapKey();
-        actionMap.put(key, findAction);
+        // TODO: Fix the hot key for entering the satellite view
+        this.addKeyListener(keyListener);
 
-        scene.getScrollPane().addKeyListener(keyListener);
-        scene.getView().addKeyListener(keyListener);
-        satelliteComponent.addKeyListener(keyListener);
+        scene.getComponent().addHierarchyBoundsListener(new HierarchyBoundsListener() {
 
-        scene.getScrollPane().addHierarchyBoundsListener(new HierarchyBoundsListener() {
-
+            @Override
             public void ancestorMoved(HierarchyEvent e) {
             }
 
+            @Override
             public void ancestorResized(HierarchyEvent e) {
-                if (!notFirstTime && scene.getScrollPane().getBounds().width > 0) {
+                if (!notFirstTime && scene.getComponent().getBounds().width > 0) {
                     notFirstTime = true;
                     SwingUtilities.invokeLater(new Runnable() {
 
+                        @Override
                         public void run() {
-                            Figure f = EditorTopComponent.this.scene.getModel().getDiagramToView().getRootFigure();
-                            if (f != null) {
-                                scene.setUndoRedoEnabled(false);
-                                scene.gotoFigure(f);
-                                scene.setUndoRedoEnabled(true);
-                            }
+                            EditorTopComponent.this.scene.initialize();
                         }
                     });
                 }
             }
         });
 
+        if (diagram.getGraph().getGroup().getGraphsCount() == 1) {
+            rangeSlider.setVisible(false);
+        }
+
         updateDisplayName();
     }
     private KeyListener keyListener = new KeyListener() {
 
+        @Override
         public void keyTyped(KeyEvent e) {
         }
 
+        @Override
         public void keyPressed(KeyEvent e) {
             if (e.getKeyCode() == KeyEvent.VK_S) {
                 EditorTopComponent.this.overviewButton.setSelected(true);
@@ -308,6 +349,7 @@
             }
         }
 
+        @Override
         public void keyReleased(KeyEvent e) {
             if (e.getKeyCode() == KeyEvent.VK_S) {
                 EditorTopComponent.this.overviewButton.setSelected(false);
@@ -317,7 +359,7 @@
     };
 
     public DiagramViewModel getDiagramModel() {
-        return scene.getModel();
+        return rangeSliderModel;
     }
 
     private void showSatellite() {
@@ -328,35 +370,15 @@
 
     private void showScene() {
         cardLayout.show(centerPanel, SCENE_STRING);
-        scene.getView().requestFocus();
-    }
-
-    public void findNode() {
-        findPanel.find();
+        scene.getComponent().requestFocus();
     }
 
     public void zoomOut() {
-        double zoom = scene.getZoomFactor();
-        Point viewPosition = scene.getScrollPane().getViewport().getViewPosition();
-        double newZoom = zoom / DiagramScene.ZOOM_INCREMENT;
-        if (newZoom > DiagramScene.ZOOM_MIN_FACTOR) {
-            scene.setZoomFactor(newZoom);
-            scene.validate();
-            scene.getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x / DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y / DiagramScene.ZOOM_INCREMENT)));
-            this.satelliteComponent.update();
-        }
+        scene.zoomOut();
     }
 
     public void zoomIn() {
-        double zoom = scene.getZoomFactor();
-        Point viewPosition = scene.getScrollPane().getViewport().getViewPosition();
-        double newZoom = zoom * DiagramScene.ZOOM_INCREMENT;
-        if (newZoom < DiagramScene.ZOOM_MAX_FACTOR) {
-            scene.setZoomFactor(newZoom);
-            scene.validate();
-            scene.getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x * DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y * DiagramScene.ZOOM_INCREMENT)));
-            this.satelliteComponent.update();
-        }
+        scene.zoomIn();
     }
 
     public void showPrevDiagram() {
@@ -370,11 +392,11 @@
     }
 
     public DiagramViewModel getModel() {
-        return scene.getModel();
+        return rangeSliderModel;
     }
 
     public FilterChain getFilterChain() {
-        return this.scene.getModel().getFilterChain();
+        return getModel().getFilterChain();
     }
 
     public static EditorTopComponent getActive() {
@@ -407,6 +429,7 @@
         // 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;
@@ -418,6 +441,7 @@
 
     @Override
     public void componentClosed() {
+        rangeSliderModel.close();
     }
 
     @Override
@@ -425,9 +449,18 @@
         return PREFERRED_ID;
     }
 
-    public void changed(RangeSliderModel model) {
-        updateDisplayName();
-    }
+    private ChangedListener<DiagramViewModel> diagramChangedListener = new ChangedListener<DiagramViewModel>() {
+
+        @Override
+        public void changed(DiagramViewModel source) {
+            updateDisplayName();
+            Collection<Object> list = new ArrayList<>();
+            list.add(new EditorInputGraphProvider(EditorTopComponent.this));
+            graphContent.set(list, null);
+            diagramProvider.getChangedEvent().fire();
+        }
+
+    };
 
     public boolean showPredSucc() {
         return (Boolean) predSuccAction.getValue(PredSuccAction.STATE);
@@ -435,24 +468,25 @@
 
     public void setSelection(PropertyMatcher matcher) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(scene.getModel().getDiagramToView().getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(getModel().getDiagramToView().getFigures());
         List<Figure> list = selector.selectMultiple(matcher);
-        boolean b = scene.getUndoRedoEnabled();
-        scene.setUndoRedoEnabled(false);
-        scene.gotoFigures(list);
-        scene.setUndoRedoEnabled(b);
+        setSelectedFigures(list);
+    }
+
+    public void setSelectedFigures(List<Figure> list) {
         scene.setSelection(list);
+        scene.centerFigures(list);
     }
 
     public void setSelectedNodes(Set<InputNode> nodes) {
 
-        List<Figure> list = new ArrayList<Figure>();
-        Set<Integer> ids = new HashSet<Integer>();
+        List<Figure> list = new ArrayList<>();
+        Set<Integer> ids = new HashSet<>();
         for (InputNode n : nodes) {
             ids.add(n.getId());
         }
 
-        for (Figure f : scene.getModel().getDiagramToView().getFigures()) {
+        for (Figure f : getModel().getDiagramToView().getFigures()) {
             for (InputNode n : f.getSource().getSourceNodes()) {
                 if (ids.contains(n.getId())) {
                     list.add(f);
@@ -461,10 +495,10 @@
             }
         }
 
-        scene.gotoFigures(list);
-        scene.setSelection(list);
+        setSelectedFigures(list);
     }
 
+    @Override
     public void propertyChange(PropertyChangeEvent evt) {
         if (evt.getSource() == this.predSuccAction) {
             boolean b = (Boolean) predSuccAction.getValue(PredSuccAction.STATE);
@@ -478,27 +512,35 @@
             }
         } else if (evt.getSource() == this.blockLayoutAction) {
             boolean b = (Boolean) blockLayoutAction.getValue(EnableBlockLayoutAction.STATE);
-            System.out.println("Showblocks = " + b);
             this.getModel().setShowBlocks(b);
+        } else if (evt.getSource() == this.hideDuplicatesAction) {
+            boolean b = (Boolean) hideDuplicatesAction.getValue(HideDuplicatesAction.STATE);
+            this.getModel().setHideDuplicates(b);
+        } else if (evt.getSource() == this.selectionModeAction || evt.getSource() == this.panModeAction) {
+            if (panModeAction.isSelected()) {
+                scene.setInteractionMode(DiagramViewer.InteractionMode.PANNING);
+            } else if (selectionModeAction.isSelected()) {
+                scene.setInteractionMode(DiagramViewer.InteractionMode.SELECTION);
+            }
         } else {
             assert false : "Unknown event source";
         }
     }
 
     public void extract() {
-        scene.showOnly(scene.getSelectedNodes());
+        getModel().showOnly(getModel().getSelectedNodes());
     }
 
     public void hideNodes() {
-        Set<Integer> selectedNodes = this.scene.getSelectedNodes();
-        HashSet<Integer> nodes = new HashSet<Integer>(scene.getModel().getHiddenNodes());
+        Set<Integer> selectedNodes = this.getModel().getSelectedNodes();
+        HashSet<Integer> nodes = new HashSet<>(getModel().getHiddenNodes());
         nodes.addAll(selectedNodes);
-        this.scene.showNot(nodes);
+        this.getModel().showNot(nodes);
     }
 
     public void expandPredecessors() {
-        Set<Figure> oldSelection = scene.getSelectedFigures();
-        Set<Figure> figures = new HashSet<Figure>();
+        Set<Figure> oldSelection = getModel().getSelectedFigures();
+        Set<Figure> figures = new HashSet<>();
 
         for (Figure f : this.getDiagramModel().getDiagramToView().getFigures()) {
             boolean ok = false;
@@ -518,12 +560,12 @@
             }
         }
 
-        scene.showAll(figures);
+        getModel().showAll(figures);
     }
 
     public void expandSuccessors() {
-        Set<Figure> oldSelection = scene.getSelectedFigures();
-        Set<Figure> figures = new HashSet<Figure>();
+        Set<Figure> oldSelection = getModel().getSelectedFigures();
+        Set<Figure> figures = new HashSet<>();
 
         for (Figure f : this.getDiagramModel().getDiagramToView().getFigures()) {
             boolean ok = false;
@@ -543,11 +585,11 @@
             }
         }
 
-        scene.showAll(figures);
+        getModel().showAll(figures);
     }
 
     public void showAll() {
-        scene.showNot(new HashSet<Integer>());
+        getModel().showNot(new HashSet<Integer>());
     }
 
     public Diagram getDiagram() {
@@ -555,23 +597,31 @@
     }
 
     @Override
-    protected void componentActivated() {
+    protected void componentHidden() {
+        super.componentHidden();
+        scene.componentHidden();
+
     }
 
     @Override
-    public void requestFocus() {
-        super.requestFocus();
-        scene.getView().requestFocus();
+    protected void componentShowing() {
+        super.componentShowing();
+        scene.componentShowing();
     }
 
     @Override
-    public boolean requestFocusInWindow() {
-        super.requestFocusInWindow();
-        return scene.getView().requestFocusInWindow();
+    public void requestActive() {
+        super.requestActive();
+        scene.getComponent().requestFocus();
     }
 
     @Override
     public UndoRedo getUndoRedo() {
         return scene.getUndoRedo();
     }
+
+    @Override
+    protected Object writeReplace() throws ObjectStreamException {
+        throw new NotSerializableException();
 }
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExportCookie.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExportCookie.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedPanAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +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;
-
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.Point;
-import org.netbeans.api.visual.widget.Scene;
-import org.netbeans.api.visual.widget.Widget;
-import org.netbeans.api.visual.action.WidgetAction;
-
-import java.awt.event.MouseEvent;
-import javax.swing.JComponent;
-import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
-
-/**
- * @author David Kaspar
- * @author Thomas Wuerthinger
- */
-public class ExtendedPanAction extends WidgetAction.LockedAdapter {
-
-    private Scene scene;
-    private JScrollPane scrollPane;
-    private Point lastLocation;
-
-    protected boolean isLocked() {
-        return scrollPane != null;
-    }
-
-    @Override
-    public State mousePressed(Widget widget, WidgetMouseEvent event) {
-        if (event.getButton() == MouseEvent.BUTTON2 || event.getButton() == MouseEvent.BUTTON1 && ((event.getModifiers() & MouseEvent.CTRL_MASK) != 0)) {
-            scene = widget.getScene();
-            scrollPane = findScrollPane(scene.getView());
-            if (scrollPane != null) {
-                lastLocation = scene.convertSceneToView(widget.convertLocalToScene(event.getPoint()));
-                SwingUtilities.convertPointToScreen(lastLocation, scrollPane.getViewport().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, scrollPane.getViewport().getView());
-        Point viewPosition = scrollPane.getViewport().getViewPosition();
-        Dimension viewSize = scrollPane.getViewport().getViewSize();
-        Dimension viewPortSize = scrollPane.getViewport().getSize();
-
-        int xOffset = lastLocation.x - newLocation.x;
-        int yOffset = lastLocation.y - newLocation.y;
-
-        if (viewPortSize.height == viewSize.height) {
-            yOffset = 0;
-        }
-
-        if (viewPortSize.width == viewSize.width) {
-            xOffset = 0;
-        }
-
-        if (xOffset == 0 && yOffset == 0) {
-            return true;
-        }
-        viewPosition = new Point(viewPosition.x + xOffset, viewPosition.y + yOffset);
-        viewPosition.x = Math.max(viewPosition.x, 0);
-        viewPosition.y = Math.max(viewPosition.y, 0);
-        viewPosition.x = Math.min(viewPosition.x, scrollPane.getViewport().getView().getSize().width - scrollPane.getViewport().getSize().width);
-        viewPosition.y = Math.min(viewPosition.y, scrollPane.getViewport().getView().getSize().height - scrollPane.getViewport().getSize().height);
-
-        scrollPane.getViewport().setViewPosition(viewPosition);
-        scrollPane.getViewport().getView().repaint();
-        lastLocation = newLocation;
-        return true;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedSatelliteComponent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedSatelliteComponent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,10 @@
  */
 package com.sun.hotspot.igv.view;
 
-import org.netbeans.api.visual.widget.Scene;
-
-import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
+import javax.swing.JComponent;
+import org.netbeans.api.visual.widget.Scene;
 
 /**
  * @author David Kaspar
@@ -48,6 +47,7 @@
         addMouseMotionListener(this);
     }
 
+    @Override
     public void addNotify() {
         super.addNotify();
         scene.addSceneListener(this);
@@ -59,6 +59,7 @@
         repaint();
     }
 
+    @Override
     public void removeNotify() {
         scene.getView().removeComponentListener(this);
         scene.removeSceneListener(this);
@@ -74,6 +75,7 @@
         }
     }
 
+    @Override
     public void paint(Graphics g) {
         Graphics2D gr = (Graphics2D) g;
         super.paint(g);
@@ -91,15 +93,15 @@
 
 
         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.setRealZoomFactor(scale);
+            double oldFactor = scene.getZoomFactor();
+            scene.setZoomFactor(scale);
             scene.paint(ig);
-            scene.setRealZoomFactor(0.0);
+            scene.setZoomFactor(oldFactor);
         }
 
         gr.drawImage(image, vx, vy, this);
@@ -121,27 +123,34 @@
         }
     }
 
+    @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) {
     }
 
@@ -174,27 +183,34 @@
         this.repaint();
     }
 
+    @Override
     public void sceneRepaint() {
     //repaint ();
     }
 
+    @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) {
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +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;
-
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
-import com.sun.hotspot.igv.data.Property;
-import java.awt.GridLayout;
-import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import javax.swing.JComboBox;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-class FindPanel extends JPanel implements KeyListener {
-
-    private JComboBox nameComboBox;
-    private JTextField valueTextField;
-
-    public FindPanel(List<Figure> figures) {
-        createDesign();
-        updateComboBox(figures);
-    }
-
-    protected void createDesign() {
-        setLayout(new GridLayout());
-        nameComboBox = new JComboBox();
-        valueTextField = new JTextField();
-        add(nameComboBox);
-        add(valueTextField);
-        valueTextField.addKeyListener(this);
-    }
-
-    public void updateComboBox(List<Figure> figures) {
-
-        String sel = (String) nameComboBox.getSelectedItem();
-        SortedSet<String> propertyNames = new TreeSet<String>();
-
-        for (Figure f : figures) {
-            Properties prop = f.getProperties();
-            for (Property p : prop) {
-                if (!propertyNames.contains(p.getName())) {
-                    propertyNames.add(p.getName());
-                }
-            }
-        }
-
-        for (String s : propertyNames) {
-            nameComboBox.addItem(s);
-        }
-        nameComboBox.setSelectedItem(sel);
-    }
-
-    public String getNameText() {
-        return (String) nameComboBox.getSelectedItem();
-    }
-
-    public String getValueText() {
-        return valueTextField.getText();
-    }
-
-    public void keyTyped(KeyEvent e) {
-    }
-
-    public void keyPressed(KeyEvent e) {
-        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
-            find();
-        }
-    }
-
-    public void find() {
-        EditorTopComponent comp = EditorTopComponent.getActive();
-        if (comp != null) {
-            RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(getNameText(), getValueText());
-            comp.setSelection(matcher);
-        }
-    }
-
-    public void keyReleased(KeyEvent e) {
-
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/GraphViewerImplementation.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/GraphViewerImplementation.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,9 @@
 import com.sun.hotspot.igv.data.services.GraphViewer;
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.settings.Settings;
+import org.openide.windows.Mode;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
 
 /**
  *
@@ -34,7 +37,25 @@
  */
 public class GraphViewerImplementation implements GraphViewer {
 
-    public void view(InputGraph graph) {
+    @Override
+    public void view(InputGraph graph, boolean clone) {
+
+        if (!clone) {
+            WindowManager manager = WindowManager.getDefault();
+            for (Mode m : manager.getModes()) {
+                for (TopComponent t : manager.getOpenedTopComponents(m)) {
+                    if (t instanceof EditorTopComponent) {
+                        EditorTopComponent etc = (EditorTopComponent) t;
+                        if (etc.getModel().getGroup().getGraphs().contains(graph)) {
+                            etc.getModel().selectGraph(graph);
+                            t.requestActive();
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
         Diagram diagram = Diagram.createDiagram(graph, Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
         EditorTopComponent tc = new EditorTopComponent(diagram);
         tc.open();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/NodeQuickSearch.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.view;
+
+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.RegexpPropertyMatcher;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
+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 = LookupHistory.getLast(InputGraphProvider.class);
+        if (p != null && p.getGraph() != null) {
+            InputGraph matchGraph = p.getGraph();
+            // Search the current graph
+            List<InputNode> matches = findMatches(name, value, p.getGraph(), response);
+            if (matches == null) {
+                // See if the it hits in a later graph
+                for (InputGraph graph : p.searchForward()) {
+                    matches = findMatches(name, value, graph, response);
+                    if (matches != null) {
+                        matchGraph = graph;
+                        break;
+                    }
+                }
+            }
+            if (matches == null) {
+                // See if it hits in a earlier graph
+                for (InputGraph graph : p.searchBackward()) {
+                    matches = findMatches(name, value, graph, response);
+                    if (matches != null) {
+                        matchGraph = graph;
+                        break;
+                    }
+                }
+            }
+
+            if (matches != null) {
+                final Set<InputNode> set = new HashSet<>(matches);
+                final InputGraph theGraph = p.getGraph() != matchGraph ? matchGraph : null;
+                response.addResult(new Runnable() {
+                    @Override
+                    public void run() {
+                        final EditorTopComponent comp = EditorTopComponent.getActive();
+                        if (comp != null) {
+                            if (theGraph != null) {
+                                comp.getDiagramModel().selectGraph(theGraph);
+                            }
+                            comp.setSelectedNodes(set);
+                            comp.requestActive();
+                        }
+                    }
+                },
+                        "All " + matches.size() + " matching nodes (" + name + "=" + value + ")" + (theGraph != null ? " in " + theGraph.getName() : "")
+                );
+
+                // 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<InputNode> tmpSet = new HashSet<>();
+                                tmpSet.add(n);
+                                if (theGraph != null) {
+                                    comp.getDiagramModel().selectGraph(theGraph);
+                                }
+                                comp.setSelectedNodes(tmpSet);
+                                comp.requestActive();
+                            }
+                        }
+                    },
+                            n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")" + (theGraph != null ? " in " + theGraph.getName() : "")
+                    );
+                }
+            }
+        } else {
+            System.out.println("no input graph provider!");
+        }
+    }
+
+    private List<InputNode> findMatches(String name, String value, InputGraph inputGraph, SearchResponse response) {
+        try {
+            RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(name, value, Pattern.CASE_INSENSITIVE);
+            Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(inputGraph.getNodes());
+            List<InputNode> matches = selector.selectMultiple(matcher);
+            return matches.size() == 0 ? null : matches;
+        } 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)"
+            );
+        }
+        return null;
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/PreferenceConstants.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +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;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class PreferenceConstants {
-
-    public static final String KEY_LINE_GENERATOR = "lineGenerator";
-    public static final String DEFAULT_LINE_GENERATOR = "com.sun.hotspot.igv.positioning.BasicLineGenerator";
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/SlotLayout.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +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;
-
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.util.Collection;
-import java.util.List;
-import org.netbeans.api.visual.layout.Layout;
-import org.netbeans.api.visual.layout.LayoutFactory;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class SlotLayout implements Layout {
-
-    public enum HorizontalAlignment {
-
-        Left,
-        Center,
-        Right
-    }
-    private Layout baseLayout;
-    private HorizontalAlignment alignment;
-    private boolean vertical;
-
-    public SlotLayout() {
-        this(HorizontalAlignment.Center, false);
-    }
-
-    public SlotLayout(HorizontalAlignment alignment, boolean vertical) {
-        this.alignment = alignment;
-        baseLayout = LayoutFactory.createVerticalFlowLayout();
-        this.vertical = vertical;
-    }
-
-    public void layout(Widget widget) {
-        if (!vertical) {
-            Collection<Widget> children = widget.getChildren();
-            int gap = 0;
-            int max = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int i = preferredBounds.width;
-                if (i > max) {
-                    max = i;
-                }
-            }
-            int pos = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int x = preferredBounds.x;
-                int y = preferredBounds.y;
-                int width = preferredBounds.width;
-                int height = preferredBounds.height;
-                if (pos == 0) {
-                    pos += height / 2;
-                }
-                int lx = -x;
-                int ly = pos - y;
-                switch (alignment) {
-                    case Center:
-                        lx += (max - width) / 2;
-                        break;
-                    case Left:
-                        break;
-                    case Right:
-                        lx += max - width;
-                        break;
-                }
-                child.resolveBounds(new Point(lx, ly), new Rectangle(x, y, width, height));
-                pos += height + gap;
-            }
-        } else {
-
-            Collection<Widget> children = widget.getChildren();
-            int gap = 0;
-            int max = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int i = preferredBounds.height;
-                if (i > max) {
-                    max = i;
-                }
-            }
-            int pos = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int x = preferredBounds.x;
-                int y = preferredBounds.y;
-                int width = preferredBounds.width;
-                int height = preferredBounds.height;
-                if (pos == 0) {
-                    pos += width / 2;
-                }
-                int lx = pos - x;
-                int ly = -y;
-                switch (alignment) {
-                    case Center:
-                        ly += (max - height) / 2;
-                        break;
-                    case Left:
-                        break;
-                    case Right:
-                        ly += max - height;
-                        break;
-                }
-                child.resolveBounds(new Point(lx, ly), new Rectangle(x, y, width, height));
-                pos += width + gap;
-            }
-
-        }
-    }
-
-    public boolean requiresJustification(Widget widget) {
-        return true;
-    }
-
-    public void justify(Widget widget) {
-        baseLayout.justify(widget);
-
-        Rectangle client = widget.getClientArea();
-        List<Widget> children = widget.getChildren();
-
-        int count = children.size();
-        int z = 0;
-
-        int maxWidth = 0;
-        for (Widget c : children) {
-            if (c.getPreferredBounds().width > maxWidth) {
-                maxWidth = c.getPreferredBounds().width;
-            }
-        }
-
-        for (Widget c : children) {
-            z++;
-            Point curLocation = c.getLocation();
-            Rectangle curBounds = c.getBounds();
-
-
-            Point location = new Point(curLocation.x, client.y + client.height * z / (count + 1) - curBounds.height / 2);
-            if (vertical) {
-                location = new Point(client.x + client.width * z / (count + 1) - maxWidth / 2, curLocation.y);
-            }
-            c.resolveBounds(location, null);
-        }
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,7 +1,6 @@
 CTL_EditorAction=Open Editor Window
-CTL_LineGeneratorAction=Line Generator
 CTL_NextDiagramAction=Show next graph
 CTL_EnableBlockLayoutAction=Enable block layout
 CTL_NodeFindAction=Find
 CTL_PrevDiagramAction=Show previous graph
-CTL_ExportAction=Export...
+CTL_ExportAction=Export current graph...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/CustomizablePanAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,146 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 1997, 2015, 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.actions;
+
+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 CustomizablePanAction 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 CustomizablePanAction(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;
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/EnableBlockLayoutAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/EnableBlockLayoutAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -38,9 +39,9 @@
     public static final String STATE = "state";
 
     public EnableBlockLayoutAction() {
-        state = true;
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
-        putValue(STATE, true);
+        state = false;
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
+        putValue(STATE, state);
         putValue(Action.SHORT_DESCRIPTION, "Cluster nodes into blocks");
     }
 
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
  */
 public final class ExpandPredecessorsAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -40,8 +41,9 @@
         }
     }
 
+    @Override
     public String getName() {
-        return "Expand Predecessors";
+        return "Expand Above";
     }
 
     @Override
@@ -49,6 +51,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
  */
 public final class ExpandSuccessorsAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -40,8 +41,9 @@
         }
     }
 
+    @Override
     public String getName() {
-        return "Expand Successors";
+        return "Expand Below";
     }
 
     @Override
@@ -49,6 +51,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExportAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExportAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,12 +32,7 @@
 import javax.swing.JFileChooser;
 import javax.swing.KeyStroke;
 import javax.swing.filechooser.FileFilter;
-import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
-import org.openide.util.LookupEvent;
-import org.openide.util.LookupListener;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
+import org.openide.util.*;
 import org.openide.util.actions.CallableSystemAction;
 
 /**
@@ -50,27 +45,31 @@
     private final Lookup.Result<ExportCookie> result;
 
     public ExportAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Export current graph as an SVG file");
+        putValue(Action.SHORT_DESCRIPTION, "Export current graph as SVG file");
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK));
         lookup = Utilities.actionsGlobalContext();
-        result = lookup.lookup(new Lookup.Template<ExportCookie>(ExportCookie.class));
+        result = lookup.lookup(new Lookup.Template<>(ExportCookie.class));
         result.addLookupListener(this);
         resultChanged(null);
     }
 
+    @Override
     public void resultChanged(LookupEvent e) {
         super.setEnabled(result.allInstances().size() > 0);
     }
 
+    @Override
     public void performAction() {
 
         JFileChooser fc = new JFileChooser();
         fc.setFileFilter(new FileFilter() {
 
+            @Override
             public boolean accept(File f) {
                 return true;
             }
 
+            @Override
             public String getDescription() {
                 return "SVG files (*.svg)";
             }
@@ -97,15 +96,17 @@
         }
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(ExportAction.class, "CTL_ExportAction");
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/export.gif";
+        return "com/sun/hotspot/igv/view/images/export.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExtractAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExtractAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
  */
 public final class ExtractAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -49,6 +50,7 @@
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK, false));
     }
 
+    @Override
     public String getName() {
         return "Extract action";
     }
@@ -58,6 +60,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/HideAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/HideAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
  */
 public final class HideAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -49,6 +50,7 @@
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.CTRL_MASK, false));
     }
 
+    @Override
     public String getName() {
         return "Hide";
     }
@@ -58,6 +60,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/HideDuplicatesAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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 Tom Rodriguez
+ */
+public class HideDuplicatesAction extends AbstractAction {
+
+    private boolean state;
+    public static final String STATE = "state";
+
+    public HideDuplicatesAction() {
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
+        putValue(Action.SHORT_DESCRIPTION, "Hide graphs which are the same as the previous graph");
+        setState(false);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent ev) {
+        setState(!state);
+    }
+
+    public void setState(boolean b) {
+        this.putValue(STATE, b);
+        this.state = b;
+    }
+
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/hideDuplicates.png";
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/MouseOverAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/MouseOverAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NextDiagramAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NextDiagramAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,15 +23,12 @@
  */
 package com.sun.hotspot.igv.view.actions;
 
-import com.sun.hotspot.igv.view.DiagramViewModel;
 import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.util.ContextAction;
+import com.sun.hotspot.igv.view.DiagramViewModel;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
-import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
+import org.openide.util.*;
 
 /**
  *
@@ -47,13 +44,15 @@
 
     public NextDiagramAction(Lookup lookup) {
         putValue(Action.SHORT_DESCRIPTION, "Show next graph of current group");
-        putValue(Action.SMALL_ICON, new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/view/images/next_diagram.png")));
+        putValue(Action.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/view/images/next_diagram.png")));
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(NextDiagramAction.class, "CTL_NextDiagramAction");
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -95,10 +94,12 @@
         return model.getSecondPosition() != model.getPositions().size() - 1;
     }
 
+    @Override
     public Action createContextAwareInstance(Lookup arg0) {
         return new NextDiagramAction(arg0);
     }
 
+    @Override
     public void changed(DiagramViewModel source) {
         update(source);
     }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NodeFindAction.java	Mon Dec 05 13:09:39 2016 -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.view.actions;
-
-import com.sun.hotspot.igv.view.EditorTopComponent;
-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 NodeFindAction extends CallableSystemAction {
-
-    public void performAction() {
-        EditorTopComponent comp = EditorTopComponent.getActive();
-        if (comp != null) {
-            comp.findNode();
-        }
-    }
-
-    public NodeFindAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Find nodes");
-    }
-
-    public String getName() {
-        return NbBundle.getMessage(NodeFindAction.class, "CTL_NodeFindAction");
-    }
-
-    public HelpCtx getHelpCtx() {
-        return HelpCtx.DEFAULT_HELP;
-    }
-
-    @Override
-    protected boolean asynchronous() {
-        return false;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return true;
-    }
-
-    @Override
-    protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/search.gif";
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/OverviewAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/OverviewAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -38,11 +39,12 @@
     public static final String STATE = "state";
 
     public OverviewAction() {
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
         putValue(Action.SHORT_DESCRIPTION, "Show satellite view of whole graph");
         setState(false);
     }
 
+    @Override
     public void actionPerformed(ActionEvent ev) {
         setState(!state);
     }
@@ -53,6 +55,6 @@
     }
 
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/overview.gif";
+        return "com/sun/hotspot/igv/view/images/overview.png";
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PanModeAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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;
+
+public class PanModeAction extends AbstractAction {
+
+    private boolean state;
+
+    public PanModeAction() {
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
+        putValue(SELECTED_KEY, false);
+        putValue(Action.SHORT_DESCRIPTION, "Panning mode");
+    }
+
+    public boolean isSelected() {
+        return (Boolean)getValue(SELECTED_KEY);
+    }
+
+    public void setSelected(boolean b) {
+        if (isSelected() != b) {
+            this.putValue(SELECTED_KEY, b);
+        }
+    }
+
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/pan_mode.png";
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -39,11 +40,12 @@
 
     public PredSuccAction() {
         state = true;
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
+        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);
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PrevDiagramAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PrevDiagramAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,14 +24,11 @@
 package com.sun.hotspot.igv.view.actions;
 
 import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.util.ContextAction;
 import com.sun.hotspot.igv.view.DiagramViewModel;
-import com.sun.hotspot.igv.util.ContextAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
-import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
+import org.openide.util.*;
 
 /**
  *
@@ -47,13 +44,15 @@
 
     public PrevDiagramAction(Lookup lookup) {
         putValue(Action.SHORT_DESCRIPTION, "Show previous graph of current group");
-        putValue(Action.SMALL_ICON, new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/view/images/prev_diagram.png")));
+        putValue(Action.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/view/images/prev_diagram.png")));
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(PrevDiagramAction.class, "CTL_PrevDiagramAction");
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -95,10 +94,12 @@
         return model.getFirstPosition() != 0;
     }
 
+    @Override
     public Action createContextAwareInstance(Lookup arg0) {
         return new PrevDiagramAction(arg0);
     }
 
+    @Override
     public void changed(DiagramViewModel source) {
         update(source);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/SelectionModeAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+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;
+
+public class SelectionModeAction extends AbstractAction {
+
+    public SelectionModeAction() {
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
+        putValue(SELECTED_KEY, false);
+        putValue(Action.SHORT_DESCRIPTION, "Selection mode");
+    }
+
+    public boolean isSelected() {
+        return (Boolean)getValue(SELECTED_KEY);
+    }
+
+    public void setSelected(boolean b) {
+        if (isSelected() != b) {
+            this.putValue(SELECTED_KEY, b);
+        }
+    }
+
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/selection_mode.png";
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ShowAllAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ShowAllAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
  */
 package com.sun.hotspot.igv.view.actions;
 
-import com.sun.hotspot.igv.view.*;
+import com.sun.hotspot.igv.view.EditorTopComponent;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import javax.swing.Action;
@@ -37,6 +37,7 @@
  */
 public final class ShowAllAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -49,6 +50,7 @@
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK));
     }
 
+    @Override
     public String getName() {
         return "Show all";
     }
@@ -58,6 +60,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomInAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomInAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
  */
 public final class ZoomInAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -44,6 +45,7 @@
         }
     }
 
+    @Override
     public String getName() {
         return "Zoom in";
     }
@@ -53,6 +55,7 @@
         putValue(Action.SHORT_DESCRIPTION, "Zoom in");
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -64,6 +67,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/zoomin.gif";
+        return "com/sun/hotspot/igv/view/images/zoom_in.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomOutAction.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomOutAction.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
  */
 public final class ZoomOutAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -50,6 +51,7 @@
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, Event.CTRL_MASK, false));
     }
 
+    @Override
     public String getName() {
         return "Zoom out";
     }
@@ -59,6 +61,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -70,6 +73,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/zoomout.gif";
+        return "com/sun/hotspot/igv/view/images/zoom_out.png";
     }
 }
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/hideDuplicates.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/overview.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/overview.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/pan_mode.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/search.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/selection_mode.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoom_in.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoom_out.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomin.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomout.gif has changed
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -24,36 +24,76 @@
         <folder name="View">
             <file name="com-sun-hotspot-igv-view-actions-PrevDiagramAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-PrevDiagramAction.instance"/>
+                <attr name="position" intvalue="100"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-NextDiagramAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-NextDiagramAction.instance"/>
+                <attr name="position" intvalue="150"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-ShowAllAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-ShowAllAction.instance"/>
+                <attr name="position" intvalue="200"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-ExtractAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-ExtractAction.instance"/>
+                <attr name="position" intvalue="300"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-HideAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-HideAction.instance"/>
+                <attr name="position" intvalue="400"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-ZoomInAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-ZoomInAction.instance"/>
+                <attr name="position" intvalue="500"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-ZoomOutAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-ZoomOutAction.instance"/>
+                <attr name="position" intvalue="550"/>
             </file>
         </folder>
         <folder name="File">
+            <file name="ExportActionSeparator.instance">
+                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                <attr name="position" intvalue="700"/>
+            </file>
             <file name="com-sun-hotspot-igv-view-actions-ExportAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-view-actions-ExportAction.instance"/>
-                <attr name="position" intvalue="600"/>
+                <attr name="position" intvalue="710"/>
             </file>
         </folder>
+        <folder name="Window">
+            <file name="Web_hidden"/>
+            <file name="org-netbeans-modules-tasks-ui-DashboardTopComponent.shadow_hidden"/>
+        </folder>
     </folder>
-    <folder name="Toolbars">
-        <folder name="Edit">
-            <attr name="com-sun-hotspot-igv-view-actions-LineGeneratorAction.shadow/com-sun-hotspot-igv-coordinator-actions-OpenGraphAction.shadow" boolvalue="true"/>
+
+    <folder name="QuickSearch">
+        <file name="Actions_hidden"/>
+        <file name="GoToOption_hidden"/>
+        <file name="GoToSymbol_hidden"/>
+        <file name="GoToType_hidden"/>
+        <file name="Help_hidden"/>
+        <file name="Hudson_hidden"/>
+        <folder name="Nodes">
+            <attr name="command" stringvalue="n"/>
+            <attr name="position" intvalue="0"/>
+            <file name="com-sun-hotspot-igv-view-NodeQuickSearch.instance"/>
+        </folder>
+        <file name="Projects_hidden"/>
+    </folder>
+    
+    <folder name="QuickSearchShadow">
+        <file name="org-netbeans-modules-quicksearch-QuickSearchAction.shadow">
+            <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-quicksearch-QuickSearchAction.instance"/>
+            
+        </file>    
+    </folder>
+    <folder name="Windows2">
+        <folder name="Modes">
+            <folder name="properties">
+                <file name="properties.wstcref" url="propertiesWstcref.xml"/>
+            </folder>
+            <file name="properties.wsmode" url="propertiesWsmode.xml"/>
         </folder>
     </folder>
 </filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/propertiesWsmode.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE mode PUBLIC
+          "-//NetBeans//DTD Mode Properties 2.0//EN"
+          "http://www.netbeans.org/dtds/mode-properties2_0.dtd">
+
+<mode version="2.0">
+    <name unique="properties" />
+    <kind type="view" />
+    <state type="joined" />
+    <constraints>
+        <path orientation="horizontal" number="90" weight="0.2"/>
+        <path orientation="vertical" number="1" weight="0.50"/>
+    </constraints>
+    <relative-bounds x="75" y="56" width="15" height="32" />
+    <active-tc id="properties" />
+    <empty-behavior permanent="true" />
+</mode>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/propertiesWstcref.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE tc-ref PUBLIC
+          "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN"
+          "http://www.netbeans.org/dtds/tc-ref2_0.dtd">
+
+<tc-ref version="2.0">
+    <module name="org.netbeans.core.ui/1" spec="1.2" />
+    <tc-id id="properties" />
+    <state opened="true" />
+</tc-ref>
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/BlockWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/BlockWidget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,7 +74,7 @@
         g.setColor(titleColor);
         g.setFont(titleFont);
 
-        String s = "B" + blockNode.toString();
+        String s = "B" + blockNode.getName();
         Rectangle2D r1 = g.getFontMetrics().getStringBounds(s, g);
         g.drawString(s, r.x + 5, r.y + (int) r1.getHeight());
         g.setStroke(old);
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/DiagramConnectionWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +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.view.DiagramScene;
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Stroke;
-import java.util.ArrayList;
-import java.util.List;
-import org.netbeans.api.visual.anchor.AnchorShape;
-import org.netbeans.api.visual.model.ObjectState;
-import org.netbeans.api.visual.widget.ConnectionWidget;
-import org.netbeans.api.visual.widget.Scene;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class DiagramConnectionWidget extends ConnectionWidget {
-
-    private static Stroke DASHED_STROKE = new BasicStroke(
-            1,
-            BasicStroke.CAP_BUTT,
-            BasicStroke.JOIN_ROUND,
-            0,
-            new float[]{2},
-            0);
-    private static Stroke NORMAL_STROKE = new BasicStroke(1);
-    private static Stroke BOLD_STROKE = new BasicStroke(3);
-    public static int WHITE_FACTOR = 5;
-    private Connection connection;
-    private Color color;
-    private Point lastSourceAnchor;
-    private Point lastTargetAnchor;
-    private List<Point> controlPoints;
-    private Rectangle clientArea;
-    private boolean split;
-    private int[] xPoints;
-    private int[] yPoints;
-    private int pointCount;
-
-    /** Creates a new instance of ConnectionWidget */
-    public DiagramConnectionWidget(Connection connection, Scene scene) {
-        super(scene);
-        this.connection = connection;
-        color = connection.getColor();
-        if (connection.getStyle() == Connection.ConnectionStyle.DASHED) {
-            this.setStroke(DASHED_STROKE);
-        } else if (connection.getStyle() == Connection.ConnectionStyle.BOLD) {
-            this.setStroke(BOLD_STROKE);
-        } else {
-            this.setStroke(NORMAL_STROKE);
-        }
-        this.setCheckClipping(true);
-        clientArea = new Rectangle();
-        updateControlPoints();
-    }
-
-    public Connection getConnection() {
-        return connection;
-    }
-
-    public void updateControlPoints() {
-        List<Point> newControlPoints = connection.getControlPoints();
-        Connection c = connection;
-        Figure f = c.getInputSlot().getFigure();
-        Point p = new Point(f.getPosition());
-        p.translate(c.getInputSlot().getRelativePosition().x, f.getSize().height / 2);
-        Point p4 = new Point(f.getPosition());
-        p4.translate(c.getInputSlot().getRelativePosition().x, c.getInputSlot().getRelativePosition().y);
-
-        Figure f2 = c.getOutputSlot().getFigure();
-        Point p2 = new Point(f2.getPosition());
-        p2.translate(c.getOutputSlot().getRelativePosition().x, f2.getSize().height / 2);
-        Point p3 = new Point(f2.getPosition());
-        p3.translate(c.getOutputSlot().getRelativePosition().x, c.getOutputSlot().getRelativePosition().y);
-
-        /*if(controlPoints.size() >= 2) {
-        String className = Preferences.userNodeForPackage(PreferenceConstants.class).get(PreferenceConstants.KEY_LINE_GENERATOR, PreferenceConstants.DEFAULT_LINE_GENERATOR);
-        try {
-        LineGenerator lg = (LineGenerator)Class.forName(className).newInstance();
-        controlPoints = lg.createLine(controlPoints, p2, p);
-        } catch (InstantiationException ex) {
-        } catch (IllegalAccessException ex) {
-        } catch (ClassNotFoundException ex) {
-        }
-        }*/
-
-        this.controlPoints = newControlPoints;
-        pointCount = newControlPoints.size();
-        xPoints = new int[pointCount];
-        yPoints = new int[pointCount];
-        int minX = Integer.MAX_VALUE;
-        int maxX = Integer.MIN_VALUE;
-        int minY = Integer.MAX_VALUE;
-        int maxY = Integer.MIN_VALUE;
-        split = false;
-        for (int i = 0; i < pointCount; i++) {
-            if (newControlPoints.get(i) == null) {
-                split = true;
-            } else {
-                int curX = newControlPoints.get(i).x;
-                int curY = newControlPoints.get(i).y;
-                this.xPoints[i] = curX;
-                this.yPoints[i] = curY;
-                minX = Math.min(minX, curX);
-                maxX = Math.max(maxX, curX);
-                minY = Math.min(minY, curY);
-                maxY = Math.max(maxY, curY);
-            }
-        }
-
-        this.clientArea = new Rectangle(minX, minY, maxX - minX, maxY - minY);
-    }
-
-    @Override
-    protected void paintWidget() {
-        Graphics2D g = this.getGraphics();
-
-        if (xPoints.length == 0 || Math.abs(xPoints[0] - xPoints[xPoints.length - 1]) > 2000) {
-            return;
-        }
-
-        //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
-        //g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
-        //g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
-
-        DiagramScene ds = (DiagramScene) this.getScene();
-        boolean shouldHide = false;//ds.getShouldHide(this);
-
-        Composite oldComposite = null;
-        if (shouldHide) {
-            Color c = new Color(255 - (255 - color.getRed()) / WHITE_FACTOR, 255 - (255 - color.getGreen()) / WHITE_FACTOR, 255 - (255 - color.getBlue()) / WHITE_FACTOR);
-            g.setPaint(c);
-        } else {
-            g.setPaint(color);
-        }
-
-        if (split) {
-            for (int i = 1; i < controlPoints.size(); i++) {
-                Point prev = controlPoints.get(i - 1);
-                Point cur = controlPoints.get(i);
-                if (cur == null || prev == null) {
-                    continue;
-                }
-
-                g.drawLine(prev.x, prev.y, cur.x, cur.y);
-            }
-        } else {
-            g.drawPolyline(xPoints, yPoints, pointCount);
-        }
-
-        /*for(int i=0; i<xPoints.length; i++) {
-        int x = xPoints[i];
-        int y = yPoints[i];
-        g.fillOval(x - 2, y - 2, 4, 4);
-        }*/
-
-        if (xPoints.length >= 2) {
-            Graphics2D g2 = (Graphics2D) g.create();
-            int xOff = xPoints[xPoints.length - 2] - xPoints[xPoints.length - 1];
-            int yOff = yPoints[yPoints.length - 2] - yPoints[yPoints.length - 1];
-            if (xOff == 0 && yOff == 0 && yPoints.length >= 3) {
-                xOff = xPoints[xPoints.length - 3] - xPoints[xPoints.length - 1];
-                yOff = yPoints[yPoints.length - 3] - yPoints[yPoints.length - 1];
-            }
-            g2.translate(xPoints[xPoints.length - 1], yPoints[yPoints.length - 1]);
-            g2.rotate(Math.atan2(yOff, xOff));
-
-            g2.scale(0.55, 0.80);
-            AnchorShape.TRIANGLE_FILLED.paint(g2, false);
-        }
-    }
-
-    @Override
-    public void notifyStateChanged(ObjectState previousState, ObjectState state) {
-
-        if (previousState.isHovered() != state.isHovered()) {
-            color = connection.getColor();
-            if (state.isHovered()) {
-                this.setStroke(BOLD_STROKE);
-            } else {
-                this.setStroke(NORMAL_STROKE);
-            }
-
-            if (state.isHovered()) {
-                this.setStroke(BOLD_STROKE);
-            } else {
-                this.setStroke(NORMAL_STROKE);
-            }
-
-            repaint();
-        }
-        super.notifyStateChanged(previousState, state);
-    }
-
-    @Override
-    public List<Point> getControlPoints() {
-        if (split) {
-            ArrayList<Point> result = new ArrayList<Point>();
-            for (Point p : controlPoints) {
-                if (p != null) {
-                    result.add(p);
-                }
-            }
-            return result;
-        } else {
-            return controlPoints;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "ConnectionWidget[" + connection + "]";
-    }
-
-    @Override
-    protected Rectangle calculateClientArea() {
-        Rectangle result = new Rectangle(clientArea);
-        result.grow(10, 10);
-        return result;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,36 +23,37 @@
  */
 package com.sun.hotspot.igv.view.widgets;
 
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.services.GraphViewer;
 import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.view.DiagramScene;
-import com.sun.hotspot.igv.view.SlotLayout;
+import com.sun.hotspot.igv.util.DoubleClickAction;
 import com.sun.hotspot.igv.util.DoubleClickHandler;
-import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.util.PropertiesSheet;
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.Graphics;
-import java.awt.Point;
+import com.sun.hotspot.igv.view.DiagramScene;
+import java.awt.*;
+import java.awt.event.ActionEvent;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Set;
+import javax.swing.AbstractAction;
 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.netbeans.api.visual.layout.LayoutFactory;
-import org.netbeans.api.visual.widget.LabelWidget;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
 import org.openide.nodes.Sheet;
+import org.openide.util.Lookup;
 
 /**
  *
@@ -61,12 +62,7 @@
 public class FigureWidget extends Widget implements Properties.Provider, PopupMenuProvider, DoubleClickHandler {
 
     public static final boolean VERTICAL_LAYOUT = true;
-    public static final int DEPTH = 5;
-    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;
@@ -74,7 +70,8 @@
     private ArrayList<LabelWidget> labelWidgets;
     private DiagramScene diagramScene;
     private boolean boundary;
-    private Node node;
+    private final Node node;
+    private Widget dummyTop;
 
     public void setBoundary(boolean b) {
         boundary = b;
@@ -88,80 +85,58 @@
         return node;
     }
 
-    private String shortenString(String string) {
-        if (string.length() > MAX_STRING_LENGTH) {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < string.length(); i++) {
-                char c = string.charAt(i);
-                if (!Character.isLetter(c) || Character.isUpperCase(c)) {
-                    sb.append(c);
-                }
-            }
-            string = sb.toString();
-        }
-        return string;
+    @Override
+    public boolean isHitAt(Point localLocation) {
+        return middleWidget.isHitAt(localLocation);
     }
 
-    public FigureWidget(final Figure f, DiagramScene s, Widget parent) {
-
-        super(s);
-
+    public FigureWidget(final Figure f, WidgetAction hoverAction, WidgetAction selectAction, DiagramScene scene, Widget parent) {
+        super(scene);
 
-        font = f.getDiagram().getFont();
-        boldFont = f.getDiagram().getFont().deriveFont(Font.BOLD);
-        this.setCheckClipping(true);
-        this.diagramScene = s;
-
-        parent.addChild(this);
-        this.figure = f;
-        this.resolveBounds(null, calculateClientArea());
+        assert this.getScene() != null;
+        assert this.getScene().getView() != null;
 
-        leftWidget = new Widget(s);
-        this.addChild(leftWidget);
-        leftWidget.setLayout(new SlotLayout(SlotLayout.HorizontalAlignment.Right, VERTICAL_LAYOUT));//LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.JUSTIFY, 0));
-
-        middleWidget = new Widget(s);
-        this.addChild(middleWidget);
+        this.figure = f;
+        this.setCheckClipping(true);
+        this.diagramScene = scene;
+        parent.addChild(this);
 
-        if (VERTICAL_LAYOUT) {
-            this.setLayout(LayoutFactory.createVerticalFlowLayout());
-        } else {
-            this.setLayout(LayoutFactory.createHorizontalFlowLayout());
-        }
+        Widget outer = new Widget(scene);
+        outer.setBackground(f.getColor());
+        outer.setLayout(LayoutFactory.createOverlayLayout());
 
-        middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout());
-
+        middleWidget = new Widget(scene);
+        middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.CENTER, 0));
         middleWidget.setBackground(f.getColor());
         middleWidget.setOpaque(true);
-        assert this.getScene() != null;
-        assert this.getScene().getView() != null;
-        middleWidget.setBorder(BorderFactory.createLineBorder(Color.BLACK));
+        middleWidget.getActions().addAction(new DoubleClickAction(this));
+        middleWidget.setCheckClipping(true);
 
-
-        labelWidgets = new ArrayList<LabelWidget>();
+        dummyTop = new Widget(scene);
+        dummyTop.setMinimumSize(new Dimension(Figure.INSET / 2, 1));
+        middleWidget.addChild(dummyTop);
 
         String[] strings = figure.getLines();
-
-        for (String cur : strings) {
+        labelWidgets = new ArrayList<>(strings.length);
 
-            String displayString = cur;
-
-            LabelWidget lw = new LabelWidget(s);
+        for (String displayString : strings) {
+            LabelWidget lw = new LabelWidget(scene);
             labelWidgets.add(lw);
             middleWidget.addChild(lw);
             lw.setLabel(displayString);
-
-            lw.setFont(font);
-            lw.setForeground(Color.BLACK);
+            lw.setFont(figure.getDiagram().getFont());
+            lw.setForeground(getTextColor());
             lw.setAlignment(LabelWidget.Alignment.CENTER);
             lw.setVerticalAlignment(LabelWidget.VerticalAlignment.CENTER);
-            lw.setMaximumSize(new Dimension(f.getWidth(), 20000));
-            lw.setMinimumSize(new Dimension(f.getWidth(), 20));
+            lw.setBorder(BorderFactory.createEmptyBorder());
         }
 
-        rightWidget = new Widget(s);
-        this.addChild(rightWidget);
-        rightWidget.setLayout(new SlotLayout(SlotLayout.HorizontalAlignment.Left, VERTICAL_LAYOUT));//LayoutFactory.createVerticalLayout(LayoutFactory.SerialAlignment.JUSTIFY, 0));
+        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()));
+        this.addChild(middleWidget);
 
         // Initialize node for property sheet
         node = new AbstractNode(Children.LEAF) {
@@ -175,22 +150,6 @@
         };
         node.setDisplayName(getName());
     }
-    private boolean firstTime = true;
-
-    @Override
-    protected void paintWidget() {
-        if (firstTime) {
-            firstTime = false;
-            for (LabelWidget w : labelWidgets) {
-                String cur = w.getLabel();
-                Graphics graphics = this.getGraphics();
-                if (graphics.getFontMetrics().stringWidth(cur) > figure.getWidth()) {
-                    w.setLabel(shortenString(cur));
-                }
-            }
-        }
-        super.paintWidget();
-    }
 
     public Widget getLeftWidget() {
         return leftWidget;
@@ -204,40 +163,29 @@
     protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
         super.notifyStateChanged(previousState, state);
 
-        Color borderColor = Color.BLACK;
-        int thickness = 1;
-        boolean repaint = false;
-        Font f = font;
+        Font font = this.figure.getDiagram().getFont();
         if (state.isSelected()) {
-            thickness = 1;
-            f = boldFont;
-        }
-
-        if (state.isHovered()) {
-            borderColor = Color.BLUE;
+            font = this.figure.getDiagram().getBoldFont();
         }
 
-        if (state.isHovered() != previousState.isHovered()) {
-            repaint = true;
-        }
-
-        if (state.isSelected() != previousState.isSelected()) {
-            repaint = true;
+        Color borderColor = Color.BLACK;
+        Color innerBorderColor = getFigure().getColor();
+        if (state.isHighlighted()) {
+            innerBorderColor = borderColor = Color.BLUE;
         }
 
-        if (repaint) {
-            middleWidget.setBorder(BorderFactory.createLineBorder(borderColor, thickness));
-            for (LabelWidget labelWidget : labelWidgets) {
-                labelWidget.setFont(f);
-            }
-            repaint();
+        middleWidget.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(borderColor, 1), BorderFactory.createLineBorder(innerBorderColor, 1)));
+        for (LabelWidget labelWidget : labelWidgets) {
+            labelWidget.setFont(font);
         }
+        repaint();
     }
 
     public String getName() {
         return getProperties().get("name");
     }
 
+    @Override
     public Properties getProperties() {
         return figure.getProperties();
     }
@@ -246,13 +194,18 @@
         return figure;
     }
 
+    private Color getTextColor() {
+        Color bg = figure.getColor();
+        double brightness = bg.getRed() * 0.21 + bg.getGreen() * 0.72 + bg.getBlue() * 0.07;
+        if (brightness < 150) {
+            return Color.WHITE;
+        } else {
+            return Color.BLACK;
+        }
+    }
+
     @Override
     protected void paintChildren() {
-
-        if (diagramScene.getRealZoomFactor() < ZOOM_FACTOR && diagramScene.getModel().getShowBlocks()) {
-            return;
-        }
-
         Composite oldComposite = null;
         if (boundary) {
             oldComposite = getScene().getGraphics().getComposite();
@@ -260,8 +213,7 @@
             this.getScene().getGraphics().setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
         }
 
-        if (diagramScene.getRealZoomFactor() < LABEL_ZOOM_FACTOR) {
-
+        if (diagramScene.getZoomFactor() < LABEL_ZOOM_FACTOR) {
             for (LabelWidget labelWidget : labelWidgets) {
                 labelWidget.setVisible(false);
             }
@@ -269,9 +221,20 @@
             for (LabelWidget labelWidget : labelWidgets) {
                 labelWidget.setVisible(true);
             }
-
         } else {
+            Color oldColor = null;
+            if (boundary) {
+                for (LabelWidget labelWidget : labelWidgets) {
+                    oldColor = labelWidget.getForeground();
+                    labelWidget.setForeground(Color.BLACK);
+                }
+            }
             super.paintChildren();
+            if (boundary) {
+                for (LabelWidget labelWidget : labelWidgets) {
+                    labelWidget.setForeground(oldColor);
+                }
+            }
         }
 
         if (boundary) {
@@ -279,80 +242,126 @@
         }
     }
 
+    @Override
     public JPopupMenu getPopupMenu(Widget widget, Point point) {
-        JPopupMenu m = diagramScene.createPopupMenu();
+        JPopupMenu menu = diagramScene.createPopupMenu();
+        menu.addSeparator();
 
-        JMenu predecessors = new JMenu("Predecessors");
-        addFigureToSubMenu(predecessors, getFigure(), false, DEPTH);
+        build(menu, getFigure(), this, false, diagramScene);
+        menu.addSeparator();
+        build(menu, getFigure(), this, true, diagramScene);
+
+        if (getFigure().getSubgraphs() != null) {
+            menu.addSeparator();
+            JMenu subgraphs = new JMenu("Subgraphs");
+            menu.add(subgraphs);
 
-        JMenu successors = new JMenu("Successors");
-        addFigureToSubMenu(successors, getFigure(), true, DEPTH);
+            final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class);
+            for (final InputGraph subgraph : getFigure().getSubgraphs()) {
+                Action a = new AbstractAction() {
 
-        m.addSeparator();
-        m.add(predecessors);
-        m.add(successors);
-        return m;
+                    @Override
+                    public void actionPerformed(ActionEvent e) {
+                        viewer.view(subgraph, true);
+                    }
+                };
+
+                a.setEnabled(true);
+                a.putValue(Action.NAME, subgraph.getName());
+                subgraphs.add(a);
+            }
+        }
+
+        return menu;
     }
 
-    public void addFigureToSubMenu(JMenu subMenu, final Figure f, boolean successor, int depth) {
-        Set<Figure> set = f.getPredecessorSet();
-        if (successor) {
-            set = f.getSuccessorSet();
+    public static void build(JPopupMenu menu, Figure figure, FigureWidget figureWidget, boolean successors, DiagramScene diagramScene) {
+        Set<Figure> set = figure.getPredecessorSet();
+        if (successors) {
+            set = figure.getSuccessorSet();
         }
 
-        int count = set.size();
-        if (set.contains(f)) {
-            count--;
-        }
-
-        for (Figure f2 : set) {
-            if (f2 == f) {
+        boolean first = true;
+        for (Figure f : set) {
+            if (f == figure) {
                 continue;
             }
 
-            count--;
-            addFigureToMenu(subMenu, f2, successor, depth - 1);
-            if (count > 0) {
-                subMenu.addSeparator();
+            if (first) {
+                first = false;
+            } else {
+                menu.addSeparator();
             }
+
+            Action go = diagramScene.createGotoAction(f);
+            menu.add(go);
+
+            JMenu preds = new JMenu("Nodes Above");
+            preds.addMenuListener(figureWidget.new NeighborMenuListener(preds, f, false));
+            menu.add(preds);
+
+            JMenu succs = new JMenu("Nodes Below");
+            succs.addMenuListener(figureWidget.new NeighborMenuListener(succs, f, true));
+            menu.add(succs);
+        }
+
+        if (figure.getPredecessorSet().isEmpty() && figure.getSuccessorSet().isEmpty()) {
+            menu.add("(none)");
         }
     }
 
-    public void addFigureToMenu(JMenu m, final Figure f, boolean successor, int depth) {
+    /**
+     * Builds the submenu for a figure's neighbors on demand.
+     */
+    public class NeighborMenuListener implements MenuListener {
 
-        Action a = diagramScene.createGotoAction(f);
-
+        private final JMenu menu;
+        private final Figure figure;
+        private final boolean successors;
 
-        m.add(a);
+        public NeighborMenuListener(JMenu menu, Figure figure, boolean successors) {
+            this.menu = menu;
+            this.figure = figure;
+            this.successors = successors;
+        }
 
-        if (depth > 0) {
-            String name = "Predecessors";
-            if (successor) {
-                name = "Successors";
+        @Override
+        public void menuSelected(MenuEvent e) {
+            if (menu.getItemCount() > 0) {
+                // already built before
+                return;
             }
 
-            JMenu subMenu = new JMenu(name);
-            addFigureToSubMenu(subMenu, f, successor, depth);
-            m.add(subMenu);
+            build(menu.getPopupMenu(), figure, FigureWidget.this, successors, diagramScene);
+        }
+
+        @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()) {
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
             hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         } else if (isBoundary()) {
 
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
             hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         } else {
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
             hiddenNodes.addAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         }
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 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.DiagramScene;
 import java.awt.Point;
@@ -40,14 +41,25 @@
     public InputSlotWidget(InputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
         super(slot, scene, parent, fw);
         inputSlot = slot;
-        init();
-        getFigureWidget().getLeftWidget().addChild(this);
+        //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<InputSlot> slots = getSlot().getFigure().getInputSlots();
+        assert slots.contains(getSlot());
+        return calculateWidth(slots.size());
+    }
+/*
     protected Point calculateRelativeLocation() {
         if (getFigureWidget().getBounds() == null) {
             return new Point(0, 0);
@@ -57,5 +69,5 @@
         List<InputSlot> slots = inputSlot.getFigure().getInputSlots();
         assert slots.contains(inputSlot);
         return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(inputSlot))));
-    }
+    }*/
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,23 +24,23 @@
 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.util.StringUtils;
 import com.sun.hotspot.igv.view.DiagramScene;
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Stroke;
+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;
@@ -51,7 +51,7 @@
  */
 public class LineWidget extends Widget implements PopupMenuProvider {
 
-    public final int BORDER = 8;
+    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;
@@ -80,7 +80,7 @@
         this.from = from;
         this.to = to;
         this.predecessor = predecessor;
-        this.successors = new ArrayList<LineWidget>();
+        this.successors = new ArrayList<>();
         if (predecessor != null) {
             predecessor.addSuccessor(this);
         }
@@ -110,6 +110,7 @@
         if (connections.size() > 0) {
             color = connections.get(0).getColor();
         }
+        this.setToolTipText("<HTML>" + generateToolTipText(this.connections) + "</HTML>");
 
         this.setCheckClipping(true);
 
@@ -120,6 +121,38 @@
             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<Figure> 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<Connection> conn) {
+        StringBuilder sb = new StringBuilder();
+        for (Connection c : conn) {
+            sb.append(StringUtils.escapeHTML(c.getToolTipText()));
+            sb.append("<br>");
+        }
+        return sb.toString();
     }
 
     public Point getFrom() {
@@ -141,13 +174,12 @@
 
     @Override
     protected void paintWidget() {
-        if (scene.getRealZoomFactor() < ZOOM_FACTOR) {
+        if (scene.getZoomFactor() < ZOOM_FACTOR) {
             return;
         }
 
         Graphics2D g = getScene().getGraphics();
         g.setPaint(this.getBackground());
-        ObjectState state = this.getState();
         float width = 1.0f;
 
         if (isBold) {
@@ -171,7 +203,7 @@
         g.drawLine(from.x, from.y, to.x, to.y);
 
         boolean sameFrom = false;
-        boolean sameTo = successors.size() == 0;
+        boolean sameTo = successors.isEmpty();
         for (LineWidget w : successors) {
             if (w.getFrom().equals(getTo())) {
                 sameTo = true;
@@ -207,6 +239,20 @@
 
     private void setHighlighted(boolean b) {
         this.highlighted = b;
+        Set<Object> highlightedObjects = new HashSet<>(scene.getHighlightedObjects());
+        Set<Object> 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);
     }
 
@@ -263,6 +309,7 @@
         }
     }
 
+    @Override
     public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
         JPopupMenu menu = new JPopupMenu();
         menu.add(scene.createGotoAction(outputSlot.getFigure()));
@@ -276,14 +323,17 @@
         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) {
             }
         });
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/MultiConnectionWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,281 +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.InputSlot;
-import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Slot;
-import com.sun.hotspot.igv.view.DiagramScene;
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Stroke;
-import java.awt.geom.Line2D;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import javax.swing.JPopupMenu;
-import javax.swing.event.PopupMenuEvent;
-import javax.swing.event.PopupMenuListener;
-import org.netbeans.api.visual.action.PopupMenuProvider;
-import org.netbeans.api.visual.model.ObjectState;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class MultiConnectionWidget extends Widget implements PopupMenuProvider {
-
-    public final int BORDER = 4;
-    public final int HOVER_STROKE_WIDTH = 3;
-
-    private static class Route {
-
-        public Point from;
-        public Point to;
-        public SortedSet<InputSlot> inputSlots;
-        public boolean decorateStart;
-        public boolean decorateEnd;
-
-        public Route(Point from, Point to) {
-            assert from != null;
-            assert to != null;
-            this.from = from;
-            this.to = to;
-            this.inputSlots = new TreeSet<InputSlot>();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-
-            if (obj instanceof Route) {
-                Route r = (Route) obj;
-                return r.from.equals(from) && r.to.equals(to);
-            }
-
-            return super.equals(obj);
-        }
-
-        @Override
-        public int hashCode() {
-            return ((((from.x * 1711) + from.y) * 1711 + to.x) * 1711 + to.y);
-        }
-    }
-    private Rectangle clientArea;
-    private OutputSlot outputSlot;
-    private Map<Route, SortedSet<InputSlot>> routeMap;
-    private List<Route> routeList;
-    private Color color;
-    private DiagramScene diagramScene;
-    private boolean popupVisible;
-
-    /** Creates a new instance of MultiConnectionWidget */
-    public MultiConnectionWidget(OutputSlot outputSlot, DiagramScene scene) {
-        super(scene);
-
-        this.diagramScene = scene;
-        this.outputSlot = outputSlot;
-        this.setCheckClipping(true);
-
-        routeMap = new HashMap<Route, SortedSet<InputSlot>>();
-        routeList = new ArrayList<Route>();
-        color = Color.BLACK;
-
-        for (Connection c : outputSlot.getConnections()) {
-            List<Point> controlPoints = c.getControlPoints();
-            InputSlot inputSlot = (InputSlot) c.getTo();
-            color = c.getColor();
-
-            for (int i = 1; i < controlPoints.size(); i++) {
-                Point prev = controlPoints.get(i - 1);
-                Point cur = controlPoints.get(i);
-
-                if (prev != null && cur != null) {
-                    Route r = new Route(prev, cur);
-                    if (routeMap.containsKey(r)) {
-                        SortedSet<InputSlot> set = routeMap.get(r);
-                        set.add(inputSlot);
-                    } else {
-                        SortedSet<InputSlot> set = new TreeSet<InputSlot>(Slot.slotFigureComparator);
-                        set.add(inputSlot);
-                        routeMap.put(r, set);
-                        routeList.add(r);
-                    }
-                }
-            }
-        }
-
-        if (routeList.size() == 0) {
-            clientArea = new Rectangle();
-        } else {
-            for (Route r : routeList) {
-
-                int x = r.from.x;
-                int y = r.from.y;
-
-                int x2 = r.to.x;
-                int y2 = r.to.y;
-
-                if (x > x2) {
-                    int tmp = x;
-                    x = x2;
-                    x2 = tmp;
-                }
-
-                if (y > y2) {
-                    int tmp = y;
-                    y = y2;
-                    y2 = tmp;
-                }
-
-                int width = x2 - x + 1;
-                int height = y2 - y + 1;
-
-                Rectangle rect = new Rectangle(x, y, width, height);
-                if (clientArea == null) {
-                    clientArea = rect;
-                } else {
-                    clientArea = clientArea.union(rect);
-                }
-            }
-
-            clientArea.grow(BORDER, BORDER);
-        }
-    }
-
-    private void setHoverPosition(Point location) {
-        Route r = getNearest(location);
-    }
-
-    private Route getNearest(Point localLocation) {
-
-        double minDist = Double.MAX_VALUE;
-        Route result = null;
-        for (Route r : routeList) {
-            double dist = Line2D.ptSegDistSq((double) r.from.x, (double) r.from.y, (double) r.to.x, (double) r.to.y, (double) localLocation.x, (double) localLocation.y);
-            if (dist < minDist) {
-                result = r;
-                minDist = dist;
-            }
-        }
-
-        assert result != null;
-
-        return result;
-    }
-
-    @Override
-    public boolean isHitAt(Point localLocation) {
-        if (!super.isHitAt(localLocation)) {
-            return false;
-        }
-
-        for (Route r : routeList) {
-            double dist = Line2D.ptSegDistSq((double) r.from.x, (double) r.from.y, (double) r.to.x, (double) r.to.y, (double) localLocation.x, (double) localLocation.y);
-            if (dist < BORDER * BORDER) {
-                setHoverPosition(localLocation);
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    protected Rectangle calculateClientArea() {
-        return clientArea;
-    }
-
-    @Override
-    protected void paintWidget() {
-        Graphics2D g = getScene().getGraphics();
-        //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
-        g.setColor(this.color);
-        ObjectState state = this.getState();
-        float width = 1.0f;
-        if (state.isHovered() || this.popupVisible) {
-            width = HOVER_STROKE_WIDTH;
-        }
-
-        Stroke oldStroke = g.getStroke();
-        g.setStroke(new BasicStroke(width));
-        for (Route r : routeList) {
-            g.drawLine(r.from.x, r.from.y, r.to.x, r.to.y);
-        }
-        g.setStroke(oldStroke);
-    }
-
-    @Override
-    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
-
-        boolean repaint = false;
-
-        if (state.isHovered() != previousState.isHovered()) {
-            repaint = true;
-        }
-
-        repaint();
-    }
-
-    public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
-        JPopupMenu menu = new JPopupMenu();
-        Route r = getNearest(localLocation);
-        assert r != null;
-        assert routeMap.containsKey(r);
-
-        menu.add(diagramScene.createGotoAction(outputSlot.getFigure()));
-        menu.addSeparator();
-
-        SortedSet<InputSlot> set = this.routeMap.get(r);
-        for (InputSlot s : set) {
-            menu.add(diagramScene.createGotoAction(s.getFigure()));
-        }
-
-        final MultiConnectionWidget w = this;
-        menu.addPopupMenuListener(new PopupMenuListener() {
-
-            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
-                w.popupVisible = true;
-                w.repaint();
-            }
-
-            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
-                w.popupVisible = false;
-                w.repaint();
-            }
-
-            public void popupMenuCanceled(PopupMenuEvent e) {
-            }
-        });
-
-        return menu;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 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.DiagramScene;
 import java.awt.Point;
@@ -40,22 +41,21 @@
     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;
+        this.setPreferredLocation(p);
     }
 
     public OutputSlot getOutputSlot() {
         return outputSlot;
     }
 
-    protected Point calculateRelativeLocation() {
-        if (getFigureWidget().getBounds() == null) {
-            return new Point(0, 0);
-        }
+    @Override
+    protected int calculateSlotWidth() {
+        List<OutputSlot> slots = getSlot().getFigure().getOutputSlots();
+        assert slots.contains(getSlot());
+        return calculateWidth(slots.size());
 
-        double x = this.getFigureWidget().getBounds().width;
-        List<OutputSlot> slots = outputSlot.getFigure().getOutputSlots();
-        assert slots.contains(outputSlot);
-        return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(outputSlot))));
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,51 +26,47 @@
 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.view.*;
+import com.sun.hotspot.igv.util.DoubleClickHandler;
+import com.sun.hotspot.igv.view.DiagramScene;
 import java.awt.Color;
 import java.awt.Font;
 import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.Point;
 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 {
+public abstract class SlotWidget extends Widget implements DoubleClickHandler {
 
     private Slot slot;
     private FigureWidget figureWidget;
-    private Image bufferImage;
     private static double TEXT_ZOOM_FACTOR = 0.9;
     private static double ZOOM_FACTOR = 0.6;
-    private DiagramScene scene;
+    private DiagramScene diagramScene;
 
     public SlotWidget(Slot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
         super(scene);
-        this.scene = scene;
+        this.diagramScene = scene;
         this.slot = slot;
         figureWidget = fw;
-        this.setToolTipText("<HTML>" + slot.getName() + "</HTML>");
+        this.setToolTipText("<HTML>" + slot.getToolTipText() + "</HTML>");
         this.setCheckClipping(true);
+        parent.addChild(this);
+
+        //this.setPreferredBounds(this.calculateClientArea());
     }
 
-    public Point getAnchorPosition() {
-        Point p = new Point(figureWidget.getFigure().getPosition());
-        Point p2 = slot.getRelativePosition();
-        p.translate(p2.x, p2.y);
-        return p;
-    }
-
-    protected void init() {
-
-        Point p = calculateRelativeLocation();
-        Rectangle r = calculateClientArea();
-        p = new Point(p.x, p.y - r.height / 2);
-        this.setPreferredLocation(p);
+    @Override
+    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
+        super.notifyStateChanged(previousState, state);
+        repaint();
     }
 
     public Slot getSlot() {
@@ -84,43 +80,98 @@
     @Override
     protected void paintWidget() {
 
-        if (scene.getRealZoomFactor() < ZOOM_FACTOR) {
+        if (getScene().getZoomFactor() < ZOOM_FACTOR) {
             return;
         }
 
-        if (bufferImage == null) {
-            Graphics2D g = this.getGraphics();
-            g.setColor(Color.DARK_GRAY);
-            int w = this.getBounds().width;
-            int h = this.getBounds().height;
+        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 (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && scene.getRealZoomFactor() >= TEXT_ZOOM_FACTOR) {
-                Font f = new Font("Arial", Font.PLAIN, 8);
-                g.setFont(f.deriveFont(7.5f));
-                Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
-                g.drawString(getSlot().getShortName(), (int) (this.getBounds().width - r1.getWidth()) / 2, (int) (this.getBounds().height + r1.getHeight()) / 2);
+            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.getSlot().getConnections().isEmpty()) {
+                if (this.getState().isHighlighted()) {
+                    g.setColor(Color.BLUE);
+                } else {
+                    g.setColor(Color.BLACK);
+                }
+                int r = 2;
                 if (slot instanceof OutputSlot) {
-                    g.fillArc(w / 4, -h / 4 - 1, w / 2, h / 2, 180, 180);
+                    g.fillOval(w / 2 - r, Figure.SLOT_WIDTH - Figure.SLOT_START - r, 2 * r, 2 * r);
                 } else {
-                    g.fillArc(w / 4, 3 * h / 4, w / 2, h / 2, 0, 180);
+                    g.fillOval(w / 2 - r, Figure.SLOT_START - r, 2 * r, 2 * r);
                 }
+            } else {
+                // Do not paint a slot with connections.
             }
         }
     }
 
     @Override
     protected Rectangle calculateClientArea() {
-        return new Rectangle(0, 0, Figure.SLOT_WIDTH, Figure.SLOT_WIDTH);
+        return new Rectangle(0, 0, slot.getWidth(), Figure.SLOT_WIDTH);
+    }
+
+    protected abstract int calculateSlotWidth();
+
+    protected int calculateWidth(int count) {
+        return getFigureWidget().getFigure().getWidth() / count;
     }
 
-    protected abstract Point calculateRelativeLocation();
+    @Override
+    public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) {
+        Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
+        if (diagramScene.isAllVisible()) {
+            hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
+        }
 
-    protected double calculateRelativeY(int size, int index) {
-        assert index >= 0 && index < size;
-        assert size > 0;
-        double height = getFigureWidget().getBounds().getHeight();
-        return height * (index + 1) / (size + 1);
+        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);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/branding.jnlp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc//DTD JNLP Descriptor 6.0//EN" "http://java.sun.com/dtd/JNLP-6.0.dtd">
+<jnlp spec="1.0+" codebase="$$codebase">
+  <information>
+      <title>${app.title}</title>
+      <vendor>${app.title} vendor</vendor>
+      <description>${app.name} application</description>
+      <icon href="${app.icon}"/>
+  </information>
+  ${jnlp.permissions}
+  <resources>
+    ${jnlp.branding.jars}
+  </resources>
+  <component-desc/>
+</jnlp>  
--- a/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,7 +1,7 @@
 currentVersion=IdealGraphVisualizer {0}
 LBL_splash_window_title=Starting IdealGraphVisualizer
 SPLASH_WIDTH=475
-SplashProgressBarBounds=0,268,473,6
+SplashProgressBarBounds=0,273,475,6
 SplashProgressBarColor=0xFFFFFF
-SplashRunningTextBounds=269,253,205,12
+SplashRunningTextBounds=10,283,460,12
 SplashRunningTextColor=0xFFFFFF
Binary file src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame32.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame48.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/splash.gif has changed
--- a/src/share/tools/IdealGraphVisualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,2 +1,2 @@
-CTL_MainWindow_Title=IdealGraphVisualizer {0}
-CTL_MainWindow_Title_No_Project=IdealGraphVisualizer {0}
+CTL_MainWindow_Title=IdealGraphVisualizer
+CTL_MainWindow_Title_No_Project=IdealGraphVisualizer
--- a/src/share/tools/IdealGraphVisualizer/build.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/build.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -5,4 +5,12 @@
 <project name="IdealGraphVisualizer" basedir=".">
     <description>Builds the module suite IdealGraphVisualizer.</description>
     <import file="nbproject/build-impl.xml"/>
+    
+    <target name="build-launchers" depends="suite.build-launchers">
+        <!-- Drop memory presets (-Xms, -Xmx) from default_options of packaged builds and let the executing VM choose reasonable defaults -->
+        <replaceregexp file="${build.launcher.dir}/etc/${app.name}.conf" byline="true" match="^default_options=.*" replace='default_options="--branding idealgraphvisualizer"' />
+    </target>
+    
+    <!-- Local (environment-specific) extensions/modifications to the build -->
+    <import file="build-local.xml" optional="true" />
 </project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/master.jnlp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc//DTD JNLP Descriptor 6.0//EN" "http://java.sun.com/dtd/JNLP-6.0.dtd">
+<jnlp spec="1.0+" codebase="$$codebase" href="master.jnlp">
+  <information>
+      <title>Ideal Graph Visualizer</title>
+      <vendor>Ideal Graph Visualizer Team</vendor>
+      <description>A graph visualization tool designed for analyzing evolving compiler graphs. It was originally designed for the ideal graph in the HotSpot server compiler, but can be used to visualize arbitrary graph data structures.</description>
+      <icon href="${app.icon}"/>
+  </information>
+  <security><all-permissions/></security>
+  <resources>
+    <!-- The following property is needed when running with unsigned jars: -->
+    <property name="netbeans.jnlp.fixPolicy" value="${netbeans.jnlp.fixPolicy}"/>
+    <extension name='branding' href='branding.jnlp' />
+<!-- The following line will be replaced with an automatically generated list of resources: -->
+<!--${jnlp.resources}-->
+  </resources>
+  <resources os="Mac OS X">
+      <property name="netbeans.user" value="${user.home}/Library/Application Support/${app.name}"/>
+  </resources>
+  <application-desc>
+    <argument>--branding</argument>
+    <argument>${branding.token}</argument>
+  </application-desc>
+</jnlp>  
--- a/src/share/tools/IdealGraphVisualizer/nbproject/build-impl.xml	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/build-impl.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="IdealGraphVisualizer-impl" basedir=".." xmlns:sproject="http://www.netbeans.org/ns/nb-module-suite-project/1">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/platform-private.properties"/>
     <property file="nbproject/platform.properties"/>
     <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
@@ -13,13 +20,29 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <sproject:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir"/>
-    <sproject:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <sproject:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/>
+    <sproject:evalprops property="cluster.path.evaluated" value="${cluster.path}"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <ant antfile="nbproject/platform.xml"/>
+    <fail message="Cannot find NetBeans build harness. ${line.separator}Check that nbplatform.${nbplatform.active}.netbeans.dest.dir and nbplatform.${nbplatform.active}.harness.dir are defined. ${line.separator}On a developer machine these are normally defined in ${user.properties.file}=${netbeans.user}/build.properties ${line.separator}but for automated builds you should pass these properties to Ant explicitly. ${line.separator}You may instead download the harness and platform: -Dbootstrap.url=.../tasks.jar -Dautoupdate.catalog.url=.../updates.xml">
+        <condition>
+            <not>
+                <available file="${harness.dir}/suite.xml"/>
             </not>
         </condition>
     </fail>
--- a/src/share/tools/IdealGraphVisualizer/nbproject/genfiles.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/genfiles.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,8 +1,11 @@
-build.xml.data.CRC32=72833581
-build.xml.script.CRC32=e9c757c5
-build.xml.stylesheet.CRC32=531c622b
+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=72833581
-nbproject/build-impl.xml.script.CRC32=1b6f3648
-nbproject/build-impl.xml.stylesheet.CRC32=196c7090
+nbproject/build-impl.xml.data.CRC32=3c2c6126
+nbproject/build-impl.xml.script.CRC32=b26e57e5
+nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.62.1
+nbproject/platform.xml.data.CRC32=3c2c6126
+nbproject/platform.xml.script.CRC32=6dcbd131
+nbproject/platform.xml.stylesheet.CRC32=4e1f53d4@2.62.1
--- a/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,29 +1,18 @@
-# Deprecated since 5.0u1; for compatibility with 5.0:
-disabled.clusters=\
-    apisupport1,\
-    gsf1,\
-    harness,\
-    ide9,\
-    java2,\
-    nb6.1,\
-    profiler3
-disabled.modules=\
-    org.netbeans.core.execution,\
-    org.netbeans.core.multiview,\
-    org.netbeans.core.output2,\
-    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=\
-    platform8
-nbjdk.active=default
+branding.token=idealgraphvisualizer
+cluster.path=\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=
+nbplatform.active.dir=${suite.dir}/nbplatform
+nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform
+nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness
+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.4/uc/final/distribution/catalog.xml.gz
+suite.dir=${basedir}
 nbplatform.active=default
+## 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,\
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/platform.xml	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="platform" default="download" basedir="..">
+    <condition property="download.required">
+        <and>
+            <not>
+                <available file="${harness.dir}/suite.xml"/>
+            </not>
+            <isset property="bootstrap.url"/>
+            <isset property="autoupdate.catalog.url"/>
+        </and>
+    </condition>
+    <target name="download" if="download.required">
+        <mkdir dir="${harness.dir}"/>
+        <pathconvert pathsep="|" property="download.clusters">
+            <mapper type="flatten"/>
+            <path path="${cluster.path}"/>
+        </pathconvert>
+        <property name="disabled.modules" value=""/>
+        <pathconvert property="module.includes" pathsep="">
+            <mapper type="glob" from="${basedir}${file.separator}*" to="(?!^\Q*\E$)"/>
+            <path>
+                <filelist files="${disabled.modules}" dir="."/>
+            </path>
+        </pathconvert>
+        <echo message="Downloading clusters ${download.clusters}"/>
+        <property name="tasks.jar" location="${java.io.tmpdir}/tasks.jar"/>
+        <get src="${bootstrap.url}" dest="${tasks.jar}" usetimestamp="true" verbose="true"/>
+        <taskdef name="autoupdate" classname="org.netbeans.nbbuild.AutoUpdate" classpath="${tasks.jar}"/>
+        <autoupdate installdir="${nbplatform.active.dir}" updatecenter="${autoupdate.catalog.url}">
+            <modules includes="${module.includes}.*" clusters="${download.clusters}"/>
+            <modules includes="org[.]netbeans[.]modules[.]apisupport[.]harness" clusters="harness"/>
+        </autoupdate>
+    </target>
+</project>
--- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Mon Feb 06 17:18:57 2017 +0100
@@ -1,7 +1,13 @@
 app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif
-app.name=idealgraphvisualizer
+app.name=${branding.token}
 app.title=IdealGraphVisualizer
-branding.token=${app.name}
+auxiliary.org-netbeans-modules-apisupport-installer.license-type=no
+auxiliary.org-netbeans-modules-apisupport-installer.os-linux=false
+auxiliary.org-netbeans-modules-apisupport-installer.os-macosx=true
+auxiliary.org-netbeans-modules-apisupport-installer.os-solaris=false
+auxiliary.org-netbeans-modules-apisupport-installer.os-windows=false
+auxiliary.org-netbeans-modules-apisupport-installer.pack200-enabled=false
+auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml
 modules=\
     ${project.com.sun.hotspot.igv.graph}:\
     ${project.com.sun.hotspot.igv.coordinator}:\
@@ -18,7 +24,9 @@
     ${project.com.sun.hotspot.igv.svg}:\
     ${project.com.sun.hotspot.connection}:\
     ${project.com.sun.hotspot.igv.servercompilerscheduler}:\
-    ${project.com.sun.hotspot.igv.filterwindow}
+    ${project.com.sun.hotspot.igv.filterwindow}:\
+    ${project.com.sun.hotspot.igv.selectioncoordinator}:\
+    ${project.com.sun.hotspot.igv.graal}
 project.com.sun.hotspot.connection=NetworkConnection
 project.com.sun.hotspot.igv.bytecodes=Bytecodes
 project.com.sun.hotspot.igv.controlflow=ControlFlow
@@ -27,13 +35,18 @@
 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.selectioncoordinator=SelectionCoordinator
 project.com.sun.hotspot.igv.servercompilerscheduler=ServerCompiler
 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
-run.args = -J-server -J-Xms64m -J-Xmx1g -J-da
-run.args.extra = -J-server -J-Xms64m -J-Xmx1g -J-da
+
+# Disable assertions for RequestProcessor to prevent annoying messages in case
+# of multiple SceneAnimator update tasks in the default RequestProcessor.
+run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g -J-Djava.lang.Integer.IntegerCache.high=200000
+debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor
--- a/src/share/tools/LogCompilation/Makefile	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/LogCompilation/Makefile	Mon Feb 06 17:18:57 2017 +0100
@@ -62,7 +62,7 @@
 
 logc.jar: filelist manifest.mf
 	@mkdir -p $(OUTPUT_DIR)
-	$(JAVAC) -source 1.5 -deprecation -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) @filelist
+	$(JAVAC) -source 1.6 -deprecation -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) @filelist
 	$(JAR) cvfm logc.jar manifest.mf -C $(OUTPUT_DIR) com
 
 .PHONY: filelist
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java	Mon Feb 06 17:18:57 2017 +0100
@@ -26,6 +26,7 @@
 
 import java.io.PrintStream;
 import java.util.ArrayList;
+import java.util.List;
 
 public class Compilation implements LogEvent {
 
@@ -44,6 +45,7 @@
     private NMethod nmethod;
     private ArrayList<Phase> phases = new ArrayList<Phase>(4);
     private String failureReason;
+    private List<JVMState> eliminatedLocks = new ArrayList<JVMState>();
 
     Compilation(int id) {
         this.id = id;
@@ -77,9 +79,11 @@
         sb.append("+");
         sb.append(getBcount());
         sb.append("\n");
-        for (CallSite site : getCall().getCalls()) {
-            sb.append(site);
-            sb.append("\n");
+        if (getCall().getCalls() != null) {
+            for (CallSite site : getCall().getCalls()) {
+                sb.append(site);
+                sb.append("\n");
+            }
         }
         if (getLateInlineCall().getCalls() != null) {
             sb.append("late inline:\n");
@@ -91,15 +95,28 @@
         return sb.toString();
     }
 
-    public void printShort(PrintStream stream) {
+    public String shortName() {
         if (getMethod() == null) {
-            stream.println(getSpecial());
+            return getSpecial();
         } else {
             int bc = isOsr() ? getOsr_bci() : -1;
-            stream.print(getId() + getMethod().decodeFlags(bc) + getMethod().format(bc));
+            return getId() + getMethod().decodeFlags(bc) + getMethod().format(bc);
         }
     }
 
+    public String longMethodName() {
+        if (getMethod() == null) {
+            return getSpecial();
+        } else {
+            int bc = isOsr() ? getOsr_bci() : -1;
+            return getMethod().decodeFlags(bc) + getMethod().formatLong(bc);
+        }
+    }
+
+    public void printShort(PrintStream stream) {
+        stream.println(shortName());
+    }
+
     public void print(PrintStream stream) {
         print(stream, 0, false);
     }
@@ -255,4 +272,12 @@
     public Compilation getCompilation() {
         return this;
     }
+
+    public void addEliminatedLock(JVMState jvms) {
+        eliminatedLocks.add(jvms);
+    }
+
+    public List<JVMState> getEliminatedLocks() {
+        return eliminatedLocks;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/JVMState.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.tools.compiler;
+
+public class JVMState {
+    final Method method;
+    final int bci;
+    JVMState outer;
+    
+    JVMState(Method method, int bci) {
+        this.method = method;
+        this.bci = bci;
+    }
+    
+    void push(JVMState jvms) {
+        if (outer == null) {
+            outer = jvms;
+        } else {
+            outer.push(jvms);
+        }
+    }
+}
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java	Mon Feb 06 17:18:57 2017 +0100
@@ -41,17 +41,23 @@
         System.out.println("  -c:   clean up malformed 1.5 xml");
         System.out.println("  -i:   print inlining decisions");
         System.out.println("  -S:   print compilation statistics");
+        System.out.println("  -R:   print method recompilation information");
         System.out.println("  -s:   sort events by start time");
         System.out.println("  -e:   sort events by elapsed time");
         System.out.println("  -n:   sort events by name and start");
+        System.out.println("  -L:   print eliminated locks");
+        System.out.println("  -Q:   print compile queue activity");
         System.exit(exitcode);
     }
 
     public static void main(String[] args) throws Exception {
         Comparator<LogEvent> defaultSort = LogParser.sortByStart;
         boolean statistics = false;
+        boolean recompilation = false;
         boolean printInlining = false;
         boolean cleanup = false;
+        boolean printEliminatedLocks = false;
+        boolean printCompileQueue = false;
         int index = 0;
 
         while (args.length > index) {
@@ -70,11 +76,20 @@
             } else if (args[index].equals("-S")) {
                 statistics = true;
                 index++;
+            } else if (args[index].equals("-R")) {
+                recompilation = true;
+                index++;
             } else if (args[index].equals("-h")) {
                 usage(0);
             } else if (args[index].equals("-i")) {
                 printInlining = true;
                 index++;
+            } else if (args[index].equals("-L")) {
+                printEliminatedLocks = true;
+                index++;
+            } else if (args[index].equals("-Q")) {
+                printCompileQueue = true;
+                index++;
             } else {
                 break;
             }
@@ -87,11 +102,21 @@
         while (index < args.length) {
             ArrayList<LogEvent> events = LogParser.parse(args[index], cleanup);
 
-            if (statistics) {
+            if (printCompileQueue) {
+                printCompileQueue(events, System.out);
+            } else if (printEliminatedLocks) {
+                printEliminatedLocks(events, System.out, defaultSort);
+            } else if (statistics) {
                 printStatistics(events, System.out);
+            } else if (recompilation) {
+                printRecompilation(events, System.out);
             } else {
                 Collections.sort(events, defaultSort);
                 for (LogEvent c : events) {
+                    if (c instanceof NMethod) continue;
+                    if (c instanceof TaskEvent) continue;
+
+                    System.out.printf("%f ", c.getStart());
                     if (printInlining && c instanceof Compilation) {
                         Compilation comp = (Compilation)c;
                         comp.print(System.out, true);
@@ -103,6 +128,126 @@
             index++;
         }
     }
+    
+    public static void printCompileQueue(ArrayList<LogEvent> events, PrintStream out) {
+        int[] levels = new int[5];
+        HashMap<String, TaskEvent> tasks = new HashMap<String, TaskEvent>();
+        
+        out.printf("%7s ", "Stamp");
+        for (int i = 1; i <= 4; i++) {
+            out.printf(" Level%d", i);
+        }
+        out.printf("   %10s", "Kind");
+        out.println();
+        for (LogEvent e : events) {
+            if (e instanceof TaskEvent) {
+                boolean demoted = false;
+                TaskEvent t = (TaskEvent) e;
+                TaskEvent start = tasks.get(t.getId());
+                switch (t.getKind()) {
+                case Enqueue:
+                    assert start == null;
+                    levels[t.getLevel()] = levels[t.getLevel()] + 1;
+                    tasks.put(t.getId(), t);
+                    break;
+                    
+                case Finish:
+                case Dequeue:
+                    if (start != null && start.getLevel() != t.getLevel()) {
+                        // Sometimes tasks are moved to a lower
+                        // compilation level when the queue fills.
+                        demoted = true;
+                        levels[start.getLevel()] = levels[start.getLevel()] - 1;
+                    } else {
+                        levels[t.getLevel()] = levels[t.getLevel()] - 1;
+                    }
+                    break;
+                default:
+                    throw new InternalError();
+                }
+                out.printf("%7.3f ", t.getStart());
+                for (int i = 1; i <= 4; i++) {
+                    out.printf(" %6d", levels[i]);
+                }
+                out.printf("   %10s", t.getKind());
+                if (t.getComment() != null) {
+                    out.printf(" %s", t.getComment());
+                }
+                if (demoted) {
+                    out.printf("  %d->%d", start.getLevel(), t.getLevel());
+                }
+                out.println();
+            }
+        }
+    }
+
+    public static void printEliminatedLocks(ArrayList<LogEvent> events, PrintStream out, Comparator<LogEvent> defaultSort) {
+        Collections.sort(events, defaultSort);
+        for (LogEvent e : events) {
+            if (e instanceof Compilation) {
+                Compilation c = (Compilation) e;
+                List<JVMState> eliminated = c.getEliminatedLocks();
+                if (!eliminated.isEmpty()) {
+                    c.print(out);
+                    out.println("  Eliminated locks");
+                    for (JVMState jvms : eliminated) {
+                        System.err.print("   ");
+                        while (jvms != null) {
+                            out.printf(" %s.%s@%d", jvms.method.getHolder().replace('/', '.'), jvms.method.getName(), jvms.bci);
+                            jvms = jvms.outer;
+                        }
+                        out.println();
+                    }
+                }
+            }
+        }
+    }
+    
+    public static void printRecompilation(ArrayList<LogEvent> events, PrintStream out) {
+        LinkedHashMap<String, Map<String, List<String>>> traps = new LinkedHashMap<String, Map<String, List<String>>>();
+        for (LogEvent e : events) {
+            if (e instanceof UncommonTrapEvent) {
+                UncommonTrapEvent uc = (UncommonTrapEvent) e;
+                Map<String, List<String>> t = traps.get(uc.getCompilation().getMethod().toString());
+                if (t == null) {
+                    t = new LinkedHashMap<String, List<String>>();
+                    traps.put(uc.getCompilation().getMethod().toString(), t);
+                }
+                String msg = uc.formatTrap().trim();
+                List<String> i = t.get(msg);
+                if (i == null) {
+                    i = new ArrayList<String>();
+                    t.put(msg, i);
+                }
+                i.add(uc.getId());
+            }
+        }
+
+        List<List<String>> recompiles = new ArrayList<List<String>>();
+        Map<List<String>, String> reverseMapping = new HashMap<List<String>, String>();
+        for (Map.Entry<String, Map<String, List<String>>> entry : traps.entrySet()) {
+            for (Map.Entry<String, List<String>> trapEntry : entry.getValue().entrySet()) {
+                recompiles.add(trapEntry.getValue());
+                reverseMapping.put(trapEntry.getValue(), trapEntry.getKey());
+            }
+        }
+        recompiles.sort(new Comparator<List<String>>() {
+            public int compare(List<String> a, List<String> b) {
+                return intCompare(a.size(), b.size());
+            }
+        });
+        for (List<String> key : recompiles) {
+	    out.print("Trap: ");
+	    out.println(reverseMapping.get(key));
+	    out.print("Compilations: ");
+	    out.println(key);
+        }
+    }
+    
+
+    private static int intCompare(int o1, int o2) {
+        return (o1 > o2 ? -1 : (o1 == o2 ? 0 : 1));
+    }
 
     public static void printStatistics(ArrayList<LogEvent> events, PrintStream out) {
         long cacheSize = 0;
@@ -141,7 +286,7 @@
                        nodes created in the phase, live nodes at the start of the phase,
                        live nodes added in the phase.
                     */
-                    out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getLiveNodes());
+                    // out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getLiveNodes());
                 }
             } else if (e instanceof MakeNotEntrantEvent) {
                 MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e;
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Mon Feb 06 17:18:57 2017 +0100
@@ -89,15 +89,12 @@
                 if (result != 0) {
                     return result;
                 }
-            }
-            double difference = (a.getStart() - b.getStart());
-            if (difference < 0) {
+            } else if (c1 == null && c2 != null) {
                 return -1;
-            }
-            if (difference > 0) {
+            } else if (c2 == null && c1 != null) {
                 return 1;
             }
-            return 0;
+            return Double.compare(a.getStart(), b.getStart());
         }
 
         public boolean equals(Object other) {
@@ -176,6 +173,7 @@
     private HashMap<String, String> types = new HashMap<String, String>();
     private HashMap<String, Method> methods = new HashMap<String, Method>();
     private LinkedHashMap<String, NMethod> nmethods = new LinkedHashMap<String, NMethod>();
+    private ArrayList<MakeNotEntrantEvent> notEntrantEvents = new ArrayList<MakeNotEntrantEvent>();
     private HashMap<String, Compilation> compiles = new HashMap<String, Compilation>();
     private String failureReason;
     private int bci;
@@ -235,15 +233,36 @@
         }
 
         // Associate compilations with their NMethods
-        for (NMethod nm : log.nmethods.values()) {
-            Compilation c = log.compiles.get(nm.getId());
-            nm.setCompilation(c);
-            // Native wrappers for methods don't have a compilation
-            if (c != null) {
-                c.setNMethod(nm);
+        for (LogEvent le : log.events) {
+            if (le instanceof BasicLogEvent) {
+                BasicLogEvent ble = (BasicLogEvent) le;
+                Compilation c = log.compiles.get(ble.getId());
+                ble.setCompilation(c);
+                if (ble instanceof NMethod) {
+                    NMethod nm = (NMethod) ble;
+                    // Native wrappers for methods don't have a compilation and Graal methods don't either.
+                    if (c == null) {
+                        c = new Compilation(Integer.parseInt(nm.getId()));
+                        log.compiles.put(ble.getId(), c);
+                    }
+                    c.setNMethod(nm);
+                } else {
+                    if (c == null) {
+                        // throw new InternalError("can't find compilation " + ble.getId() + " for " + ble);
+                    }
+                }
             }
         }
 
+
+        for (MakeNotEntrantEvent ne : log.notEntrantEvents) {
+            Compilation c = log.compiles.get(ne.getId());
+            if (c == null) {
+                throw new InternalError("can't find compilation " + ne.getId());
+            }
+            ne.setCompilation(c);
+        }
+
         // Initially we want the LogEvent log sorted by timestamp
         Collections.sort(log.events, sortByStart);
 
@@ -331,9 +350,14 @@
             compile.setBCount(search(atts, "backedge_count", "0"));
 
             String method = atts.getValue("method");
+            Method m = new Method();
             int space = method.indexOf(' ');
-            method = method.substring(0, space) + "::" +
-                    method.substring(space + 1, method.indexOf(' ', space + 1) + 1);
+            m.setHolder(method.substring(0, space));
+            m.setName(method.substring(space + 1, method.indexOf(' ', space + 1) + 1));
+            m.setReturnType(method.substring(method.lastIndexOf(')') + 1));
+            m.setArguments(method.substring(method.indexOf('(') + 1, method.lastIndexOf(')')));
+            m.setFlags("0");
+            compile.setMethod(m);
             String compiler = atts.getValue("compiler");
             if (compiler == null) {
                 compiler = "";
@@ -345,10 +369,11 @@
             if (kind.equals("osr")) {
                 compile.setOsr(true);
                 compile.setOsr_bci(Integer.parseInt(search(atts, "osr_bci")));
+                compile.setMethod(m);
             } else if (kind.equals("c2i")) {
                 compile.setSpecial("--- adapter " + method);
             } else {
-                compile.setSpecial(compile.getId() + " " + method + " (0 bytes)");
+                compile.setMethod(m);
             }
             events.add(compile);
             compiles.put(makeId(atts), compile);
@@ -388,6 +413,17 @@
             scopes.peek().last().setReason(search(atts, "reason"));
         } else if (qname.equals("failure")) {
             failureReason = search(atts, "reason");
+        } else if (qname.equals("task_queued")) {
+            String id = makeId(atts);
+            int level = Integer.parseInt(search(atts, "level", "4"));
+            TaskEvent t = new TaskEvent(Double.parseDouble(search(atts, "stamp")), id, level, TaskEvent.Kind.Enqueue);
+            events.add(t);
+        } else if (qname.equals("task_dequeued")) {
+            String id = makeId(atts);
+            int level = Integer.parseInt(search(atts, "level", "4"));
+            TaskEvent t = new TaskEvent(Double.parseDouble(search(atts, "stamp")), id, level, TaskEvent.Kind.Dequeue);
+            t.setComment(search(atts, "comment"));
+            events.add(t);
         } else if (qname.equals("task_done")) {
             compile.setEnd(Double.parseDouble(search(atts, "stamp")));
             if (Integer.parseInt(search(atts, "success")) == 0) {
@@ -397,8 +433,9 @@
             String id = makeId(atts);
             NMethod nm = nmethods.get(id);
             if (nm == null) throw new InternalError();
-            LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
-                                                 atts.getValue("zombie") != null, nm);
+            MakeNotEntrantEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
+                                                            atts.getValue("zombie") != null, nm);
+            notEntrantEvents.add(e);
             events.add(e);
         } else if (qname.equals("uncommon_trap")) {
             String id = atts.getValue("compile_id");
@@ -444,11 +481,18 @@
         } else if (qname.equals("nmethod")) {
             String id = makeId(atts);
             NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")),
-                    id,
-                    parseLong(atts.getValue("address")),
-                    parseLong(atts.getValue("size")));
+                                     id,
+                                     atts.getValue("compile_kind"),
+                                     parseLong(atts.getValue("address")),
+                                     parseLong(atts.getValue("size")));
             nmethods.put(id, nm);
             events.add(nm);
+
+            int level = Integer.parseInt(search(atts, "level", "4"));
+            if (level > 0) {
+                TaskEvent t = new TaskEvent(Double.parseDouble(search(atts, "stamp")), id, level, TaskEvent.Kind.Finish);
+                events.add(t);
+            }
         } else if (qname.equals("parse")) {
             Method m = method(search(atts, "method"));
             if (scopes.size() == 0) {
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -43,9 +43,9 @@
 
     public void print(PrintStream stream) {
         if (isZombie()) {
-            stream.printf("%s make_zombie\n", getId());
+            stream.printf("%s make_zombie\n", compilation.shortName());
         } else {
-            stream.printf("%s make_not_entrant\n", getId());
+            stream.printf("%s make_not_entrant\n", compilation.shortName());
         }
     }
 
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java	Mon Feb 06 17:18:57 2017 +0100
@@ -50,11 +50,19 @@
     }
 
     String format(int osr_bci) {
+        String bci = "";
         if (osr_bci >= 0) {
-            return getHolder().replace('/', '.') + "::" + getName() + " @ " + osr_bci + " (" + getBytes() + " bytes)";
-        } else {
-            return getHolder().replace('/', '.') + "::" + getName() + " (" + getBytes() + " bytes)";
+            bci = " @ " + osr_bci;
         }
+        return getHolder().replace('/', '.') + "::" + getName() + bci + " (" + getBytes() + " bytes)";
+    }
+
+    String formatLong(int osr_bci) {
+        String bci = "";
+        if (osr_bci >= 0) {
+            bci = " @ " + osr_bci;
+        }
+        return getReturnType() + " " + getHolder().replace('/', '.') + "::" + getName() + "(" + getArguments() + ")" + bci;
     }
 
     @Override
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java	Mon Feb 06 17:18:57 2017 +0100
@@ -30,11 +30,17 @@
 
     private long address;
     private long size;
+    private String compileKind;
 
-    NMethod(double s, String i, long a, long sz) {
+    NMethod(double s, String i, String k, long a, long sz) {
         super(s, i);
         address = a;
         size = sz;
+        if (k == null) {
+            compileKind = "normal";
+        } else {
+            compileKind = k;
+        }
     }
 
     public void print(PrintStream out) {
@@ -50,6 +56,10 @@
         this.address = address;
     }
 
+    public String getKind() {
+        return compileKind;
+    }
+
     public long getSize() {
         return size;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/TaskEvent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.tools.compiler;
+
+import java.io.PrintStream;
+
+public class TaskEvent extends BasicLogEvent {
+    private int level;
+    private String comment;
+    private Kind kind;
+
+    enum Kind {
+        Enqueue,
+        Dequeue,
+        Finish
+    }
+    
+    public TaskEvent(double start, String id, int level, Kind kind) {
+        super(start, id);
+        this.level = level;
+        this.kind = kind;
+    }
+
+    void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    String getComment() {
+        return comment;
+    }
+
+    int getLevel() {
+        return level;
+    }
+
+    Kind getKind() {
+        return kind;
+    }
+
+    public void print(PrintStream stream) {
+        stream.printf("%s id='%s' level='%s' %s%n", start, id, level, kind);
+    }
+}
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java	Mon Feb 06 17:18:57 2017 +0100
@@ -50,10 +50,14 @@
     }
 
     public void print(PrintStream stream) {
-        stream.printf("%s uncommon trap %.3f %s %s\n", getId(), getStart(), getReason(), getAction());
+        stream.printf("%s %s uncommon trap %.3f %s %s\n", compilation.shortName(), getId(), getStart(), getReason(), getAction());
         stream.print(getJvms());
     }
 
+    public String formatTrap() {
+        return String.format("uncommon trap %s %s\n%s", getReason(), getAction(), getJvms());
+    }
+
     public String getReason() {
         return reason;
     }
--- a/src/share/tools/ProjectCreator/BuildConfig.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/ProjectCreator/BuildConfig.java	Mon Feb 06 17:18:57 2017 +0100
@@ -67,6 +67,24 @@
         String outDir = buildBase;
         String jdkTargetRoot = getFieldString(null, "JdkTargetRoot");
 
+        String value = System.getenv("OUT_DIR");
+        if (value != null) {
+            outDir = value;
+            int lastDirectorySeparator = Math.max(outDir.lastIndexOf("/"), outDir.lastIndexOf("\\"));
+            if (lastDirectorySeparator >= 0) {
+                outDir = outDir.substring(0, lastDirectorySeparator);
+            }
+            outDir += Util.sep + build + Util.sep + "jre" + Util.sep + "bin";
+            if (flavour.equals("jvmci")) {
+                outDir += Util.sep + "jvmci";
+            } else if (flavour.equals("compiler1")) {
+                outDir += Util.sep + "client";
+            } else {
+                outDir += Util.sep + "server";
+            }
+            buildBase = outDir;
+        }
+
         put("Id", flavourBuild);
         put("OutputDir", outDir);
         put("SourceBase", sourceBase);
@@ -211,7 +229,19 @@
 
     void initDefaultDefines(Vector defines) {
         Vector sysDefines = new Vector();
-        sysDefines.add("WIN32");
+
+        if( vars.get("PlatformName").equals("Win32")) {
+            sysDefines.add("WIN32");
+        } else {
+            sysDefines.add("_AMD64_");
+            sysDefines.add("AMD64");
+            sysDefines.add("_WIN64");
+            sysDefines.add("_LP64");
+            if (System.getenv("MSC_VER") != null)
+               sysDefines.add("MSC_VER=" + System.getenv("MSC_VER"));
+            sysDefines.add("HOTSPOT_LIB_ARCH=\\\"amd64\\\"");
+        }
+	
         sysDefines.add("_WINDOWS");
         sysDefines.add("HOTSPOT_BUILD_USER=\\\""+System.getProperty("user.name")+"\\\"");
         sysDefines.add("HOTSPOT_BUILD_TARGET=\\\""+get("Build")+"\\\"");
@@ -287,6 +317,10 @@
         return get("Build");
     }
 
+    String outputDir() {
+        return get("OutputDir");
+    }
+
     Object getSpecificField(String field) {
         return getField(get("Id"), field);
     }
@@ -481,6 +515,9 @@
                 case 'f':
                     sb.append(flavour());
                     break;
+                case 'o':
+                    sb.append(outputDir());
+                    break;
                 default:
                     sb.append(ch);
                     sb.append(ch1);
@@ -516,6 +553,28 @@
    }
 }
 
+class GraalDebugConfig extends GenericDebugNonKernelConfig {
+    String getOptFlag() {
+        return getCI().getNoOptFlag();
+    }
+
+    GraalDebugConfig() {
+        initNames("jvmci", "debug", "jvm.dll");
+        init(getIncludes(), getDefines());
+    }
+}
+
+class GraalFastDebugConfig extends GenericDebugNonKernelConfig {
+    String getOptFlag() {
+        return getCI().getOptFlag();
+    }
+
+    GraalFastDebugConfig() {
+        initNames("jvmci", "fastdebug", "jvm.dll");
+        init(getIncludes(), getDefines());
+    }
+}
+
 class C1DebugConfig extends GenericDebugNonKernelConfig {
     String getOptFlag() {
         return getCI().getNoOptFlag();
@@ -594,6 +653,13 @@
     }
 }
 
+class GraalProductConfig extends ProductConfig {
+    GraalProductConfig() {
+        initNames("jvmci", "product", "jvm.dll");
+        init(getIncludes(), getDefines());
+    }
+}
+
 class C1ProductConfig extends ProductConfig {
     C1ProductConfig() {
         initNames("compiler1", "product", "jvm.dll");
--- a/src/share/tools/ProjectCreator/FileTreeCreatorVC10.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/ProjectCreator/FileTreeCreatorVC10.java	Mon Feb 06 17:18:57 2017 +0100
@@ -96,7 +96,8 @@
                if (addFile.equals(fileName)) {
                   // supress any ignore
                   // TODO - may need some adjustments
-                  if (file.toAbsolutePath().toString().contains(cfg.get("Flavour"))) {
+                  String relativePath = startDir.toUri().relativize(file.toUri()).getPath();
+                  if (relativePath.contains(cfg.get("Flavour"))) {
                      currentFileAttr.removeFromIgnored(cfg);
                   }
                }
--- a/src/share/tools/ProjectCreator/WinGammaPlatform.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/ProjectCreator/WinGammaPlatform.java	Mon Feb 06 17:18:57 2017 +0100
@@ -567,6 +567,10 @@
     Vector createAllConfigs(String platform) {
         Vector allConfigs = new Vector();
 
+        allConfigs.add(new GraalDebugConfig());
+        allConfigs.add(new GraalFastDebugConfig());
+        allConfigs.add(new GraalProductConfig());
+
         allConfigs.add(new C1DebugConfig());
         allConfigs.add(new C1FastDebugConfig());
         allConfigs.add(new C1ProductConfig());
--- a/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java	Mon Feb 06 17:18:57 2017 +0100
@@ -352,8 +352,7 @@
         // Set /On option
         addAttr(rv, "Optimization", opt);
         // Set /FR option.
-        addAttr(rv, "BrowseInformation", "true");
-        addAttr(rv, "BrowseInformationFile", "$(IntDir)");
+        addAttr(rv, "BrowseInformation", "false");
         // Set /MD option.
         addAttr(rv, "RuntimeLibrary", "MultiThreadedDLL");
         // Set /Oy- option
--- a/src/share/tools/hsdis/Makefile	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/hsdis/Makefile	Mon Feb 06 17:18:57 2017 +0100
@@ -142,6 +142,10 @@
 endif	# Linux
 endif	# SunOS
 
+ifneq ($(ATT_SYNTAX),)
+CFLAGS += -DATT_SYNTAX
+endif
+
 LIBARCH		= $(ARCH)
 ifdef		LP64
 LIBARCH64/sparc	= sparcv9
@@ -163,10 +167,15 @@
 endif
 
 CPPFLAGS	+= -I$(BINUTILSDIR)/include -I$(BINUTILSDIR)/bfd -I$(TARGET_DIR)/bfd
-CPPFLAGS	+= -DLIBARCH_$(LIBARCH) -DLIBARCH=\"$(LIBARCH)\" -DLIB_EXT=\"$(LIB_EXT)\"
+CPPFLAGS	+= -DLIBARCH_$(LIBARCH) -DLIBARCH=\"$(LIBARCH)\" -DLIB_EXT=\"$(LIB_EXT)\" -DBINUTILS="\"$(BINUTILS)\""
 
 TARGET_DIR	= build/$(OS)-$(JDKARCH)
-TARGET		= $(TARGET_DIR)/hsdis-$(LIBARCH)$(LIB_EXT)
+TARGET_LIBRARY  = hsdis-$(LIBARCH)$(LIB_EXT)
+ifeq ($(ALT_TARGET_DIR),)
+TARGET		= $(TARGET_DIR)/$(TARGET_LIBRARY)
+else
+TARGET		= $(ALT_TARGET_DIR)/$(TARGET_LIBRARY)
+endif
 
 SOURCE		= hsdis.c
 
@@ -203,5 +212,12 @@
 $(TARGET_DIR):
 	[ -d $@ ] || mkdir -p $@
 
+variants: att intel
+	make $(MAKEFLAGS) ALT_TARGET_DIR=intel 
+	make $(MAKEFLAGS) ALT_TARGET_DIR=att ATT_SYNTAX=1 all
+
+att intel:
+	mkdir $@
+
 clean:
 	rm -rf $(TARGET_DIR)
--- a/src/share/tools/hsdis/hsdis.c	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/tools/hsdis/hsdis.c	Mon Feb 06 17:18:57 2017 +0100
@@ -70,6 +70,19 @@
   char insn_options[256];
 };
 
+#if defined(LIBARCH_i386) || defined(LIBARCH_amd64)
+#ifdef ATT_SYNTAX
+#define PLATFORM_OPTIONS "att"
+#else
+#define PLATFORM_OPTIONS "intel"
+#endif
+#else
+#define PLATFORM_OPTIONS ""
+#endif
+static const char* platform_options = PLATFORM_OPTIONS;
+
+const char* hsdis_version_string = "built from " BINUTILS " with disassembler options \"" PLATFORM_OPTIONS "\" on " __DATE__ " at " __TIME__;
+
 static void* decode(struct hsdis_app_data* app_data, const char* options);
 
 #define DECL_APP_DATA(dinfo) \
@@ -125,7 +138,7 @@
                     event_callback_t  event_callback_arg,  void* event_stream_arg,
                     printf_callback_t printf_callback_arg, void* printf_stream_arg,
                     const char* options) {
-  decode_instructions_virtual((uintptr_t)start_pv,
+  return decode_instructions_virtual((uintptr_t)start_pv,
                              (uintptr_t)end_pv,
                              (unsigned char*)start_pv,
                              (uintptr_t)end_pv - (uintptr_t)start_pv,
@@ -150,6 +163,8 @@
 
     (*event_callback)(event_stream, "insns", (void*)start);
 
+    (*event_callback)(event_stream, "options='%s'",
+                      (void*) app_data->insn_options);
     (*event_callback)(event_stream, "mach name='%s'",
                       (void*) app_data->arch_info->printable_name);
     if (app_data->dinfo.bytes_per_line != 0) {
@@ -205,6 +220,7 @@
 
   const char* type = "unknown";
   switch (itype) {
+  case dis_noninsn:
   case dis_nonbranch:   type = NULL;         break;
   case dis_branch:      type = "branch";     break;
   case dis_condbranch:  type = "condbranch"; break;
@@ -285,9 +301,14 @@
   */
   set_optional_callbacks(app_data);
 
+  memset(app_data->insn_options, 0, sizeof(app_data->insn_options));
+  if (platform_options != NULL) {
+    parse_caller_options(app_data, platform_options);
+  }
   /* Look into caller_options for anything interesting. */
-  if (caller_options != NULL)
+  if (caller_options != NULL) {
     parse_caller_options(app_data, caller_options);
+  }
 
   /* Discover which architecture we are going to disassemble. */
   app_data->arch_name = &app_data->mach_option[0];
@@ -385,6 +406,11 @@
   char* iop_base = app_data->insn_options;
   char* iop_limit = iop_base + sizeof(app_data->insn_options) - 1;
   char* iop = iop_base;
+
+  // Move to the end of any options already in the buffer
+  while (*iop != '\0' && iop < iop_limit) {
+    iop++;
+  }
   const char* p;
   for (p = caller_options; p != NULL; ) {
     const char* q = strchr(p, ',');
--- a/src/share/vm/adlc/Doc/Syntax.doc	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/adlc/Doc/Syntax.doc	Mon Feb 06 17:18:57 2017 +0100
@@ -33,7 +33,7 @@
 the architecture of a processor, and is the input to the ADL Compiler.  The
 ADL Compiler compiles an ADL file into code which is incorporated into the
 Optimizing Just In Time Compiler (OJIT) to generate efficient and correct code
-for the target architecture.  The ADL describes three bassic different types
+for the target architecture.  The ADL describes three basic different types
 of architectural features.  It describes the instruction set (and associated
 operands) of the target architecture.  It describes the register set of the
 target architecture along with relevant information for the register allocator.
--- a/src/share/vm/asm/codeBuffer.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/asm/codeBuffer.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -972,6 +972,7 @@
 
 void CodeBuffer::log_section_sizes(const char* name) {
   if (xtty != NULL) {
+    ttyLocker ttyl;
     // log info about buffer usage
     xtty->print_cr("<blob name='%s' size='%d'>", name, _total_size);
     for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
@@ -1122,8 +1123,9 @@
     CodeString* c = find(offset);
     while (c && c->offset() == offset) {
       stream->bol();
-      stream->print("  ;; ");
-      stream->print_cr("%s", c->string());
+      stream->print_raw("  ;; ");
+      // Don't interpret as format strings since it could contain %
+      stream->print_raw_cr(c->string());
       c = c->next_comment();
     }
   }
--- a/src/share/vm/c1/c1_Compiler.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/c1/c1_Compiler.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -43,7 +43,8 @@
 #include "runtime/sharedRuntime.hpp"
 
 
-Compiler::Compiler () {}
+Compiler::Compiler() : AbstractCompiler(c1) {
+}
 
 void Compiler::init_c1_runtime() {
   BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -3610,6 +3610,8 @@
     case vmIntrinsics::_updateBytesCRC32:
     case vmIntrinsics::_updateByteBufferCRC32:
       if (!UseCRC32Intrinsics) return false;
+      // JVMCI-409: CRC32 C1 intrinsics cause errors on jdk version earlier than 8
+      if (!JDK_Version::is_gte_jdk18x_version()) return false;
       cantrap = false;
       preserves_state = true;
       break;
--- a/src/share/vm/c1/c1_IR.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/c1/c1_IR.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -240,7 +240,8 @@
     // reexecute allowed only for the topmost frame
     bool reexecute = topmost ? should_reexecute() : false;
     bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
-    recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+    bool rethrow_exception = false;
+    recorder->describe_scope(pc_offset, methodHandle(), scope()->method(), bci(), reexecute, rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
   }
 };
 
--- a/src/share/vm/c1/c1_LIRAssembler.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -336,7 +336,6 @@
 
 
 void LIR_Assembler::add_debug_info_for_branch(CodeEmitInfo* info) {
-  _masm->code_section()->relocate(pc(), relocInfo::poll_type);
   int pc_offset = code_offset();
   flush_debug_info(pc_offset);
   info->record_debug_info(compilation()->debug_info_recorder(), pc_offset);
@@ -424,7 +423,8 @@
     if (s == NULL)  break;
     IRScope* scope = s->scope();
     //Always pass false for reexecute since these ScopeDescs are never used for deopt
-    debug_info->describe_scope(pc_offset, scope->method(), s->bci(), false/*reexecute*/);
+    methodHandle null_mh;
+    debug_info->describe_scope(pc_offset, null_mh, scope->method(), s->bci(), false/*reexecute*/);
   }
 
   debug_info->end_non_safepoint(pc_offset);
--- a/src/share/vm/c1/c1_Runtime1.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -547,9 +547,8 @@
     // normal bytecode execution.
     thread->clear_exception_oop_and_pc();
 
-    Handle original_exception(thread, exception());
-
-    continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false);
+    bool recursive_exception = false;
+    continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false, recursive_exception);
     // If an exception was thrown during exception dispatch, the exception oop may have changed
     thread->set_exception_oop(exception());
     thread->set_exception_pc(pc);
@@ -557,8 +556,9 @@
     // the exception cache is used only by non-implicit exceptions
     // Update the exception cache only when there didn't happen
     // another exception during the computation of the compiled
-    // exception handler.
-    if (continuation != NULL && original_exception() == exception()) {
+    // exception handler. Checking for exception oop equality is not
+    // sufficient because some exceptions are pre-allocated and reused.
+    if (continuation != NULL && !recursive_exception) {
       nm->add_handler_for_exception_and_pc(exception, pc, continuation);
     }
   }
--- a/src/share/vm/classfile/classFileParser.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/classfile/classFileParser.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1806,6 +1806,12 @@
     if (_location != _in_method)  break;  // only allow for methods
     if (!privileged)              break;  // only allow in privileged code
     return _method_LambdaForm_Hidden;
+#if INCLUDE_JVMCI
+  case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_vm_ci_hotspot_Stable_signature):
+    if (_location != _in_field)   break;  // only allow for fields
+    if (!privileged && loader_data->class_loader() != SystemDictionary::jvmci_loader()) break;  // only allow in privileged code
+    return _field_Stable;
+#endif
   case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_Stable_signature):
     if (_location != _in_field)   break;  // only allow for fields
     if (!privileged)              break;  // only allow in privileged code
--- a/src/share/vm/classfile/javaClasses.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/classfile/javaClasses.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -563,6 +563,12 @@
   set_init_lock(mirror(), r);
 
   // Set protection domain also
+#if INCLUDE_JVMCI
+  if (k->class_loader() == SystemDictionary::jvmci_loader()) {
+    // Same protection domain as for classes loaded by the boot loader
+    protection_domain = Handle();
+  }
+#endif
   set_protection_domain(mirror(), protection_domain());
 
   // Initialize static fields
@@ -1534,7 +1540,7 @@
   while (h_throwable.not_null()) {
     objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable())));
     if (result.is_null()) {
-      st->print_cr("%s", no_stack_trace_message());
+      st->print_raw_cr(no_stack_trace_message());
       return;
     }
 
@@ -1612,7 +1618,7 @@
     }
     return;
   }
-
+  
   // Instead of using vframe directly, this version of fill_in_stack_trace
   // basically handles everything by hand. This significantly improved the
   // speed of this method call up to 28.5% on Solaris sparc. 27.1% on Windows.
--- a/src/share/vm/classfile/javaClasses.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/classfile/javaClasses.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -153,7 +153,12 @@
     if (count_offset > 0) {
       return java_string->int_field(count_offset);
     } else {
-      return ((typeArrayOop)java_string->obj_field(value_offset))->length();
+      typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset));
+      if (value_array == NULL) {
+        return 0;
+      } else {
+        return value_array->length();
+      }
     }
   }
   static int utf8_length(oop java_string);
--- a/src/share/vm/classfile/metadataOnStackMark.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/classfile/metadataOnStackMark.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -32,6 +32,9 @@
 #include "runtime/thread.hpp"
 #include "services/threadService.hpp"
 #include "utilities/chunkedList.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 
 volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
 volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;
@@ -53,6 +56,9 @@
   CompileBroker::mark_on_stack();
   JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
   ThreadService::metadata_do(Metadata::mark_on_stack);
+#if INCLUDE_JVMCI
+  JVMCIRuntime::metadata_do(Metadata::mark_on_stack);
+#endif
 }
 
 MetadataOnStackMark::~MetadataOnStackMark() {
--- a/src/share/vm/classfile/systemDictionary.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/classfile/systemDictionary.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -64,6 +64,9 @@
 #include "services/threadService.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/ticks.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 #if INCLUDE_TRACE
 #include "trace/tracing.hpp"
 #endif
@@ -93,6 +96,10 @@
 bool        SystemDictionary::_has_loadClassInternal      =  false;
 bool        SystemDictionary::_has_checkPackageAccess     =  false;
 
+#if INCLUDE_JVMCI
+oop         SystemDictionary::_jvmci_loader               = NULL;
+#endif
+
 // lazily initialized klass variables
 Klass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL;
 
@@ -224,7 +231,7 @@
 // Forwards to resolve_instance_class_or_null
 
 Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
-  assert(!THREAD->is_Compiler_thread(),
+  assert(THREAD->can_call_java(),
          err_msg("can not load classes with compiler thread: class=%s, classloader=%s",
                  class_name->as_C_string(),
                  class_loader.is_null() ? "null" : class_loader->klass()->name()->as_C_string()));
@@ -1723,6 +1730,7 @@
   strong->do_oop(&_java_system_loader);
   strong->do_oop(&_system_loader_lock_obj);
   CDS_ONLY(SystemDictionaryShared::roots_oops_do(strong);)
+  JVMCI_ONLY(strong->do_oop(&_jvmci_loader);)
 
   // Adjust dictionary
   dictionary()->roots_oops_do(strong, weak);
@@ -1735,6 +1743,7 @@
   f->do_oop(&_java_system_loader);
   f->do_oop(&_system_loader_lock_obj);
   CDS_ONLY(SystemDictionaryShared::oops_do(f);)
+  JVMCI_ONLY(f->do_oop(&_jvmci_loader);)
 
   // Adjust dictionary
   dictionary()->oops_do(f);
@@ -1856,9 +1865,16 @@
   int  sid  = (info >> CEIL_LG_OPTION_LIMIT);
   Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
   Klass**    klassp = &_well_known_klasses[id];
-  bool must_load = (init_opt < SystemDictionary::Opt);
   if ((*klassp) == NULL) {
-    if (must_load) {
+#if INCLUDE_JVMCI
+    if (EnableJVMCI && init_opt == SystemDictionary::Jvmci) {
+      assert(id >= (int)FIRST_JVMCI_WKID && id <= (int)LAST_JVMCI_WKID,
+          "JVMCI WKIDs must be contiguous and separate from non-JVMCI WKIDs");
+      (*klassp) = resolve_or_fail(symbol, _jvmci_loader, Handle(), true, CHECK_0); // load required JVMCI class
+      return ((*klassp) != NULL);
+    }
+#endif
+    if (init_opt < SystemDictionary::Opt) {
       (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class
     } else {
       (*klassp) = resolve_or_null(symbol,       CHECK_0); // load optional klass
@@ -1935,7 +1951,7 @@
     scan = WKID(jsr292_group_end + 1);
   }
 
-  initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
+  initialize_wk_klasses_until(NOT_JVMCI(WKID_LIMIT) JVMCI_ONLY(FIRST_JVMCI_WKID), scan, CHECK);
 
   _box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
   _box_klasses[T_CHAR]    = WK_KLASS(Character_klass);
@@ -2307,8 +2323,8 @@
     }
   }
 
-  assert(spe != NULL && spe->method() != NULL, "");
-  assert(Arguments::is_interpreter_only() || (spe->method()->has_compiled_code() &&
+  guarantee(spe != NULL && spe->method() != NULL, "");
+  guarantee(Arguments::is_interpreter_only() || (spe->method()->has_compiled_code() &&
          spe->method()->code()->entry_point() == spe->method()->from_compiled_entry()),
          "MH intrinsic invariant");
   return spe->method();
@@ -2356,7 +2372,7 @@
                                                           TRAPS) {
   methodHandle empty;
   assert(EnableInvokeDynamic, "");
-  assert(!THREAD->is_Compiler_thread(), "");
+  assert(THREAD->can_call_java() ,"");
   Handle method_type =
     SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty));
 
@@ -2424,7 +2440,7 @@
   if (spe != NULL && spe->method_type() != NULL) {
     assert(java_lang_invoke_MethodType::is_instance(spe->method_type()), "");
     return Handle(THREAD, spe->method_type());
-  } else if (THREAD->is_Compiler_thread()) {
+  } else if (!THREAD->can_call_java()) {
     warning("SystemDictionary::find_method_handle_type called from compiler thread");  // FIXME
     return Handle();  // do not attempt from within compiler, unless it was cached
   }
--- a/src/share/vm/classfile/systemDictionary.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/classfile/systemDictionary.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 #include "runtime/reflectionUtils.hpp"
 #include "utilities/hashtable.hpp"
 #include "utilities/hashtable.inline.hpp"
+#include "jvmci/systemDictionary_jvmci.hpp"
 
 
 // The system dictionary stores all loaded classes and maps:
@@ -195,6 +196,10 @@
   do_klass(Short_klass,                                 java_lang_Short,                           Pre                 ) \
   do_klass(Integer_klass,                               java_lang_Integer,                         Pre                 ) \
   do_klass(Long_klass,                                  java_lang_Long,                            Pre                 ) \
+                                                                                                                         \
+  /* JVMCI classes. These are loaded on-demand. */                                                                       \
+  JVMCI_WK_KLASSES_DO(do_klass) \
+
   /*end*/
 
 
@@ -212,6 +217,11 @@
 
     WKID_LIMIT,
 
+#if INCLUDE_JVMCI
+    FIRST_JVMCI_WKID = WK_KLASS_ENUM_NAME(JVMCI_klass),
+    LAST_JVMCI_WKID  = WK_KLASS_ENUM_NAME(Value_klass),
+#endif
+
     FIRST_WKID = NO_WKID + 1
   };
 
@@ -225,6 +235,9 @@
     Opt,                        // preload tried; NULL if not present
     Opt_Only_JDK14NewRef,       // preload tried; use only with NewReflection
     Opt_Only_JDK15,             // preload tried; use only with JDK1.5+
+#if INCLUDE_JVMCI
+    Jvmci,                      // preload tried; error if not present, use only with JVMCI
+#endif
     OPTION_LIMIT,
     CEIL_LG_OPTION_LIMIT = 4    // OPTION_LIMIT <= (1<<CEIL_LG_OPTION_LIMIT)
   };
@@ -414,6 +427,9 @@
     // despite the optional loading, if you use this it must be present:
     return check_klass(k);
   }
+#if INCLUDE_JVMCI
+  static Klass* check_klass_Jvmci(Klass* k)      { return k; }
+#endif
 
   static bool initialize_wk_klass(WKID id, int init_opt, TRAPS);
   static void initialize_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS);
@@ -479,6 +495,18 @@
   // Returns default system loader
   static oop java_system_loader();
 
+#if INCLUDE_JVMCI
+  // Returns the JVMCI loader. This will be NULL if !UseJVMCIClassLoader
+  // in which case it's equivalent to the boot loader
+  static oop jvmci_loader()                 { return _jvmci_loader; }
+
+  // Sets the JVMCI loader. This is called at most once.
+  static void init_jvmci_loader(oop loader) {
+    assert(UseJVMCIClassLoader == (loader != NULL), "must be");
+    _jvmci_loader = loader;
+  }
+#endif
+
   // Compute the default system loader
   static void compute_java_system_loader(TRAPS);
 
@@ -709,6 +737,9 @@
   static Klass* _box_klasses[T_VOID+1];
 
   static oop  _java_system_loader;
+#if INCLUDE_JVMCI
+  static oop  _jvmci_loader;
+#endif
 
   static bool _has_loadClassInternal;
   static bool _has_checkPackageAccess;
--- a/src/share/vm/classfile/verifier.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/classfile/verifier.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -94,7 +94,7 @@
 // Methods in Verifier
 
 bool Verifier::should_verify_for(oop class_loader, bool should_verify_class) {
-  return (class_loader == NULL || !should_verify_class) ?
+  return (class_loader == NULL JVMCI_ONLY(|| class_loader == SystemDictionary::jvmci_loader()) || !should_verify_class) ?
     BytecodeVerificationLocal : BytecodeVerificationRemote;
 }
 
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -28,6 +28,7 @@
 #include "oops/symbol.hpp"
 #include "memory/iterator.hpp"
 #include "trace/traceMacros.hpp"
+#include "jvmci/vmSymbols_jvmci.hpp"
 
 // The class vmSymbols is a name space for fast lookup of
 // symbols commonly used in the VM.
@@ -301,6 +302,9 @@
   NOT_LP64(  do_alias(intptr_signature,               int_signature)  )                           \
   LP64_ONLY( do_alias(intptr_signature,               long_signature) )                           \
                                                                                                   \
+  /* Support for JVMCI */                                                                                                             \
+  JVMCI_VM_SYMBOLS_DO(template, do_alias)                                                         \
+                                                                                                  \
   /* common method and field names */                                                             \
   template(object_initializer_name,                   "<init>")                                   \
   template(class_initializer_name,                    "<clinit>")                                 \
@@ -327,6 +331,7 @@
   template(nthreads_name,                             "nthreads")                                 \
   template(ngroups_name,                              "ngroups")                                  \
   template(shutdown_method_name,                      "shutdown")                                 \
+  template(bootstrapFinished_method_name,             "bootstrapFinished")                        \
   template(finalize_method_name,                      "finalize")                                 \
   template(reference_lock_name,                       "lock")                                     \
   template(reference_discovered_name,                 "discovered")                               \
@@ -384,6 +389,7 @@
   template(bitCount_name,                             "bitCount")                                 \
   template(profile_name,                              "profile")                                  \
   template(equals_name,                               "equals")                                   \
+  template(length_name,                               "length")                                   \
   template(target_name,                               "target")                                   \
   template(toString_name,                             "toString")                                 \
   template(values_name,                               "values")                                   \
@@ -435,6 +441,7 @@
   template(void_long_signature,                       "()J")                                      \
   template(void_float_signature,                      "()F")                                      \
   template(void_double_signature,                     "()D")                                      \
+  template(bool_void_signature,                       "(Z)V")                                     \
   template(int_void_signature,                        "(I)V")                                     \
   template(int_int_signature,                         "(I)I")                                     \
   template(char_char_signature,                       "(C)C")                                     \
--- a/src/share/vm/code/codeBlob.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/codeBlob.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -105,6 +105,7 @@
 
   virtual bool is_compiled_by_c2() const         { return false; }
   virtual bool is_compiled_by_c1() const         { return false; }
+  virtual bool is_compiled_by_jvmci() const      { return false; }
 
   // Casting
   nmethod* as_nmethod_or_null()                  { return is_nmethod() ? (nmethod*) this : NULL; }
@@ -356,6 +357,12 @@
 
   int _unpack_with_exception_in_tls;
 
+#if INCLUDE_JVMCI
+  // Offset when JVMCI calls uncommon_trap.
+  int _uncommon_trap_offset;
+  int _implicit_exception_uncommon_trap_offset;
+#endif
+
   // Creation support
   DeoptimizationBlob(
     CodeBuffer* cb,
@@ -408,6 +415,21 @@
     assert(code_contains(code_begin() + _unpack_with_exception_in_tls), "must be PC inside codeblob");
   }
   address unpack_with_exception_in_tls() const   { return code_begin() + _unpack_with_exception_in_tls; }
+
+#if INCLUDE_JVMCI
+  // Offset when JVMCI calls uncommon_trap.
+  void set_uncommon_trap_offset(int offset) {
+    _uncommon_trap_offset = offset;
+    assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob");
+  }
+  address uncommon_trap() const                  { return code_begin() + _uncommon_trap_offset;     }
+
+  void set_implicit_exception_uncommon_trap_offset(int offset) {
+    _implicit_exception_uncommon_trap_offset = offset;
+    assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob");
+  }
+  address implicit_exception_uncommon_trap() const                  { return code_begin() + _implicit_exception_uncommon_trap_offset;     }
+#endif
 };
 
 
--- a/src/share/vm/code/compiledIC.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/compiledIC.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -280,11 +280,13 @@
   bool is_monomorphic = (cb != NULL && cb->is_nmethod());
   // Check that the cached_value is a klass for non-optimized monomorphic calls
   // This assertion is invalid for compiler1: a call that does not look optimized (no static stub) can be used
-  // for calling directly to vep without using the inline cache (i.e., cached_value == NULL)
+  // for calling directly to vep without using the inline cache (i.e., cached_value == NULL).
+  // For JVMCI this occurs because CHA is only used to improve inlining so call sites which could be optimized
+  // virtuals because there are no currently loaded subclasses of a type are left as virtual call sites.
 #ifdef ASSERT
   CodeBlob* caller = CodeCache::find_blob_unsafe(instruction_address());
-  bool is_c1_method = caller->is_compiled_by_c1();
-  assert( is_c1_method ||
+  bool is_c1_or_jvmci_method = caller->is_compiled_by_c1() || caller->is_compiled_by_jvmci();
+  assert( is_c1_or_jvmci_method ||
          !is_monomorphic ||
          is_optimized() ||
          !caller->is_alive() ||
--- a/src/share/vm/code/compiledIC.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/compiledIC.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -320,7 +320,7 @@
   friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site);
 
   // Code
-  static address emit_to_interp_stub(CodeBuffer &cbuf);
+  static address emit_to_interp_stub(CodeBuffer &cbuf, address mark = NULL);
   static int to_interp_stub_size();
   static int reloc_to_interp_stub();
 
--- a/src/share/vm/code/debugInfo.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/debugInfo.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -52,7 +52,7 @@
 #ifdef ASSERT
   assert(_obj_pool != NULL, "object pool does not exist");
   for (int i = _obj_pool->length() - 1; i >= 0; i--) {
-    assert(((ObjectValue*) _obj_pool->at(i))->id() != id, "should not be read twice");
+    assert(_obj_pool->at(i)->as_ObjectValue()->id() != id, "should not be read twice");
   }
 #endif
   ObjectValue* result = new ObjectValue(id);
@@ -66,7 +66,7 @@
   int id = read_int();
   assert(_obj_pool != NULL, "object pool does not exist");
   for (int i = _obj_pool->length() - 1; i >= 0; i--) {
-    ObjectValue* ov = (ObjectValue*) _obj_pool->at(i);
+    ObjectValue* ov = _obj_pool->at(i)->as_ObjectValue();
     if (ov->id() == id) {
       return ov;
     }
--- a/src/share/vm/code/debugInfo.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/debugInfo.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -41,6 +41,7 @@
 // - ConstantValue   describes a constant
 
 class ConstantOopReadValue;
+class ObjectValue;
 
 class ScopeValue: public ResourceObj {
  public:
@@ -58,6 +59,11 @@
     return (ConstantOopReadValue*) this;
   }
 
+  ObjectValue* as_ObjectValue() {
+    assert(is_object(), "must be");
+    return (ObjectValue*)this;
+  }
+
   // Serialization of debugging information
   virtual void write_on(DebugInfoWriteStream* stream) = 0;
   static ScopeValue* read_from(DebugInfoReadStream* stream);
--- a/src/share/vm/code/debugInfoRec.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/debugInfoRec.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -37,6 +37,9 @@
   int  _offset; // location in the stream of this scope
   int  _length; // number of bytes in the stream
   int  _hash;   // hash of stream bytes (for quicker reuse)
+#if INCLUDE_JVMCI
+  DebugInformationRecorder* _DIR;
+#endif
 
   void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() {
     assert(ignore == sizeof(DIR_Chunk), "");
@@ -51,6 +54,9 @@
   DIR_Chunk(int offset, int length, DebugInformationRecorder* dir) {
     _offset = offset;
     _length = length;
+#if INCLUDE_JVMCI
+    _DIR = dir;
+#endif
     unsigned int hash = 0;
     address p = dir->stream()->buffer() + _offset;
     for (int i = 0; i < length; i++) {
@@ -77,6 +83,25 @@
     }
     return NULL;
   }
+
+#if INCLUDE_JVMCI
+  static int compare(DIR_Chunk*& a, DIR_Chunk*& b) {
+    if (b->_hash > a->_hash) {
+      return 1;
+    }
+    if (b->_hash < a->_hash) {
+      return -1;
+    }
+    if (b->_length > a->_length) {
+      return 1;
+    }
+    if (b->_length < a->_length) {
+      return -1;
+    }
+    address buf = a->_DIR->stream()->buffer();
+    return memcmp(buf + b->_offset, buf + a->_offset, a->_length);
+  }
+#endif
 };
 
 static inline bool compute_recording_non_safepoints() {
@@ -113,7 +138,9 @@
   _oop_recorder = oop_recorder;
 
   _all_chunks    = new GrowableArray<DIR_Chunk*>(300);
+#if !INCLUDE_JVMCI
   _shared_chunks = new GrowableArray<DIR_Chunk*>(30);
+#endif
   _next_chunk = _next_chunk_limit = NULL;
 
   add_new_pc_offset(PcDesc::lower_offset_limit);  // sentinel record
@@ -235,10 +262,13 @@
 
 
 int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) {
-  // Only pull this trick if non-safepoint recording
-  // is enabled, for now.
-  if (!recording_non_safepoints())
+  if (FLAG_IS_DEFAULT(ShareDebugInfo)) {
+    if (!ShareDebugInfo && !recording_non_safepoints()) {
+      return serialized_null;
+    }
+  } else if (!ShareDebugInfo) {
     return serialized_null;
+  }
 
   NOT_PRODUCT(++dir_stats.chunks_queried);
   int stream_length = stream()->position() - stream_offset;
@@ -247,6 +277,19 @@
 
   DIR_Chunk* ns = new(this) DIR_Chunk(stream_offset, stream_length, this);
 
+#if INCLUDE_JVMCI
+  DIR_Chunk* match = _all_chunks->insert_sorted<DIR_Chunk::compare>(ns);
+  if (match != ns) {
+    // Found an existing chunk
+    NOT_PRODUCT(++dir_stats.chunks_shared);
+    assert(ns+1 == _next_chunk, "");
+    _next_chunk = ns;
+    return match->_offset;
+  } else {
+    // Inserted this chunk, so nothing to do
+    return serialized_null;
+  }
+#else
   // Look in previously shared scopes first:
   DIR_Chunk* ms = ns->find_match(_shared_chunks, 0, this);
   if (ms != NULL) {
@@ -274,15 +317,18 @@
   // No match.  Add this guy to the list, in hopes of future shares.
   _all_chunks->append(ns);
   return serialized_null;
+#endif
 }
 
 
 // must call add_safepoint before: it sets PcDesc and this routine uses
 // the last PcDesc set
 void DebugInformationRecorder::describe_scope(int         pc_offset,
+                                              methodHandle methodH,
                                               ciMethod*   method,
                                               int         bci,
                                               bool        reexecute,
+                                              bool        rethrow_exception,
                                               bool        is_method_handle_invoke,
                                               bool        return_oop,
                                               DebugToken* locals,
@@ -298,6 +344,7 @@
 
   // Record flags into pcDesc.
   last_pd->set_should_reexecute(reexecute);
+  last_pd->set_rethrow_exception(rethrow_exception);
   last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
   last_pd->set_return_oop(return_oop);
 
@@ -305,7 +352,14 @@
   stream()->write_int(sender_stream_offset);
 
   // serialize scope
-  Metadata* method_enc = (method == NULL)? NULL: method->constant_encoding();
+  Metadata* method_enc;
+  if (method != NULL) {
+    method_enc = method->constant_encoding();
+  } else if (methodH.not_null()) {
+    method_enc = methodH();
+  } else {
+    method_enc = NULL;
+  }
   stream()->write_int(oop_recorder()->find_index(method_enc));
   stream()->write_bci(bci);
   assert(method == NULL ||
@@ -338,7 +392,7 @@
   PcDesc* last_pd = &_pcs[_pcs_length-1];
   if (objects != NULL) {
     for (int i = objects->length() - 1; i >= 0; i--) {
-      ((ObjectValue*) objects->at(i))->set_visited(false);
+      objects->at(i)->as_ObjectValue()->set_visited(false);
     }
   }
   int offset = serialize_scope_values(objects);
--- a/src/share/vm/code/debugInfoRec.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/debugInfoRec.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -98,9 +98,11 @@
   // by add_non_safepoint, and the locals, expressions, and monitors
   // must all be null.
   void describe_scope(int         pc_offset,
+                      methodHandle methodH,
                       ciMethod*   method,
                       int         bci,
                       bool        reexecute,
+                      bool        rethrow_exception = false,
                       bool        is_method_handle_invoke = false,
                       bool        return_oop = false,
                       DebugToken* locals      = NULL,
@@ -161,7 +163,9 @@
 
   // Scopes that have been described so far.
   GrowableArray<DIR_Chunk*>* _all_chunks;
+#if !INCLUDE_JVMCI
   GrowableArray<DIR_Chunk*>* _shared_chunks;
+#endif
   DIR_Chunk* _next_chunk;
   DIR_Chunk* _next_chunk_limit;
 
--- a/src/share/vm/code/dependencies.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/dependencies.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -30,6 +30,7 @@
 #include "code/dependencies.hpp"
 #include "compiler/compileLog.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/objArrayKlass.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/thread.inline.hpp"
@@ -51,6 +52,9 @@
   _oop_recorder = env->oop_recorder();
   _log = env->log();
   _dep_seen = new(arena) GrowableArray<int>(arena, 500, 0, 0);
+#if INCLUDE_JVMCI
+  _using_dep_values = false;
+#endif
   DEBUG_ONLY(_deps[end_marker] = NULL);
   for (int i = (int)FIRST_TYPE; i < (int)TYPE_LIMIT; i++) {
     _deps[i] = new(arena) GrowableArray<ciBaseObject*>(arena, 10, 0, 0);
@@ -120,6 +124,65 @@
   assert_common_2(call_site_target_value, call_site, method_handle);
 }
 
+#if INCLUDE_JVMCI
+
+Dependencies::Dependencies(Arena* arena, OopRecorder* oop_recorder, CompileLog* log) {
+  _oop_recorder = oop_recorder;
+  _log = log;
+  _dep_seen = new(arena) GrowableArray<int>(arena, 500, 0, 0);
+  _using_dep_values = true;
+  DEBUG_ONLY(_dep_values[end_marker] = NULL);
+  for (int i = (int)FIRST_TYPE; i < (int)TYPE_LIMIT; i++) {
+    _dep_values[i] = new(arena) GrowableArray<DepValue>(arena, 10, 0, DepValue());
+  }
+  _content_bytes = NULL;
+  _size_in_bytes = (size_t)-1;
+
+  assert(TYPE_LIMIT <= (1<<LG2_TYPE_LIMIT), "sanity");
+}
+
+void Dependencies::assert_evol_method(Method* m) {
+  assert_common_1(evol_method, DepValue(_oop_recorder, m));
+}
+
+void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) {
+  check_ctxk(ctxk);
+  assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk));
+}
+
+void Dependencies::assert_leaf_type(Klass* ctxk) {
+  if (ctxk->oop_is_array()) {
+    // As a special case, support this assertion on an array type,
+    // which reduces to an assertion on its element type.
+    // Note that this cannot be done with assertions that
+    // relate to concreteness or abstractness.
+    BasicType elemt = ArrayKlass::cast(ctxk)->element_type();
+    if (is_java_primitive(elemt))  return;   // Ex:  int[][]
+    ctxk = ObjArrayKlass::cast(ctxk)->bottom_klass();
+    //if (ctxk->is_final())  return;            // Ex:  String[][]
+  }
+  check_ctxk(ctxk);
+  assert_common_1(leaf_type, DepValue(_oop_recorder, ctxk));
+}
+
+void Dependencies::assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck) {
+  check_ctxk_abstract(ctxk);
+  DepValue ctxk_dv(_oop_recorder, ctxk);
+  DepValue conck_dv(_oop_recorder, conck, &ctxk_dv);
+  assert_common_2(abstract_with_unique_concrete_subtype, ctxk_dv, conck_dv);
+}
+
+void Dependencies::assert_unique_concrete_method(Klass* ctxk, Method* uniqm) {
+  check_ctxk(ctxk);
+  assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm));
+}
+
+void Dependencies::assert_call_site_target_value(oop call_site, oop method_handle) {
+  assert_common_2(call_site_target_value, DepValue(_oop_recorder, JNIHandles::make_local(call_site)), DepValue(_oop_recorder, JNIHandles::make_local(method_handle)));
+}
+#endif // INCLUDE_JVMCI
+
+
 // Helper function.  If we are adding a new dep. under ctxk2,
 // try to find an old dep. under a broader* ctxk1.  If there is
 //
@@ -231,6 +294,78 @@
   deps->append(x2);
 }
 
+#if INCLUDE_JVMCI
+bool Dependencies::maybe_merge_ctxk(GrowableArray<DepValue>* deps,
+                                    int ctxk_i, DepValue ctxk2_dv) {
+  Klass* ctxk1 = deps->at(ctxk_i).as_klass(_oop_recorder);
+  Klass* ctxk2 = ctxk2_dv.as_klass(_oop_recorder);
+  if (ctxk2->is_subtype_of(ctxk1)) {
+    return true;  // success, and no need to change
+  } else if (ctxk1->is_subtype_of(ctxk2)) {
+    // new context class fully subsumes previous one
+    deps->at_put(ctxk_i, ctxk2_dv);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+void Dependencies::assert_common_1(DepType dept, DepValue x) {
+  assert(dep_args(dept) == 1, "sanity");
+  //log_dependency(dept, x);
+  GrowableArray<DepValue>* deps = _dep_values[dept];
+
+  // see if the same (or a similar) dep is already recorded
+  if (note_dep_seen(dept, x)) {
+    assert(deps->find(x) >= 0, "sanity");
+  } else {
+    deps->append(x);
+  }
+}
+
+void Dependencies::assert_common_2(DepType dept,
+                                   DepValue x0, DepValue x1) {
+  assert(dep_args(dept) == 2, "sanity");
+  //log_dependency(dept, x0, x1);
+  GrowableArray<DepValue>* deps = _dep_values[dept];
+
+  // see if the same (or a similar) dep is already recorded
+  bool has_ctxk = has_explicit_context_arg(dept);
+  if (has_ctxk) {
+    assert(dep_context_arg(dept) == 0, "sanity");
+    if (note_dep_seen(dept, x1)) {
+      // look in this bucket for redundant assertions
+      const int stride = 2;
+      for (int i = deps->length(); (i -= stride) >= 0; ) {
+        DepValue y1 = deps->at(i+1);
+        if (x1 == y1) {  // same subject; check the context
+          if (maybe_merge_ctxk(deps, i+0, x0)) {
+            return;
+          }
+        }
+      }
+    }
+  } else {
+    assert(dep_implicit_context_arg(dept) == 0, "sanity");
+    if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) {
+      // look in this bucket for redundant assertions
+      const int stride = 2;
+      for (int i = deps->length(); (i -= stride) >= 0; ) {
+        DepValue y0 = deps->at(i+0);
+        DepValue y1 = deps->at(i+1);
+        if (x0 == y0 && x1 == y1) {
+          return;
+        }
+      }
+    }
+  }
+
+  // append the assertion in the correct bucket:
+  deps->append(x0);
+  deps->append(x1);
+}
+#endif // INCLUDE_JVMCI
+
 /// Support for encoding dependencies into an nmethod:
 
 void Dependencies::copy_to(nmethod* nm) {
@@ -257,7 +392,40 @@
 static int sort_dep_arg_3(ciBaseObject** p1, ciBaseObject** p2)
 { return sort_dep(p1, p2, 3); }
 
+#if INCLUDE_JVMCI
+// metadata deps are sorted before object deps
+static int sort_dep_value(Dependencies::DepValue* p1, Dependencies::DepValue* p2, int narg) {
+  for (int i = 0; i < narg; i++) {
+    int diff = p1[i].sort_key() - p2[i].sort_key();
+    if (diff != 0)  return diff;
+  }
+  return 0;
+}
+static int sort_dep_value_arg_1(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
+{ return sort_dep_value(p1, p2, 1); }
+static int sort_dep_value_arg_2(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
+{ return sort_dep_value(p1, p2, 2); }
+static int sort_dep_value_arg_3(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
+{ return sort_dep_value(p1, p2, 3); }
+#endif // INCLUDE_JVMCI
+
 void Dependencies::sort_all_deps() {
+#if INCLUDE_JVMCI
+  if (_using_dep_values) {
+    for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
+      DepType dept = (DepType)deptv;
+      GrowableArray<DepValue>* deps = _dep_values[dept];
+      if (deps->length() <= 1)  continue;
+      switch (dep_args(dept)) {
+      case 1: deps->sort(sort_dep_value_arg_1, 1); break;
+      case 2: deps->sort(sort_dep_value_arg_2, 2); break;
+      case 3: deps->sort(sort_dep_value_arg_3, 3); break;
+      default: ShouldNotReachHere();
+      }
+    }
+    return;
+  }
+#endif
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
     DepType dept = (DepType)deptv;
     GrowableArray<ciBaseObject*>* deps = _deps[dept];
@@ -273,6 +441,16 @@
 
 size_t Dependencies::estimate_size_in_bytes() {
   size_t est_size = 100;
+#if INCLUDE_JVMCI
+  if (_using_dep_values) {
+    for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
+      DepType dept = (DepType)deptv;
+      GrowableArray<DepValue>* deps = _dep_values[dept];
+      est_size += deps->length() * 2;  // tags and argument(s)
+    }
+    return est_size;
+  }
+#endif
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
     DepType dept = (DepType)deptv;
     GrowableArray<ciBaseObject*>* deps = _deps[dept];
@@ -312,6 +490,37 @@
   // cast is safe, no deps can overflow INT_MAX
   CompressedWriteStream bytes((int)estimate_size_in_bytes());
 
+#if INCLUDE_JVMCI
+  if (_using_dep_values) {
+    for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
+      DepType dept = (DepType)deptv;
+      GrowableArray<DepValue>* deps = _dep_values[dept];
+      if (deps->length() == 0)  continue;
+      int stride = dep_args(dept);
+      int ctxkj  = dep_context_arg(dept);  // -1 if no context arg
+      assert(stride > 0, "sanity");
+      for (int i = 0; i < deps->length(); i += stride) {
+        jbyte code_byte = (jbyte)dept;
+        int skipj = -1;
+        if (ctxkj >= 0 && ctxkj+1 < stride) {
+          Klass*  ctxk = deps->at(i+ctxkj+0).as_klass(_oop_recorder);
+          DepValue x = deps->at(i+ctxkj+1);  // following argument
+          if (ctxk == ctxk_encoded_as_null(dept, x.as_metadata(_oop_recorder))) {
+            skipj = ctxkj;  // we win:  maybe one less oop to keep track of
+            code_byte |= default_context_type_bit;
+          }
+        }
+        bytes.write_byte(code_byte);
+        for (int j = 0; j < stride; j++) {
+          if (j == skipj)  continue;
+          DepValue v = deps->at(i+j);
+          int idx = v.index();
+          bytes.write_int(idx);
+        }
+      }
+    }
+  } else {
+#endif
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
     DepType dept = (DepType)deptv;
     GrowableArray<ciBaseObject*>* deps = _deps[dept];
@@ -345,6 +554,9 @@
       }
     }
   }
+#if INCLUDE_JVMCI
+  }
+#endif
 
   // write a sentinel byte to mark the end
   bytes.write_byte(end_marker);
@@ -541,10 +753,10 @@
 }
 
 void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* args,
-                                    Klass* witness) {
+                                    Klass* witness, outputStream* st) {
   ResourceMark rm;
   ttyLocker ttyl;   // keep the following output all in one block
-  tty->print_cr("%s of type %s",
+  st->print_cr("%s of type %s",
                 (witness == NULL)? "Dependency": "Failed dependency",
                 dep_name(dept));
   // print arguments
@@ -566,18 +778,22 @@
     } else {
       what = "object ";
     }
-    tty->print("  %s = %s", what, (put_star? "*": ""));
-    if (arg.is_klass())
-      tty->print("%s", ((Klass*)arg.metadata_value())->external_name());
-    else if (arg.is_method())
-      ((Method*)arg.metadata_value())->print_value();
-    else
+    st->print("  %s = %s", what, (put_star? "*": ""));
+    if (arg.is_klass()) {
+      st->print("%s", ((Klass*)arg.metadata_value())->external_name());
+    } else if (arg.is_method()) {
+      ((Method*)arg.metadata_value())->print_value_on(st);
+    } else if (arg.is_oop()) {
+      arg.oop_value()->print_value_on(st);
+    } else {
       ShouldNotReachHere(); // Provide impl for this type.
-    tty->cr();
+    }
+
+    st->cr();
   }
   if (witness != NULL) {
     bool put_star = !Dependencies::is_concrete_klass(witness);
-    tty->print_cr("  witness = %s%s",
+    st->print_cr("  witness = %s%s",
                   (put_star? "*": ""),
                   witness->external_name());
   }
@@ -597,27 +813,37 @@
   }
   int argslen = args->length();
   if (_deps != NULL && _deps->log() != NULL) {
-    Dependencies::write_dependency_to(_deps->log(), type(), args, witness);
+    if (ciEnv::current() != NULL) {
+      Dependencies::write_dependency_to(_deps->log(),
+                                        type(), args, witness);
+    } else {
+      // Treat the CompileLog as an xmlstream instead
+      Dependencies::write_dependency_to((xmlStream*)_deps->log(),
+                                        type(), args, witness);
+    }
   } else {
     Dependencies::write_dependency_to(xtty, type(), args, witness);
   }
   guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
 }
 
-void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) {
-  ResourceMark rm;
+void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose, outputStream* st) {
   int nargs = argument_count();
   GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs);
   for (int j = 0; j < nargs; j++) {
-    args->push(argument(j));
+    if (type() == call_site_target_value) {
+      args->push(argument_oop(j));
+    } else {
+      args->push(argument(j));
+    }
   }
   int argslen = args->length();
-  Dependencies::print_dependency(type(), args, witness);
+  Dependencies::print_dependency(type(), args, witness, st);
   if (verbose) {
     if (_code != NULL) {
-      tty->print("  code: ");
-      _code->print_value_on(tty);
-      tty->cr();
+      st->print("  code: ");
+      _code->print_value_on(st);
+      st->cr();
     }
   }
   guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
@@ -832,12 +1058,11 @@
     if (!(m->is_public() || m->is_protected()))
       // The override story is complex when packages get involved.
       return true;  // Must punt the assertion to true.
-    Klass* k = ctxk;
-    Method* lm = k->lookup_method(m->name(), m->signature());
-    if (lm == NULL && k->oop_is_instance()) {
+    Method* lm = ctxk->lookup_method(m->name(), m->signature());
+    if (lm == NULL && ctxk->oop_is_instance()) {
       // It might be an interface method
-        lm = ((InstanceKlass*)k)->lookup_method_in_ordered_interfaces(m->name(),
-                                                                m->signature());
+      lm = ((InstanceKlass*)ctxk)->lookup_method_in_ordered_interfaces(m->name(),
+                                                                       m->signature());
     }
     if (lm == m)
       // Method m is inherited into ctxk.
@@ -851,11 +1076,19 @@
         // Static methods don't override non-static so punt
         return true;
       }
-      if (   !Dependencies::is_concrete_method(lm, k)
-          && !Dependencies::is_concrete_method(m, ctxk)
-          && lm->method_holder()->is_subtype_of(m->method_holder()))
-        // Method m is overridden by lm, but both are non-concrete.
-        return true;
+      if (!Dependencies::is_concrete_method(lm, ctxk) &&
+          !Dependencies::is_concrete_method(m, ctxk)) {
+        // They are both non-concrete
+        if (lm->method_holder()->is_subtype_of(m->method_holder())) {
+          // Method m is overridden by lm, but both are non-concrete.
+          return true;
+        }
+        if (lm->method_holder()->is_interface() && m->method_holder()->is_interface() &&
+            ctxk->is_subtype_of(m->method_holder()) && ctxk->is_subtype_of(lm->method_holder())) {
+          // Interface method defined in multiple super interfaces
+          return true;
+        }
+      }
     }
     ResourceMark rm;
     tty->print_cr("Dependency method not found in the associated context:");
--- a/src/share/vm/code/dependencies.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/dependencies.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -166,7 +166,7 @@
     LG2_TYPE_LIMIT = 4,  // assert(TYPE_LIMIT <= (1<<LG2_TYPE_LIMIT))
 
     // handy categorizations of dependency types:
-    all_types           = ((1 << TYPE_LIMIT) - 1) & ((-1) << FIRST_TYPE),
+    all_types           = ((1 << TYPE_LIMIT) - 1) & ((~0u) << FIRST_TYPE),
 
     non_klass_types     = (1 << call_site_target_value),
     klass_types         = all_types & ~non_klass_types,
@@ -200,10 +200,59 @@
 
   static void check_valid_dependency_type(DepType dept);
 
+#if INCLUDE_JVMCI
+  // A Metadata* or object value recorded in an OopRecorder
+  class DepValue VALUE_OBJ_CLASS_SPEC {
+   private:
+    // Unique identifier of the value within the associated OopRecorder that
+    // encodes both the category of the value (0: invalid, positive: metadata, negative: object)
+    // and the index within a category specific array (metadata: index + 1, object: -(index + 1))
+    int _id;
+
+   public:
+    DepValue() : _id(0) {}
+    DepValue(OopRecorder* rec, Metadata* metadata, DepValue* candidate = NULL) {
+      assert(candidate == NULL || candidate->is_metadata(), "oops");
+      if (candidate != NULL && candidate->as_metadata(rec) == metadata) {
+        _id = candidate->_id;
+      } else {
+        _id = rec->find_index(metadata) + 1;
+      }
+    }
+    DepValue(OopRecorder* rec, jobject obj, DepValue* candidate = NULL) {
+      assert(candidate == NULL || candidate->is_object(), "oops");
+      if (candidate != NULL && candidate->as_object(rec) == obj) {
+        _id = candidate->_id;
+      } else {
+        _id = -(rec->find_index(obj) + 1);
+      }
+    }
+
+    // Used to sort values in ascending order of index() with metadata values preceding object values
+    int sort_key() const { return -_id; }
+
+    bool operator == (const DepValue& other) const   { return other._id == _id; }
+
+    bool is_valid() const             { return _id != 0; }
+    int  index() const                { assert(is_valid(), "oops"); return _id < 0 ? -(_id + 1) : _id - 1; }
+    bool is_metadata() const          { assert(is_valid(), "oops"); return _id > 0; }
+    bool is_object() const            { assert(is_valid(), "oops"); return _id < 0; }
+
+    Metadata*  as_metadata(OopRecorder* rec) const    { assert(is_metadata(), "oops"); return rec->metadata_at(index()); }
+    Klass*     as_klass(OopRecorder* rec) const       { assert(as_metadata(rec)->is_klass(), "oops"); return (Klass*) as_metadata(rec); }
+    Method*    as_method(OopRecorder* rec) const      { assert(as_metadata(rec)->is_method(), "oops"); return (Method*) as_metadata(rec); }
+    jobject    as_object(OopRecorder* rec) const      { assert(is_object(), "oops"); return rec->oop_at(index()); }
+  };
+#endif
+
  private:
   // State for writing a new set of dependencies:
   GrowableArray<int>*       _dep_seen;  // (seen[h->ident] & (1<<dept))
   GrowableArray<ciBaseObject*>*  _deps[TYPE_LIMIT];
+#if INCLUDE_JVMCI
+  bool _using_dep_values;
+  GrowableArray<DepValue>*  _dep_values[TYPE_LIMIT];
+#endif
 
   static const char* _dep_name[TYPE_LIMIT];
   static int         _dep_args[TYPE_LIMIT];
@@ -222,8 +271,25 @@
     return (seen & (1<<dept)) != 0;
   }
 
+#if INCLUDE_JVMCI
+  bool note_dep_seen(int dept, DepValue x) {
+    assert(dept < BitsPerInt, "oops");
+    // place metadata deps at even indexes, object deps at odd indexes
+    int x_id = x.is_metadata() ? x.index() * 2 : (x.index() * 2) + 1;
+    assert(_dep_seen != NULL, "deps must be writable");
+    int seen = _dep_seen->at_grow(x_id, 0);
+    _dep_seen->at_put(x_id, seen | (1<<dept));
+    // return true if we've already seen dept/x
+    return (seen & (1<<dept)) != 0;
+  }
+#endif
+
   bool maybe_merge_ctxk(GrowableArray<ciBaseObject*>* deps,
                         int ctxk_i, ciKlass* ctxk);
+#if INCLUDE_JVMCI
+  bool maybe_merge_ctxk(GrowableArray<DepValue>* deps,
+                        int ctxk_i, DepValue ctxk);
+#endif
 
   void sort_all_deps();
   size_t estimate_size_in_bytes();
@@ -245,6 +311,9 @@
   Dependencies(ciEnv* env) {
     initialize(env);
   }
+#if INCLUDE_JVMCI
+  Dependencies(Arena* arena, OopRecorder* oop_recorder, CompileLog* log);
+#endif
 
  private:
   // Check for a valid context type.
@@ -277,6 +346,27 @@
   void assert_has_no_finalizable_subclasses(ciKlass* ctxk);
   void assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle);
 
+#if INCLUDE_JVMCI
+ private:
+  static void check_ctxk(Klass* ctxk) {
+    assert(ctxk->oop_is_instance(), "java types only");
+  }
+  static void check_ctxk_abstract(Klass* ctxk) {
+    check_ctxk(ctxk);
+    assert(ctxk->is_abstract(), "must be abstract");
+  }
+  void assert_common_1(DepType dept, DepValue x);
+  void assert_common_2(DepType dept, DepValue x0, DepValue x1);
+
+ public:
+  void assert_evol_method(Method* m);
+  void assert_has_no_finalizable_subclasses(Klass* ctxk);
+  void assert_leaf_type(Klass* ctxk);
+  void assert_unique_concrete_method(Klass* ctxk, Method* uniqm);
+  void assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck);
+  void assert_call_site_target_value(oop callSite, oop methodHandle);
+#endif // JVMCI
+
   // Define whether a given method or type is concrete.
   // These methods define the term "concrete" as used in this module.
   // For this module, an "abstract" class is one which is non-concrete.
@@ -420,7 +510,7 @@
 
   static void print_dependency(DepType dept,
                                GrowableArray<DepArgument>* args,
-                               Klass* witness = NULL);
+                               Klass* witness = NULL, outputStream* st = tty);
 
  private:
   // helper for encoding common context types as zero:
@@ -529,7 +619,7 @@
     void log_dependency(Klass* witness = NULL);
 
     // Print the current dependency to tty.
-    void print_dependency(Klass* witness = NULL, bool verbose = false);
+    void print_dependency(Klass* witness = NULL, bool verbose = false, outputStream* st = tty);
   };
   friend class Dependencies::DepStream;
 
--- a/src/share/vm/code/exceptionHandlerTable.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/exceptionHandlerTable.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -88,12 +88,12 @@
   int                _length;   // the current length of the table
   int                _size;     // the number of allocated entries
   ReallocMark        _nesting;  // assertion check for reallocations
-
+  
+ public:
   // add the entry & grow the table if needed
   void add_entry(HandlerTableEntry entry);
   HandlerTableEntry* subtable_for(int catch_pco) const;
 
- public:
   // (compile-time) construction within compiler
   ExceptionHandlerTable(int initial_size = 8);
 
--- a/src/share/vm/code/nmethod.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/nmethod.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -43,9 +43,27 @@
 #include "utilities/dtrace.hpp"
 #include "utilities/events.hpp"
 #include "utilities/xmlstream.hpp"
+#ifdef TARGET_ARCH_x86
+# include "nativeInst_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "nativeInst_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "nativeInst_zero.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "nativeInst_arm.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "nativeInst_ppc.hpp"
+#endif
 #ifdef SHARK
 #include "shark/sharkCompiler.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
@@ -103,6 +121,11 @@
   }
   return compiler()->is_c1();
 }
+bool nmethod::is_compiled_by_jvmci() const {
+  if (compiler() == NULL || method() == NULL)  return false;  // can happen during debug printing
+  if (is_native_method()) return false;
+  return compiler()->is_jvmci();
+}
 bool nmethod::is_compiled_by_c2() const {
   if (compiler() == NULL) {
     return false;
@@ -124,11 +147,9 @@
 //   PrintC1Statistics, PrintOptoStatistics, LogVMOutput, and LogCompilation.
 // (In the latter two cases, they like other stats are printed to the log only.)
 
-#ifndef PRODUCT
 // These variables are put into one block to reduce relocations
 // and make it simpler to print from the debugger.
-static
-struct nmethod_stats_struct {
+struct java_nmethod_stats_struct {
   int nmethod_count;
   int total_size;
   int relocation_size;
@@ -141,6 +162,7 @@
   int handler_table_size;
   int nul_chk_table_size;
   int oops_size;
+  int metadata_size;
 
   void note_nmethod(nmethod* nm) {
     nmethod_count += 1;
@@ -150,39 +172,46 @@
     insts_size          += nm->insts_size();
     stub_size           += nm->stub_size();
     oops_size           += nm->oops_size();
+    metadata_size       += nm->metadata_size();
     scopes_data_size    += nm->scopes_data_size();
     scopes_pcs_size     += nm->scopes_pcs_size();
     dependencies_size   += nm->dependencies_size();
     handler_table_size  += nm->handler_table_size();
     nul_chk_table_size  += nm->nul_chk_table_size();
   }
-  void print_nmethod_stats() {
+  void print_nmethod_stats(const char* name) {
     if (nmethod_count == 0)  return;
-    tty->print_cr("Statistics for %d bytecoded nmethods:", nmethod_count);
+    tty->print_cr("Statistics for %d bytecoded nmethods for %s:", nmethod_count, name);
     if (total_size != 0)          tty->print_cr(" total in heap  = %d", total_size);
+    if (nmethod_count != 0)       tty->print_cr(" header         = %d", nmethod_count * sizeof(nmethod));
     if (relocation_size != 0)     tty->print_cr(" relocation     = %d", relocation_size);
     if (consts_size != 0)         tty->print_cr(" constants      = %d", consts_size);
     if (insts_size != 0)          tty->print_cr(" main code      = %d", insts_size);
     if (stub_size != 0)           tty->print_cr(" stub code      = %d", stub_size);
     if (oops_size != 0)           tty->print_cr(" oops           = %d", oops_size);
+    if (metadata_size != 0)       tty->print_cr(" metadata       = %d", metadata_size);
     if (scopes_data_size != 0)    tty->print_cr(" scopes data    = %d", scopes_data_size);
     if (scopes_pcs_size != 0)     tty->print_cr(" scopes pcs     = %d", scopes_pcs_size);
     if (dependencies_size != 0)   tty->print_cr(" dependencies   = %d", dependencies_size);
     if (handler_table_size != 0)  tty->print_cr(" handler table  = %d", handler_table_size);
     if (nul_chk_table_size != 0)  tty->print_cr(" nul chk table  = %d", nul_chk_table_size);
   }
-
+};
+
+struct native_nmethod_stats_struct {
   int native_nmethod_count;
   int native_total_size;
   int native_relocation_size;
   int native_insts_size;
   int native_oops_size;
+  int native_metadata_size;
   void note_native_nmethod(nmethod* nm) {
     native_nmethod_count += 1;
     native_total_size       += nm->size();
     native_relocation_size  += nm->relocation_size();
     native_insts_size       += nm->insts_size();
     native_oops_size        += nm->oops_size();
+    native_metadata_size    += nm->metadata_size();
   }
   void print_native_nmethod_stats() {
     if (native_nmethod_count == 0)  return;
@@ -191,8 +220,11 @@
     if (native_relocation_size != 0)  tty->print_cr(" N. relocation  = %d", native_relocation_size);
     if (native_insts_size != 0)       tty->print_cr(" N. main code   = %d", native_insts_size);
     if (native_oops_size != 0)        tty->print_cr(" N. oops        = %d", native_oops_size);
+    if (native_metadata_size != 0)    tty->print_cr(" N. metadata    = %d", native_metadata_size);
   }
-
+};
+
+struct pc_nmethod_stats_struct {
   int pc_desc_resets;   // number of resets (= number of caches)
   int pc_desc_queries;  // queries to nmethod::find_pc_desc
   int pc_desc_approx;   // number of those which have approximate true
@@ -213,9 +245,54 @@
                   pc_desc_repeats, pc_desc_hits,
                   pc_desc_tests, pc_desc_searches, pc_desc_adds);
   }
-} nmethod_stats;
-#endif //PRODUCT
-
+};
+
+#ifdef COMPILER1
+static java_nmethod_stats_struct c1_java_nmethod_stats;
+#endif
+#ifdef COMPILER2
+static java_nmethod_stats_struct c2_java_nmethod_stats;
+#endif
+#if INCLUDE_JVMCI
+static java_nmethod_stats_struct jvmci_java_nmethod_stats;
+#endif
+#ifdef SHARK
+static java_nmethod_stats_struct shark_java_nmethod_stats;
+#endif
+static java_nmethod_stats_struct unknown_java_nmethod_stats;
+
+static native_nmethod_stats_struct native_nmethod_stats;
+static pc_nmethod_stats_struct pc_nmethod_stats;
+
+static void note_native_wrapper_nmethod(nmethod* nm) {
+  native_nmethod_stats.note_native_nmethod(nm);
+}
+
+static void note_java_nmethod(nmethod* nm) {
+#ifdef COMPILER1
+  if (nm->is_compiled_by_c1()) {
+    c1_java_nmethod_stats.note_nmethod(nm);
+  } else
+#endif
+#ifdef COMPILER2
+  if (nm->is_compiled_by_c2()) {
+    c2_java_nmethod_stats.note_nmethod(nm);
+  } else
+#endif
+#if INCLUDE_JVMCI
+  if (nm->is_compiled_by_jvmci()) {
+    jvmci_java_nmethod_stats.note_nmethod(nm);
+  } else
+#endif
+#ifdef SHARK
+  if (nm->is_compiled_by_shark()) {
+    shark_java_nmethod_stats.note_nmethod(nm);
+  } else
+#endif
+  {
+    unknown_java_nmethod_stats.note_nmethod(nm);
+  }
+}
 
 //---------------------------------------------------------------------------------
 
@@ -295,7 +372,7 @@
 
 // Helper used by both find_pc_desc methods.
 static inline bool match_desc(PcDesc* pc, int pc_offset, bool approximate) {
-  NOT_PRODUCT(++nmethod_stats.pc_desc_tests);
+  NOT_PRODUCT(++pc_nmethod_stats.pc_desc_tests);
   if (!approximate)
     return pc->pc_offset() == pc_offset;
   else
@@ -307,7 +384,7 @@
     _pc_descs[0] = NULL; // native method; no PcDescs at all
     return;
   }
-  NOT_PRODUCT(++nmethod_stats.pc_desc_resets);
+  NOT_PRODUCT(++pc_nmethod_stats.pc_desc_resets);
   // reset the cache by filling it with benign (non-null) values
   assert(initial_pc_desc->pc_offset() < 0, "must be sentinel");
   for (int i = 0; i < cache_size; i++)
@@ -315,8 +392,8 @@
 }
 
 PcDesc* PcDescCache::find_pc_desc(int pc_offset, bool approximate) {
-  NOT_PRODUCT(++nmethod_stats.pc_desc_queries);
-  NOT_PRODUCT(if (approximate) ++nmethod_stats.pc_desc_approx);
+  NOT_PRODUCT(++pc_nmethod_stats.pc_desc_queries);
+  NOT_PRODUCT(if (approximate) ++pc_nmethod_stats.pc_desc_approx);
 
   // Note: one might think that caching the most recently
   // read value separately would be a win, but one would be
@@ -332,7 +409,7 @@
   res = _pc_descs[0];
   if (res == NULL) return NULL;  // native method; no PcDescs at all
   if (match_desc(res, pc_offset, approximate)) {
-    NOT_PRODUCT(++nmethod_stats.pc_desc_repeats);
+    NOT_PRODUCT(++pc_nmethod_stats.pc_desc_repeats);
     return res;
   }
 
@@ -341,7 +418,7 @@
     res = _pc_descs[i];
     if (res->pc_offset() < 0) break;  // optimization: skip empty cache
     if (match_desc(res, pc_offset, approximate)) {
-      NOT_PRODUCT(++nmethod_stats.pc_desc_hits);
+      NOT_PRODUCT(++pc_nmethod_stats.pc_desc_hits);
       return res;
     }
   }
@@ -351,7 +428,7 @@
 }
 
 void PcDescCache::add_pc_desc(PcDesc* pc_desc) {
-  NOT_PRODUCT(++nmethod_stats.pc_desc_adds);
+  NOT_PRODUCT(++pc_nmethod_stats.pc_desc_adds);
   // Update the LRU cache by shifting pc_desc forward.
   for (int i = 0; i < cache_size; i++)  {
     PcDesc* next = _pc_descs[i];
@@ -497,6 +574,10 @@
 #if INCLUDE_RTM_OPT
   _rtm_state               = NoRTM;
 #endif
+#if INCLUDE_JVMCI
+  _jvmci_installed_code   = NULL;
+  _speculation_log        = NULL;
+#endif
 #ifdef HAVE_DTRACE_H
   _trap_offset             = 0;
 #endif // def HAVE_DTRACE_H
@@ -525,7 +606,7 @@
                                             code_buffer, frame_size,
                                             basic_lock_owner_sp_offset,
                                             basic_lock_sp_offset, oop_maps);
-    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_native_nmethod(nm));
+    if (nm != NULL)  note_native_wrapper_nmethod(nm);
     if (PrintAssembly && nm != NULL) {
       Disassembler::decode(nm);
     }
@@ -561,7 +642,7 @@
     nm = new (nmethod_size) nmethod(method(), nmethod_size,
                                     &offsets, code_buffer, frame_size);
 
-    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_nmethod(nm));
+    if (nm != NULL)  note_java_nmethod(nm);
     if (PrintAssembly && nm != NULL) {
       Disassembler::decode(nm);
     }
@@ -591,6 +672,10 @@
   ImplicitExceptionTable* nul_chk_table,
   AbstractCompiler* compiler,
   int comp_level
+#if INCLUDE_JVMCI
+  , Handle installed_code,
+  Handle speculationLog
+#endif
 )
 {
   assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
@@ -613,7 +698,12 @@
             handler_table,
             nul_chk_table,
             compiler,
-            comp_level);
+            comp_level
+#if INCLUDE_JVMCI
+            , installed_code,
+            speculationLog
+#endif
+            );
 
     if (nm != NULL) {
       // To make dependency checking during class loading fast, record
@@ -633,7 +723,7 @@
         // record this nmethod as dependent on this klass
         InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
       }
-      NOT_PRODUCT(nmethod_stats.note_nmethod(nm));
+      if (nm != NULL)  note_java_nmethod(nm);
       if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
         Disassembler::decode(nm);
       }
@@ -796,7 +886,8 @@
     CodeCache::commit(this);
   }
 
-  if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
+  bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level;
+  if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
     ttyLocker ttyl;  // keep the following output all in one block
     // This output goes directly to the tty, not the compiler log.
     // To enable tools to match it up with the compilation activity,
@@ -810,7 +901,7 @@
     // print the header part first
     print();
     // then print the requested information
-    if (PrintNMethods) {
+    if (printnmethods) {
       print_code();
     }
     if (PrintRelocations) {
@@ -844,6 +935,10 @@
   ImplicitExceptionTable* nul_chk_table,
   AbstractCompiler* compiler,
   int comp_level
+#if INCLUDE_JVMCI
+  , Handle installed_code,
+  Handle speculation_log
+#endif
   )
   : CodeBlob("nmethod", code_buffer, sizeof(nmethod),
              nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
@@ -868,15 +963,42 @@
     _consts_offset           = content_offset()      + code_buffer->total_offset_of(code_buffer->consts());
     _stub_offset             = content_offset()      + code_buffer->total_offset_of(code_buffer->stubs());
 
+#if INCLUDE_JVMCI
+    _jvmci_installed_code = installed_code();
+    _speculation_log = (instanceOop)speculation_log();
+
+    if (compiler->is_jvmci()) {
+      // JVMCI might not produce any stub sections
+      if (offsets->value(CodeOffsets::Exceptions) != -1) {
+        _exception_offset        = code_offset()          + offsets->value(CodeOffsets::Exceptions);
+      } else {
+        _exception_offset = -1;
+      }
+      if (offsets->value(CodeOffsets::Deopt) != -1) {
+        _deoptimize_offset       = code_offset()          + offsets->value(CodeOffsets::Deopt);
+      } else {
+        _deoptimize_offset = -1;
+      }
+      if (offsets->value(CodeOffsets::DeoptMH) != -1) {
+        _deoptimize_mh_offset  = code_offset()          + offsets->value(CodeOffsets::DeoptMH);
+      } else {
+        _deoptimize_mh_offset  = -1;
+      }
+    } else {
+#endif
     // Exception handler and deopt handler are in the stub section
     assert(offsets->value(CodeOffsets::Exceptions) != -1, "must be set");
     assert(offsets->value(CodeOffsets::Deopt     ) != -1, "must be set");
+
     _exception_offset        = _stub_offset          + offsets->value(CodeOffsets::Exceptions);
     _deoptimize_offset       = _stub_offset          + offsets->value(CodeOffsets::Deopt);
     if (offsets->value(CodeOffsets::DeoptMH) != -1) {
       _deoptimize_mh_offset  = _stub_offset          + offsets->value(CodeOffsets::DeoptMH);
     } else {
       _deoptimize_mh_offset  = -1;
+#if INCLUDE_JVMCI
+    }
+#endif
     }
     if (offsets->value(CodeOffsets::UnwindHandler) != -1) {
       _unwind_handler_offset = code_offset()         + offsets->value(CodeOffsets::UnwindHandler);
@@ -920,12 +1042,12 @@
 
     // we use the information of entry points to find out if a method is
     // static or non static
-    assert(compiler->is_c2() ||
+    assert(compiler->is_c2() || compiler->is_jvmci() ||
            _method->is_static() == (entry_point() == _verified_entry_point),
            " entry points must be same for static methods and vice versa");
   }
 
-  bool printnmethods = PrintNMethods
+  bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level
     || CompilerOracle::should_print(_method)
     || CompilerOracle::has_option_string(_method, "PrintNMethods");
   if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
@@ -974,6 +1096,7 @@
     LOG_OFFSET(xtty, handler_table);
     LOG_OFFSET(xtty, nul_chk_table);
     LOG_OFFSET(xtty, oops);
+    LOG_OFFSET(xtty, metadata);
 
     xtty->method(method());
     xtty->stamp();
@@ -1015,13 +1138,13 @@
       oop_maps()->print();
     }
   }
-  if (PrintDebugInfo) {
+  if (PrintDebugInfo || CompilerOracle::has_option_string(_method, "PrintDebugInfo")) {
     print_scopes();
   }
-  if (PrintRelocations) {
+  if (PrintRelocations || CompilerOracle::has_option_string(_method, "PrintRelocations")) {
     print_relocations();
   }
-  if (PrintDependencies) {
+  if (PrintDependencies || CompilerOracle::has_option_string(_method, "PrintDependencies")) {
     print_dependencies();
   }
   if (PrintExceptionHandlers) {
@@ -1131,7 +1254,7 @@
   PcDesc* pd = pc_desc_at(pc);
   guarantee(pd != NULL, "scope must be present");
   return new ScopeDesc(this, pd->scope_decode_offset(),
-                       pd->obj_decode_offset(), pd->should_reexecute(),
+                       pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
                        pd->return_oop());
 }
 
@@ -1302,7 +1425,7 @@
 }
 
 void nmethod::inc_decompile_count() {
-  if (!is_compiled_by_c2()) return;
+  if (!is_compiled_by_c2() && !is_compiled_by_jvmci()) return;
   // Could be gated by ProfileTraps, but do not bother...
   Method* m = method();
   if (m == NULL)  return;
@@ -1366,6 +1489,7 @@
     }
     _method = NULL;            // Clear the method of this dead nmethod
   }
+
   // Make the class unloaded - i.e., change state and notify sweeper
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   if (is_in_use()) {
@@ -1383,6 +1507,19 @@
   // Log the unloading.
   log_state_change();
 
+#if INCLUDE_JVMCI
+  // The method can only be unloaded after the pointer to the installed code
+  // Java wrapper is no longer alive. Here we need to clear out this weak
+  // reference to the dead object. Nulling out the reference has to happen
+  // after the method is unregistered since the original value may be still
+  // tracked by the rset.
+  maybe_invalidate_installed_code();
+  // Clear these out after the nmethod has been unregistered and any
+  // updates to the InstalledCode instance have been performed.
+  _jvmci_installed_code = NULL;
+  _speculation_log = NULL;
+#endif
+
   // The Method* is gone at this point
   assert(_method == NULL, "Tautology");
 
@@ -1495,6 +1632,9 @@
     // Log the transition once
     log_state_change();
 
+    // Invalidate while holding the patching lock
+    JVMCI_ONLY(maybe_invalidate_installed_code());
+
     // Remove nmethod from method.
     // We need to check if both the _code and _from_compiled_code_entry_point
     // refer to this nmethod because there is a race in setting these two fields
@@ -1521,6 +1661,10 @@
       MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       if (nmethod_needs_unregister) {
         Universe::heap()->unregister_nmethod(this);
+#ifdef JVMCI
+        _jvmci_installed_code = NULL;
+        _speculation_log = NULL;
+#endif
       }
       flush_dependencies(NULL);
     }
@@ -1545,7 +1689,8 @@
   }
 
   if (TraceCreateZombies) {
-    tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
+    ResourceMark m;
+    tty->print_cr("nmethod <" INTPTR_FORMAT "> %s code made %s", this, this->method() ? this->method()->name_and_sig_as_C_string() : "null", (state == not_entrant) ? "not entrant" : "zombie");
   }
 
   NMethodSweeper::report_state_change(this);
@@ -1852,6 +1997,31 @@
     }
   }
 
+#if INCLUDE_JVMCI
+  // Follow JVMCI method
+  BarrierSet* bs = Universe::heap()->barrier_set();
+  if (_jvmci_installed_code != NULL) {
+    if (_jvmci_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) {
+      if (!is_alive->do_object_b(_jvmci_installed_code)) {
+        clear_jvmci_installed_code();
+      }
+    } else {
+      if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) {
+        return;
+      }
+    }
+  }
+
+  if (_speculation_log != NULL) {
+    if (!is_alive->do_object_b(_speculation_log)) {
+      bs->write_ref_nmethod_pre(&_speculation_log, this);
+      _speculation_log = NULL;
+      bs->write_ref_nmethod_post(&_speculation_log, this);
+    }
+  }
+#endif
+
+
   // Ensure that all metadata is still alive
   verify_metadata_loaders(low_boundary, is_alive);
 }
@@ -2030,6 +2200,30 @@
     return postponed;
   }
 
+#if INCLUDE_JVMCI
+  // Follow JVMCI method
+  BarrierSet* bs = Universe::heap()->barrier_set();
+  if (_jvmci_installed_code != NULL) {
+    if (_jvmci_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) {
+      if (!is_alive->do_object_b(_jvmci_installed_code)) {
+        clear_jvmci_installed_code();
+      }
+    } else {
+      if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) {
+        is_unloaded = true;
+      }
+    }
+  }
+
+  if (_speculation_log != NULL) {
+    if (!is_alive->do_object_b(_speculation_log)) {
+      bs->write_ref_nmethod_pre(&_speculation_log, this);
+      _speculation_log = NULL;
+      bs->write_ref_nmethod_post(&_speculation_log, this);
+    }
+  }
+#endif
+
   // Ensure that all metadata is still alive
   verify_metadata_loaders(low_boundary, is_alive);
 
@@ -2214,6 +2408,15 @@
     // (See comment above.)
   }
 
+#if INCLUDE_JVMCI
+  if (_jvmci_installed_code != NULL) {
+    f->do_oop((oop*) &_jvmci_installed_code);
+  }
+  if (_speculation_log != NULL) {
+    f->do_oop((oop*) &_speculation_log);
+  }
+#endif
+
   RelocIterator iter(this, low_boundary);
 
   while (iter.next()) {
@@ -2415,6 +2618,14 @@
   memcpy(scopes_data_begin(), buffer, size);
 }
 
+// When using JVMCI the address might be off by the size of a call instruction.
+bool nmethod::is_deopt_entry(address pc) {
+  return pc == deopt_handler_begin()
+#if INCLUDE_JVMCI
+    || (is_compiled_by_jvmci() && pc == (deopt_handler_begin() + NativeCall::instruction_size))
+#endif
+    ;
+}
 
 #ifdef ASSERT
 static PcDesc* linear_search(nmethod* nm, int pc_offset, bool approximate) {
@@ -2423,7 +2634,7 @@
   lower += 1; // exclude initial sentinel
   PcDesc* res = NULL;
   for (PcDesc* p = lower; p < upper; p++) {
-    NOT_PRODUCT(--nmethod_stats.pc_desc_tests);  // don't count this call to match_desc
+    NOT_PRODUCT(--pc_nmethod_stats.pc_desc_tests);  // don't count this call to match_desc
     if (match_desc(p, pc_offset, approximate)) {
       if (res == NULL)
         res = p;
@@ -2470,7 +2681,7 @@
 
   // Use the last successful return as a split point.
   PcDesc* mid = _pc_desc_cache.last_pc_desc();
-  NOT_PRODUCT(++nmethod_stats.pc_desc_searches);
+  NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches);
   if (mid->pc_offset() < pc_offset) {
     lower = mid;
   } else {
@@ -2483,7 +2694,7 @@
   for (int step = (1 << (LOG2_RADIX*3)); step > 1; step >>= LOG2_RADIX) {
     while ((mid = lower + step) < upper) {
       assert_LU_OK;
-      NOT_PRODUCT(++nmethod_stats.pc_desc_searches);
+      NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches);
       if (mid->pc_offset() < pc_offset) {
         lower = mid;
       } else {
@@ -2498,7 +2709,7 @@
   while (true) {
     assert_LU_OK;
     mid = lower + 1;
-    NOT_PRODUCT(++nmethod_stats.pc_desc_searches);
+    NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches);
     if (mid->pc_offset() < pc_offset) {
       lower = mid;
     } else {
@@ -2769,7 +2980,7 @@
   PcDesc* pd = pc_desc_at(nativeCall_at(call_site)->return_address());
   assert(pd != NULL, "PcDesc must exist");
   for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(),
-                                     pd->obj_decode_offset(), pd->should_reexecute(),
+                                     pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
                                      pd->return_oop());
        !sd->is_top(); sd = sd->sender()) {
     sd->verify();
@@ -2862,6 +3073,8 @@
     tty->print("(c2) ");
   } else if (is_compiled_by_shark()) {
     tty->print("(shark) ");
+  } else if (is_compiled_by_jvmci()) {
+    tty->print("(JVMCI) ");
   } else {
     tty->print("(nm) ");
   }
@@ -2946,7 +3159,10 @@
       continue;
 
     ScopeDesc* sd = scope_desc_at(p->real_pc(this));
-    sd->print_on(tty, p);
+    while (sd != NULL) {
+      sd->print_on(tty, p);
+      sd = sd->sender();
+    }
   }
 }
 
@@ -3053,7 +3269,7 @@
   PcDesc* p = pc_desc_near(begin+1);
   if (p != NULL && p->real_pc(this) <= end) {
     return new ScopeDesc(this, p->scope_decode_offset(),
-                         p->obj_decode_offset(), p->should_reexecute(),
+                         p->obj_decode_offset(), p->should_reexecute(), p->rethrow_exception(),
                          p->return_oop());
   }
   return NULL;
@@ -3062,9 +3278,9 @@
 void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) const {
   if (block_begin == entry_point())             stream->print_cr("[Entry Point]");
   if (block_begin == verified_entry_point())    stream->print_cr("[Verified Entry Point]");
-  if (block_begin == exception_begin())         stream->print_cr("[Exception Handler]");
+  if (JVMCI_ONLY(_exception_offset >= 0 &&) block_begin == exception_begin())         stream->print_cr("[Exception Handler]");
   if (block_begin == stub_begin())              stream->print_cr("[Stub Code]");
-  if (block_begin == deopt_handler_begin())     stream->print_cr("[Deopt Handler Code]");
+  if (JVMCI_ONLY(_deoptimize_offset >= 0 &&) block_begin == deopt_handler_begin())     stream->print_cr("[Deopt Handler Code]");
 
   if (has_method_handle_invokes())
     if (block_begin == deopt_mh_handler_begin())  stream->print_cr("[Deopt MH Handler Code]");
@@ -3229,6 +3445,7 @@
           }
         }
       }
+      st->print(" {reexecute=%d rethrow=%d return_oop=%d}", sd->should_reexecute(), sd->rethrow_exception(), sd->return_oop());
     }
 
     // Print all scopes
@@ -3297,16 +3514,130 @@
 void nmethod::print_nul_chk_table() {
   ImplicitExceptionTable(this).print(code_begin());
 }
+#endif // PRODUCT
 
 void nmethod::print_statistics() {
   ttyLocker ttyl;
   if (xtty != NULL)  xtty->head("statistics type='nmethod'");
-  nmethod_stats.print_native_nmethod_stats();
-  nmethod_stats.print_nmethod_stats();
+  native_nmethod_stats.print_native_nmethod_stats();
+#ifdef COMPILER1
+  c1_java_nmethod_stats.print_nmethod_stats("C1");
+#endif
+#ifdef COMPILER2
+  c2_java_nmethod_stats.print_nmethod_stats("C2");
+#endif
+#if INCLUDE_JVMCI
+  jvmci_java_nmethod_stats.print_nmethod_stats("JVMCI");
+#endif
+#ifdef SHARK
+  shark_java_nmethod_stats.print_nmethod_stats("Shark");
+#endif
+  unknown_java_nmethod_stats.print_nmethod_stats("Unknown");
   DebugInformationRecorder::print_statistics();
-  nmethod_stats.print_pc_stats();
+#ifndef PRODUCT
+  pc_nmethod_stats.print_pc_stats();
+#endif
   Dependencies::print_statistics();
   if (xtty != NULL)  xtty->tail("statistics");
 }
 
-#endif // PRODUCT
+#if INCLUDE_JVMCI
+void nmethod::clear_jvmci_installed_code() {
+  // write_ref_method_pre/post can only be safely called at a
+  // safepoint or while holding the CodeCache_lock
+  assert(CodeCache_lock->is_locked() ||
+         SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
+  if (_jvmci_installed_code != NULL) {
+    // This must be done carefully to maintain nmethod remembered sets properly
+    BarrierSet* bs = Universe::heap()->barrier_set();
+    bs->write_ref_nmethod_pre(&_jvmci_installed_code, this);
+    _jvmci_installed_code = NULL;
+    bs->write_ref_nmethod_post(&_jvmci_installed_code, this);
+  }
+}
+
+void nmethod::maybe_invalidate_installed_code() {
+  assert(Patching_lock->is_locked() ||
+         SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
+  oop installed_code = jvmci_installed_code();
+  if (installed_code != NULL) {
+    nmethod* nm = (nmethod*)InstalledCode::address(installed_code);
+    if (nm == NULL || nm != this) {
+      // The link has been broken or the InstalledCode instance is
+      // associated with another nmethod so do nothing.
+      return;
+    }
+    if (!is_alive()) {
+      // Break the link between nmethod and InstalledCode such that the nmethod
+      // can subsequently be flushed safely.  The link must be maintained while
+      // the method could have live activations since invalidateInstalledCode
+      // might want to invalidate all existing activations.
+      InstalledCode::set_address(installed_code, 0);
+      InstalledCode::set_entryPoint(installed_code, 0);
+    } else if (is_not_entrant()) {
+      // Remove the entry point so any invocation will fail but keep
+      // the address link around that so that existing activations can
+      // be invalidated.
+      InstalledCode::set_entryPoint(installed_code, 0);
+    }
+  }
+}
+
+void nmethod::invalidate_installed_code(Handle installedCode, TRAPS) {
+  if (installedCode() == NULL) {
+    THROW(vmSymbols::java_lang_NullPointerException());
+  }
+  jlong nativeMethod = InstalledCode::address(installedCode);
+  nmethod* nm = (nmethod*)nativeMethod;
+  if (nm == NULL) {
+    // Nothing to do
+    return;
+  }
+
+  nmethodLocker nml(nm);
+#ifdef ASSERT
+  {
+    MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+    // This relationship can only be checked safely under a lock
+    assert(nm == NULL || !nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check");
+  }
+#endif
+
+  if (nm->is_alive()) {
+    // The nmethod state machinery maintains the link between the
+    // HotSpotInstalledCode and nmethod* so as long as the nmethod appears to be
+    // alive assume there is work to do and deoptimize the nmethod.
+    nm->mark_for_deoptimization();
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+
+  MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+  // Check that it's still associated with the same nmethod and break
+  // the link if it is.
+  if (InstalledCode::address(installedCode) == nativeMethod) {
+    InstalledCode::set_address(installedCode, 0);
+  }
+}
+
+char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
+  if (!this->is_compiled_by_jvmci()) {
+    return NULL;
+  }
+  oop installedCode = this->jvmci_installed_code();
+  if (installedCode != NULL) {
+    oop installedCodeName = NULL;
+    if (installedCode->is_a(InstalledCode::klass())) {
+      installedCodeName = InstalledCode::name(installedCode);
+    }
+    if (installedCodeName != NULL) {
+      return java_lang_String::as_utf8_string(installedCodeName, buf, (int)buflen);
+    } else {
+      jio_snprintf(buf, buflen, "null");
+      return buf;
+    }
+  }
+  jio_snprintf(buf, buflen, "noInstalledCode");
+  return buf;
+}
+#endif
--- a/src/share/vm/code/nmethod.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/nmethod.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -126,6 +126,12 @@
   int       _entry_bci;        // != InvocationEntryBci if this nmethod is an on-stack replacement method
   jmethodID _jmethod_id;       // Cache of method()->jmethod_id()
 
+#if INCLUDE_JVMCI
+  // Needed to keep nmethods alive that are not the default nmethod for the associated Method.
+  oop       _jvmci_installed_code;
+  oop       _speculation_log;
+#endif
+
   // To support simple linked-list chaining of nmethods:
   nmethod*  _osr_link;         // from InstanceKlass::osr_nmethods_head
 
@@ -292,7 +298,12 @@
           ExceptionHandlerTable* handler_table,
           ImplicitExceptionTable* nul_chk_table,
           AbstractCompiler* compiler,
-          int comp_level);
+          int comp_level
+#if INCLUDE_JVMCI
+          , Handle installed_code,
+          Handle speculation_log
+#endif
+          );
 
   // helper methods
   void* operator new(size_t size, int nmethod_size) throw();
@@ -328,7 +339,12 @@
                               ExceptionHandlerTable* handler_table,
                               ImplicitExceptionTable* nul_chk_table,
                               AbstractCompiler* compiler,
-                              int comp_level);
+                              int comp_level
+#if INCLUDE_JVMCI
+                              , Handle installed_code = Handle(),
+                              Handle speculation_log = Handle()
+#endif
+  );
 
   static nmethod* new_native_nmethod(methodHandle method,
                                      int compile_id,
@@ -367,6 +383,7 @@
   bool is_osr_method() const                      { return _entry_bci != InvocationEntryBci; }
 
   bool is_compiled_by_c1() const;
+  bool is_compiled_by_jvmci() const;
   bool is_compiled_by_c2() const;
   bool is_compiled_by_shark() const;
 
@@ -396,7 +413,7 @@
   address handler_table_begin   () const          { return           header_begin() + _handler_table_offset ; }
   address handler_table_end     () const          { return           header_begin() + _nul_chk_table_offset ; }
   address nul_chk_table_begin   () const          { return           header_begin() + _nul_chk_table_offset ; }
-  address nul_chk_table_end     () const          { return           header_begin() + _nmethod_end_offset   ; }
+  address nul_chk_table_end     () const          { return           header_begin() + _nmethod_end_offset;    }
 
   // Sizes
   int consts_size       () const                  { return            consts_end       () -            consts_begin       (); }
@@ -610,6 +627,25 @@
   // Evolution support. We make old (discarded) compiled methods point to new Method*s.
   void set_method(Method* method) { _method = method; }
 
+#if INCLUDE_JVMCI
+  oop jvmci_installed_code() { return _jvmci_installed_code ; }
+  char* jvmci_installed_code_name(char* buf, size_t buflen);
+
+  // Update the state of any InstalledCode instance associated with
+  // this nmethod based on the current value of _state.
+  void maybe_invalidate_installed_code();
+  
+  // Helper function to invalidate InstalledCode instances
+  static void invalidate_installed_code(Handle installed_code, TRAPS);
+  
+  oop speculation_log() { return _speculation_log ; }
+  
+ private:
+  void clear_jvmci_installed_code();
+  
+ public:
+#endif
+
   // GC support
   void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
   //  The parallel versions are used by G1.
@@ -670,7 +706,7 @@
   // Deopt
   // Return true is the PC is one would expect if the frame is being deopted.
   bool is_deopt_pc      (address pc) { return is_deopt_entry(pc) || is_deopt_mh_entry(pc); }
-  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin(); }
+  bool is_deopt_entry(address pc);
   bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
   // Accessor/mutator for the original pc of a frame before a frame was deopted.
   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
@@ -721,7 +757,7 @@
 
   // Prints a comment for one native instruction (reloc info, pc desc)
   void print_code_comment_on(outputStream* st, int column, address begin, address end);
-  static void print_statistics()                  PRODUCT_RETURN;
+  static void print_statistics();
 
   // Compiler task identification.  Note that all OSR methods
   // are numbered in an independent sequence if CICountOSR is true,
--- a/src/share/vm/code/oopRecorder.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/oopRecorder.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -157,3 +157,49 @@
 // Explicitly instantiate these types
 template class ValueRecorder<Metadata*>;
 template class ValueRecorder<jobject>;
+
+oop ObjectLookup::ObjectEntry::oop_value() { return JNIHandles::resolve(_value); }
+
+ObjectLookup::ObjectLookup(): _gc_count(Universe::heap()->total_collections()), _values(4) {}
+
+void ObjectLookup::maybe_resort() {
+  // The values are kept sorted by address which may be invalidated
+  // after a GC, so resort if a GC has occurred since last time.
+  if (_gc_count != Universe::heap()->total_collections()) {
+    _gc_count = Universe::heap()->total_collections();
+    _values.sort(sort_by_address);
+  }
+}
+
+int ObjectLookup::sort_by_address(oop a, oop b) {
+  if (b > a) return 1;
+  if (a > b) return -1;
+  return 0;
+}
+
+int ObjectLookup::sort_by_address(ObjectEntry* a, ObjectEntry* b) {
+  return sort_by_address(a->oop_value(), b->oop_value());
+}
+
+int ObjectLookup::sort_oop_by_address(oop& a, ObjectEntry& b) {
+  return sort_by_address(a, b.oop_value());
+}
+  
+int ObjectLookup::find_index(jobject handle, OopRecorder* oop_recorder) {
+  if (handle == NULL) {
+    return 0;
+  }
+  oop object = JNIHandles::resolve(handle);
+  maybe_resort();
+  bool found;
+  int location = _values.find_sorted<oop, sort_oop_by_address>(object, found);
+  if (!found) {
+    assert(location <= _values.length(), "out of range");
+    jobject handle = JNIHandles::make_local(object);
+    ObjectEntry r(handle, oop_recorder->allocate_oop_index(handle));
+    _values.insert_before(location, r);
+    return r.index();
+  }
+  return _values.at(location).index();
+}
+
--- a/src/share/vm/code/oopRecorder.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/oopRecorder.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -146,18 +146,57 @@
 #endif
 };
 
+class OopRecorder;
+
+class ObjectLookup : public ResourceObj {
+ private:
+  class ObjectEntry {
+   private:
+    jobject _value;
+    int     _index;
+
+   public:
+    ObjectEntry(jobject value, int index): _value(value), _index(index) {}
+    ObjectEntry() {}
+    oop oop_value(); // { return JNIHandles::resolve(_value); }
+    int index() { return _index; }
+  };
+
+  GrowableArray<ObjectEntry> _values;
+  unsigned int _gc_count;
+
+  // Utility sort functions
+  static int sort_by_address(oop a, oop b);
+  static int sort_by_address(ObjectEntry* a, ObjectEntry* b);
+  static int sort_oop_by_address(oop& a, ObjectEntry& b);
+
+ public:
+  ObjectLookup();
+  
+  // Resort list if a GC has occurred since the last sort
+  void maybe_resort();
+  int find_index(jobject object, OopRecorder* oop_recorder);
+};
+
 class OopRecorder : public ResourceObj {
  private:
   ValueRecorder<jobject>      _oops;
   ValueRecorder<Metadata*>    _metadata;
+  ObjectLookup*               _object_lookup;
  public:
-  OopRecorder(Arena* arena = NULL): _oops(arena), _metadata(arena) {}
+  OopRecorder(Arena* arena = NULL, bool deduplicate = false): _oops(arena), _metadata(arena) {
+    if (deduplicate) {
+      _object_lookup = new ObjectLookup();
+    } else {
+      _object_lookup = NULL;
+    }
+  }
 
   int allocate_oop_index(jobject h) {
     return _oops.allocate_index(h);
   }
   int find_index(jobject h) {
-    return _oops.find_index(h);
+    return _object_lookup != NULL ? _object_lookup->find_index(h, this) : _oops.find_index(h);
   }
   jobject oop_at(int index) {
     return _oops.at(index);
--- a/src/share/vm/code/pcDesc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/pcDesc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -42,7 +42,8 @@
   enum {
     PCDESC_reexecute               = 1 << 0,
     PCDESC_is_method_handle_invoke = 1 << 1,
-    PCDESC_return_oop              = 1 << 2
+    PCDESC_return_oop              = 1 << 2,
+    PCDESC_rethrow_exception       = 1 << 3
   };
 
   int _flags;
@@ -71,6 +72,8 @@
   };
 
   // Flags
+  bool     rethrow_exception()              const { return (_flags & PCDESC_rethrow_exception) != 0; }
+  void set_rethrow_exception(bool z)              { set_flag(PCDESC_rethrow_exception, z);    }
   bool     should_reexecute()              const { return (_flags & PCDESC_reexecute) != 0; }
   void set_should_reexecute(bool z)              { set_flag(PCDESC_reexecute, z); }
 
--- a/src/share/vm/code/relocInfo.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/relocInfo.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -30,6 +30,7 @@
 #include "memory/resourceArea.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "utilities/copy.hpp"
+#include "oops/oop.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
@@ -424,6 +425,30 @@
   ShouldNotReachHere();
 }
 
+void Relocation::const_set_data_value(address x) {
+#ifdef _LP64
+  if (format() == relocInfo::narrow_oop_in_const) {
+    *(narrowOop*)addr() = oopDesc::encode_heap_oop((oop) x);
+  } else {
+#endif
+    *(address*)addr() = x;
+#ifdef _LP64
+  }
+#endif
+}
+
+void Relocation::const_verify_data_value(address x) {
+#ifdef _LP64
+  if (format() == relocInfo::narrow_oop_in_const) {
+    assert(*(narrowOop*)addr() == oopDesc::encode_heap_oop((oop) x), "must agree");
+  } else {
+#endif
+    assert(*(address*)addr() == x, "must agree");
+#ifdef _LP64
+  }
+#endif
+}
+
 
 RelocationHolder Relocation::spec_simple(relocInfo::relocType rtype) {
   if (rtype == relocInfo::none)  return RelocationHolder::none;
--- a/src/share/vm/code/relocInfo.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/relocInfo.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -210,6 +210,11 @@
 //   See [About Offsets] below.
 //   //%note reloc_2
 //
+// relocInfo::poll_[return_]type -- a safepoint poll
+//   Value:  none
+//   Instruction types: memory load or test
+//   Data:  none
+//
 // For example:
 //
 //   INSTRUCTIONS                        RELOC: TYPE    PREFIX DATA
@@ -441,6 +446,11 @@
   };
  public:
   enum {
+#ifdef _LP64
+    // for use in format
+    // format_width must be at least 1 on _LP64
+    narrow_oop_in_const = 1,
+#endif
     // Conservatively large estimate of maximum length (in shorts)
     // of any relocation record.
     // Extended format is length prefix, data words, and tag/offset suffix.
@@ -760,6 +770,9 @@
   }
 
  protected:
+  // platform-independent utility for patching constant section
+  void       const_set_data_value    (address x);
+  void       const_verify_data_value (address x);
   // platform-dependent utilities for decoding and patching instructions
   void       pd_set_data_value       (address x, intptr_t off, bool verify_only = false); // a set or mem-ref
   void       pd_verify_data_value    (address x, intptr_t off) { pd_set_data_value(x, off, true); }
@@ -870,13 +883,13 @@
   void        set_value(address x)             { set_value(x, offset()); }
   void        set_value(address x, intptr_t o) {
     if (addr_in_const())
-      *(address*)addr() = x;
+      const_set_data_value(x);
     else
       pd_set_data_value(x, o);
   }
   void        verify_value(address x) {
     if (addr_in_const())
-      assert(*(address*)addr() == x, "must agree");
+      const_verify_data_value(x);
     else
       pd_verify_data_value(x, offset());
   }
@@ -1316,10 +1329,8 @@
   void     fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
 };
 
-class poll_return_Relocation : public Relocation {
-  bool          is_data()                      { return true; }
+class poll_return_Relocation : public poll_Relocation {
   relocInfo::relocType type() { return relocInfo::poll_return_type; }
-  void     fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
 };
 
 // We know all the xxx_Relocation classes, so now we can define these:
--- a/src/share/vm/code/scopeDesc.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/scopeDesc.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -32,21 +32,23 @@
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
   _code          = code;
   _decode_offset = decode_offset;
   _objects       = decode_object_values(obj_decode_offset);
   _reexecute     = reexecute;
   _return_oop    = return_oop;
+  _rethrow_exception = rethrow_exception;
   decode_body();
 }
 
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
   _code          = code;
   _decode_offset = decode_offset;
   _objects       = decode_object_values(DebugInformationRecorder::serialized_null);
   _reexecute     = reexecute;
   _return_oop    = return_oop;
+  _rethrow_exception = rethrow_exception;
   decode_body();
 }
 
@@ -56,6 +58,7 @@
   _decode_offset = parent->_sender_decode_offset;
   _objects       = parent->_objects;
   _reexecute     = false; //reexecute only applies to the first scope
+  _rethrow_exception = false;
   _return_oop    = false;
   decode_body();
 }
@@ -223,17 +226,18 @@
     }
   }
 
-#ifdef COMPILER2
-  if (DoEscapeAnalysis && is_top() && _objects != NULL) {
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  if (NOT_JVMCI(DoEscapeAnalysis &&) is_top() && _objects != NULL) {
     tty->print_cr("Objects");
     for (int i = 0; i < _objects->length(); i++) {
-      ObjectValue* sv = (ObjectValue*) _objects->at(i);
+      ObjectValue* sv = _objects->at(i)->as_ObjectValue();
       tty->print(" - %d: ", sv->id());
+      tty->print("%s ", java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())->external_name());
       sv->print_fields_on(tty);
       tty->cr();
     }
   }
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
 }
 
 #endif
--- a/src/share/vm/code/scopeDesc.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/code/scopeDesc.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -60,17 +60,18 @@
 class ScopeDesc : public ResourceObj {
  public:
   // Constructor
-  ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop);
+  ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
 
   // Calls above, giving default value of "serialized_null" to the
   // "obj_decode_offset" argument.  (We don't use a default argument to
   // avoid a .hpp-.hpp dependency.)
-  ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop);
+  ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
 
   // JVM state
   Method* method()      const { return _method; }
   int          bci()      const { return _bci;    }
   bool should_reexecute() const { return _reexecute; }
+  bool rethrow_exception() const { return _rethrow_exception; }
   bool return_oop()       const { return _return_oop; }
 
   GrowableArray<ScopeValue*>*   locals();
@@ -97,6 +98,7 @@
   Method*       _method;
   int           _bci;
   bool          _reexecute;
+  bool          _rethrow_exception;
   bool          _return_oop;
 
   // Decoding offsets
--- a/src/share/vm/compiler/abstractCompiler.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/compiler/abstractCompiler.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -58,7 +58,7 @@
 }
 
 void AbstractCompiler::set_state(int state) {
-  // Ensure that ste is only set by one thread at a time
+  // Ensure that state is only set by one thread at a time
   MutexLocker only_one(CompileThread_lock);
   _compiler_state =  state;
   CompileThread_lock->notify_all();
--- a/src/share/vm/compiler/abstractCompiler.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/compiler/abstractCompiler.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -27,6 +27,47 @@
 
 #include "ci/compilerInterface.hpp"
 
+typedef void (*initializer)(void);
+
+#if INCLUDE_JVMCI
+// Per-compiler statistics
+class CompilerStatistics VALUE_OBJ_CLASS_SPEC {
+  friend class VMStructs;
+
+  class Data VALUE_OBJ_CLASS_SPEC {
+    friend class VMStructs;
+  public:
+    elapsedTimer _time;  // time spent compiling
+    int _bytes;          // number of bytecodes compiled, including inlined bytecodes
+    int _count;          // number of compilations
+    Data() : _bytes(0), _count(0) {}
+    void update(elapsedTimer time, int bytes) {
+      _time.add(time);
+      _bytes += bytes;
+      _count++;
+    }
+    void reset() {
+      _time.reset();
+    }
+  };
+
+ public:
+  Data _standard;  // stats for non-OSR compilations
+  Data _osr;       // stats for OSR compilations
+  int _nmethods_size; //
+  int _nmethods_code_size;
+  int bytes_per_second() {
+    int bytes = _standard._bytes + _osr._bytes;
+    if (bytes == 0) {
+      return 0;
+    }
+    double seconds = _standard._time.seconds() + _osr._time.seconds();
+    return seconds == 0.0 ? 0 : (int) (bytes / seconds);
+  }
+  CompilerStatistics() : _nmethods_size(0), _nmethods_code_size(0) {}
+};
+#endif
+
 class AbstractCompiler : public CHeapObj<mtCompiler> {
  private:
   volatile int _num_compiler_threads;
@@ -40,8 +81,20 @@
   // This thread will initialize the compiler runtime.
   bool should_perform_init();
 
+  // The (closed set) of concrete compiler classes. Using an tag like this
+  // avoids a confusing use of macros around the definition of the
+  // 'is_<compiler type>' methods.
+  enum Type { c1, c2, shark, jvmci };
+
+ private:
+  Type _type;
+
+#if INCLUDE_JVMCI
+  CompilerStatistics _stats;
+#endif
+
  public:
-  AbstractCompiler() : _compiler_state(uninitialized), _num_compiler_threads(0) {}
+  AbstractCompiler(Type type) : _type(type), _compiler_state(uninitialized), _num_compiler_threads(0) {}
 
   // This function determines the compiler thread that will perform the
   // shutdown of the corresponding compiler runtime.
@@ -50,31 +103,19 @@
   // Name of this compiler
   virtual const char* name() = 0;
 
-  // Missing feature tests
+  // Should a native wrapper be generated by the runtime. This method
+  // does *not* answer the question "can this compiler generate code for
+  // a native method".
   virtual bool supports_native()                 { return true; }
   virtual bool supports_osr   ()                 { return true; }
   virtual bool can_compile_method(methodHandle method)  { return true; }
-#if defined(TIERED) || ( !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK))
-  virtual bool is_c1   ()                        { return false; }
-  virtual bool is_c2   ()                        { return false; }
-  virtual bool is_shark()                        { return false; }
-#else
-#ifdef COMPILER1
-  bool is_c1   ()                                { return true; }
-  bool is_c2   ()                                { return false; }
-  bool is_shark()                                { return false; }
-#endif // COMPILER1
-#ifdef COMPILER2
-  bool is_c1   ()                                { return false; }
-  bool is_c2   ()                                { return true; }
-  bool is_shark()                                { return false; }
-#endif // COMPILER2
-#ifdef SHARK
-  bool is_c1   ()                                { return false; }
-  bool is_c2   ()                                { return false; }
-  bool is_shark()                                { return true; }
-#endif // SHARK
-#endif // TIERED
+  bool is_c1   ()                                { return _type == c1; }
+  bool is_c2   ()                                { return _type == c2; }
+  bool is_shark()                                { return _type == shark; }
+  bool is_jvmci()                                { return _type == jvmci; }
+
+  // Extra tests to identity trivial methods for the tiered compilation policy.
+  virtual bool is_trivial(Method* method) { return false; }
 
   // Customization
   virtual void initialize () = 0;
@@ -97,6 +138,10 @@
   virtual void print_timers() {
     ShouldNotReachHere();
   }
+
+#if INCLUDE_JVMCI
+  CompilerStatistics* stats() { return &_stats; }
+#endif
 };
 
 #endif // SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
--- a/src/share/vm/compiler/compileBroker.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/compiler/compileBroker.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -49,6 +49,11 @@
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "runtime/vframe.hpp"
+#endif
 #ifdef COMPILER2
 #include "opto/c2compiler.hpp"
 #endif
@@ -230,6 +235,11 @@
 CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
   CompilerThread* thread = CompilerThread::current();
   thread->set_task(task);
+#if INCLUDE_JVMCI
+  if (task->is_blocking() && CompileBroker::compiler(task->comp_level())->is_jvmci()) {
+    task->set_jvmci_compiler_thread(thread);
+  }
+#endif
   CompileLog*     log  = thread->log();
   if (log != NULL)  task->log_task_start(log);
 }
@@ -243,10 +253,28 @@
   task->set_code_handle(NULL);
   thread->set_env(NULL);
   if (task->is_blocking()) {
-    MutexLocker notifier(task->lock(), thread);
-    task->mark_complete();
-    // Notify the waiting thread that the compilation has completed.
-    task->lock()->notify_all();
+    bool free_task = false;
+    {
+      MutexLocker notifier(task->lock(), thread);
+      task->mark_complete();
+#if INCLUDE_JVMCI
+      if (CompileBroker::compiler(task->comp_level())->is_jvmci()) {
+        if (!task->has_waiter()) {
+          // The waiting thread timed out and thus did not free the task.
+          free_task = true;
+        }
+        task->set_jvmci_compiler_thread(NULL);
+      }
+#endif
+      if (!free_task) {
+        // Notify the waiting thread that the compilation has completed.
+        task->lock()->notify_all();
+      }
+    }
+    if (free_task) {
+      // The task can only be freed once the task lock is released.
+      CompileTask::free(task);
+    }
   } else {
     task->mark_complete();
 
@@ -275,7 +303,7 @@
   } else {
     task = new CompileTask();
     DEBUG_ONLY(_num_allocated_tasks++;)
-    assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?");
+    NOT_JVMCI(assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?");)
     task->set_next(NULL);
     task->set_is_free(true);
   }
@@ -317,6 +345,10 @@
   _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder());
   _osr_bci = osr_bci;
   _is_blocking = is_blocking;
+#if INCLUDE_JVMCI
+  _has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();
+  _jvmci_compiler_thread = NULL;
+#endif
   _comp_level = comp_level;
   _num_inlined_bytecodes = 0;
 
@@ -401,8 +433,6 @@
 // CompileTask::print_line
 void CompileTask::print_line() {
   ttyLocker ttyl;  // keep the following output all in one block
-  // print compiler name if requested
-  if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
   print_compilation();
 }
 
@@ -415,6 +445,8 @@
   if (!short_form) {
     st->print("%7d ", (int) st->time_stamp().milliseconds());  // print timestamp
   }
+  // print compiler name if requested
+  if (CIPrintCompilerName) st->print("%s:", CompileBroker::compiler_name(comp_level));
   st->print("%4d ", compile_id);    // print compilation number
 
   // For unloaded methods the transition to zombie occurs after the
@@ -547,7 +579,8 @@
   if (_osr_bci != CompileBroker::standard_entry_bci) {
     log->print(" osr_bci='%d'", _osr_bci);
   }
-  if (_comp_level != CompLevel_highest_tier) {
+  // Always print the level in tiered.
+  if (_comp_level != CompLevel_highest_tier || TieredCompilation) {
     log->print(" level='%d'", _comp_level);
   }
   if (_is_blocking) {
@@ -584,6 +617,24 @@
 
 
 // ------------------------------------------------------------------
+// CompileTask::log_task_dequeued
+void CompileTask::log_task_dequeued(const char* comment) {
+  if (LogCompilation && xtty != NULL) {
+    Thread* thread = Thread::current();
+    ttyLocker ttyl;
+    ResourceMark rm(thread);
+
+    xtty->begin_elem("task_dequeued");
+    log_task(xtty);
+    if (comment != NULL) {
+      xtty->print(" comment='%s'", comment);
+    }
+    xtty->end_elem();
+  }
+}
+
+
+// ------------------------------------------------------------------
 // CompileTask::log_task_start
 void CompileTask::log_task_start(CompileLog* log)   {
   log->begin_head("task");
@@ -879,7 +930,7 @@
 // CompileBroker::compilation_init
 //
 // Initialize the Compilation object
-void CompileBroker::compilation_init() {
+void CompileBroker::compilation_init(TRAPS) {
   _last_method_compiled[0] = '\0';
 
   // No need to initialize compilation system if we do not use it.
@@ -890,6 +941,54 @@
   // Set the interface to the current compiler(s).
   int c1_count = CompilationPolicy::policy()->compiler_count(CompLevel_simple);
   int c2_count = CompilationPolicy::policy()->compiler_count(CompLevel_full_optimization);
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    JVMCICompiler* jvmci = new JVMCICompiler();
+    if (JVMCIPrintProperties) {
+      // Initialize JVMCI eagerly if JVMCIPrintProperties is enabled.
+      // The JVMCI Java initialization code will read this flag and
+      // do the printing if it's set.
+      JVMCIRuntime::ensure_jvmci_class_loader_is_initialized();
+      JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK);
+    }
+    if (UseJVMCICompiler) {
+      _compilers[1] = jvmci;
+      if (FLAG_IS_DEFAULT(JVMCIThreads)) {
+        if (BootstrapJVMCI) {
+          // JVMCI will bootstrap so give it more threads
+          c2_count = MIN2(32, os::active_processor_count());
+        }
+      } else {
+        c2_count = JVMCIThreads;
+      }
+      if (FLAG_IS_DEFAULT(JVMCIHostThreads)) {
+      } else {
+        c1_count = JVMCIHostThreads;
+      }
+      if (!UseInterpreter || !BackgroundCompilation) {
+        // Force initialization of JVMCI compiler otherwise JVMCI
+        // compilations will not block until JVMCI is initialized
+        JVMCIRuntime::ensure_jvmci_class_loader_is_initialized();
+        ResourceMark rm;
+        TempNewSymbol getCompiler = SymbolTable::new_symbol("getCompiler", CHECK);
+        TempNewSymbol sig = SymbolTable::new_symbol("()Ljdk/vm/ci/runtime/JVMCICompiler;", CHECK);
+        Handle jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK);
+        JavaValue result(T_OBJECT);
+        JavaCalls::call_virtual(&result, jvmciRuntime, HotSpotJVMCIRuntime::klass(), getCompiler, sig, CHECK);
+      }
+#ifndef COMPILER2
+    } else {
+      c2_count = 0;
+#endif
+    }
+  }
+#ifndef COMPILER2
+  else {
+    c2_count = 0;
+  }
+#endif
+#endif // INCLUDE_JVMCI
+
 #ifdef COMPILER1
   if (c1_count > 0) {
     _compilers[0] = new Compiler();
@@ -897,8 +996,10 @@
 #endif // COMPILER1
 
 #ifdef COMPILER2
-  if (c2_count > 0) {
-    _compilers[1] = new C2Compiler();
+  if (true JVMCI_ONLY( && !UseJVMCICompiler)) {
+    if (c2_count > 0) {
+      _compilers[1] = new C2Compiler();
+    }
   }
 #endif // COMPILER2
 
@@ -1097,7 +1198,7 @@
 void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) {
   EXCEPTION_MARK;
 #if !defined(ZERO) && !defined(SHARK)
-  assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?");
+  assert(c2_compiler_count > 0 || c1_compiler_count > 0 JVMCI_ONLY(|| UseJVMCICompiler), "No compilers?");
 #endif // !ZERO && !SHARK
   // Initialize the compilation queue
   if (c2_compiler_count > 0) {
@@ -1117,7 +1218,7 @@
   char name_buffer[256];
   for (int i = 0; i < c2_compiler_count; i++) {
     // Create a name for our thread.
-    sprintf(name_buffer, "C2 CompilerThread%d", i);
+    sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i);
     CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK);
     // Shark and C2
     CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_compile_queue, counters, _compilers[1], CHECK);
@@ -1184,7 +1285,7 @@
     if (osr_bci != InvocationEntryBci) {
       tty->print(" osr_bci: %d", osr_bci);
     }
-    tty->print(" comment: %s count: %d", comment, hot_count);
+    tty->print(" level: %d comment: %s count: %d", comp_level, comment, hot_count);
     if (!hot_method.is_null()) {
       tty->print(" hot: ");
       if (hot_method() != method()) {
@@ -1276,6 +1377,40 @@
     // Should this thread wait for completion of the compile?
     blocking = is_compile_blocking();
 
+#if INCLUDE_JVMCI
+    if (UseJVMCICompiler && blocking) {
+      // Don't allow blocking compiles for requests triggered by JVMCI.
+      if (thread->is_Compiler_thread()) {
+        blocking = false;
+      }
+
+      // Don't allow blocking compiles if inside a class initializer or while performing class loading
+      vframeStream vfst((JavaThread*) thread);
+      for (; !vfst.at_end(); vfst.next()) {
+        if (vfst.method()->is_static_initializer() ||
+            (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
+             vfst.method()->name() == vmSymbols::loadClass_name())) {
+          blocking = false;
+          break;
+        }
+      }
+
+      // Don't allow blocking compilation requests to JVMCI
+      // if JVMCI itself is not yet initialized
+      if (!JVMCIRuntime::is_HotSpotJVMCIRuntime_initialized() && compiler(comp_level)->is_jvmci()) {
+        blocking = false;
+      }
+
+      // Don't allow blocking compilation requests if we are in JVMCIRuntime::shutdown
+      // to avoid deadlock between compiler thread(s) and threads run at shutdown
+      // such as the DestroyJavaVM thread.
+      if (JVMCIRuntime::shutdown_called()) {
+        blocking = false;
+      }
+    }
+    // Don't allow blocking compiles
+#endif
+
     // We will enter the compilation in the queue.
     // 14012000: Note that this sets the queued_for_compile bits in
     // the target method. We can now reason that a method cannot be
@@ -1556,6 +1691,16 @@
 #endif
 }
 
+
+// ------------------------------------------------------------------
+// CompileBroker::assign_compile_id_unlocked
+//
+// Public wrapper for assign_compile_id that acquires the needed locks
+uint CompileBroker::assign_compile_id_unlocked(Thread* thread, methodHandle method, int osr_bci) {
+  MutexLocker locker(MethodCompileQueue_lock, thread);
+  return assign_compile_id(method, osr_bci);
+}
+
 /**
  * Should the current thread block until this compilation request
  * has been fulfilled?
@@ -1596,6 +1741,62 @@
   return new_task;
 }
 
+#if INCLUDE_JVMCI
+// The number of milliseconds to wait before checking if
+// JVMCI compilation has made progress.
+static const long JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE = 500;
+
+// The number of JVMCI compilation progress checks that must fail
+// before unblocking a thread waiting for a blocking compilation.
+static const int JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS = 5;
+
+/**
+ * Waits for a JVMCI compiler to complete a given task. This thread
+ * waits until either the task completes or it sees no JVMCI compilation
+ * progress for N consecutive milliseconds where N is
+ * JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE *
+ * JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS.
+ *
+ * @return true if this thread needs to free/recycle the task
+ */
+bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask* task, JavaThread* thread) {
+  MutexLocker waiter(task->lock(), thread);
+  int progress_wait_attempts = 0;
+  int methods_compiled = jvmci->methods_compiled();
+  while (!task->is_complete() && !is_compilation_disabled_forever() &&
+         task->lock()->wait(!Mutex::_no_safepoint_check_flag, JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE)) {
+    CompilerThread* jvmci_compiler_thread = task->jvmci_compiler_thread();
+
+    bool progress;
+    if (jvmci_compiler_thread != NULL) {
+      // If the JVMCI compiler thread is not blocked, we deem it to be making progress.
+      progress = jvmci_compiler_thread->thread_state() != _thread_blocked;
+    } else {
+      // Still waiting on JVMCI compiler queue. This thread may be holding a lock
+      // that all JVMCI compiler threads are blocked on. We use the counter for
+      // successful JVMCI compilations to determine whether JVMCI compilation
+      // is still making progress through the JVMCI compiler queue.
+      progress = jvmci->methods_compiled() != methods_compiled;
+    }
+
+    if (!progress) {
+      if (++progress_wait_attempts == JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS) {
+        if (PrintCompilation) {
+          task->print_compilation(tty, "wait for blocking compilation timed out");
+        }
+        break;
+      }
+    } else {
+      progress_wait_attempts = 0;
+      if (jvmci_compiler_thread == NULL) {
+        methods_compiled = jvmci->methods_compiled();
+      }
+    }
+  }
+  task->clear_waiter();
+  return task->is_complete();
+}
+#endif
 
 /**
  *  Wait for the compilation task to complete.
@@ -1612,30 +1813,38 @@
   thread->set_blocked_on_compilation(true);
 
   methodHandle method(thread, task->method());
+  bool free_task = true;
+#if INCLUDE_JVMCI
+  AbstractCompiler* comp = compiler(task->comp_level());
+  if (comp->is_jvmci()) {
+    free_task = wait_for_jvmci_completion((JVMCICompiler*) comp, task, thread);
+  } else
+#endif
   {
     MutexLocker waiter(task->lock(), thread);
-
     while (!task->is_complete() && !is_compilation_disabled_forever()) {
       task->lock()->wait();
     }
   }
 
   thread->set_blocked_on_compilation(false);
-  if (is_compilation_disabled_forever()) {
-    CompileTask::free(task);
-    return;
-  }
+  if (free_task) {
+    if (is_compilation_disabled_forever()) {
+      CompileTask::free(task);
+      return;
+    }
 
-  // It is harmless to check this status without the lock, because
-  // completion is a stable property (until the task object is recycled).
-  assert(task->is_complete(), "Compilation should have completed");
-  assert(task->code_handle() == NULL, "must be reset");
+    // It is harmless to check this status without the lock, because
+    // completion is a stable property (until the task object is recycled).
+    assert(task->is_complete(), "Compilation should have completed");
+    assert(task->code_handle() == NULL, "must be reset");
 
-  // By convention, the waiter is responsible for recycling a
-  // blocking CompileTask. Since there is only one waiter ever
-  // waiting on a CompileTask, we know that no one else will
-  // be using this CompileTask; we can free it.
-  CompileTask::free(task);
+    // By convention, the waiter is responsible for recycling a
+    // blocking CompileTask. Since there is only one waiter ever
+    // waiting on a CompileTask, we know that no one else will
+    // be using this CompileTask; we can free it.
+    CompileTask::free(task);
+  }
 }
 
 /**
@@ -1907,6 +2116,35 @@
   tty->print("%s", s.as_string());
 }
 
+void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, EventCompilation& event, bool success, ciEnv* ci_env) {
+
+  if (success) {
+    task->mark_success();
+    if (ci_env != NULL) {
+      task->set_num_inlined_bytecodes(ci_env->num_inlined_bytecodes());
+    }
+    if (_compilation_log != NULL) {
+      nmethod* code = task->code();
+      if (code != NULL) {
+        _compilation_log->log_nmethod(thread, code);
+      }
+    }
+  }
+
+  // simulate crash during compilation
+  assert(task->compile_id() != CICrashAt, "just as planned");
+  if (event.should_commit()) {
+    event.set_method(task->method());
+    event.set_compileID(task->compile_id());
+    event.set_compileLevel(task->comp_level());
+    event.set_succeded(task->is_success());
+    event.set_isOsr(task->osr_bci() != CompileBroker::standard_entry_bci);
+    event.set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size());
+    event.set_inlinedBytes(task->num_inlined_bytecodes());
+    event.commit();
+  }
+}
+
 // ------------------------------------------------------------------
 // CompileBroker::invoke_compiler_on_method
 //
@@ -1955,13 +2193,37 @@
   push_jni_handle_block();
   Method* target_handle = task->method();
   int compilable = ciEnv::MethodCompilable;
+  const char* failure_reason = NULL;
+  const char* retry_message = NULL;
+  AbstractCompiler *comp = compiler(task_level);
+
+  int system_dictionary_modification_counter;
   {
-    int system_dictionary_modification_counter;
-    {
-      MutexLocker locker(Compile_lock, thread);
-      system_dictionary_modification_counter = SystemDictionary::number_of_modifications();
+    MutexLocker locker(Compile_lock, thread);
+    system_dictionary_modification_counter = SystemDictionary::number_of_modifications();
+  }
+#if INCLUDE_JVMCI
+  if (comp != NULL && comp->is_jvmci()) {
+    JVMCICompiler* jvmci = (JVMCICompiler*) comp;
+
+    TraceTime t1("compilation", &time);
+    EventCompilation event;
+
+    JVMCIEnv env(task, system_dictionary_modification_counter);
+    methodHandle method(thread, target_handle);
+    jvmci->compile_method(method, osr_bci, &env);
+
+    post_compile(thread, task, event, task->code() != NULL, NULL);
+
+    failure_reason = env.failure_reason();
+    if (!env.retryable()) {
+      retry_message = "not retryable";
+      compilable = ciEnv::MethodCompilable_not_at_tier;
     }
 
+  } else
+#endif // INCLUDE_JVMCI
+  {
     NoHandleMark  nhm;
     ThreadToNativeFromVM ttn(thread);
 
@@ -1986,7 +2248,6 @@
     TraceTime t1("compilation", &time);
     EventCompilation event;
 
-    AbstractCompiler *comp = compiler(task_level);
     if (comp == NULL) {
       ci_env.record_method_not_compilable("no compiler", !TieredCompilation);
     } else {
@@ -2004,41 +2265,28 @@
     compilable = ci_env.compilable();
 
     if (ci_env.failing()) {
-      task->set_failure_reason(ci_env.failure_reason());
-      const char* retry_message = ci_env.retry_message();
-      if (_compilation_log != NULL) {
-        _compilation_log->log_failure(thread, task, ci_env.failure_reason(), retry_message);
-      }
-      if (PrintCompilation) {
-        FormatBufferResource msg = retry_message != NULL ?
-            err_msg_res("COMPILE SKIPPED: %s (%s)", ci_env.failure_reason(), retry_message) :
-            err_msg_res("COMPILE SKIPPED: %s",      ci_env.failure_reason());
-        task->print_compilation(tty, msg);
-      }
-    } else {
-      task->mark_success();
-      task->set_num_inlined_bytecodes(ci_env.num_inlined_bytecodes());
-      if (_compilation_log != NULL) {
-        nmethod* code = task->code();
-        if (code != NULL) {
-          _compilation_log->log_nmethod(thread, code);
-        }
-      }
+      failure_reason = ci_env.failure_reason();
+      retry_message = ci_env.retry_message();
     }
-    // simulate crash during compilation
-    assert(task->compile_id() != CICrashAt, "just as planned");
-    if (event.should_commit()) {
-      event.set_method(target->get_Method());
-      event.set_compileID(compile_id);
-      event.set_compileLevel(task->comp_level());
-      event.set_succeded(task->is_success());
-      event.set_isOsr(is_osr);
-      event.set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size());
-      event.set_inlinedBytes(task->num_inlined_bytecodes());
-      event.commit();
+
+    post_compile(thread, task, event, !ci_env.failing(), &ci_env);
+  }
+  // Remove the JNI handle block after the ciEnv destructor has run in
+  // the previous block.
+  pop_jni_handle_block();
+
+  if (failure_reason != NULL) {
+    if (_compilation_log != NULL) {
+      _compilation_log->log_failure(thread, task, failure_reason, retry_message);
+    }
+    if (PrintCompilation) {
+      FormatBufferResource msg = retry_message != NULL ?
+        err_msg_res("COMPILE SKIPPED: %s (%s)", failure_reason, retry_message) :
+        err_msg_res("COMPILE SKIPPED: %s",      failure_reason);
+      task->print_compilation(tty, msg);
     }
   }
-  pop_jni_handle_block();
+
 
   methodHandle method(thread, task->method());
 
@@ -2291,13 +2539,19 @@
     _peak_compilation_time = time.milliseconds() > _peak_compilation_time ? time.milliseconds() : _peak_compilation_time;
 
     if (CITime) {
+      int bytes_compiled = method->code_size() + task->num_inlined_bytecodes();
+      JVMCI_ONLY(CompilerStatistics* stats = compiler(task->comp_level())->stats();)
       if (is_osr) {
         _t_osr_compilation.add(time);
-        _sum_osr_bytes_compiled += method->code_size() + task->num_inlined_bytecodes();
+        _sum_osr_bytes_compiled += bytes_compiled;
+        JVMCI_ONLY(stats->_osr.update(time, bytes_compiled);)
       } else {
         _t_standard_compilation.add(time);
         _sum_standard_bytes_compiled += method->code_size() + task->num_inlined_bytecodes();
+        JVMCI_ONLY(stats->_standard.update(time, bytes_compiled);)
       }
+      JVMCI_ONLY(stats->_nmethods_size += code->total_size();)
+      JVMCI_ONLY(stats->_nmethods_code_size += code->insts_size();)
     }
 
     if (UsePerfData) {
@@ -2353,17 +2607,101 @@
   }
 }
 
-void CompileBroker::print_times() {
+#if INCLUDE_JVMCI
+void CompileBroker::print_times(AbstractCompiler* comp) {
+  CompilerStatistics* stats = comp->stats();
+  tty->print_cr("  %s {speed: %d bytes/s; standard: %6.3f s, %d bytes, %d methods; osr: %6.3f s, %d bytes, %d methods; nmethods_size: %d bytes; nmethods_code_size: %d bytes}",
+                comp->name(), stats->bytes_per_second(),
+                stats->_standard._time.seconds(), stats->_standard._bytes, stats->_standard._count,
+                stats->_osr._time.seconds(), stats->_osr._bytes, stats->_osr._count,
+                stats->_nmethods_size, stats->_nmethods_code_size);
+  comp->print_timers();
+}
+#endif
+
+void CompileBroker::print_times(bool per_compiler, bool aggregate) {
+#if INCLUDE_JVMCI
+  elapsedTimer standard_compilation;
+  elapsedTimer total_compilation;
+  elapsedTimer osr_compilation;
+
+  int standard_bytes_compiled = 0;
+  int osr_bytes_compiled = 0;
+
+  int standard_compile_count = 0;
+  int osr_compile_count = 0;
+  int total_compile_count = 0;
+
+  int nmethods_size = 0;
+  int nmethods_code_size = 0;
+  bool printedHeader = false;
+
+  for (unsigned int i = 0; i < sizeof(_compilers) / sizeof(AbstractCompiler*); i++) {
+    AbstractCompiler* comp = _compilers[i];
+    if (comp != NULL) {
+      if (per_compiler && aggregate && !printedHeader) {
+        printedHeader = true;
+        tty->cr();
+        tty->print_cr("Individual compiler times (for compiled methods only)");
+        tty->print_cr("------------------------------------------------");
+        tty->cr();
+      }
+      CompilerStatistics* stats = comp->stats();
+
+      standard_compilation.add(stats->_standard._time);
+      osr_compilation.add(stats->_osr._time);
+
+      standard_bytes_compiled += stats->_standard._bytes;
+      osr_bytes_compiled += stats->_osr._bytes;
+
+      standard_compile_count += stats->_standard._count;
+      osr_compile_count += stats->_osr._count;
+
+      nmethods_size += stats->_nmethods_size;
+      nmethods_code_size += stats->_nmethods_code_size;
+
+      if (per_compiler) {
+        print_times(comp);
+      }
+    }
+  }
+  total_compile_count = osr_compile_count + standard_compile_count;
+  total_compilation.add(osr_compilation);
+  total_compilation.add(standard_compilation);
+
+  if (!UseJVMCICompiler) {
+    // In hosted mode, print the JVMCI compiler specific counters manually.
+    JVMCICompiler::print_compilation_timers();
+  }
+#else
+  elapsedTimer standard_compilation = CompileBroker::_t_standard_compilation;
+  elapsedTimer osr_compilation = CompileBroker::_t_osr_compilation;
+  elapsedTimer total_compilation = CompileBroker::_t_total_compilation;
+
+  int standard_bytes_compiled = CompileBroker::_sum_standard_bytes_compiled;
+  int osr_bytes_compiled = CompileBroker::_sum_osr_bytes_compiled;
+
+  int standard_compile_count = CompileBroker::_total_standard_compile_count;
+  int osr_compile_count = CompileBroker::_total_osr_compile_count;
+  int total_compile_count = CompileBroker::_total_compile_count;
+
+  int nmethods_size = CompileBroker::_sum_nmethod_code_size;
+  int nmethods_code_size = CompileBroker::_sum_nmethod_size;
+#endif
+
+  if (!aggregate) {
+    return;
+  }
   tty->cr();
   tty->print_cr("Accumulated compiler times (for compiled methods only)");
   tty->print_cr("------------------------------------------------");
                //0000000000111111111122222222223333333333444444444455555555556666666666
                //0123456789012345678901234567890123456789012345678901234567890123456789
-  tty->print_cr("  Total compilation time   : %6.3f s", CompileBroker::_t_total_compilation.seconds());
+  tty->print_cr("  Total compilation time   : %6.3f s", total_compilation.seconds());
   tty->print_cr("    Standard compilation   : %6.3f s, Average : %2.3f",
-                CompileBroker::_t_standard_compilation.seconds(),
-                CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count);
-  tty->print_cr("    On stack replacement   : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count);
+                standard_compilation.seconds(),
+                standard_compilation.seconds() / standard_compile_count);
+  tty->print_cr("    On stack replacement   : %6.3f s, Average : %2.3f", osr_compilation.seconds(), osr_compilation.seconds() / osr_compile_count);
 
   AbstractCompiler *comp = compiler(CompLevel_simple);
   if (comp != NULL) {
@@ -2374,18 +2712,19 @@
     comp->print_timers();
   }
   tty->cr();
-  tty->print_cr("  Total compiled methods   : %6d methods", CompileBroker::_total_compile_count);
-  tty->print_cr("    Standard compilation   : %6d methods", CompileBroker::_total_standard_compile_count);
-  tty->print_cr("    On stack replacement   : %6d methods", CompileBroker::_total_osr_compile_count);
-  int tcb = CompileBroker::_sum_osr_bytes_compiled + CompileBroker::_sum_standard_bytes_compiled;
+  tty->print_cr("  Total compiled methods   : %6d methods", total_compile_count);
+  tty->print_cr("    Standard compilation   : %6d methods", standard_compile_count);
+  tty->print_cr("    On stack replacement   : %6d methods", osr_compile_count);
+  int tcb = osr_bytes_compiled + standard_bytes_compiled;
   tty->print_cr("  Total compiled bytecodes : %6d bytes", tcb);
-  tty->print_cr("    Standard compilation   : %6d bytes", CompileBroker::_sum_standard_bytes_compiled);
-  tty->print_cr("    On stack replacement   : %6d bytes", CompileBroker::_sum_osr_bytes_compiled);
-  int bps = (int)(tcb / CompileBroker::_t_total_compilation.seconds());
+  tty->print_cr("    Standard compilation   : %6d bytes", standard_bytes_compiled);
+  tty->print_cr("    On stack replacement   : %6d bytes", osr_bytes_compiled);
+  double tcs = total_compilation.seconds();
+  int bps = tcs == 0.0 ? 0 : (int)(tcb / tcs);
   tty->print_cr("  Average compilation speed: %6d bytes/s", bps);
   tty->cr();
-  tty->print_cr("  nmethod code size        : %6d bytes", CompileBroker::_sum_nmethod_code_size);
-  tty->print_cr("  nmethod total size       : %6d bytes", CompileBroker::_sum_nmethod_size);
+  tty->print_cr("  nmethod code size        : %6d bytes", nmethods_code_size);
+  tty->print_cr("  nmethod total size       : %6d bytes", nmethods_size);
 }
 
 // Debugging output for failure
--- a/src/share/vm/compiler/compileBroker.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/compiler/compileBroker.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -28,6 +28,10 @@
 #include "ci/compilerInterface.hpp"
 #include "compiler/abstractCompiler.hpp"
 #include "runtime/perfData.hpp"
+#include "trace/tracing.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciCompiler.hpp"
+#endif
 
 class nmethod;
 class nmethodLocker;
@@ -53,6 +57,11 @@
   bool         _is_complete;
   bool         _is_success;
   bool         _is_blocking;
+#if INCLUDE_JVMCI
+  bool         _has_waiter;
+  // Compiler thread for a blocking JVMCI compilation
+  CompilerThread* _jvmci_compiler_thread;
+#endif
   int          _comp_level;
   int          _num_inlined_bytecodes;
   nmethodLocker* _code_handle;  // holder of eventual result
@@ -84,6 +93,16 @@
   bool         is_complete() const               { return _is_complete; }
   bool         is_blocking() const               { return _is_blocking; }
   bool         is_success() const                { return _is_success; }
+#if INCLUDE_JVMCI
+  bool         has_waiter() const                { return _has_waiter; }
+  void         clear_waiter()                    { _has_waiter = false; }
+  CompilerThread* jvmci_compiler_thread() const  { return _jvmci_compiler_thread; }
+  void         set_jvmci_compiler_thread(CompilerThread* t) {
+    assert(is_blocking(), "must be");
+    assert((t == NULL) != (_jvmci_compiler_thread == NULL), "must be");
+    _jvmci_compiler_thread = t;
+  }
+#endif
 
   nmethodLocker* code_handle() const             { return _code_handle; }
   void         set_code_handle(nmethodLocker* l) { _code_handle = l; }
@@ -137,6 +156,7 @@
 
   void         log_task(xmlStream* log);
   void         log_task_queued();
+  void         log_task_dequeued(const char* comment);
   void         log_task_start(CompileLog* log);
   void         log_task_done(CompileLog* log);
 
@@ -354,8 +374,12 @@
                                           const char*   comment,
                                           bool          blocking);
   static void wait_for_completion(CompileTask* task);
+#if INCLUDE_JVMCI
+  static bool wait_for_jvmci_completion(JVMCICompiler* comp, CompileTask* task, JavaThread* thread);
+#endif
 
   static void invoke_compiler_on_method(CompileTask* task);
+  static void post_compile(CompilerThread* thread, CompileTask* task, EventCompilation& event, bool success, ciEnv* ci_env);
   static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level);
   static void push_jni_handle_block();
   static void pop_jni_handle_block();
@@ -394,7 +418,7 @@
     CompileQueue *q = compile_queue(comp_level);
     return q != NULL ? q->size() : 0;
   }
-  static void compilation_init();
+  static void compilation_init(TRAPS);
   static void init_compiler_thread_log();
   static nmethod* compile_method(methodHandle method,
                                  int osr_bci,
@@ -403,6 +427,9 @@
                                  int hot_count,
                                  const char* comment, Thread* thread);
 
+  // Acquire any needed locks and assign a compile id
+  static uint assign_compile_id_unlocked(Thread* thread, methodHandle method, int osr_bci);
+
   static void compiler_thread_loop();
   static uint get_compilation_id() { return _compilation_id; }
 
@@ -450,8 +477,13 @@
   // Redefine Classes support
   static void mark_on_stack();
 
+#if INCLUDE_JVMCI
+  // Print curent compilation time stats for a given compiler
+  static void print_times(AbstractCompiler* comp);
+#endif
+
   // Print a detailed accounting of compilation time
-  static void print_times();
+  static void print_times(bool per_compiler = true, bool aggregate = true);
 
   // Debugging output for failure
   static void print_last_compile();
--- a/src/share/vm/compiler/compilerOracle.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/compiler/compilerOracle.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -510,7 +510,8 @@
   int match = MethodMatcher::Exact;
   while (name[0] == '*') {
     match |= MethodMatcher::Suffix;
-    strcpy(name, name + 1);
+    // Copy remaining string plus NUL to the beginning
+    memmove(name, name + 1, strlen(name + 1) + 1);
   }
 
   if (strcmp(name, "*") == 0) return MethodMatcher::Any;
--- a/src/share/vm/compiler/disassembler.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/compiler/disassembler.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -496,8 +496,13 @@
 
 void Disassembler::decode(CodeBlob* cb, outputStream* st) {
   if (!load_library())  return;
+  if (cb->is_nmethod()) {
+    decode((nmethod*)cb, st);
+    return;
+  }
   decode_env env(cb, st);
-  env.output()->print_cr("Decoding CodeBlob " PTR_FORMAT, cb);
+  env.output()->print_cr("----------------------------------------------------------------------");
+  env.output()->print_cr("%s at  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", cb->name(), cb->code_begin(), cb->code_end(), ((jlong)(cb->code_end() - cb->code_begin())) * sizeof(unsigned char*));
   env.decode_instructions(cb->code_begin(), cb->code_end());
 }
 
@@ -510,8 +515,7 @@
 void Disassembler::decode(nmethod* nm, outputStream* st) {
   if (!load_library())  return;
   decode_env env(nm, st);
-  env.output()->print_cr("Decoding compiled method " PTR_FORMAT ":", nm);
-  env.output()->print_cr("Code:");
+  env.output()->print_cr("----------------------------------------------------------------------");
 
 #ifdef SHARK
   SharkEntry* entry = (SharkEntry *) nm->code_begin();
@@ -522,6 +526,20 @@
   unsigned char* end = nm->code_end();
 #endif // SHARK
 
+  nm->method()->method_holder()->name()->print_symbol_on(env.output());
+  env.output()->print(".");
+  nm->method()->name()->print_symbol_on(env.output());
+#if INCLUDE_JVMCI
+  {
+    char buffer[O_BUFLEN];
+    char* jvmciName = nm->jvmci_installed_code_name(buffer, O_BUFLEN);
+    if (jvmciName != NULL) {
+      env.output()->print(" (%s)", jvmciName);
+    }
+  }
+#endif
+  env.output()->print_cr("  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", p, end, ((jlong)(end - p)));
+
   // If there has been profiling, print the buckets.
   if (FlatProfiler::bucket_start_for(p) != NULL) {
     unsigned char* p1 = p;
--- a/src/share/vm/compiler/oopMap.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/compiler/oopMap.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -36,6 +36,9 @@
 #ifdef COMPILER1
 #include "c1/c1_Defs.hpp"
 #endif
+#ifdef SPARC
+#include "vmreg_sparc.inline.hpp"
+#endif
 
 // OopMapStream
 
@@ -176,8 +179,6 @@
 
 void OopMap::set_value(VMReg reg) {
   // At this time, we only need value entries in our OopMap when ZapDeadCompiledLocals is active.
-  if (ZapDeadCompiledLocals)
-    set_xxx(reg, OopMapValue::value_value, VMRegImpl::Bad());
 }
 
 
@@ -317,12 +318,12 @@
 static DoNothingClosure do_nothing;
 
 static void add_derived_oop(oop* base, oop* derived) {
-#ifndef TIERED
+#if !defined(TIERED) && !defined(INCLUDE_JVMCI)
   COMPILER1_PRESENT(ShouldNotReachHere();)
-#endif // TIERED
-#ifdef COMPILER2
+#endif // !defined(TIERED) && !defined(INCLUDE_JVMCI)
+#if defined(COMPILER2) || INCLUDE_JVMCI
   DerivedPointerTable::add(derived, base);
-#endif // COMPILER2
+#endif // COMPILER2 || JVMCI
 }
 
 
@@ -388,72 +389,73 @@
       do {
         omv = oms.current();
         oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
-        if ( loc != NULL ) {
-          oop *base_loc    = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
-          oop *derived_loc = loc;
-          oop val = *base_loc;
-          if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
-            // Ignore NULL oops and decoded NULL narrow oops which
-            // equal to Universe::narrow_oop_base when a narrow oop
-            // implicit null check is used in compiled code.
-            // The narrow_oop_base could be NULL or be the address
-            // of the page below heap depending on compressed oops mode.
-          } else
-            derived_oop_fn(base_loc, derived_loc);
+        guarantee(loc != NULL, "missing saved register");
+        oop *base_loc    = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
+        oop *derived_loc = loc;
+        oop val = *base_loc;
+        if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
+          // Ignore NULL oops and decoded NULL narrow oops which
+          // equal to Universe::narrow_oop_base when a narrow oop
+          // implicit null check is used in compiled code.
+          // The narrow_oop_base could be NULL or be the address
+          // of the page below heap depending on compressed oops mode.
+        } else {
+          derived_oop_fn(base_loc, derived_loc);
         }
         oms.next();
       }  while (!oms.is_done());
     }
   }
 
-  // We want coop, value and oop oop_types
-  int mask = OopMapValue::oop_value | OopMapValue::value_value | OopMapValue::narrowoop_value;
+  // We want narrowoop and oop oop_types
+  int mask = OopMapValue::oop_value | OopMapValue::narrowoop_value;
   {
     for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) {
       omv = oms.current();
       oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
-      if ( loc != NULL ) {
-        if ( omv.type() == OopMapValue::oop_value ) {
-          oop val = *loc;
-          if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
-            // Ignore NULL oops and decoded NULL narrow oops which
-            // equal to Universe::narrow_oop_base when a narrow oop
-            // implicit null check is used in compiled code.
-            // The narrow_oop_base could be NULL or be the address
-            // of the page below heap depending on compressed oops mode.
-            continue;
-          }
+      // It should be an error if no location can be found for a
+      // register mentioned as contained an oop of some kind.  Maybe
+      // this was allowed previously because value_value items might
+      // be missing?
+      guarantee(loc != NULL, "missing saved register");
+      if ( omv.type() == OopMapValue::oop_value ) {
+        oop val = *loc;
+        if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
+          // Ignore NULL oops and decoded NULL narrow oops which
+          // equal to Universe::narrow_oop_base when a narrow oop
+          // implicit null check is used in compiled code.
+          // The narrow_oop_base could be NULL or be the address
+          // of the page below heap depending on compressed oops mode.
+          continue;
+        }
 #ifdef ASSERT
-          if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
-             !Universe::heap()->is_in_or_null(*loc)) {
-            tty->print_cr("# Found non oop pointer.  Dumping state at failure");
-            // try to dump out some helpful debugging information
-            trace_codeblob_maps(fr, reg_map);
-            omv.print();
-            tty->print_cr("register r");
-            omv.reg()->print();
-            tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc);
-            // do the real assert.
-            assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer");
-          }
+        if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
+            !Universe::heap()->is_in_or_null(*loc)) {
+          tty->print_cr("# Found non oop pointer.  Dumping state at failure");
+          // try to dump out some helpful debugging information
+          trace_codeblob_maps(fr, reg_map);
+          omv.print();
+          tty->print_cr("register r");
+          omv.reg()->print();
+          tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc);
+          // do the real assert.
+          assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer");
+        }
 #endif // ASSERT
-          oop_fn->do_oop(loc);
-        } else if ( omv.type() == OopMapValue::value_value ) {
-          assert((*loc) == (oop)NULL || !Universe::is_narrow_oop_base(*loc),
-                 "found invalid value pointer");
-          value_fn->do_oop(loc);
-        } else if ( omv.type() == OopMapValue::narrowoop_value ) {
-          narrowOop *nl = (narrowOop*)loc;
+        oop_fn->do_oop(loc);
+      } else if ( omv.type() == OopMapValue::narrowoop_value ) {
+        narrowOop *nl = (narrowOop*)loc;
 #ifndef VM_LITTLE_ENDIAN
-          if (!omv.reg()->is_stack()) {
-            // compressed oops in registers only take up 4 bytes of an
-            // 8 byte register but they are in the wrong part of the
-            // word so adjust loc to point at the right place.
-            nl = (narrowOop*)((address)nl + 4);
-          }
+        VMReg vmReg = omv.reg();
+        // Don't do this on SPARC float registers as they can be individually addressed
+        if (!vmReg->is_stack() SPARC_ONLY(&& !vmReg->is_FloatRegister())) {
+          // compressed oops in registers only take up 4 bytes of an
+          // 8 byte register but they are in the wrong part of the
+          // word so adjust loc to point at the right place.
+          nl = (narrowOop*)((address)nl + 4);
+        }
 #endif
-          oop_fn->do_oop(nl);
-        }
+        oop_fn->do_oop(nl);
       }
     }
   }
@@ -494,7 +496,7 @@
 
   // Check that runtime stubs save all callee-saved registers
 #ifdef COMPILER2
-  assert(cb->is_compiled_by_c1() || !cb->is_runtime_stub() ||
+  assert(cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() ||
          (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),
          "must save all");
 #endif // COMPILER2
@@ -506,15 +508,15 @@
 #ifndef PRODUCT
 
 bool OopMap::has_derived_pointer() const {
-#ifndef TIERED
+#if !defined(TIERED) && !defined(INCLUDE_JVMCI)
   COMPILER1_PRESENT(return false);
 #endif // !TIERED
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
   return oms.is_done();
 #else
   return false;
-#endif // COMPILER2
+#endif // COMPILER2 || JVMCI
 }
 
 #endif //PRODUCT
@@ -528,9 +530,6 @@
   case OopMapValue::oop_value:
     st->print("Oop");
     break;
-  case OopMapValue::value_value:
-    st->print("Value");
-    break;
   case OopMapValue::narrowoop_value:
     st->print("NarrowOop");
     break;
@@ -584,7 +583,7 @@
 
 //------------------------------DerivedPointerTable---------------------------
 
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
 
 class DerivedPointerEntry : public CHeapObj<mtCompiler> {
  private:
@@ -677,4 +676,4 @@
   _active = false;
 }
 
-#endif // COMPILER2
+#endif // COMPILER2 || JVMCI
--- a/src/share/vm/compiler/oopMap.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/compiler/oopMap.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -54,7 +54,7 @@
 
 public:
   // Constants
-  enum { type_bits                = 5,
+  enum { type_bits                = 4,
          register_bits            = BitsPerShort - type_bits };
 
   enum { type_shift               = 0,
@@ -68,10 +68,9 @@
   enum oop_types {              // must fit in type_bits
          unused_value =0,       // powers of 2, for masking OopMapStream
          oop_value = 1,
-         value_value = 2,
-         narrowoop_value = 4,
-         callee_saved_value = 8,
-         derived_oop_value= 16 };
+         narrowoop_value = 2,
+         callee_saved_value = 4,
+         derived_oop_value= 8 };
 
   // Constructors
   OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); }
@@ -96,13 +95,11 @@
 
   // Querying
   bool is_oop()               { return mask_bits(value(), type_mask_in_place) == oop_value; }
-  bool is_value()             { return mask_bits(value(), type_mask_in_place) == value_value; }
   bool is_narrowoop()           { return mask_bits(value(), type_mask_in_place) == narrowoop_value; }
   bool is_callee_saved()      { return mask_bits(value(), type_mask_in_place) == callee_saved_value; }
   bool is_derived_oop()       { return mask_bits(value(), type_mask_in_place) == derived_oop_value; }
 
   void set_oop()              { set_value((value() & register_mask_in_place) | oop_value); }
-  void set_value()            { set_value((value() & register_mask_in_place) | value_value); }
   void set_narrowoop()          { set_value((value() & register_mask_in_place) | narrowoop_value); }
   void set_callee_saved()     { set_value((value() & register_mask_in_place) | callee_saved_value); }
   void set_derived_oop()      { set_value((value() & register_mask_in_place) | derived_oop_value); }
@@ -286,7 +283,7 @@
 // oops, it is filled in with references to all locations that contains a
 // derived oop (assumed to be very few).  When the GC is complete, the derived
 // pointers are updated based on their base pointers new value and an offset.
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
 class DerivedPointerTable : public AllStatic {
   friend class VMStructs;
  private:
@@ -322,6 +319,6 @@
     }
   }
 };
-#endif // COMPILER2
+#endif // COMPILER2 || JVMCI
 
 #endif // SHARE_VM_COMPILER_OOPMAP_HPP
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2547,7 +2547,9 @@
   if (UseAdaptiveSizePolicy) {
     size_policy()->ms_collection_begin();
   }
-  COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact);
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  DerivedPointerTableDeactivate dpt_deact;
+#endif
 
   HandleMark hm;  // Discard invalid handles created during verification
 
@@ -3021,7 +3023,9 @@
   // way with the marking information used by GC.
   NoRefDiscovery no_discovery(ref_processor());
 
-  COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  DerivedPointerTableDeactivate dpt_deact;
+#endif
 
   // Clear any marks from a previous round
   verification_mark_bm()->clear_all();
@@ -3731,7 +3735,9 @@
   }
 
   {
-    COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
+#if defined(COMPILER2) || INCLUDE_JVMCI
+    DerivedPointerTableDeactivate dpt_deact;
+#endif
     if (CMSParallelInitialMarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
       // The parallel version.
       FlexibleWorkGang* workers = gch->workers();
@@ -5121,7 +5127,9 @@
     }
 
     {
-      COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
+#if defined(COMPILER2) || INCLUDE_JVMCI
+      DerivedPointerTableDeactivate dpt_deact;
+#endif
 
       // Note on the role of the mod union table:
       // Since the marker in "markFromRoots" marks concurrently with
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1321,7 +1321,9 @@
       check_bitmaps("Full GC Start");
       pre_full_gc_dump(gc_timer);
 
-      COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+      DerivedPointerTable::clear();
+#endif
 
       // Disable discovery and empty the discovered lists
       // for the CM ref processor.
@@ -1381,7 +1383,9 @@
       // not been removed from the discovered lists.
       ref_processor_stw()->enqueue_discovered_references();
 
-      COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+      DerivedPointerTable::update_pointers();
+#endif
 
       MemoryService::track_memory_usage();
 
@@ -3600,8 +3604,9 @@
   // FIXME: what is this about?
   // I'm ignoring the "fill_newgen()" call if "alloc_event_enabled"
   // is set.
-  COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(),
-                        "derived pointer present"));
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  assert(DerivedPointerTable::is_empty(), "derived pointer present");
+#endif
   // always_do_update_barrier = true;
 
   resize_all_tlabs();
@@ -4043,7 +4048,9 @@
       verify_before_gc();
       check_bitmaps("GC Start");
 
-      COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+      DerivedPointerTable::clear();
+#endif
 
       // Please see comment in g1CollectedHeap.hpp and
       // G1CollectedHeap::ref_processing_init() to see how
@@ -5877,7 +5884,9 @@
   enqueue_discovered_references(n_workers);
 
   redirty_logged_cards();
-  COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  DerivedPointerTable::update_pointers();
+#endif
 }
 
 void G1CollectedHeap::free_region(HeapRegion* hr,
@@ -6831,6 +6840,7 @@
     } else {
       ShouldNotReachHere();
     }
+    hr->rem_set()->verify();
     return false;
   }
 
--- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -90,8 +90,10 @@
 
   mark_sweep_phase2();
 
+#if defined(COMPILER2) || INCLUDE_JVMCI
   // Don't add any more derived pointers during phase3
-  COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+  DerivedPointerTable::set_active(false);
+#endif
 
   mark_sweep_phase3();
 
@@ -172,7 +174,9 @@
 
   if (VerifyDuringGC) {
     HandleMark hm;  // handle scope
-    COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact);
+#if defined(COMPILER2) || INCLUDE_JVMCI
+    DerivedPointerTableDeactivate dpt_deact;
+#endif
     Universe::heap()->prepare_for_verify();
     // Note: we can verify only the heap here. When an object is
     // marked, the previous value of the mark word (including
--- a/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -138,6 +138,13 @@
   OopClosure* const weak_roots = &buf_scan_non_heap_weak_roots;
   OopClosure* const strong_roots = &buf_scan_non_heap_roots;
 
+  bool trace_codecache = false;
+#if INCLUDE_JVMCI
+  bool during_im = _g1h->g1_policy()->during_initial_mark_pause();
+  // Without eager nmethod unloading, we need to treat all oops in code cache as strong during the initial mark
+  trace_codecache = during_im && !ClassUnloadingWithConcurrentMark;
+#endif
+
   // CodeBlobClosures are not interoperable with BufferingOopClosures
   G1CodeBlobClosure root_code_blobs(scan_non_heap_roots);
 
@@ -145,7 +152,7 @@
                      trace_metadata ? scan_strong_clds : NULL,
                      scan_strong_clds,
                      trace_metadata ? NULL : scan_weak_clds,
-                     &root_code_blobs,
+                     trace_codecache ? NULL : &root_code_blobs,
                      phase_times,
                      worker_i);
 
@@ -157,6 +164,12 @@
 
   process_vm_roots(strong_roots, weak_roots, phase_times, worker_i);
 
+#if INCLUDE_JVMCI
+  if (trace_codecache && !_process_strong_tasks.is_task_claimed(G1RP_PS_CodeCache_oops_do)) {
+    CodeCache::blobs_do(&root_code_blobs);
+  }
+#endif
+
   {
     // Now the CM ref_processor roots.
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CMRefRoots, worker_i);
--- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -255,3 +255,52 @@
     }
   }
 }
+
+void G1SATBCardTableModRefBS::write_ref_nmethod_post(oop* dst, nmethod* nm) {
+  oop obj = oopDesc::load_heap_oop(dst);
+  if (obj != NULL) {
+    G1CollectedHeap* g1h = G1CollectedHeap::heap();
+    HeapRegion* hr = g1h->heap_region_containing(obj);
+    hr->add_strong_code_root(nm);
+  }
+}
+
+class G1EnsureLastRefToRegion : public OopClosure {
+  G1CollectedHeap* _g1h;
+  HeapRegion* _hr;
+  oop* _dst;
+
+  bool _value;
+public:
+  G1EnsureLastRefToRegion(G1CollectedHeap* g1h, HeapRegion* hr, oop* dst) :
+    _g1h(g1h), _hr(hr), _dst(dst), _value(true) {}
+
+  void do_oop(oop* p) {
+    if (_value && p != _dst) {
+      oop obj = oopDesc::load_heap_oop(p);
+      if (obj != NULL) {
+        HeapRegion* hr = _g1h->heap_region_containing(obj);
+        if (hr == _hr) {
+          // Another reference to the same region.
+          _value = false;
+        }
+      }
+    }
+  }
+  void do_oop(narrowOop* p) { ShouldNotReachHere(); }
+  bool value() const        { return _value;  }
+};
+
+void G1SATBCardTableModRefBS::write_ref_nmethod_pre(oop* dst, nmethod* nm) {
+  oop obj = oopDesc::load_heap_oop(dst);
+  if (obj != NULL) {
+    G1CollectedHeap* g1h = G1CollectedHeap::heap();
+    HeapRegion* hr = g1h->heap_region_containing(obj);
+    G1EnsureLastRefToRegion ensure_last_ref(g1h, hr, dst);
+    nm->oops_do(&ensure_last_ref);
+    if (ensure_last_ref.value()) {
+      // Last reference to this region, remove the nmethod from the rset.
+      hr->remove_strong_code_root(nm);
+    }
+  }
+}
--- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -126,6 +126,9 @@
     jbyte val = _byte_map[card_index];
     return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
   }
+  virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm);
+  virtual void write_ref_nmethod_post(oop* dst, nmethod* nm);
+
 };
 
 class G1SATBCardTableLoggingModRefBSChangedListener : public G1MappingChangedListener {
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -875,6 +875,22 @@
   guarantee(G1RSetSparseRegionEntries > 0 && G1RSetRegionEntries > 0 , "Sanity");
 }
 
+class VerifyNoZombies : public CodeBlobClosure {
+private:
+  HeapRegionRemSet* _rem_set;
+public:
+  VerifyNoZombies(HeapRegionRemSet* rem_set) : _rem_set(rem_set) {}
+  void do_code_blob(CodeBlob* blob) {
+    guarantee(blob->as_nmethod_or_null()->is_alive(), err_msg("zombie nmethod %d " INTPTR_FORMAT " " INTPTR_FORMAT " in remembered set",
+              blob->as_nmethod_or_null()->compile_id(), blob, _rem_set));
+  }
+};
+
+void HeapRegionRemSet::verify() {
+  VerifyNoZombies blk(this);
+  _code_roots.nmethods_do(&blk);
+}
+
 bool HeapRegionRemSet::claim_iter() {
   if (_iter_state != Unclaimed) return false;
   jint res = Atomic::cmpxchg(Claimed, (jint*)(&_iter_state), Unclaimed);
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -272,6 +272,8 @@
   static uint num_par_rem_sets();
   static void setup_remset_size();
 
+  void verify();
+
   HeapRegion* hr() const {
     return _other_regions.hr();
   }
--- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -193,7 +193,9 @@
 
     allocate_stacks();
 
-    COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+    DerivedPointerTable::clear();
+#endif
 
     ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
     ref_processor()->setup_policy(clear_all_softrefs);
@@ -202,9 +204,11 @@
 
     mark_sweep_phase2();
 
+#if defined(COMPILER2) || INCLUDE_JVMCI
     // Don't add any more derived pointers during phase3
-    COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
-    COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+    assert(DerivedPointerTable::is_active(), "Sanity");
+    DerivedPointerTable::set_active(false);
+#endif
 
     mark_sweep_phase3();
 
@@ -253,7 +257,9 @@
     CodeCache::gc_epilogue();
     JvmtiExport::gc_epilogue();
 
-    COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+    DerivedPointerTable::update_pointers();
+#endif
 
     ref_processor()->enqueue_discovered_references(NULL);
 
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1068,7 +1068,9 @@
   CodeCache::gc_epilogue();
   JvmtiExport::gc_epilogue();
 
-  COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  DerivedPointerTable::update_pointers();
+#endif
 
   ref_processor()->enqueue_discovered_references(NULL);
 
@@ -2067,7 +2069,9 @@
     CodeCache::gc_prologue();
     Threads::gc_prologue();
 
-    COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+    DerivedPointerTable::clear();
+#endif
 
     ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
     ref_processor()->setup_policy(maximum_heap_compaction);
@@ -2081,8 +2085,10 @@
       && gc_cause == GCCause::_java_lang_system_gc;
     summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
 
-    COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
-    COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+#if defined(COMPILER2) || INCLUDE_JVMCI
+    assert(DerivedPointerTable::is_active(), "Sanity");
+    DerivedPointerTable::set_active(false);
+#endif
 
     // adjust_roots() updates Universe::_intArrayKlassObj which is
     // needed by the compaction for filling holes in the dense prefix.
--- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -359,7 +359,9 @@
     }
     save_to_space_top_before_gc();
 
-    COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+    DerivedPointerTable::clear();
+#endif
 
     reference_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
     reference_processor()->setup_policy(false);
@@ -632,7 +634,9 @@
       assert(young_gen->to_space()->is_empty(), "to space should be empty now");
     }
 
-    COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+    DerivedPointerTable::update_pointers();
+#endif
 
     NOT_PRODUCT(reference_processor()->verify_no_references_recorded());
 
--- a/src/share/vm/gc_interface/collectedHeap.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_interface/collectedHeap.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -214,7 +214,7 @@
 void CollectedHeap::pre_initialize() {
   // Used for ReduceInitialCardMarks (when COMPILER2 is used);
   // otherwise remains unused.
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   _defer_initial_card_mark =    ReduceInitialCardMarks && can_elide_tlab_store_barriers()
                              && (DeferInitialCardMark || card_mark_must_follow_store());
 #else
@@ -524,7 +524,7 @@
          " to threads list is doomed to failure!");
   for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
      if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
      // The deferred store barriers must all have been flushed to the
      // card-table (or other remembered set structure) before GC starts
      // processing the card-table (or other remembered set).
--- a/src/share/vm/gc_interface/collectedHeap.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/gc_interface/collectedHeap.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -94,7 +94,8 @@
 
   GCHeapLog* _gc_heap_log;
 
-  // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2 is being used
+  // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2
+  // or INCLUDE_JVMCI is being used
   bool _defer_initial_card_mark;
 
  protected:
--- a/src/share/vm/interpreter/interpreter.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/interpreter/interpreter.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -409,7 +409,7 @@
 address AbstractInterpreter::deopt_reexecute_entry(Method* method, address bcp) {
   assert(method->contains(bcp), "just checkin'");
   Bytecodes::Code code   = Bytecodes::java_code_at(method, bcp);
-#ifdef COMPILER1
+#if defined(COMPILER1) || INCLUDE_JVMCI
   if(code == Bytecodes::_athrow ) {
     return Interpreter::rethrow_exception_entry();
   }
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -479,6 +479,17 @@
     }
   } while (should_repeat == true);
 
+#if INCLUDE_JVMCI
+  if (EnableJVMCI && h_method->method_data() != NULL) {
+    ResourceMark rm(thread);
+    ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci, NULL);
+    if (pdata != NULL && pdata->is_BitData()) {
+      BitData* bit_data = (BitData*) pdata;
+      bit_data->set_exception_seen();
+    }
+  }
+#endif
+
   // notify JVMTI of an exception throw; JVMTI will detect if this is a first
   // time throw or a stack unwinding throw and accordingly notify the debugger
   if (JvmtiExport::can_post_on_exceptions()) {
--- a/src/share/vm/interpreter/linkResolver.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/interpreter/linkResolver.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -107,30 +107,7 @@
   _resolved_appendix = Handle();
   DEBUG_ONLY(verify());  // verify before making side effects
 
-  if (CompilationPolicy::must_be_compiled(selected_method)) {
-    // This path is unusual, mostly used by the '-Xcomp' stress test mode.
-
-    // Note: with several active threads, the must_be_compiled may be true
-    //       while can_be_compiled is false; remove assert
-    // assert(CompilationPolicy::can_be_compiled(selected_method), "cannot compile");
-    if (THREAD->is_Compiler_thread()) {
-      // don't force compilation, resolve was on behalf of compiler
-      return;
-    }
-    if (selected_method->method_holder()->is_not_initialized()) {
-      // 'is_not_initialized' means not only '!is_initialized', but also that
-      // initialization has not been started yet ('!being_initialized')
-      // Do not force compilation of methods in uninitialized classes.
-      // Note that doing this would throw an assert later,
-      // in CompileBroker::compile_method.
-      // We sometimes use the link resolver to do reflective lookups
-      // even before classes are initialized.
-      return;
-    }
-    CompileBroker::compile_method(selected_method, InvocationEntryBci,
-                                  CompilationPolicy::policy()->initial_compile_level(),
-                                  methodHandle(), 0, "must_be_compiled", CHECK);
-  }
+  CompilationPolicy::compile_if_required(selected_method, THREAD);
 }
 
 // utility query for unreflecting a method
@@ -386,7 +363,7 @@
         return;
       }
     } else if (iid == vmIntrinsics::_invokeGeneric
-               && !THREAD->is_Compiler_thread()
+               && THREAD->can_call_java()
                && appendix_result_or_null != NULL) {
       // This is a method with type-checking semantics.
       // We will ask Java code to spin an adapter method for it.
@@ -759,6 +736,10 @@
 }
 
 void LinkResolver::resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
+  resolve_field_access(result, pool, index, byte, true, true, THREAD);
+}
+
+void LinkResolver::resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_access, bool initialize_class, TRAPS) {
   // Load these early in case the resolve of the containing klass fails
   Symbol* field = pool->name_ref_at(index);
   Symbol* sig   = pool->signature_ref_at(index);
@@ -768,7 +749,7 @@
   resolve_klass(resolved_klass, pool, index, CHECK);
 
   KlassHandle  current_klass(THREAD, pool->pool_holder());
-  resolve_field(result, resolved_klass, field, sig, current_klass, byte, true, true, CHECK);
+  resolve_field(result, resolved_klass, field, sig, current_klass, byte, check_access, initialize_class, CHECK);
 }
 
 void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass, Symbol* field, Symbol* sig,
--- a/src/share/vm/interpreter/linkResolver.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/interpreter/linkResolver.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -125,7 +125,9 @@
 
  private:
   static void lookup_method_in_klasses          (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS);
+ JVMCI_ONLY(public:) // Needed for CompilerToVM.resolveMethod()
   static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
+ JVMCI_ONLY(private:)
   static void lookup_method_in_interfaces       (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
   static void lookup_polymorphic_method         (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
                                                  KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
@@ -139,8 +141,10 @@
 
   static void linktime_resolve_static_method    (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
   static void linktime_resolve_special_method   (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+ JVMCI_ONLY(public:) // Needed for CompilerToVM.resolveMethod()
   static void linktime_resolve_virtual_method   (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS);
   static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+ JVMCI_ONLY(private:)
 
   static void runtime_resolve_special_method    (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS);
   static void runtime_resolve_virtual_method    (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
@@ -159,6 +163,7 @@
 
   // runtime/static resolving for fields
   static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
+  static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_access, bool initialize_class, TRAPS);
   static void resolve_field(fieldDescriptor& result, KlassHandle resolved_klass, Symbol* field_name, Symbol* field_signature,
                             KlassHandle current_klass, Bytecodes::Code access_kind, bool check_access, bool initialize_class, TRAPS);
 
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -298,16 +298,16 @@
     for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) {
       Interpreter::_deopt_entry[i] =
         EntryPoint(
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(atos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(ltos, i),
-          generate_deopt_entry_for(ftos, i),
-          generate_deopt_entry_for(dtos, i),
-          generate_deopt_entry_for(vtos, i)
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(atos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(ltos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(ftos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(dtos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(vtos, i)
         );
     }
   }
--- a/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -55,7 +55,6 @@
   address generate_continuation_for(TosState state);
   address generate_return_entry_for(TosState state, int step, size_t index_size);
   address generate_earlyret_entry_for(TosState state);
-  address generate_deopt_entry_for(TosState state, int step);
   address generate_safept_entry_for(TosState state, address runtime_entry);
   void    generate_throw_exception();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1115 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "code/compiledIC.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/disassembler.hpp"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+
+#ifdef TARGET_ARCH_x86
+# include "vmreg_x86.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "vmreg_sparc.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "vmreg_zero.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "vmreg_arm.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "vmreg_ppc.inline.hpp"
+#endif
+
+
+// frequently used constants
+// Allocate them with new so they are never destroyed (otherwise, a
+// forced exit could destroy these objects while they are still in
+// use).
+ConstantOopWriteValue* CodeInstaller::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
+ConstantIntValue*      CodeInstaller::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
+ConstantIntValue*      CodeInstaller::_int_0_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(0);
+ConstantIntValue*      CodeInstaller::_int_1_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
+ConstantIntValue*      CodeInstaller::_int_2_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
+LocationValue*         CodeInstaller::_illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
+
+Method* getMethodFromHotSpotMethod(oop hotspot_method) {
+  assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass()), "sanity");
+  return CompilerToVM::asMethod(hotspot_method);
+}
+
+VMReg getVMRegFromLocation(Handle location, int total_frame_size, TRAPS) {
+  if (location.is_null()) {
+    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+  }
+
+  Handle reg = code_Location::reg(location);
+  jint offset = code_Location::offset(location);
+
+  if (reg.not_null()) {
+    // register
+    jint number = code_Register::number(reg);
+    VMReg vmReg = CodeInstaller::get_hotspot_reg(number, CHECK_NULL);
+    if (offset % 4 == 0) {
+      return vmReg->next(offset / 4);
+    } else {
+      JVMCI_ERROR_NULL("unaligned subregister offset %d in oop map", offset);
+    }
+  } else {
+    // stack slot
+    if (offset % 4 == 0) {
+      VMReg vmReg = VMRegImpl::stack2reg(offset / 4);
+      if (!OopMapValue::legal_vm_reg_name(vmReg)) {
+        // This restriction only applies to VMRegs that are used in OopMap but
+        // since that's the only use of VMRegs it's simplest to put this test
+        // here.  This test should also be equivalent legal_vm_reg_name but JVMCI
+        // clients can use max_oop_map_stack_stack_offset to detect this problem
+        // directly.  The asserts just ensure that the tests are in agreement.
+        assert(offset > CompilerToVM::Data::max_oop_map_stack_offset(), "illegal VMReg");
+        JVMCI_ERROR_NULL("stack offset %d is too large to be encoded in OopMap (max %d)",
+                         offset, CompilerToVM::Data::max_oop_map_stack_offset());
+      }
+      assert(OopMapValue::legal_vm_reg_name(vmReg), "illegal VMReg");
+      return vmReg;
+    } else {
+      JVMCI_ERROR_NULL("unaligned stack offset %d in oop map", offset);
+    }
+  }
+}
+
+// creates a HotSpot oop map out of the byte arrays provided by DebugInfo
+OopMap* CodeInstaller::create_oop_map(Handle debug_info, TRAPS) {
+  Handle reference_map = DebugInfo::referenceMap(debug_info);
+  if (reference_map.is_null()) {
+    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+  }
+  if (!reference_map->is_a(HotSpotReferenceMap::klass())) {
+    JVMCI_ERROR_NULL("unknown reference map: %s", reference_map->klass()->signature_name());
+  }
+  if (HotSpotReferenceMap::maxRegisterSize(reference_map) > 16) {
+    _has_wide_vector = true;
+  }
+  OopMap* map = new OopMap(_total_frame_size, _parameter_count);
+  objArrayHandle objects = HotSpotReferenceMap::objects(reference_map);
+  objArrayHandle derivedBase = HotSpotReferenceMap::derivedBase(reference_map);
+  typeArrayHandle sizeInBytes = HotSpotReferenceMap::sizeInBytes(reference_map);
+  if (objects.is_null() || derivedBase.is_null() || sizeInBytes.is_null()) {
+    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+  }
+  if (objects->length() != derivedBase->length() || objects->length() != sizeInBytes->length()) {
+    JVMCI_ERROR_NULL("arrays in reference map have different sizes: %d %d %d", objects->length(), derivedBase->length(), sizeInBytes->length());
+  }
+  for (int i = 0; i < objects->length(); i++) {
+    Handle location = objects->obj_at(i);
+    Handle baseLocation = derivedBase->obj_at(i);
+    int bytes = sizeInBytes->int_at(i);
+
+    VMReg vmReg = getVMRegFromLocation(location, _total_frame_size, CHECK_NULL);
+    if (baseLocation.not_null()) {
+      // derived oop
+#ifdef _LP64
+      if (bytes == 8) {
+#else
+      if (bytes == 4) {
+#endif
+        VMReg baseReg = getVMRegFromLocation(baseLocation, _total_frame_size, CHECK_NULL);
+        map->set_derived_oop(vmReg, baseReg);
+      } else {
+        JVMCI_ERROR_NULL("invalid derived oop size in ReferenceMap: %d", bytes);
+      }
+#ifdef _LP64
+    } else if (bytes == 8) {
+      // wide oop
+      map->set_oop(vmReg);
+    } else if (bytes == 4) {
+      // narrow oop
+      map->set_narrowoop(vmReg);
+#else
+    } else if (bytes == 4) {
+      map->set_oop(vmReg);
+#endif
+    } else {
+      JVMCI_ERROR_NULL("invalid oop size in ReferenceMap: %d", bytes);
+    }
+  }
+
+  Handle callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info);
+  if (callee_save_info.not_null()) {
+    objArrayHandle registers = RegisterSaveLayout::registers(callee_save_info);
+    typeArrayHandle slots = RegisterSaveLayout::slots(callee_save_info);
+    for (jint i = 0; i < slots->length(); i++) {
+      Handle jvmci_reg = registers->obj_at(i);
+      jint jvmci_reg_number = code_Register::number(jvmci_reg);
+      VMReg hotspot_reg = CodeInstaller::get_hotspot_reg(jvmci_reg_number, CHECK_NULL);
+      // HotSpot stack slots are 4 bytes
+      jint jvmci_slot = slots->int_at(i);
+      jint hotspot_slot = jvmci_slot * VMRegImpl::slots_per_word;
+      VMReg hotspot_slot_as_reg = VMRegImpl::stack2reg(hotspot_slot);
+      map->set_callee_saved(hotspot_slot_as_reg, hotspot_reg);
+#ifdef _LP64
+      // (copied from generate_oop_map() in c1_Runtime1_x86.cpp)
+      VMReg hotspot_slot_hi_as_reg = VMRegImpl::stack2reg(hotspot_slot + 1);
+      map->set_callee_saved(hotspot_slot_hi_as_reg, hotspot_reg->next());
+#endif
+    }
+  }
+  return map;
+}
+
+  void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
+  /*
+   * This method needs to return a raw (untyped) pointer, since the value of a pointer to the base
+   * class is in general not equal to the pointer of the subclass. When patching metaspace pointers,
+   * the compiler expects a direct pointer to the subclass (Klass* or Method*), not a pointer to the
+   * base class (Metadata* or MetaspaceObj*).
+   */
+  oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
+  if (obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) {
+    Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
+    assert(!HotSpotMetaspaceConstantImpl::compressed(constant), err_msg("unexpected compressed klass pointer %s @ " INTPTR_FORMAT, klass->name()->as_C_string(), p2i(klass)));
+    int index = _oop_recorder->find_index(klass);
+    section->relocate(dest, metadata_Relocation::spec(index));
+    TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string());
+    return klass;
+  } else if (obj->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+    Method* method = (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(obj);
+    assert(!HotSpotMetaspaceConstantImpl::compressed(constant), err_msg("unexpected compressed method pointer %s @ " INTPTR_FORMAT, method->name()->as_C_string(), p2i(method)));
+    int index = _oop_recorder->find_index(method);
+    section->relocate(dest, metadata_Relocation::spec(index));
+    TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), method->name()->as_C_string());
+    return method;
+  } else {
+    JVMCI_ERROR_NULL("unexpected metadata reference for constant of type %s", obj->klass()->signature_name());
+  }
+}
+
+#ifdef _LP64
+narrowKlass CodeInstaller::record_narrow_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
+  oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
+  assert(HotSpotMetaspaceConstantImpl::compressed(constant), err_msg("unexpected uncompressed pointer"));
+
+  if (!obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) {
+    JVMCI_ERROR_0("unexpected compressed pointer of type %s", obj->klass()->signature_name());
+  }
+
+  Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
+  int index = _oop_recorder->find_index(klass);
+  section->relocate(dest, metadata_Relocation::spec(index));
+  TRACE_jvmci_3("narrowKlass[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string());
+  return Klass::encode_klass(klass);
+}
+#endif
+
+Location::Type CodeInstaller::get_oop_type(Handle value) {
+  Handle valueKind = Value::valueKind(value);
+  Handle platformKind = ValueKind::platformKind(valueKind);
+
+  if (platformKind == word_kind()) {
+    return Location::oop;
+  } else {
+    return Location::narrowoop;
+  }
+}
+
+ScopeValue* CodeInstaller::get_scope_value(Handle value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, TRAPS) {
+  second = NULL;
+  if (value.is_null()) {
+    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+  } else if (value == Value::ILLEGAL()) {
+    if (type != T_ILLEGAL) {
+      JVMCI_ERROR_NULL("unexpected illegal value, expected %s", basictype_to_str(type));
+    }
+    return _illegal_value;
+  } else if (value->is_a(RegisterValue::klass())) {
+    Handle reg = RegisterValue::reg(value);
+    jint number = code_Register::number(reg);
+    VMReg hotspotRegister = get_hotspot_reg(number, CHECK_NULL);
+    if (is_general_purpose_reg(hotspotRegister)) {
+      Location::Type locationType;
+      if (type == T_OBJECT) {
+        locationType = get_oop_type(value);
+      } else if (type == T_LONG) {
+        locationType = Location::lng;
+      } else if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) {
+        locationType = Location::int_in_long;
+      } else {
+        JVMCI_ERROR_NULL("unexpected type %s in cpu register", basictype_to_str(type));
+      }
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, hotspotRegister));
+      if (type == T_LONG) {
+        second = value;
+      }
+      return value;
+    } else {
+      Location::Type locationType;
+      if (type == T_FLOAT) {
+        // this seems weird, but the same value is used in c1_LinearScan
+        locationType = Location::normal;
+      } else if (type == T_DOUBLE) {
+        locationType = Location::dbl;
+      } else {
+        JVMCI_ERROR_NULL("unexpected type %s in floating point register", basictype_to_str(type));
+      }
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, hotspotRegister));
+      if (type == T_DOUBLE) {
+        second = value;
+      }
+      return value;
+    }
+  } else if (value->is_a(StackSlot::klass())) {
+    jint offset = StackSlot::offset(value);
+    if (StackSlot::addFrameSize(value)) {
+      offset += _total_frame_size;
+    }
+
+    Location::Type locationType;
+    if (type == T_OBJECT) {
+      locationType = get_oop_type(value);
+    } else if (type == T_LONG) {
+      locationType = Location::lng;
+    } else if (type == T_DOUBLE) {
+      locationType = Location::dbl;
+    } else if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) {
+      locationType = Location::normal;
+    } else {
+      JVMCI_ERROR_NULL("unexpected type %s in stack slot", basictype_to_str(type));
+    }
+    ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset));
+    if (type == T_DOUBLE || type == T_LONG) {
+      second = value;
+    }
+    return value;
+  } else if (value->is_a(JavaConstant::klass())) {
+    if (value->is_a(PrimitiveConstant::klass())) {
+      if (value->is_a(RawConstant::klass())) {
+        jlong prim = PrimitiveConstant::primitive(value);
+        return new ConstantLongValue(prim);
+      } else {
+        BasicType constantType = JVMCIRuntime::kindToBasicType(PrimitiveConstant::kind(value), CHECK_NULL);
+        if (type != constantType) {
+          JVMCI_ERROR_NULL("primitive constant type doesn't match, expected %s but got %s", basictype_to_str(type), basictype_to_str(constantType));
+        }
+        if (type == T_INT || type == T_FLOAT) {
+          jint prim = (jint)PrimitiveConstant::primitive(value);
+          switch (prim) {
+            case -1: return _int_m1_scope_value;
+            case  0: return _int_0_scope_value;
+            case  1: return _int_1_scope_value;
+            case  2: return _int_2_scope_value;
+            default: return new ConstantIntValue(prim);
+          }
+        } else if (type == T_LONG || type == T_DOUBLE) {
+          jlong prim = PrimitiveConstant::primitive(value);
+          second = _int_1_scope_value;
+          return new ConstantLongValue(prim);
+        } else {
+          JVMCI_ERROR_NULL("unexpected primitive constant type %s", basictype_to_str(type));
+        }
+      }
+    } else if (value->is_a(NullConstant::klass()) || value->is_a(HotSpotCompressedNullConstant::klass())) {
+      if (type == T_OBJECT) {
+        return _oop_null_scope_value;
+      } else {
+        JVMCI_ERROR_NULL("unexpected null constant, expected %s", basictype_to_str(type));
+      }
+    } else if (value->is_a(HotSpotObjectConstantImpl::klass())) {
+      if (type == T_OBJECT) {
+        oop obj = HotSpotObjectConstantImpl::object(value);
+        if (obj == NULL) {
+          JVMCI_ERROR_NULL("null value must be in NullConstant");
+        }
+        return new ConstantOopWriteValue(JNIHandles::make_local(obj));
+      } else {
+        JVMCI_ERROR_NULL("unexpected object constant, expected %s", basictype_to_str(type));
+      }
+    }
+  } else if (value->is_a(VirtualObject::klass())) {
+    if (type == T_OBJECT) {
+      int id = VirtualObject::id(value);
+      if (0 <= id && id < objects->length()) {
+        ScopeValue* object = objects->at(id);
+        if (object != NULL) {
+          return object;
+        }
+      }
+      JVMCI_ERROR_NULL("unknown virtual object id %d", id);
+    } else {
+      JVMCI_ERROR_NULL("unexpected virtual object, expected %s", basictype_to_str(type));
+    }
+  }
+
+  JVMCI_ERROR_NULL("unexpected value in scope: %s", value->klass()->signature_name())
+}
+
+void CodeInstaller::record_object_value(ObjectValue* sv, Handle value, GrowableArray<ScopeValue*>* objects, TRAPS) {
+  Handle type = VirtualObject::type(value);
+  int id = VirtualObject::id(value);
+  oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type);
+  Klass* klass = java_lang_Class::as_Klass(javaMirror);
+  bool isLongArray = klass == Universe::longArrayKlassObj();
+
+  objArrayHandle values = VirtualObject::values(value);
+  objArrayHandle slotKinds = VirtualObject::slotKinds(value);
+  for (jint i = 0; i < values->length(); i++) {
+    ScopeValue* cur_second = NULL;
+    Handle object = values->obj_at(i);
+    BasicType type = JVMCIRuntime::kindToBasicType(slotKinds->obj_at(i), CHECK);
+    ScopeValue* value = get_scope_value(object, type, objects, cur_second, CHECK);
+
+    if (isLongArray && cur_second == NULL) {
+      // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations.
+      // add an int 0 constant
+      cur_second = _int_0_scope_value;
+    }
+
+    if (cur_second != NULL) {
+      sv->field_values()->append(cur_second);
+    }
+    assert(value != NULL, "missing value");
+    sv->field_values()->append(value);
+  }
+}
+
+MonitorValue* CodeInstaller::get_monitor_value(Handle value, GrowableArray<ScopeValue*>* objects, TRAPS) {
+  if (value.is_null()) {
+    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+  }
+  if (!value->is_a(StackLockValue::klass())) {
+    JVMCI_ERROR_NULL("Monitors must be of type StackLockValue, got %s", value->klass()->signature_name());
+  }
+
+  ScopeValue* second = NULL;
+  ScopeValue* owner_value = get_scope_value(StackLockValue::owner(value), T_OBJECT, objects, second, CHECK_NULL);
+  assert(second == NULL, "monitor cannot occupy two stack slots");
+
+  ScopeValue* lock_data_value = get_scope_value(StackLockValue::slot(value), T_LONG, objects, second, CHECK_NULL);
+  assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots");
+  assert(lock_data_value->is_location(), "invalid monitor location");
+  Location lock_data_loc = ((LocationValue*)lock_data_value)->location();
+
+  bool eliminated = false;
+  if (StackLockValue::eliminated(value)) {
+    eliminated = true;
+  }
+
+  return new MonitorValue(owner_value, lock_data_loc, eliminated);
+}
+
+void CodeInstaller::initialize_dependencies(oop compiled_code, TRAPS) {
+  JavaThread* thread = JavaThread::current();
+  CompilerThread* compilerThread = thread->is_Compiler_thread() ? thread->as_CompilerThread() : NULL;
+  _oop_recorder = new OopRecorder(&_arena, true);
+  _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL);
+  objArrayHandle assumptions = HotSpotCompiledCode::assumptions(compiled_code);
+  if (!assumptions.is_null()) {
+    int length = assumptions->length();
+    for (int i = 0; i < length; ++i) {
+      Handle assumption = assumptions->obj_at(i);
+      if (!assumption.is_null()) {
+        if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) {
+          assumption_NoFinalizableSubclass(assumption);
+        } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) {
+          assumption_ConcreteSubtype(assumption);
+        } else if (assumption->klass() == Assumptions_LeafType::klass()) {
+          assumption_LeafType(assumption);
+        } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) {
+          assumption_ConcreteMethod(assumption);
+        } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) {
+          assumption_CallSiteTargetValue(assumption);
+        } else {
+          JVMCI_ERROR("unexpected Assumption subclass %s", assumption->klass()->signature_name());
+        }
+      }
+    }
+  }
+  if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
+    objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code);
+    if (!methods.is_null()) {
+      int length = methods->length();
+      for (int i = 0; i < length; ++i) {
+        Handle method_handle = methods->obj_at(i);
+        methodHandle method = getMethodFromHotSpotMethod(method_handle());
+        _dependencies->assert_evol_method(method());
+      }
+    }
+  }
+}
+
+// constructor used to create a method
+JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Handle target, Handle compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log, TRAPS) {
+  CodeBuffer buffer("JVMCI Compiler CodeBuffer");
+  jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
+  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), CHECK_OK);
+
+  // Get instructions and constants CodeSections early because we need it.
+  _instructions = buffer.insts();
+  _constants = buffer.consts();
+
+  initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
+  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, CHECK_OK);
+  if (result != JVMCIEnv::ok) {
+    return result;
+  }
+
+  int stack_slots = _total_frame_size / HeapWordSize; // conversion to words
+
+  if (!compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
+    oop stubName = HotSpotCompiledCode::name(compiled_code_obj);
+    char* name = strdup(java_lang_String::as_utf8_string(stubName));
+    cb = RuntimeStub::new_runtime_stub(name,
+                                       &buffer,
+                                       CodeOffsets::frame_never_safe,
+                                       stack_slots,
+                                       _debug_recorder->_oopmaps,
+                                       false);
+    result = JVMCIEnv::ok;
+  } else {
+    nmethod* nm = NULL;
+    methodHandle method = getMethodFromHotSpotMethod(HotSpotCompiledNmethod::method(compiled_code));
+    jint entry_bci = HotSpotCompiledNmethod::entryBCI(compiled_code);
+    jint id = HotSpotCompiledNmethod::id(compiled_code);
+    bool has_unsafe_access = HotSpotCompiledNmethod::hasUnsafeAccess(compiled_code) == JNI_TRUE;
+    JVMCIEnv* env = (JVMCIEnv*) (address) HotSpotCompiledNmethod::jvmciEnv(compiled_code);
+    if (id == -1) {
+      // Make sure a valid compile_id is associated with every compile
+      id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci);
+    }
+    result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _orig_pc_offset, &buffer,
+                                       stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+                                       compiler, _debug_recorder, _dependencies, env, id,
+                                       has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log);
+    cb = nm;
+  }
+
+  if (cb != NULL) {
+    // Make sure the pre-calculated constants section size was correct.
+    guarantee((cb->code_begin() - cb->content_begin()) >= _constants_size, err_msg("%d < %d", (int)(cb->code_begin() - cb->content_begin()), _constants_size));
+  }
+  return result;
+}
+
+void CodeInstaller::initialize_fields(oop target, oop compiled_code, TRAPS) {
+  if (compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
+    Handle hotspotJavaMethod = HotSpotCompiledNmethod::method(compiled_code);
+    methodHandle method = getMethodFromHotSpotMethod(hotspotJavaMethod());
+    _parameter_count = method->size_of_parameters();
+    TRACE_jvmci_2("installing code for %s", method->name_and_sig_as_C_string());
+  } else {
+    // Must be a HotSpotCompiledRuntimeStub.
+    // Only used in OopMap constructor for non-product builds
+    _parameter_count = 0;
+  }
+  _sites_handle = JNIHandles::make_local(HotSpotCompiledCode::sites(compiled_code));
+
+  _code_handle = JNIHandles::make_local(HotSpotCompiledCode::targetCode(compiled_code));
+  _code_size = HotSpotCompiledCode::targetCodeSize(compiled_code);
+  _total_frame_size = HotSpotCompiledCode::totalFrameSize(compiled_code);
+
+  oop deoptRescueSlot = HotSpotCompiledCode::deoptRescueSlot(compiled_code);
+  if (deoptRescueSlot == NULL) {
+    _orig_pc_offset = -1;
+  } else {
+    _orig_pc_offset = StackSlot::offset(deoptRescueSlot);
+    if (StackSlot::addFrameSize(deoptRescueSlot)) {
+      _orig_pc_offset += _total_frame_size;
+    }
+    if (_orig_pc_offset < 0) {
+      JVMCI_ERROR("invalid deopt rescue slot: %d", _orig_pc_offset);
+    }
+  }
+
+  // Pre-calculate the constants section size.  This is required for PC-relative addressing.
+  _data_section_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSection(compiled_code));
+  if ((_constants->alignment() % HotSpotCompiledCode::dataSectionAlignment(compiled_code)) != 0) {
+    JVMCI_ERROR("invalid data section alignment: %d", HotSpotCompiledCode::dataSectionAlignment(compiled_code));
+  }
+  _constants_size = data_section()->length();
+
+  _data_section_patches_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSectionPatches(compiled_code));
+
+#ifndef PRODUCT
+  _comments_handle = JNIHandles::make_local(HotSpotCompiledCode::comments(compiled_code));
+#endif
+
+  _next_call_type = INVOKE_INVALID;
+
+  _has_wide_vector = false;
+
+  oop arch = TargetDescription::arch(target);
+  _word_kind_handle = JNIHandles::make_local(Architecture::wordKind(arch));
+}
+
+int CodeInstaller::estimate_stubs_size(TRAPS) {
+  // Estimate the number of static call stubs that might be emitted.
+  int static_call_stubs = 0;
+  objArrayOop sites = this->sites();
+  for (int i = 0; i < sites->length(); i++) {
+    oop site = sites->obj_at(i);
+    if (site != NULL && site->is_a(site_Mark::klass())) {
+      oop id_obj = site_Mark::id(site);
+      if (id_obj != NULL) {
+        if (!java_lang_boxing_object::is_instance(id_obj, T_INT)) {
+          JVMCI_ERROR_0("expected Integer id, got %s", id_obj->klass()->signature_name());
+        }
+        jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+        if (id == INVOKESTATIC || id == INVOKESPECIAL) {
+          static_call_stubs++;
+        }
+      }
+    }
+  }
+  return static_call_stubs * CompiledStaticCall::to_interp_stub_size();
+}
+
+// perform data and call relocation on the CodeBuffer
+JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, TRAPS) {
+  HandleMark hm;
+  objArrayHandle sites = this->sites();
+  int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
+
+  // Allocate enough space in the stub section for the static call
+  // stubs.  Stubs have extra relocs but they are managed by the stub
+  // section itself so they don't need to be accounted for in the
+  // locs_buffer above.
+  int stubs_size = estimate_stubs_size(CHECK_OK);
+  int total_size = round_to(_code_size, buffer.insts()->alignment()) + round_to(_constants_size, buffer.consts()->alignment()) + round_to(stubs_size, buffer.stubs()->alignment());
+
+  if (total_size > JVMCINMethodSizeLimit) {
+    return JVMCIEnv::code_too_large;
+  }
+
+  buffer.initialize(total_size, locs_buffer_size);
+  if (buffer.blob() == NULL) {
+    return JVMCIEnv::cache_full;
+  }
+  buffer.initialize_stubs_size(stubs_size);
+  buffer.initialize_consts_size(_constants_size);
+
+  _debug_recorder = new DebugInformationRecorder(_oop_recorder);
+  _debug_recorder->set_oopmaps(new OopMapSet());
+
+  buffer.initialize_oop_recorder(_oop_recorder);
+
+  // copy the constant data into the newly created CodeBuffer
+  address end_data = _constants->start() + _constants_size;
+  memcpy(_constants->start(), data_section()->base(T_BYTE), _constants_size);
+  _constants->set_end(end_data);
+
+  // copy the code into the newly created CodeBuffer
+  address end_pc = _instructions->start() + _code_size;
+  guarantee(_instructions->allocates2(end_pc), "initialize should have reserved enough space for all the code");
+  memcpy(_instructions->start(), code()->base(T_BYTE), _code_size);
+  _instructions->set_end(end_pc);
+
+  for (int i = 0; i < data_section_patches()->length(); i++) {
+    Handle patch = data_section_patches()->obj_at(i);
+    if (patch.is_null()) {
+      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+    }
+    Handle reference = site_DataPatch::reference(patch);
+    if (reference.is_null()) {
+      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+    }
+    if (!reference->is_a(site_ConstantReference::klass())) {
+      JVMCI_ERROR_OK("invalid patch in data section: %s", reference->klass()->signature_name());
+    }
+    Handle constant = site_ConstantReference::constant(reference);
+    if (constant.is_null()) {
+      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+    }
+    address dest = _constants->start() + site_Site::pcOffset(patch);
+    if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
+      if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+#ifdef _LP64
+        *((narrowKlass*) dest) = record_narrow_metadata_reference(_constants, dest, constant, CHECK_OK);
+#else
+        JVMCI_ERROR_OK("unexpected compressed Klass* in 32-bit mode");
+#endif
+      } else {
+        *((void**) dest) = record_metadata_reference(_constants, dest, constant, CHECK_OK);
+      }
+    } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
+      Handle obj = HotSpotObjectConstantImpl::object(constant);
+      jobject value = JNIHandles::make_local(obj());
+      int oop_index = _oop_recorder->find_index(value);
+
+      if (HotSpotObjectConstantImpl::compressed(constant)) {
+#ifdef _LP64
+        _constants->relocate(dest, oop_Relocation::spec(oop_index), relocInfo::narrow_oop_in_const);
+#else
+        JVMCI_ERROR_OK("unexpected compressed oop in 32-bit mode");
+#endif
+      } else {
+        _constants->relocate(dest, oop_Relocation::spec(oop_index));
+      }
+    } else {
+      JVMCI_ERROR_OK("invalid constant in data section: %s", constant->klass()->signature_name());
+    }
+  }
+  jint last_pc_offset = -1;
+  for (int i = 0; i < sites->length(); i++) {
+    Handle site = sites->obj_at(i);
+    if (site.is_null()) {
+      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+    }
+
+    jint pc_offset = site_Site::pcOffset(site);
+
+    if (site->is_a(site_Call::klass())) {
+      TRACE_jvmci_4("call at %i", pc_offset);
+      site_Call(buffer, pc_offset, site, CHECK_OK);
+    } else if (site->is_a(site_Infopoint::klass())) {
+      // three reasons for infopoints denote actual safepoints
+      oop reason = site_Infopoint::reason(site);
+      if (site_InfopointReason::SAFEPOINT() == reason || site_InfopointReason::CALL() == reason || site_InfopointReason::IMPLICIT_EXCEPTION() == reason) {
+        TRACE_jvmci_4("safepoint at %i", pc_offset);
+        site_Safepoint(buffer, pc_offset, site, CHECK_OK);
+        if (_orig_pc_offset < 0) {
+          JVMCI_ERROR_OK("method contains safepoint, but has no deopt rescue slot");
+        }
+      } else {
+        TRACE_jvmci_4("infopoint at %i", pc_offset);
+        site_Infopoint(buffer, pc_offset, site, CHECK_OK);
+      }
+    } else if (site->is_a(site_DataPatch::klass())) {
+      TRACE_jvmci_4("datapatch at %i", pc_offset);
+      site_DataPatch(buffer, pc_offset, site, CHECK_OK);
+    } else if (site->is_a(site_Mark::klass())) {
+      TRACE_jvmci_4("mark at %i", pc_offset);
+      site_Mark(buffer, pc_offset, site, CHECK_OK);
+    } else if (site->is_a(site_ExceptionHandler::klass())) {
+      TRACE_jvmci_4("exceptionhandler at %i", pc_offset);
+      site_ExceptionHandler(pc_offset, site);
+    } else {
+      JVMCI_ERROR_OK("unexpected site subclass: %s", site->klass()->signature_name());
+    }
+    last_pc_offset = pc_offset;
+
+    if (CodeInstallSafepointChecks && SafepointSynchronize::do_call_back()) {
+      // this is a hacky way to force a safepoint check but nothing else was jumping out at me.
+      ThreadToNativeFromVM ttnfv(JavaThread::current());
+    }
+  }
+
+#ifndef PRODUCT
+  if (comments() != NULL) {
+    for (int i = 0; i < comments()->length(); i++) {
+      oop comment = comments()->obj_at(i);
+      assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce");
+      jint offset = HotSpotCompiledCode_Comment::pcOffset(comment);
+      char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment));
+      buffer.block_comment(offset, text);
+    }
+  }
+#endif
+  return JVMCIEnv::ok;
+}
+
+void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) {
+  Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption());
+  Klass* receiverType = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(receiverType_handle));
+  _dependencies->assert_has_no_finalizable_subclasses(receiverType);
+}
+
+void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) {
+  Handle context_handle = Assumptions_ConcreteSubtype::context(assumption());
+  Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption());
+  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+  Klass* subtype = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(subtype_handle));
+
+  assert(context->is_abstract(), "");
+  _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype);
+}
+
+void CodeInstaller::assumption_LeafType(Handle assumption) {
+  Handle context_handle = Assumptions_LeafType::context(assumption());
+  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+
+  _dependencies->assert_leaf_type(context);
+}
+
+void CodeInstaller::assumption_ConcreteMethod(Handle assumption) {
+  Handle impl_handle = Assumptions_ConcreteMethod::impl(assumption());
+  Handle context_handle = Assumptions_ConcreteMethod::context(assumption());
+
+  methodHandle impl = getMethodFromHotSpotMethod(impl_handle());
+  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+
+  _dependencies->assert_unique_concrete_method(context, impl());
+}
+
+void CodeInstaller::assumption_CallSiteTargetValue(Handle assumption) {
+  Handle callSite = Assumptions_CallSiteTargetValue::callSite(assumption());
+  Handle methodHandle = Assumptions_CallSiteTargetValue::methodHandle(assumption());
+
+  _dependencies->assert_call_site_target_value(callSite(), methodHandle());
+}
+
+void CodeInstaller::site_ExceptionHandler(jint pc_offset, Handle exc) {
+  jint handler_offset = site_ExceptionHandler::handlerPos(exc);
+
+  // Subtable header
+  _exception_handler_table.add_entry(HandlerTableEntry(1, pc_offset, 0));
+
+  // Subtable entry
+  _exception_handler_table.add_entry(HandlerTableEntry(-1, handler_offset, 0));
+}
+
+// If deoptimization happens, the interpreter should reexecute these bytecodes.
+// This function mainly helps the compilers to set up the reexecute bit.
+static bool bytecode_should_reexecute(Bytecodes::Code code) {
+  switch (code) {
+    case Bytecodes::_invokedynamic:
+    case Bytecodes::_invokevirtual:
+    case Bytecodes::_invokeinterface:
+    case Bytecodes::_invokespecial:
+    case Bytecodes::_invokestatic:
+      return false;
+    default:
+      return true;
+    }
+  return true;
+}
+
+GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(Handle debug_info, TRAPS) {
+  objArrayHandle virtualObjects = DebugInfo::virtualObjectMapping(debug_info);
+  if (virtualObjects.is_null()) {
+    return NULL;
+  }
+  GrowableArray<ScopeValue*>* objects = new GrowableArray<ScopeValue*>(virtualObjects->length(), virtualObjects->length(), NULL);
+  // Create the unique ObjectValues
+  for (int i = 0; i < virtualObjects->length(); i++) {
+    Handle value = virtualObjects->obj_at(i);
+    int id = VirtualObject::id(value);
+    Handle type = VirtualObject::type(value);
+    oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type);
+    ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror)));
+    if (id < 0 || id >= objects->length()) {
+      JVMCI_ERROR_NULL("virtual object id %d out of bounds", id);
+    }
+    if (objects->at(id) != NULL) {
+      JVMCI_ERROR_NULL("duplicate virtual object id %d", id);
+    }
+    objects->at_put(id, sv);
+  }
+  // All the values which could be referenced by the VirtualObjects
+  // exist, so now describe all the VirtualObjects themselves.
+  for (int i = 0; i < virtualObjects->length(); i++) {
+    Handle value = virtualObjects->obj_at(i);
+    int id = VirtualObject::id(value);
+    record_object_value(objects->at(id)->as_ObjectValue(), value, objects, CHECK_NULL);
+  }
+  _debug_recorder->dump_object_pool(objects);
+  return objects;
+}
+
+void CodeInstaller::record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, bool return_oop, TRAPS) {
+  Handle position = DebugInfo::bytecodePosition(debug_info);
+  if (position.is_null()) {
+    // Stubs do not record scope info, just oop maps
+    return;
+  }
+
+  GrowableArray<ScopeValue*>* objectMapping;
+  if (scope_mode == CodeInstaller::FullFrame) {
+    objectMapping = record_virtual_objects(debug_info, CHECK);
+  } else {
+    objectMapping = NULL;
+  }
+  record_scope(pc_offset, position, scope_mode, objectMapping, return_oop, CHECK);
+}
+
+void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, TRAPS) {
+  Handle frame;
+  if (scope_mode == CodeInstaller::FullFrame) {
+    if (!position->is_a(BytecodeFrame::klass())) {
+      JVMCI_ERROR("Full frame expected for debug info at %i", pc_offset);
+    }
+    frame = position;
+  }
+  Handle caller_frame = BytecodePosition::caller(position);
+  if (caller_frame.not_null()) {
+    record_scope(pc_offset, caller_frame, scope_mode, objects, return_oop, CHECK);
+  }
+
+  Handle hotspot_method = BytecodePosition::method(position);
+  Method* method = getMethodFromHotSpotMethod(hotspot_method());
+  jint bci = BytecodePosition::bci(position);
+  if (bci == BytecodeFrame::BEFORE_BCI()) {
+    bci = SynchronizationEntryBCI;
+  }
+
+  TRACE_jvmci_2("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string());
+
+  bool reexecute = false;
+  if (frame.not_null()) {
+    if (bci == SynchronizationEntryBCI){
+       reexecute = false;
+    } else {
+      Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci));
+      reexecute = bytecode_should_reexecute(code);
+      if (frame.not_null()) {
+        reexecute = (BytecodeFrame::duringCall(frame) == JNI_FALSE);
+      }
+    }
+  }
+
+  DebugToken* locals_token = NULL;
+  DebugToken* expressions_token = NULL;
+  DebugToken* monitors_token = NULL;
+  bool throw_exception = false;
+
+  if (frame.not_null()) {
+    jint local_count = BytecodeFrame::numLocals(frame);
+    jint expression_count = BytecodeFrame::numStack(frame);
+    jint monitor_count = BytecodeFrame::numLocks(frame);
+    objArrayHandle values = BytecodeFrame::values(frame);
+    objArrayHandle slotKinds = BytecodeFrame::slotKinds(frame);
+
+    if (values.is_null() || slotKinds.is_null()) {
+      THROW(vmSymbols::java_lang_NullPointerException());
+    }
+    if (local_count + expression_count + monitor_count != values->length()) {
+      JVMCI_ERROR("unexpected values length %d in scope (%d locals, %d expressions, %d monitors)", values->length(), local_count, expression_count, monitor_count);
+    }
+    if (local_count + expression_count != slotKinds->length()) {
+      JVMCI_ERROR("unexpected slotKinds length %d in scope (%d locals, %d expressions)", slotKinds->length(), local_count, expression_count);
+    }
+
+    GrowableArray<ScopeValue*>* locals = local_count > 0 ? new GrowableArray<ScopeValue*> (local_count) : NULL;
+    GrowableArray<ScopeValue*>* expressions = expression_count > 0 ? new GrowableArray<ScopeValue*> (expression_count) : NULL;
+    GrowableArray<MonitorValue*>* monitors = monitor_count > 0 ? new GrowableArray<MonitorValue*> (monitor_count) : NULL;
+
+    TRACE_jvmci_2("Scope at bci %d with %d values", bci, values->length());
+    TRACE_jvmci_2("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count);
+
+    for (jint i = 0; i < values->length(); i++) {
+      ScopeValue* second = NULL;
+      Handle value = values->obj_at(i);
+      if (i < local_count) {
+        BasicType type = JVMCIRuntime::kindToBasicType(slotKinds->obj_at(i), CHECK);
+        ScopeValue* first = get_scope_value(value, type, objects, second, CHECK);
+        if (second != NULL) {
+          locals->append(second);
+        }
+        locals->append(first);
+      } else if (i < local_count + expression_count) {
+        BasicType type = JVMCIRuntime::kindToBasicType(slotKinds->obj_at(i), CHECK);
+        ScopeValue* first = get_scope_value(value, type, objects, second, CHECK);
+        if (second != NULL) {
+          expressions->append(second);
+        }
+        expressions->append(first);
+      } else {
+        MonitorValue *monitor = get_monitor_value(value, objects, CHECK);
+        monitors->append(monitor);
+      }
+      if (second != NULL) {
+        i++;
+        if (i >= values->length() || values->obj_at(i) != Value::ILLEGAL()) {
+          JVMCI_ERROR("double-slot value not followed by Value.ILLEGAL");
+        }
+      }
+    }
+
+    locals_token = _debug_recorder->create_scope_values(locals);
+    expressions_token = _debug_recorder->create_scope_values(expressions);
+    monitors_token = _debug_recorder->create_monitor_values(monitors);
+
+    throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE;
+  }
+
+  _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, return_oop,
+                                  locals_token, expressions_token, monitors_token);
+}
+
+void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
+  Handle debug_info = site_Infopoint::debugInfo(site);
+  if (debug_info.is_null()) {
+    JVMCI_ERROR("debug info expected at safepoint at %i", pc_offset);
+  }
+
+  // address instruction = _instructions->start() + pc_offset;
+  // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start();
+  OopMap *map = create_oop_map(debug_info, CHECK);
+  _debug_recorder->add_safepoint(pc_offset, map);
+  record_scope(pc_offset, debug_info, CodeInstaller::FullFrame, CHECK);
+  _debug_recorder->end_safepoint(pc_offset);
+}
+
+void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
+  Handle debug_info = site_Infopoint::debugInfo(site);
+  if (debug_info.is_null()) {
+    JVMCI_ERROR("debug info expected at infopoint at %i", pc_offset);
+  }
+
+  // We'd like to check that pc_offset is greater than the
+  // last pc recorded with _debug_recorder (raising an exception if not)
+  // but DebugInformationRecorder doesn't have sufficient public API.
+
+  _debug_recorder->add_non_safepoint(pc_offset);
+  record_scope(pc_offset, debug_info, CodeInstaller::BytecodePosition, CHECK);
+  _debug_recorder->end_non_safepoint(pc_offset);
+}
+
+void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
+  Handle target = site_Call::target(site);
+  InstanceKlass* target_klass = InstanceKlass::cast(target->klass());
+
+  Handle hotspot_method; // JavaMethod
+  Handle foreign_call;
+
+  if (target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) {
+    foreign_call = target;
+  } else {
+    hotspot_method = target;
+  }
+
+  Handle debug_info = site_Call::debugInfo(site);
+
+  assert(hotspot_method.not_null() ^ foreign_call.not_null(), "Call site needs exactly one type");
+
+  NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
+  jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method, CHECK);
+
+  if (debug_info.not_null()) {
+    OopMap *map = create_oop_map(debug_info, CHECK);
+    _debug_recorder->add_safepoint(next_pc_offset, map);
+
+    bool return_oop = hotspot_method.not_null() && getMethodFromHotSpotMethod(hotspot_method())->is_returning_oop();
+
+    record_scope(next_pc_offset, debug_info, CodeInstaller::FullFrame, return_oop, CHECK);
+  }
+
+  if (foreign_call.not_null()) {
+    jlong foreign_call_destination = HotSpotForeignCallTarget::address(foreign_call);
+    CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination, CHECK);
+  } else { // method != NULL
+    if (debug_info.is_null()) {
+      JVMCI_ERROR("debug info expected at call at %i", pc_offset);
+    }
+
+    TRACE_jvmci_3("method call");
+    CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset, CHECK);
+    if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) {
+      // Need a static call stub for transitions from compiled to interpreted.
+      CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset);
+    }
+  }
+
+  _next_call_type = INVOKE_INVALID;
+
+  if (debug_info.not_null()) {
+    _debug_recorder->end_safepoint(next_pc_offset);
+  }
+}
+
+void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
+  Handle reference = site_DataPatch::reference(site);
+  if (reference.is_null()) {
+    THROW(vmSymbols::java_lang_NullPointerException());
+  } else if (reference->is_a(site_ConstantReference::klass())) {
+    Handle constant = site_ConstantReference::constant(reference);
+    if (constant.is_null()) {
+      THROW(vmSymbols::java_lang_NullPointerException());
+    } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
+      pd_patch_OopConstant(pc_offset, constant, CHECK);
+    } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
+      pd_patch_MetaspaceConstant(pc_offset, constant, CHECK);
+    } else {
+      JVMCI_ERROR("unknown constant type in data patch: %s", constant->klass()->signature_name());
+    }
+  } else if (reference->is_a(site_DataSectionReference::klass())) {
+    int data_offset = site_DataSectionReference::offset(reference);
+    if (0 <= data_offset && data_offset < _constants_size) {
+      pd_patch_DataSectionReference(pc_offset, data_offset, CHECK);
+    } else {
+      JVMCI_ERROR("data offset 0x%X points outside data section (size 0x%X)", data_offset, _constants_size);
+    }
+  } else {
+    JVMCI_ERROR("unknown data patch type: %s", reference->klass()->signature_name());
+  }
+}
+
+void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
+  Handle id_obj = site_Mark::id(site);
+
+  if (id_obj.not_null()) {
+    if (!java_lang_boxing_object::is_instance(id_obj(), T_INT)) {
+      JVMCI_ERROR("expected Integer id, got %s", id_obj->klass()->signature_name());
+    }
+    jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+
+    address pc = _instructions->start() + pc_offset;
+
+    switch (id) {
+      case UNVERIFIED_ENTRY:
+        _offsets.set_value(CodeOffsets::Entry, pc_offset);
+        break;
+      case VERIFIED_ENTRY:
+        _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset);
+        break;
+      case OSR_ENTRY:
+        _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset);
+        break;
+      case EXCEPTION_HANDLER_ENTRY:
+        _offsets.set_value(CodeOffsets::Exceptions, pc_offset);
+        break;
+      case DEOPT_HANDLER_ENTRY:
+        _offsets.set_value(CodeOffsets::Deopt, pc_offset);
+        break;
+      case INVOKEVIRTUAL:
+      case INVOKEINTERFACE:
+      case INLINE_INVOKE:
+      case INVOKESTATIC:
+      case INVOKESPECIAL:
+        _next_call_type = (MarkId) id;
+        _invoke_mark_pc = pc;
+        break;
+      case POLL_NEAR:
+      case POLL_FAR:
+      case POLL_RETURN_NEAR:
+      case POLL_RETURN_FAR:
+        pd_relocate_poll(pc, id, CHECK);
+        break;
+      case CARD_TABLE_SHIFT:
+      case CARD_TABLE_ADDRESS:
+        break;
+      default:
+        JVMCI_ERROR("invalid mark id: %d", id);
+        break;
+    }
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_CODE_INSTALLER_HPP
+#define SHARE_VM_JVMCI_JVMCI_CODE_INSTALLER_HPP
+
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
+
+/*
+ * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod.
+ */
+class CodeInstaller : public StackObj {
+  friend class VMStructs;
+private:
+  enum MarkId {
+    VERIFIED_ENTRY             = 1,
+    UNVERIFIED_ENTRY           = 2,
+    OSR_ENTRY                  = 3,
+    EXCEPTION_HANDLER_ENTRY    = 4,
+    DEOPT_HANDLER_ENTRY        = 5,
+    INVOKEINTERFACE            = 6,
+    INVOKEVIRTUAL              = 7,
+    INVOKESTATIC               = 8,
+    INVOKESPECIAL              = 9,
+    INLINE_INVOKE              = 10,
+    POLL_NEAR                  = 11,
+    POLL_RETURN_NEAR           = 12,
+    POLL_FAR                   = 13,
+    POLL_RETURN_FAR            = 14,
+    CARD_TABLE_ADDRESS         = 15,
+    CARD_TABLE_SHIFT           = 16,
+    INVOKE_INVALID             = -1
+  };
+
+  Arena         _arena;
+
+  jobject       _data_section_handle;
+  jobject       _data_section_patches_handle;
+  jobject       _sites_handle;
+  CodeOffsets   _offsets;
+
+  jobject       _code_handle;
+  jint          _code_size;
+  jint          _total_frame_size;
+  jint          _orig_pc_offset;
+  jint          _parameter_count;
+  jint          _constants_size;
+#ifndef PRODUCT
+  jobject       _comments_handle;
+#endif
+
+  bool          _has_wide_vector;
+  jobject       _word_kind_handle;
+
+  MarkId        _next_call_type;
+  address       _invoke_mark_pc;
+
+  CodeSection*  _instructions;
+  CodeSection*  _constants;
+
+  OopRecorder*              _oop_recorder;
+  DebugInformationRecorder* _debug_recorder;
+  Dependencies*             _dependencies;
+  ExceptionHandlerTable     _exception_handler_table;
+
+  static ConstantOopWriteValue* _oop_null_scope_value;
+  static ConstantIntValue*    _int_m1_scope_value;
+  static ConstantIntValue*    _int_0_scope_value;
+  static ConstantIntValue*    _int_1_scope_value;
+  static ConstantIntValue*    _int_2_scope_value;
+  static LocationValue*       _illegal_value;
+
+  jint pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS);
+  void pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS);
+  void pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS);
+  void pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS);
+  void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS);
+  void pd_relocate_JavaMethod(Handle method, jint pc_offset, TRAPS);
+  void pd_relocate_poll(address pc, jint mark, TRAPS);
+
+  objArrayOop sites() { return (objArrayOop) JNIHandles::resolve(_sites_handle); }
+  arrayOop code() { return (arrayOop) JNIHandles::resolve(_code_handle); }
+  arrayOop data_section() { return (arrayOop) JNIHandles::resolve(_data_section_handle); }
+  objArrayOop data_section_patches() { return (objArrayOop) JNIHandles::resolve(_data_section_patches_handle); }
+#ifndef PRODUCT
+  objArrayOop comments() { return (objArrayOop) JNIHandles::resolve(_comments_handle); }
+#endif
+
+  oop word_kind() { return (oop) JNIHandles::resolve(_word_kind_handle); }
+
+public:
+
+  CodeInstaller() : _arena(mtCompiler) {}
+  JVMCIEnv::CodeInstallResult install(JVMCICompiler* compiler, Handle target, Handle compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log, TRAPS);
+
+  static address runtime_call_target_address(oop runtime_call);
+  static VMReg get_hotspot_reg(jint jvmciRegisterNumber, TRAPS);
+  static bool is_general_purpose_reg(VMReg hotspotRegister);
+
+private:
+  Location::Type get_oop_type(Handle value);
+  ScopeValue* get_scope_value(Handle value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, TRAPS);
+  MonitorValue* get_monitor_value(Handle value, GrowableArray<ScopeValue*>* objects, TRAPS);
+
+  void* record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS);
+#ifdef _LP64
+  narrowKlass record_narrow_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS);
+#endif
+
+  // extract the fields of the HotSpotCompiledCode
+  void initialize_fields(oop target, oop target_method, TRAPS);
+  void initialize_dependencies(oop target_method, TRAPS);
+  
+  int estimate_stubs_size(TRAPS);
+  
+  // perform data and call relocation on the CodeBuffer
+  JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, TRAPS);
+
+  void assumption_NoFinalizableSubclass(Handle assumption);
+  void assumption_ConcreteSubtype(Handle assumption);
+  void assumption_LeafType(Handle assumption);
+  void assumption_ConcreteMethod(Handle assumption);
+  void assumption_CallSiteTargetValue(Handle assumption);
+
+  void site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
+  void site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
+  void site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
+  void site_DataPatch(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
+  void site_Mark(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
+  void site_ExceptionHandler(jint pc_offset, Handle site);
+
+  OopMap* create_oop_map(Handle debug_info, TRAPS);
+
+  /**
+   * Specifies the level of detail to record for a scope.
+   */
+  enum ScopeMode {
+    // Only record a method and BCI
+    BytecodePosition,
+    // Record a method, bci and JVM frame state
+    FullFrame
+  };
+
+  void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, bool return_oop, TRAPS);
+  void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, TRAPS) { 
+    record_scope(pc_offset, debug_info, scope_mode, false /* return_oop */, THREAD);
+  }
+  void record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, TRAPS);
+  void record_object_value(ObjectValue* sv, Handle value, GrowableArray<ScopeValue*>* objects, TRAPS);
+
+  GrowableArray<ScopeValue*>* record_virtual_objects(Handle debug_info, TRAPS);
+
+  int estimateStubSpace(int static_call_stubs);
+};
+
+/**
+ * Gets the Method metaspace object from a HotSpotResolvedJavaMethodImpl Java object.
+ */
+Method* getMethodFromHotSpotMethod(oop hotspot_method);
+
+
+
+#endif // SHARE_VM_JVMCI_JVMCI_CODE_INSTALLER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciCompiler.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "memory/oopFactory.hpp"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "runtime/compilationPolicy.hpp"
+#include "runtime/globals_extension.hpp"
+
+JVMCICompiler* JVMCICompiler::_instance = NULL;
+elapsedTimer JVMCICompiler::_codeInstallTimer;
+
+JVMCICompiler::JVMCICompiler() : AbstractCompiler(jvmci) {
+  _bootstrapping = false;
+  _bootstrap_compilation_request_handled = false;
+  _methods_compiled = 0;
+  assert(_instance == NULL, "only one instance allowed");
+  _instance = this;
+}
+
+// Initialization
+void JVMCICompiler::initialize() {
+  if (!UseCompiler || !UseJVMCICompiler || !should_perform_init()) {
+    return;
+  }
+
+  set_state(initialized);
+
+  // JVMCI is considered as application code so we need to
+  // stop the VM deferring compilation now.
+  CompilationPolicy::completed_vm_startup();
+}
+
+void JVMCICompiler::bootstrap(TRAPS) {
+  if (Arguments::mode() == Arguments::_int) {
+    // Nothing to do in -Xint mode
+    return;
+  }
+#ifndef PRODUCT
+  // We turn off CompileTheWorld so that compilation requests are not
+  // ignored during bootstrap or that JVMCI can be compiled by C1/C2.
+  FlagSetting ctwOff(CompileTheWorld, false);
+#endif
+
+  _bootstrapping = true;
+  // Allow bootstrap to perform JVMCI compilations of itself
+  ResourceMark rm;
+  HandleMark hm;
+  if (PrintBootstrap) {
+    tty->print("Bootstrapping JVMCI");
+  }
+  jlong start = os::javaTimeMillis();
+
+  Array<Method*>* objectMethods = InstanceKlass::cast(SystemDictionary::Object_klass())->methods();
+  // Initialize compile queue with a selected set of methods.
+  int len = objectMethods->length();
+  for (int i = 0; i < len; i++) {
+    methodHandle mh = objectMethods->at(i);
+    if (!mh->is_native() && !mh->is_static() && !mh->is_initializer()) {
+      ResourceMark rm;
+      int hot_count = 10; // TODO: what's the appropriate value?
+      CompileBroker::compile_method(mh, InvocationEntryBci, CompLevel_full_optimization, mh, hot_count, "bootstrap", THREAD);
+    }
+  }
+
+  int qsize;
+  int z = 0;
+  do {
+    // Loop until there is something in the queue.
+    do {
+      os::sleep(THREAD, 100, true);
+      qsize = CompileBroker::queue_size(CompLevel_full_optimization);
+    } while (!_bootstrap_compilation_request_handled);
+    if (PrintBootstrap) {
+      while (z < (_methods_compiled / 100)) {
+        ++z;
+        tty->print_raw(".");
+      }
+    }
+  } while (qsize != 0);
+
+  if (PrintBootstrap) {
+    tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methods_compiled);
+  }
+  _bootstrapping = false;
+  JVMCIRuntime::bootstrap_finished(CHECK);
+}
+
+void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JVMCIEnv* env) {
+  JVMCI_EXCEPTION_CONTEXT
+
+  bool is_osr = entry_bci != InvocationEntryBci;
+  if (_bootstrapping && is_osr) {
+      // no OSR compilations during bootstrap - the compiler is just too slow at this point,
+      // and we know that there are no endless loops
+      return;
+  }
+
+  JVMCIRuntime::ensure_jvmci_class_loader_is_initialized();
+  HandleMark hm;
+  Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_EXIT);
+
+  JavaValue method_result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_long((jlong) (address) method());
+  JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(),
+                         vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
+
+  JavaValue result(T_OBJECT);
+  if (!HAS_PENDING_EXCEPTION) {
+    JavaCallArguments args;
+    args.push_oop(receiver);
+    args.push_oop((oop)method_result.get_jobject());
+    args.push_int(entry_bci);
+    args.push_long((jlong) (address) env);
+    args.push_int(env->task()->compile_id());
+    JavaCalls::call_special(&result, receiver->klass(),
+                            vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD);
+  }
+
+  // An uncaught exception was thrown during compilation.  Generally these
+  // should be handled by the Java code in some useful way but if they leak
+  // through to here report them instead of dying or silently ignoring them.
+  if (HAS_PENDING_EXCEPTION) {
+    Handle throwable = PENDING_EXCEPTION;
+    CLEAR_PENDING_EXCEPTION;
+
+    java_lang_Throwable::print(throwable, tty);
+    tty->cr();
+    java_lang_Throwable::print_stack_trace(throwable(), tty);
+
+    env->set_failure("exception throw", false);
+  } else {
+    oop result_object = (oop) result.get_jobject();
+    if (result_object != NULL) {
+      oop failure_message = HotSpotCompilationRequestResult::failureMessage(result_object);
+      if (failure_message != NULL) {
+        const char* failure_reason = java_lang_String::as_utf8_string(failure_message);
+        env->set_failure(failure_reason, HotSpotCompilationRequestResult::retry(result_object) != 0);
+      } else {
+        if (env->task()->code() == NULL) {
+          env->set_failure("no nmethod produced", true);
+        } else {
+          env->task()->set_num_inlined_bytecodes(HotSpotCompilationRequestResult::inlinedBytecodes(result_object));
+          Atomic::inc(&_methods_compiled);
+        }
+      }
+    } else {
+      assert(false, "JVMCICompiler.compileMethod should always return non-null");
+    }
+  }
+  if (_bootstrapping) {
+    _bootstrap_compilation_request_handled = true;
+  }
+}
+
+
+// Compilation entry point for methods
+void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+  ShouldNotReachHere();
+}
+
+bool JVMCICompiler::is_trivial(Method* method) {
+  if (_bootstrapping) {
+    return false;
+  }
+  return JVMCIRuntime::treat_as_trivial(method);
+}
+
+// Print compilation timers and statistics
+void JVMCICompiler::print_timers() {
+  print_compilation_timers();
+}
+
+// Print compilation timers and statistics
+void JVMCICompiler::print_compilation_timers() {
+  TRACE_jvmci_1("JVMCICompiler::print_timers");
+  tty->print_cr("       JVMCI code install time:        %6.3f s",    _codeInstallTimer.seconds());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciCompiler.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_COMPILER_HPP
+#define SHARE_VM_JVMCI_JVMCI_COMPILER_HPP
+
+#include "compiler/abstractCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
+
+class JVMCICompiler : public AbstractCompiler {
+private:
+  bool _bootstrapping;
+
+  /**
+   * True if we have seen a bootstrap compilation request.
+   */
+  volatile bool _bootstrap_compilation_request_handled;
+
+  /**
+   * Number of methods successfully compiled by a call to
+   * JVMCICompiler::compile_method().
+   */
+  volatile int _methods_compiled;
+
+  static JVMCICompiler* _instance;
+
+  static elapsedTimer _codeInstallTimer;
+
+public:
+  JVMCICompiler();
+
+  static JVMCICompiler* instance(TRAPS) {
+    if (!EnableJVMCI) {
+      THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
+    }
+    return _instance;
+  }
+
+  virtual const char* name() { return "JVMCI"; }
+
+  virtual bool supports_native()                 { return true; }
+  virtual bool supports_osr   ()                 { return true; }
+
+  bool is_jvmci()                                { return true; }
+  bool is_c1   ()                                { return false; }
+  bool is_c2   ()                                { return false; }
+
+  bool needs_stubs            () { return false; }
+
+  // Initialization
+  virtual void initialize();
+
+  /**
+   * Initialize the compile queue with the methods in java.lang.Object and
+   * then wait until the queue is empty.
+   */
+  void bootstrap(TRAPS);
+
+  bool is_bootstrapping() const { return _bootstrapping; }
+
+  // Compilation entry point for methods
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+
+  void compile_method(const methodHandle& target, int entry_bci, JVMCIEnv* env);
+
+  virtual bool is_trivial(Method* method);
+
+  // Print compilation timers and statistics
+  virtual void print_timers();
+
+  /**
+   * Gets the number of methods that have been successfully compiled by
+   * a call to JVMCICompiler::compile_method().
+   */
+  int methods_compiled() { return _methods_compiled; }
+
+  // Print compilation timers and statistics
+  static void print_compilation_timers();
+
+  static elapsedTimer* codeInstallTimer() { return &_codeInstallTimer; }
+};
+
+#endif // SHARE_VM_JVMCI_JVMCI_COMPILER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,1731 @@
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "code/codeCache.hpp"
+#include "code/scopeDesc.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/generateOopMap.hpp"
+#include "oops/fieldStreams.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/fieldDescriptor.hpp"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "compiler/abstractCompiler.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/compilerOracle.hpp"
+#include "compiler/disassembler.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "gc_implementation/g1/heapRegion.hpp"
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/deoptimization.hpp"
+#include "runtime/vframe.hpp"
+#include "runtime/vframe_hp.hpp"
+#include "runtime/vmStructs.hpp"
+#include "utilities/resourceHash.hpp"
+
+
+// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
+#define C2V_VMENTRY(result_type, name, signature) \
+  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
+  TRACE_jvmci_1("CompilerToVM::" #name); \
+  TRACE_CALL(result_type, jvmci_ ## name signature) \
+  JVMCI_VM_ENTRY_MARK; \
+
+#define C2V_END }
+
+oop CompilerToVM::get_jvmci_method(const methodHandle& method, TRAPS) {
+  if (method() != NULL) {
+    JavaValue result(T_OBJECT);
+    JavaCallArguments args;
+    args.push_long((jlong) (address) method());
+    JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, CHECK_NULL);
+
+    return (oop)result.get_jobject();
+  }
+  return NULL;
+}
+
+oop CompilerToVM::get_jvmci_type(KlassHandle klass, TRAPS) {
+  if (klass() != NULL) {
+    JavaValue result(T_OBJECT);
+    JavaCallArguments args;
+    args.push_oop(klass->java_mirror());
+    JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedObjectTypeImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::klass_fromMetaspace_signature(), &args, CHECK_NULL);
+
+    return (oop)result.get_jobject();
+  }
+  return NULL;
+}
+
+int CompilerToVM::Data::Klass_vtable_start_offset;
+int CompilerToVM::Data::Klass_vtable_length_offset;
+
+int CompilerToVM::Data::Method_extra_stack_entries;
+
+address CompilerToVM::Data::SharedRuntime_ic_miss_stub;
+address CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub;
+address CompilerToVM::Data::SharedRuntime_deopt_blob_unpack;
+address CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap;
+
+size_t CompilerToVM::Data::ThreadLocalAllocBuffer_alignment_reserve;
+
+CollectedHeap* CompilerToVM::Data::Universe_collectedHeap;
+int CompilerToVM::Data::Universe_base_vtable_size;
+address CompilerToVM::Data::Universe_narrow_oop_base;
+int CompilerToVM::Data::Universe_narrow_oop_shift;
+address CompilerToVM::Data::Universe_narrow_klass_base;
+int CompilerToVM::Data::Universe_narrow_klass_shift;
+void* CompilerToVM::Data::Universe_non_oop_bits;
+uintptr_t CompilerToVM::Data::Universe_verify_oop_mask;
+uintptr_t CompilerToVM::Data::Universe_verify_oop_bits;
+
+bool       CompilerToVM::Data::_supports_inline_contig_alloc;
+HeapWord** CompilerToVM::Data::_heap_end_addr;
+HeapWord** CompilerToVM::Data::_heap_top_addr;
+int CompilerToVM::Data::_max_oop_map_stack_offset;
+
+jbyte* CompilerToVM::Data::cardtable_start_address;
+int CompilerToVM::Data::cardtable_shift;
+int CompilerToVM::Data::g1_young_card;
+int CompilerToVM::Data::dirty_card;
+
+int CompilerToVM::Data::vm_page_size;
+
+int CompilerToVM::Data::sizeof_vtableEntry = sizeof(vtableEntry);
+int CompilerToVM::Data::sizeof_ExceptionTableElement = sizeof(ExceptionTableElement);
+int CompilerToVM::Data::sizeof_LocalVariableTableElement = sizeof(LocalVariableTableElement);
+int CompilerToVM::Data::sizeof_ConstantPool = sizeof(ConstantPool);
+int CompilerToVM::Data::sizeof_SymbolPointer = sizeof(Symbol*);
+int CompilerToVM::Data::sizeof_narrowKlass = sizeof(narrowKlass);
+int CompilerToVM::Data::sizeof_arrayOopDesc = sizeof(arrayOopDesc);
+int CompilerToVM::Data::sizeof_BasicLock = sizeof(BasicLock);
+
+address CompilerToVM::Data::CodeCache_low_bound;
+address CompilerToVM::Data::CodeCache_high_bound;
+
+address CompilerToVM::Data::dsin;
+address CompilerToVM::Data::dcos;
+address CompilerToVM::Data::dtan;
+address CompilerToVM::Data::dexp;
+address CompilerToVM::Data::dlog;
+address CompilerToVM::Data::dlog10;
+address CompilerToVM::Data::dpow;
+
+address CompilerToVM::Data::symbol_init;
+address CompilerToVM::Data::symbol_clinit;
+
+void CompilerToVM::Data::initialize(TRAPS) {
+  Klass_vtable_start_offset = InstanceKlass::vtable_start_offset() * HeapWordSize;
+  Klass_vtable_length_offset = InstanceKlass::vtable_length_offset() * HeapWordSize;
+  Method_extra_stack_entries = Method::extra_stack_entries();
+
+  SharedRuntime_ic_miss_stub = SharedRuntime::get_ic_miss_stub();
+  SharedRuntime_handle_wrong_method_stub = SharedRuntime::get_handle_wrong_method_stub();
+  SharedRuntime_deopt_blob_unpack = SharedRuntime::deopt_blob()->unpack();
+  SharedRuntime_deopt_blob_uncommon_trap = SharedRuntime::deopt_blob()->uncommon_trap();
+
+  ThreadLocalAllocBuffer_alignment_reserve = ThreadLocalAllocBuffer::alignment_reserve();
+
+  Universe_collectedHeap = Universe::heap();
+  Universe_base_vtable_size = Universe::base_vtable_size();
+  Universe_narrow_oop_base = Universe::narrow_oop_base();
+  Universe_narrow_oop_shift = Universe::narrow_oop_shift();
+  Universe_narrow_klass_base = Universe::narrow_klass_base();
+  Universe_narrow_klass_shift = Universe::narrow_klass_shift();
+  Universe_non_oop_bits = Universe::non_oop_word();
+  Universe_verify_oop_mask = Universe::verify_oop_mask();
+  Universe_verify_oop_bits = Universe::verify_oop_bits();
+
+  _supports_inline_contig_alloc = Universe::heap()->supports_inline_contig_alloc();
+  _heap_end_addr = _supports_inline_contig_alloc ? Universe::heap()->end_addr() : (HeapWord**) -1;
+  _heap_top_addr = _supports_inline_contig_alloc ? Universe::heap()->top_addr() : (HeapWord**) -1;
+
+  _max_oop_map_stack_offset = (OopMapValue::register_mask - VMRegImpl::stack2reg(0)->value()) * VMRegImpl::stack_slot_size;
+  int max_oop_map_stack_index = _max_oop_map_stack_offset / VMRegImpl::stack_slot_size;
+  assert(OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index)), "should be valid");
+  assert(!OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index + 1)), "should be invalid");
+
+  g1_young_card = G1SATBCardTableModRefBS::g1_young_card_val();
+  dirty_card = CardTableModRefBS::dirty_card_val();
+
+  CodeCache_low_bound = CodeCache::low_bound();
+  CodeCache_high_bound = CodeCache::high_bound();
+
+  symbol_init = (address) vmSymbols::object_initializer_name();
+  symbol_clinit = (address) vmSymbols::class_initializer_name();
+
+  BarrierSet* bs = Universe::heap()->barrier_set();
+  switch (bs->kind()) {
+  case BarrierSet::CardTableModRef:
+  case BarrierSet::CardTableExtension:
+  case BarrierSet::G1SATBCT:
+  case BarrierSet::G1SATBCTLogging: {
+    jbyte* base = ((CardTableModRefBS*) bs)->byte_map_base;
+    assert(base != 0, "unexpected byte_map_base");
+    cardtable_start_address = base;
+    cardtable_shift = CardTableModRefBS::card_shift;
+    break;
+  }
+  case BarrierSet::ModRef:
+    cardtable_start_address = 0;
+    cardtable_shift = 0;
+    // No post barriers
+    break;
+  default:
+    JVMCI_ERROR("Unsupported BarrierSet kind %d", bs->kind());
+    break;
+  }
+
+  vm_page_size = os::vm_page_size();
+
+#define SET_TRIGFUNC(name)                                      \
+  name = CAST_FROM_FN_PTR(address, SharedRuntime::name);      \
+
+  SET_TRIGFUNC(dsin);
+  SET_TRIGFUNC(dcos);
+  SET_TRIGFUNC(dtan);
+  SET_TRIGFUNC(dexp);
+  SET_TRIGFUNC(dlog10);
+  SET_TRIGFUNC(dlog);
+  SET_TRIGFUNC(dpow);
+
+#undef SET_TRIGFUNC
+}
+
+objArrayHandle CompilerToVM::initialize_intrinsics(TRAPS) {
+  objArrayHandle vmIntrinsics = oopFactory::new_objArray(VMIntrinsicMethod::klass(), (vmIntrinsics::ID_LIMIT - 1), CHECK_(objArrayHandle()));
+  int index = 0;
+  // The intrinsics for a class are usually adjacent to each other.
+  // When they are, the string for the class name can be reused.
+  vmSymbols::SID kls_sid = vmSymbols::NO_SID;
+  Handle kls_str;
+#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n)
+#define VM_SYMBOL_TO_STRING(s) \
+  java_lang_String::create_from_symbol(vmSymbols::symbol_at(SID_ENUM(s)), CHECK_(objArrayHandle()))
+#define VM_INTRINSIC_INFO(id, kls, name, sig, ignore_fcode) {             \
+    instanceHandle vmIntrinsicMethod = InstanceKlass::cast(VMIntrinsicMethod::klass())->allocate_instance_handle(CHECK_(objArrayHandle())); \
+    if (kls_sid != SID_ENUM(kls)) {                                       \
+      kls_str = VM_SYMBOL_TO_STRING(kls);                                 \
+      kls_sid = SID_ENUM(kls);                                            \
+    }                                                                     \
+    Handle name_str = VM_SYMBOL_TO_STRING(name);                          \
+    Handle sig_str = VM_SYMBOL_TO_STRING(sig);                            \
+    VMIntrinsicMethod::set_declaringClass(vmIntrinsicMethod, kls_str());  \
+    VMIntrinsicMethod::set_name(vmIntrinsicMethod, name_str());           \
+    VMIntrinsicMethod::set_descriptor(vmIntrinsicMethod, sig_str());      \
+    VMIntrinsicMethod::set_id(vmIntrinsicMethod, vmIntrinsics::id);       \
+    vmIntrinsics->obj_at_put(index++, vmIntrinsicMethod());               \
+  }
+
+  VM_INTRINSICS_DO(VM_INTRINSIC_INFO, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE)
+#undef SID_ENUM
+#undef VM_SYMBOL_TO_STRING
+#undef VM_INTRINSIC_INFO
+  assert(index == vmIntrinsics::ID_LIMIT - 1, "must be");
+
+  return vmIntrinsics;
+}
+
+/**
+ * The set of VM flags known to be used.
+ */
+#define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_intx_flag, do_uintx_flag) \
+  do_intx_flag(AllocateInstancePrefetchLines)                              \
+  do_intx_flag(AllocatePrefetchDistance)                                   \
+  do_intx_flag(AllocatePrefetchInstr)                                      \
+  do_intx_flag(AllocatePrefetchLines)                                      \
+  do_intx_flag(AllocatePrefetchStepSize)                                   \
+  do_intx_flag(AllocatePrefetchStyle)                                      \
+  do_intx_flag(BciProfileWidth)                                            \
+  do_bool_flag(BootstrapJVMCI)                                             \
+  do_bool_flag(CITime)                                                     \
+  do_bool_flag(CITimeEach)                                                 \
+  do_uintx_flag(CodeCacheSegmentSize)                                      \
+  do_intx_flag(CodeEntryAlignment)                                         \
+  do_bool_flag(CompactFields)                                              \
+  NOT_PRODUCT(do_intx_flag(CompileTheWorldStartAt))                        \
+  NOT_PRODUCT(do_intx_flag(CompileTheWorldStopAt))                         \
+  do_intx_flag(ContendedPaddingWidth)                                      \
+  do_bool_flag(DontCompileHugeMethods)                                     \
+  do_bool_flag(EnableContended)                                            \
+  do_intx_flag(FieldsAllocationStyle)                                      \
+  do_bool_flag(FoldStableValues)                                           \
+  do_bool_flag(ForceUnreachable)                                           \
+  do_intx_flag(HugeMethodLimit)                                            \
+  do_bool_flag(Inline)                                                     \
+  do_intx_flag(JVMCICounterSize)                                           \
+  do_bool_flag(JVMCIPrintProperties)                                       \
+  do_bool_flag(JVMCIUseFastLocking)                                        \
+  do_intx_flag(MethodProfileWidth)                                         \
+  do_intx_flag(ObjectAlignmentInBytes)                                     \
+  do_bool_flag(PrintInlining)                                              \
+  do_bool_flag(ReduceInitialCardMarks)                                     \
+  do_bool_flag(RestrictContended)                                          \
+  /* do_intx_flag(StackReservedPages) JDK 9 */                             \
+  do_intx_flag(StackShadowPages)                                           \
+  do_bool_flag(TLABStats)                                                  \
+  do_uintx_flag(TLABWasteIncrement)                                        \
+  do_intx_flag(TypeProfileWidth)                                           \
+  do_bool_flag(UseAESIntrinsics)                                           \
+  X86_ONLY(do_intx_flag(UseAVX))                                           \
+  do_bool_flag(UseBiasedLocking)                                           \
+  do_bool_flag(UseCRC32Intrinsics)                                         \
+  do_bool_flag(UseCompressedClassPointers)                                 \
+  do_bool_flag(UseCompressedOops)                                          \
+  do_bool_flag(UseConcMarkSweepGC)                                         \
+  X86_ONLY(do_bool_flag(UseCountLeadingZerosInstruction))                  \
+  X86_ONLY(do_bool_flag(UseCountTrailingZerosInstruction))                 \
+  do_bool_flag(UseG1GC)                                                    \
+  COMPILER2_PRESENT(do_bool_flag(UseMontgomeryMultiplyIntrinsic))          \
+  COMPILER2_PRESENT(do_bool_flag(UseMontgomerySquareIntrinsic))            \
+  COMPILER2_PRESENT(do_bool_flag(UseMulAddIntrinsic))                      \
+  COMPILER2_PRESENT(do_bool_flag(UseMultiplyToLenIntrinsic))               \
+  do_bool_flag(UsePopCountInstruction)                                     \
+  do_bool_flag(UseSHA1Intrinsics)                                          \
+  do_bool_flag(UseSHA256Intrinsics)                                        \
+  do_bool_flag(UseSHA512Intrinsics)                                        \
+  do_intx_flag(UseSSE)                                                     \
+  COMPILER2_PRESENT(do_bool_flag(UseSquareToLenIntrinsic))                 \
+  do_bool_flag(UseStackBanging)                                            \
+  do_bool_flag(UseTLAB)                                                    \
+  do_bool_flag(VerifyOops)                                                 \
+
+#define BOXED_BOOLEAN(name, value) oop name = ((jboolean)(value) ? boxedTrue() : boxedFalse())
+#define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0)
+#define BOXED_LONG(name, value) \
+  oop name; \
+  do { \
+    jvalue p; p.j = (jlong) (value); \
+    Handle* e = longs.get(p.j); \
+    if (e == NULL) { \
+      Handle h = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); \
+      longs.put(p.j, h); \
+      name = h(); \
+    } else { \
+      name = (*e)(); \
+    } \
+  } while (0)
+
+#define STRING(name, value) \
+  Handle name; \
+  do { \
+    if (value != NULL) { \
+      Handle* e = strings.get(value); \
+      if (e == NULL) { \
+        Handle h = java_lang_String::create_from_str(value, CHECK_NULL); \
+        strings.put(value, h); \
+        name = h(); \
+      } else { \
+        name = (*e)(); \
+      } \
+    } \
+  } while (0)
+
+C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
+  ResourceMark rm;
+  HandleMark hm;
+
+  // Used to canonicalize Long and String values.
+  ResourceHashtable<jlong, Handle> longs;
+  ResourceHashtable<const char*, Handle, &CompilerToVM::cstring_hash, &CompilerToVM::cstring_equals> strings;
+
+  jvalue prim;
+  prim.z = true;  Handle boxedTrue =  java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
+  prim.z = false; Handle boxedFalse = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
+
+  CompilerToVM::Data::initialize(CHECK_NULL);
+
+  VMField::klass()->initialize(CHECK_NULL);
+  VMFlag::klass()->initialize(CHECK_NULL);
+  VMIntrinsicMethod::klass()->initialize(CHECK_NULL);
+
+  int len = VMStructs::localHotSpotVMStructs_count();
+  objArrayHandle vmFields = oopFactory::new_objArray(VMField::klass(), len, CHECK_NULL);
+  for (int i = 0; i < len ; i++) {
+    VMStructEntry vmField = VMStructs::localHotSpotVMStructs[i];
+    instanceHandle vmFieldObj = InstanceKlass::cast(VMField::klass())->allocate_instance_handle(CHECK_NULL);
+    size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */;
+    char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1);
+    sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName);
+    STRING(name, name_buf);
+    STRING(type, vmField.typeString);
+    VMField::set_name(vmFieldObj, name());
+    VMField::set_type(vmFieldObj, type());
+    VMField::set_offset(vmFieldObj, vmField.offset);
+    VMField::set_address(vmFieldObj, (jlong) vmField.address);
+    if (vmField.isStatic && vmField.typeString != NULL) {
+      if (strcmp(vmField.typeString, "bool") == 0) {
+        BOXED_BOOLEAN(box, *(jbyte*) vmField.address);
+        VMField::set_value(vmFieldObj, box);
+      } else if (strcmp(vmField.typeString, "int") == 0 ||
+                 strcmp(vmField.typeString, "jint") == 0) {
+        BOXED_LONG(box, *(jint*) vmField.address);
+        VMField::set_value(vmFieldObj, box);
+      } else if (strcmp(vmField.typeString, "uint64_t") == 0) {
+        BOXED_LONG(box, *(uint64_t*) vmField.address);
+        VMField::set_value(vmFieldObj, box);
+      } else if (strcmp(vmField.typeString, "address") == 0 ||
+                 strcmp(vmField.typeString, "intptr_t") == 0 ||
+                 strcmp(vmField.typeString, "uintptr_t") == 0 ||
+                 strcmp(vmField.typeString, "size_t") == 0 ||
+                 // All foo* types are addresses.
+                 vmField.typeString[strlen(vmField.typeString) - 1] == '*') {
+        BOXED_LONG(box, *((address*) vmField.address));
+        VMField::set_value(vmFieldObj, box);
+      }
+    }
+    vmFields->obj_at_put(i, vmFieldObj());
+  }
+
+  int ints_len = VMStructs::localHotSpotVMIntConstants_count();
+  int longs_len = VMStructs::localHotSpotVMLongConstants_count();
+  len = ints_len + longs_len;
+  objArrayHandle vmConstants = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
+  int insert = 0;
+  for (int i = 0; i < ints_len ; i++) {
+    VMIntConstantEntry c = VMStructs::localHotSpotVMIntConstants[i];
+    STRING(name, c.name);
+    BOXED_LONG(value, c.value);
+    vmConstants->obj_at_put(insert++, name());
+    vmConstants->obj_at_put(insert++, value);
+  }
+  for (int i = 0; i < longs_len ; i++) {
+    VMLongConstantEntry c = VMStructs::localHotSpotVMLongConstants[i];
+    STRING(name, c.name);
+    BOXED_LONG(value, c.value);
+    vmConstants->obj_at_put(insert++, name());
+    vmConstants->obj_at_put(insert++, value);
+  }
+  assert(insert == len * 2, "must be");
+
+  len = VMStructs::localHotSpotVMAddresses_count();
+  objArrayHandle vmAddresses = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
+  for (int i = 0; i < len ; i++) {
+    VMAddressEntry a = VMStructs::localHotSpotVMAddresses[i];
+    STRING(name, a.name);
+    BOXED_LONG(value, a.value);
+    vmAddresses->obj_at_put(i * 2, name());
+    vmAddresses->obj_at_put(i * 2 + 1, value);
+  }
+
+#define COUNT_FLAG(ignore) +1
+#ifdef ASSERT
+#define CHECK_FLAG(type, name) { \
+  Flag* flag = Flag::find_flag(#name, strlen(#name), /*allow_locked*/ true, /* return_flag */ true); \
+  assert(flag != NULL, "No such flag named " #name); \
+  assert(flag->is_##type(), "Flag " #name " is not of type " #type); \
+}
+#else
+#define CHECK_FLAG(type, name)
+#endif
+
+#define ADD_FLAG(type, name, convert) { \
+  CHECK_FLAG(type, name) \
+  instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL); \
+  STRING(fname, #name); \
+  STRING(ftype, #type); \
+  VMFlag::set_name(vmFlagObj, fname()); \
+  VMFlag::set_type(vmFlagObj, ftype()); \
+  convert(value, name); \
+  VMFlag::set_value(vmFlagObj, value); \
+  vmFlags->obj_at_put(i++, vmFlagObj()); \
+}
+#define ADD_BOOL_FLAG(name)  ADD_FLAG(bool, name, BOXED_BOOLEAN)
+#define ADD_INTX_FLAG(name)  ADD_FLAG(intx, name, BOXED_LONG)
+#define ADD_UINTX_FLAG(name) ADD_FLAG(uintx, name, BOXED_LONG)
+
+  len = 0 + PREDEFINED_CONFIG_FLAGS(COUNT_FLAG, COUNT_FLAG, COUNT_FLAG);
+  objArrayHandle vmFlags = oopFactory::new_objArray(VMFlag::klass(), len, CHECK_NULL);
+  int i = 0;
+  PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG)
+
+  objArrayHandle vmIntrinsics = CompilerToVM::initialize_intrinsics(CHECK_NULL);
+
+  objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 5, CHECK_NULL);
+  data->obj_at_put(0, vmFields());
+  data->obj_at_put(1, vmConstants());
+  data->obj_at_put(2, vmAddresses());
+  data->obj_at_put(3, vmFlags());
+  data->obj_at_put(4, vmIntrinsics());
+
+  return (jobjectArray) JNIHandles::make_local(THREAD, data);
+#undef COUNT_FLAG
+#undef ADD_FLAG
+#undef ADD_BOOL_FLAG
+#undef ADD_INTX_FLAG
+#undef ADD_UINTX_FLAG
+#undef CHECK_FLAG
+C2V_END
+
+C2V_VMENTRY(jobject, getFlagValue, (JNIEnv *, jobject c2vm, jobject name_handle))
+#define RETURN_BOXED_LONG(value) oop box; jvalue p; p.j = (jlong) (value); box = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
+#define RETURN_BOXED_DOUBLE(value) oop box; jvalue p; p.d = (jdouble) (value); box = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
+  Handle name = JNIHandles::resolve(name_handle);
+  if (name.is_null()) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+  const char* cstring = java_lang_String::as_utf8_string(name());
+  Flag* flag = Flag::find_flag(cstring, strlen(cstring), /* allow_locked */ true, /* return_flag */ true);
+  if (flag == NULL) {
+    return c2vm;
+  }
+  if (flag->is_bool()) {
+    jvalue prim;
+    prim.z = flag->get_bool();
+    oop box = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
+    return JNIHandles::make_local(THREAD, box);
+  } else if (flag->is_ccstr()) {
+    Handle value = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_NULL);
+    return JNIHandles::make_local(THREAD, value());
+  } else if (flag->is_intx()) {
+    RETURN_BOXED_LONG(flag->get_intx());
+/*} else if (flag->is_int()) {
+    RETURN_BOXED_LONG(flag->get_int());
+  } else if (flag->is_uint()) {
+    RETURN_BOXED_LONG(flag->get_uint());*/
+  } else if (flag->is_uint64_t()) {
+    RETURN_BOXED_LONG(flag->get_uint64_t());
+/*} else if (flag->is_size_t()) {
+    RETURN_BOXED_LONG(flag->get_size_t());*/
+  } else if (flag->is_uintx()) {
+    RETURN_BOXED_LONG(flag->get_uintx());
+  } else if (flag->is_double()) {
+    RETURN_BOXED_DOUBLE(flag->get_double());
+  } else {
+    JVMCI_ERROR_NULL("VM flag %s has unsupported type %s", flag->_name, flag->_type);
+  }
+C2V_END
+
+#undef BOXED_LONG
+#undef BOXED_DOUBLE
+#undef STRING
+
+C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jobject jvmci_method))
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  ResourceMark rm;
+
+  int code_size = method->code_size();
+  typeArrayOop reconstituted_code = oopFactory::new_byteArray(code_size, CHECK_NULL);
+
+  guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten");
+  // iterate over all bytecodes and replace non-Java bytecodes
+
+  for (BytecodeStream s(method); s.next() != Bytecodes::_illegal; ) {
+    Bytecodes::Code code = s.code();
+    Bytecodes::Code raw_code = s.raw_code();
+    int bci = s.bci();
+    int len = s.instruction_size();
+
+    // Restore original byte code.
+    reconstituted_code->byte_at_put(bci, (jbyte) (s.is_wide()? Bytecodes::_wide : code));
+    if (len > 1) {
+      memcpy(reconstituted_code->byte_at_addr(bci + 1), s.bcp()+1, len-1);
+    }
+
+    if (len > 1) {
+      // Restore the big-endian constant pool indexes.
+      // Cf. Rewriter::scan_method
+      switch (code) {
+        case Bytecodes::_getstatic:
+        case Bytecodes::_putstatic:
+        case Bytecodes::_getfield:
+        case Bytecodes::_putfield:
+        case Bytecodes::_invokevirtual:
+        case Bytecodes::_invokespecial:
+        case Bytecodes::_invokestatic:
+        case Bytecodes::_invokeinterface:
+        case Bytecodes::_invokehandle: {
+          int cp_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
+          Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
+          break;
+        }
+
+        case Bytecodes::_invokedynamic:
+          int cp_index = Bytes::get_native_u4((address) reconstituted_code->byte_at_addr(bci + 1));
+          Bytes::put_Java_u4((address) reconstituted_code->byte_at_addr(bci + 1), (u4) cp_index);
+          break;
+      }
+
+      // Not all ldc byte code are rewritten.
+      switch (raw_code) {
+        case Bytecodes::_fast_aldc: {
+          int cpc_index = reconstituted_code->byte_at(bci + 1) & 0xff;
+          int cp_index = method->constants()->object_to_cp_index(cpc_index);
+          assert(cp_index < method->constants()->length(), "sanity check");
+          reconstituted_code->byte_at_put(bci + 1, (jbyte) cp_index);
+          break;
+        }
+
+        case Bytecodes::_fast_aldc_w: {
+          int cpc_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
+          int cp_index = method->constants()->object_to_cp_index(cpc_index);
+          assert(cp_index < method->constants()->length(), "sanity check");
+          Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
+          break;
+        }
+      }
+    }
+  }
+
+  return (jbyteArray) JNIHandles::make_local(THREAD, reconstituted_code);
+C2V_END
+
+C2V_VMENTRY(jint, getExceptionTableLength, (JNIEnv *, jobject, jobject jvmci_method))
+  ResourceMark rm;
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  return method->exception_table_length();
+C2V_END
+
+C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv *, jobject, jobject jvmci_method))
+  ResourceMark rm;
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  if (method->exception_table_length() == 0) {
+    return 0L;
+  }
+  return (jlong) (address) method->exception_table_start();
+C2V_END
+
+C2V_VMENTRY(jobject, asResolvedJavaMethod, (JNIEnv *, jobject, jobject executable_handle))
+  oop executable = JNIHandles::resolve(executable_handle);
+  oop mirror = NULL;
+  int slot = 0;
+
+  if (executable->klass() == SystemDictionary::reflect_Constructor_klass()) {
+    mirror = java_lang_reflect_Constructor::clazz(executable);
+    slot = java_lang_reflect_Constructor::slot(executable);
+  } else {
+    assert(executable->klass() == SystemDictionary::reflect_Method_klass(), "wrong type");
+    mirror = java_lang_reflect_Method::clazz(executable);
+    slot = java_lang_reflect_Method::slot(executable);
+  }
+  Klass* holder = java_lang_Class::as_Klass(mirror);
+  methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot);
+  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+}
+
+C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv *, jobject, jobject base, jlong offset))
+  methodHandle method;
+  oop base_object = JNIHandles::resolve(base);
+  if (base_object == NULL) {
+    method = *((Method**)(offset));
+  } else if (base_object->is_a(SystemDictionary::MemberName_klass())) {
+    method = (Method*) (intptr_t) base_object->long_field(offset);
+  } else if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+    method = *((Method**)(HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object) + offset));
+  } else {
+    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Unexpected type: %s", base_object->klass()->external_name()));
+  }
+  assert (method.is_null() || method->is_method(), "invalid read");
+  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+}
+
+C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject object_handle))
+  constantPoolHandle cp;
+  oop object = JNIHandles::resolve(object_handle);
+  if (object == NULL) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+  if (object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+    cp = CompilerToVM::asMethod(object)->constMethod()->constants();
+  } else if (object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
+    cp = InstanceKlass::cast(CompilerToVM::asKlass(object))->constants();
+  } else {
+    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Unexpected type: %s", object->klass()->external_name()));
+  }
+  assert(!cp.is_null(), "npe");
+  JavaValue method_result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_long((jlong) (address) cp());
+  JavaCalls::call_static(&method_result, SystemDictionary::HotSpotConstantPool_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::constantPool_fromMetaspace_signature(), &args, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, (oop)method_result.get_jobject());
+}
+
+C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlong offset, jboolean compressed))
+  KlassHandle klass;
+  oop base_object = JNIHandles::resolve(base);
+  jlong base_address = 0;
+  if (base_object != NULL && offset == oopDesc::klass_offset_in_bytes()) {
+    klass = base_object->klass();
+  } else if (!compressed) {
+    if (base_object != NULL) {
+      if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+        base_address = HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object);
+      } else if (base_object->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
+        base_address = HotSpotConstantPool::metaspaceConstantPool(base_object);
+      } else if (base_object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
+        base_address = (jlong) CompilerToVM::asKlass(base_object);
+      } else if (base_object->is_a(SystemDictionary::Class_klass())) {
+        base_address = (jlong) (address) base_object;
+      } else {
+        THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+                    err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", base_object->klass()->external_name(), offset, compressed ? "true" : "false"));
+      }
+    }
+    klass = *((Klass**) (intptr_t) (base_address + offset));
+  } else {
+    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", base_object->klass()->external_name(), offset, compressed ? "true" : "false"));
+  }
+  assert (klass.is_null() || klass->is_klass(), "invalid read");
+  oop result = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+}
+
+C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method))
+  ResourceMark rm;
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  KlassHandle holder = CompilerToVM::asKlass(jvmci_type);
+  if (holder->is_interface()) {
+    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", holder->external_name()));
+  }
+
+  methodHandle ucm;
+  {
+    MutexLocker locker(Compile_lock);
+    ucm = Dependencies::find_unique_concrete_method(holder(), method());
+  }
+  oop result = CompilerToVM::get_jvmci_method(ucm, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jobject, getImplementor, (JNIEnv *, jobject, jobject jvmci_type))
+  InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type);
+  oop implementor = CompilerToVM::get_jvmci_type(klass->implementor(), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, implementor);
+C2V_END
+
+C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv *, jobject, jobject jvmci_method))
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  return method->is_ignored_by_security_stack_walk();
+C2V_END
+
+C2V_VMENTRY(jboolean, isCompilable,(JNIEnv *, jobject, jobject jvmci_method))
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  // Ignore the not_compilable flags in hosted mode since they are never set by
+  // the JVMCI compiler.
+  return UseJVMCICompiler || !method->is_not_compilable(CompLevel_full_optimization);
+C2V_END
+
+C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv *, jobject, jobject jvmci_method))
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  return CompilerOracle::should_not_inline(method) || method->dont_inline();
+C2V_END
+
+C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  return CompilerOracle::should_inline(method) || method->force_inline();
+C2V_END
+
+C2V_VMENTRY(jobject, lookupType, (JNIEnv*, jobject, jstring jname, jclass accessing_class, jboolean resolve))
+  ResourceMark rm;
+  Handle name = JNIHandles::resolve(jname);
+  Symbol* class_name = java_lang_String::as_symbol(name, CHECK_0);
+  if (java_lang_String::length(name()) <= 1) {
+    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string()));
+  }
+
+  Klass* resolved_klass = NULL;
+  Handle class_loader;
+  Handle protection_domain;
+  if (JNIHandles::resolve(accessing_class) == NULL) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+  Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class));
+  class_loader = accessing_klass->class_loader();
+  protection_domain = accessing_klass->protection_domain();
+
+  if (resolve) {
+    resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0);
+  } else {
+    if (class_name->byte_at(0) == 'L' &&
+      class_name->byte_at(class_name->utf8_length()-1) == ';') {
+      // This is a name from a signature.  Strip off the trimmings.
+      // Call recursive to keep scope of strippedsym.
+      TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1,
+                                                          class_name->utf8_length()-2,
+                                                          CHECK_0);
+      resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, CHECK_0);
+    } else if (FieldType::is_array(class_name)) {
+      FieldArrayInfo fd;
+      // dimension and object_key in FieldArrayInfo are assigned as a side-effect
+      // of this call
+      BasicType t = FieldType::get_array_info(class_name, fd, CHECK_0);
+      if (t == T_OBJECT) {
+        TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1+fd.dimension(),
+                                                            class_name->utf8_length()-2-fd.dimension(),
+                                                            CHECK_0);
+        // naked oop "k" is OK here -- we assign back into it
+        resolved_klass = SystemDictionary::find(strippedsym,
+                                                             class_loader,
+                                                             protection_domain,
+                                                             CHECK_0);
+        if (resolved_klass != NULL) {
+          resolved_klass = resolved_klass->array_klass(fd.dimension(), CHECK_0);
+        }
+      } else {
+        resolved_klass = Universe::typeArrayKlassObj(t);
+        resolved_klass = TypeArrayKlass::cast(resolved_klass)->array_klass(fd.dimension(), CHECK_0);
+      }
+    }
+  }
+  Handle result = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result());
+C2V_END
+
+C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  oop result = cp->resolve_constant_at(index, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  oop result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  return cp->name_and_type_ref_index_at(index);
+C2V_END
+
+C2V_VMENTRY(jobject, lookupNameInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint which))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  Handle sym = java_lang_String::create_from_symbol(cp->name_ref_at(which), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, sym());
+C2V_END
+
+C2V_VMENTRY(jobject, lookupSignatureInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint which))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  Handle sym = java_lang_String::create_from_symbol(cp->signature_ref_at(which), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, sym());
+C2V_END
+
+C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  return cp->klass_ref_index_at(index);
+C2V_END
+
+C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  Klass* resolved_klass = cp->klass_at(index, CHECK_NULL);
+  Handle klass = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, klass());
+C2V_END
+
+C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  KlassHandle loading_klass(cp->pool_holder());
+  bool is_accessible = false;
+  KlassHandle klass = JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass);
+  Symbol* symbol = NULL;
+  if (klass.is_null()) {
+    // We have to lock the cpool to keep the oop from being resolved
+    // while we are accessing it.
+    MonitorLockerEx ml(cp->lock());
+    constantTag tag = cp->tag_at(index);
+    if (tag.is_klass()) {
+      // The klass has been inserted into the constant pool
+      // very recently.
+      klass = cp->resolved_klass_at(index);
+    } else if (tag.is_symbol()) {
+      symbol = cp->symbol_at(index);
+    } else {
+      assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag");
+      symbol = cp->unresolved_klass_at(index);
+    }
+  }
+  Handle result;
+  if (!klass.is_null()) {
+    result = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
+  } else {
+    result = java_lang_String::create_from_symbol(symbol, CHECK_NULL);
+  }
+  return JNIHandles::make_local(THREAD, result());
+C2V_END
+
+C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index);
+  return JNIHandles::make_local(THREAD, appendix_oop);
+C2V_END
+
+C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  instanceKlassHandle pool_holder(cp->pool_holder());
+  Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
+  methodHandle method = JVMCIEnv::get_method_by_index(cp, index, bc, pool_holder);
+  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  return cp->remap_instruction_operand_from_cache(index);
+C2V_END
+
+C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode, jintArray info_handle))
+  ResourceMark rm;
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
+  fieldDescriptor fd;
+  LinkResolver::resolve_field_access(fd, cp, index, Bytecodes::java_code(code), true, false, CHECK_0);
+  typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
+  if (info == NULL || info->length() != 3) {
+    JVMCI_ERROR_NULL("info must not be null and have a length of 3");
+  }
+  info->int_at_put(0, fd.access_flags().as_int());
+  info->int_at_put(1, fd.offset());
+  info->int_at_put(2, fd.index());
+  oop field_holder = CompilerToVM::get_jvmci_type(fd.field_holder(), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, field_holder);
+C2V_END
+
+C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method))
+  ResourceMark rm;
+  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+  Method* method = CompilerToVM::asMethod(jvmci_method);
+  if (klass->is_interface()) {
+    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", klass->external_name()));
+  }
+  if (!method->method_holder()->is_interface()) {
+    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string()));
+  }
+  if (!InstanceKlass::cast(klass)->is_linked()) {
+    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Class %s must be linked", klass->external_name()));
+  }
+  return LinkResolver::vtable_index_of_interface_method(klass, method);
+C2V_END
+
+C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type))
+  KlassHandle recv_klass = CompilerToVM::asKlass(receiver_jvmci_type);
+  KlassHandle caller_klass = CompilerToVM::asKlass(caller_jvmci_type);
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+
+  KlassHandle h_resolved   (THREAD, method->method_holder());
+  Symbol* h_name      = method->name();
+  Symbol* h_signature = method->signature();
+
+  methodHandle m;
+  // Only do exact lookup if receiver klass has been linked.  Otherwise,
+  // the vtable has not been setup, and the LinkResolver will fail.
+  if (recv_klass->oop_is_array() ||
+      InstanceKlass::cast(recv_klass())->is_linked() && !recv_klass->is_interface()) {
+    bool check_access = true;
+    if (h_resolved->is_interface()) {
+      m = LinkResolver::resolve_interface_call_or_null(recv_klass, h_resolved, h_name, h_signature, caller_klass, check_access);
+    } else {
+      m = LinkResolver::resolve_virtual_call_or_null(recv_klass, h_resolved, h_name, h_signature, caller_klass, check_access);
+    }
+  }
+
+  if (m.is_null()) {
+    // Return NULL only if there was a problem with lookup (uninitialized class, etc.)
+    return NULL;
+  }
+
+  oop result = CompilerToVM::get_jvmci_method(m, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject jvmci_type))
+  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+  assert(klass != NULL, "method must not be called for primitive types");
+  return Dependencies::find_finalizable_subclass(klass) != NULL;
+C2V_END
+
+C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv *, jobject, jobject jvmci_type))
+  InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type);
+  oop result = CompilerToVM::get_jvmci_method(klass->class_initializer(), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv*, jobject, jlong addr))
+  address target_addr = (address) addr;
+  if (target_addr != 0x0) {
+    int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int));
+    int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int));
+    return MAX2(ABS(off_low), ABS(off_high));
+  }
+  return -1;
+C2V_END
+
+C2V_VMENTRY(void, doNotInlineOrCompile,(JNIEnv *, jobject,  jobject jvmci_method))
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  method->set_not_c1_compilable();
+  method->set_not_c2_compilable();
+  method->set_dont_inline(true);
+C2V_END
+
+C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject compiled_code, jobject installed_code, jobject speculation_log))
+  ResourceMark rm;
+  HandleMark hm;
+  Handle target_handle = JNIHandles::resolve(target);
+  Handle compiled_code_handle = JNIHandles::resolve(compiled_code);
+  CodeBlob* cb = NULL;
+  Handle installed_code_handle = JNIHandles::resolve(installed_code);
+  Handle speculation_log_handle = JNIHandles::resolve(speculation_log);
+
+  JVMCICompiler* compiler = JVMCICompiler::instance(CHECK_(JNI_ERR));
+
+  TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer());
+  CodeInstaller installer;
+  JVMCIEnv::CodeInstallResult result = installer.install(compiler, target_handle, compiled_code_handle, cb, installed_code_handle, speculation_log_handle, CHECK_0);
+
+  if (PrintCodeCacheOnCompilation) {
+    stringStream s;
+    // Dump code cache  into a buffer before locking the tty,
+    {
+      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      CodeCache::print_summary(&s, false);
+    }
+    ttyLocker ttyl;
+    tty->print_raw_cr(s.as_string());
+  }
+
+  if (result != JVMCIEnv::ok) {
+    assert(cb == NULL, "should be");
+  } else {
+    if (!installed_code_handle.is_null()) {
+      assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
+      nmethod::invalidate_installed_code(installed_code_handle, CHECK_0);
+      {
+        // Ensure that all updates to the InstalledCode fields are consistent.
+        MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+        InstalledCode::set_address(installed_code_handle, (jlong) cb);
+        InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
+        if (cb->is_nmethod()) {
+          InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->as_nmethod_or_null()->verified_entry_point());
+        } else {
+          InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->code_begin());
+        }
+        if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
+          HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
+          HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
+          HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
+        }
+      }
+      nmethod* nm = cb->as_nmethod_or_null();
+      if (nm != NULL && installed_code_handle->is_scavengable()) {
+        assert(nm->detect_scavenge_root_oops(), "nm should be scavengable if installed_code is scavengable");
+        if (!UseG1GC) {
+          assert(nm->on_scavenge_root_list(), "nm should be on scavengable list");
+        }
+      }
+    }
+  }
+  return result;
+C2V_END
+
+C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
+  JVMCICompiler* compiler = JVMCICompiler::instance(CHECK);
+  CompilerStatistics* stats = compiler->stats();
+  stats->_standard.reset();
+  stats->_osr.reset();
+C2V_END
+
+C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jobject installedCode))
+  ResourceMark rm;
+  HandleMark hm;
+
+  if (installedCode == NULL) {
+    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "installedCode is null");
+  }
+
+  jlong codeBlob = InstalledCode::address(installedCode);
+  if (codeBlob == 0L) {
+    return NULL;
+  }
+
+  CodeBlob* cb = (CodeBlob*) (address) codeBlob;
+  if (cb == NULL) {
+    return NULL;
+  }
+
+  // We don't want the stringStream buffer to resize during disassembly as it
+  // uses scoped resource memory. If a nested function called during disassembly uses
+  // a ResourceMark and the buffer expands within the scope of the mark,
+  // the buffer becomes garbage when that scope is exited. Experience shows that
+  // the disassembled code is typically about 10x the code size so a fixed buffer
+  // sized to 20x code size plus a fixed amount for header info should be sufficient.
+  int bufferSize = cb->code_size() * 20 + 1024;
+  char* buffer = NEW_RESOURCE_ARRAY(char, bufferSize);
+  stringStream st(buffer, bufferSize);
+  if (cb->is_nmethod()) {
+    nmethod* nm = (nmethod*) cb;
+    if (!nm->is_alive()) {
+      return NULL;
+    }
+    Disassembler::decode(nm, &st);
+  } else {
+    Disassembler::decode(cb, &st);
+  }
+  if (st.size() <= 0) {
+    return NULL;
+  }
+
+  Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result());
+C2V_END
+
+C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv*, jobject, jobject jvmci_method, int bci))
+  ResourceMark rm;
+  HandleMark hm;
+
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, element);
+C2V_END
+
+C2V_VMENTRY(jobject, executeInstalledCode, (JNIEnv*, jobject, jobject args, jobject hotspotInstalledCode))
+  ResourceMark rm;
+  HandleMark hm;
+
+  jlong nmethodValue = InstalledCode::address(hotspotInstalledCode);
+  if (nmethodValue == 0L) {
+    THROW_NULL(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException());
+  }
+  nmethod* nm = (nmethod*) (address) nmethodValue;
+  methodHandle mh = nm->method();
+  Symbol* signature = mh->signature();
+  JavaCallArguments jca(mh->size_of_parameters());
+
+  JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
+  JavaValue result(jap.get_ret_type());
+  jca.set_alternative_target(nm);
+  JavaCalls::call(&result, mh, &jca, CHECK_NULL);
+
+  if (jap.get_ret_type() == T_VOID) {
+    return NULL;
+  } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) {
+    return JNIHandles::make_local(THREAD, (oop) result.get_jobject());
+  } else {
+    jvalue *value = (jvalue *) result.get_value_addr();
+    // Narrow the value down if required (Important on big endian machines)
+    switch (jap.get_ret_type()) {
+      case T_BOOLEAN:
+       value->z = (jboolean) value->i;
+       break;
+      case T_BYTE:
+       value->b = (jbyte) value->i;
+       break;
+      case T_CHAR:
+       value->c = (jchar) value->i;
+       break;
+      case T_SHORT:
+       value->s = (jshort) value->i;
+       break;
+     }
+    oop o = java_lang_boxing_object::create(jap.get_ret_type(), value, CHECK_NULL);
+    return JNIHandles::make_local(THREAD, o);
+  }
+C2V_END
+
+C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv *, jobject, jobject jvmci_method))
+  Method* method = CompilerToVM::asMethod(jvmci_method);
+  if (!method->has_linenumber_table()) {
+    return NULL;
+  }
+  u2 num_entries = 0;
+  CompressedLineNumberReadStream streamForSize(method->compressed_linenumber_table());
+  while (streamForSize.read_pair()) {
+    num_entries++;
+  }
+
+  CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
+  typeArrayOop result = oopFactory::new_longArray(2 * num_entries, CHECK_NULL);
+
+  int i = 0;
+  jlong value;
+  while (stream.read_pair()) {
+    value = ((long) stream.bci());
+    result->long_at_put(i, value);
+    value = ((long) stream.line());
+    result->long_at_put(i + 1, value);
+    i += 2;
+  }
+
+  return (jlongArray) JNIHandles::make_local(THREAD, result);
+C2V_END
+
+C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv *, jobject, jobject jvmci_method))
+  ResourceMark rm;
+  Method* method = CompilerToVM::asMethod(jvmci_method);
+  if (!method->has_localvariable_table()) {
+    return 0;
+  }
+  return (jlong) (address) method->localvariable_table_start();
+C2V_END
+
+C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv *, jobject, jobject jvmci_method))
+  ResourceMark rm;
+  Method* method = CompilerToVM::asMethod(jvmci_method);
+  return method->localvariable_table_length();
+C2V_END
+
+C2V_VMENTRY(void, reprofile, (JNIEnv*, jobject, jobject jvmci_method))
+  Method* method = CompilerToVM::asMethod(jvmci_method);
+  MethodCounters* mcs = method->method_counters();
+  if (mcs != NULL) {
+    mcs->clear_counters();
+  }
+  NOT_PRODUCT(method->set_compiled_invocation_count(0));
+
+  nmethod* code = method->code();
+  if (code != NULL) {
+    code->make_not_entrant();
+  }
+
+  MethodData* method_data = method->method_data();
+  if (method_data == NULL) {
+    ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
+    method_data = MethodData::allocate(loader_data, method, CHECK);
+    method->set_method_data(method_data);
+  } else {
+    method_data->initialize();
+  }
+C2V_END
+
+
+C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject installed_code))
+  Handle installed_code_handle = JNIHandles::resolve(installed_code);
+  nmethod::invalidate_installed_code(installed_code_handle, CHECK);
+C2V_END
+
+C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv*, jobject, jlong addr))
+  oop ret = oopDesc::load_decode_heap_oop((oop*)(address)addr);
+  return JNIHandles::make_local(THREAD, ret);
+C2V_END
+
+C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv*, jobject))
+  typeArrayOop arrayOop = oopFactory::new_longArray(JVMCICounterSize, CHECK_NULL);
+  JavaThread::collect_counters(arrayOop);
+  return (jlongArray) JNIHandles::make_local(THREAD, arrayOop);
+C2V_END
+
+C2V_VMENTRY(int, allocateCompileId, (JNIEnv*, jobject, jobject jvmci_method, int entry_bci))
+  HandleMark hm;
+  ResourceMark rm;
+  if (JNIHandles::resolve(jvmci_method) == NULL) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+  Method* method = CompilerToVM::asMethod(jvmci_method);
+  if (entry_bci >= method->code_size() || entry_bci < -1) {
+    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Unexpected bci %d", entry_bci));
+  }
+  return CompileBroker::assign_compile_id_unlocked(THREAD, method, entry_bci);
+C2V_END
+
+
+C2V_VMENTRY(jboolean, isMature, (JNIEnv*, jobject, jlong metaspace_method_data))
+  MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data);
+  return mdo != NULL && mdo->is_mature();
+C2V_END
+
+C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv*, jobject, jobject jvmci_method, int entry_bci, int comp_level))
+  Method* method = CompilerToVM::asMethod(jvmci_method);
+  return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL;
+C2V_END
+
+C2V_VMENTRY(jobject, getSymbol, (JNIEnv*, jobject, jlong symbol))
+  Handle sym = java_lang_String::create_from_symbol((Symbol*)(address)symbol, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, sym());
+C2V_END
+
+bool matches(jobjectArray methods, Method* method) {
+  objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods);
+
+  for (int i = 0; i < methods_oop->length(); i++) {
+    oop resolved = methods_oop->obj_at(i);
+    if (resolved->is_a(HotSpotResolvedJavaMethodImpl::klass()) && CompilerToVM::asMethod(resolved) == method) {
+      return true;
+    }
+  }
+  return false;
+}
+
+C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject hs_frame, jobjectArray methods, jint initialSkip))
+  ResourceMark rm;
+
+  if (!thread->has_last_Java_frame()) return NULL;
+  Handle result = HotSpotStackFrameReference::klass()->allocate_instance(thread);
+  HotSpotStackFrameReference::klass()->initialize(thread);
+
+  StackFrameStream fst(thread);
+  if (hs_frame != NULL) {
+    // look for the correct stack frame if one is given
+    intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
+    while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
+      fst.next();
+    }
+    if (fst.current()->sp() != stack_pointer) {
+      THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
+    }
+  }
+
+  int frame_number = 0;
+  vframe* vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+  if (hs_frame != NULL) {
+    // look for the correct vframe within the stack frame if one is given
+    int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
+    while (frame_number < last_frame_number) {
+      if (vf->is_top()) {
+        THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
+      }
+      vf = vf->sender();
+      frame_number ++;
+    }
+    // move one frame forward
+    if (vf->is_top()) {
+      if (fst.is_done()) {
+        return NULL;
+      }
+      fst.next();
+      vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+      frame_number = 0;
+    } else {
+      vf = vf->sender();
+      frame_number++;
+    }
+  }
+
+  while (true) {
+    // look for the given method
+    while (true) {
+      StackValueCollection* locals = NULL;
+      if (vf->is_compiled_frame()) {
+        // compiled method frame
+        compiledVFrame* cvf = compiledVFrame::cast(vf);
+        if (methods == NULL || matches(methods, cvf->method())) {
+          if (initialSkip > 0) {
+            initialSkip --;
+          } else {
+            ScopeDesc* scope = cvf->scope();
+            // native wrapper do not have a scope
+            if (scope != NULL && scope->objects() != NULL) {
+              bool realloc_failures = Deoptimization::realloc_objects(thread, fst.current(), scope->objects(), THREAD);
+              Deoptimization::reassign_fields(fst.current(), fst.register_map(), scope->objects(), realloc_failures, false);
+
+              GrowableArray<ScopeValue*>* local_values = scope->locals();
+              typeArrayHandle array = oopFactory::new_boolArray(local_values->length(), thread);
+              for (int i = 0; i < local_values->length(); i++) {
+                ScopeValue* value = local_values->at(i);
+                if (value->is_object()) {
+                  array->bool_at_put(i, true);
+                }
+              }
+              HotSpotStackFrameReference::set_localIsVirtual(result, array());
+            } else {
+              HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
+            }
+
+            locals = cvf->locals();
+            HotSpotStackFrameReference::set_bci(result, cvf->bci());
+            oop method = CompilerToVM::get_jvmci_method(cvf->method(), CHECK_NULL);
+            HotSpotStackFrameReference::set_method(result, method);
+          }
+        }
+      } else if (vf->is_interpreted_frame()) {
+        // interpreted method frame
+        interpretedVFrame* ivf = interpretedVFrame::cast(vf);
+        if (methods == NULL || matches(methods, ivf->method())) {
+          if (initialSkip > 0) {
+            initialSkip --;
+          } else {
+            locals = ivf->locals();
+            HotSpotStackFrameReference::set_bci(result, ivf->bci());
+            oop method = CompilerToVM::get_jvmci_method(ivf->method(), CHECK_NULL);
+            HotSpotStackFrameReference::set_method(result, method);
+            HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
+          }
+        }
+      }
+
+      // locals != NULL means that we found a matching frame and result is already partially initialized
+      if (locals != NULL) {
+        HotSpotStackFrameReference::set_compilerToVM(result, JNIHandles::resolve(compilerToVM));
+        HotSpotStackFrameReference::set_stackPointer(result, (jlong) fst.current()->sp());
+        HotSpotStackFrameReference::set_frameNumber(result, frame_number);
+
+        // initialize the locals array
+        objArrayHandle array = oopFactory::new_objectArray(locals->size(), thread);
+        for (int i = 0; i < locals->size(); i++) {
+          StackValue* var = locals->at(i);
+          if (var->type() == T_OBJECT) {
+            array->obj_at_put(i, locals->at(i)->get_obj()());
+          }
+        }
+        HotSpotStackFrameReference::set_locals(result, array());
+
+        return JNIHandles::make_local(thread, result());
+      }
+
+      if (vf->is_top()) {
+        break;
+      }
+      frame_number++;
+      vf = vf->sender();
+    } // end of vframe loop
+
+    if (fst.is_done()) {
+      break;
+    }
+    fst.next();
+    vf = vframe::new_vframe(fst.current(), fst.register_map(), thread);
+    frame_number = 0;
+  } // end of frame loop
+
+  // the end was reached without finding a matching method
+  return NULL;
+C2V_END
+
+C2V_VMENTRY(void, resolveInvokeDynamicInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  CallInfo callInfo;
+  LinkResolver::resolve_invokedynamic(callInfo, cp, index, CHECK);
+  ConstantPoolCacheEntry* cp_cache_entry = cp->invokedynamic_cp_cache_entry_at(index);
+  cp_cache_entry->set_dynamic_call(cp, callInfo);
+C2V_END
+
+C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  KlassHandle holder = cp->klass_ref_at(index, CHECK);
+  Symbol* name = cp->name_ref_at(index);
+  if (MethodHandles::is_signature_polymorphic_name(holder(), name)) {
+    CallInfo callInfo;
+    LinkResolver::resolve_invokehandle(callInfo, cp, index, CHECK);
+    ConstantPoolCacheEntry* cp_cache_entry = cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
+    cp_cache_entry->set_method_handle(cp, callInfo);
+  }
+C2V_END
+
+C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv*, jobject))
+  objArrayHandle holders = oopFactory::new_objArray(SystemDictionary::String_klass(), 2, CHECK_NULL);
+  Handle mh = java_lang_String::create_from_str("Ljava/lang/invoke/MethodHandle;", CHECK_NULL);
+  Handle vh = java_lang_String::create_from_str("Ljava/lang/invoke/VarHandle;", CHECK_NULL);
+  holders->obj_at_put(0, mh());
+  holders->obj_at_put(1, vh());
+  return JNIHandles::make_local(THREAD, holders());
+C2V_END
+
+C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv*, jobject))
+  //see compute_recording_non_safepoints in debugInfroRec.cpp
+  if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
+    return true;
+  }
+  return DebugNonSafepoints;
+C2V_END
+
+// public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
+C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame, bool invalidate))
+  ResourceMark rm;
+
+  if (hs_frame == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null")
+  }
+
+  HotSpotStackFrameReference::klass()->initialize(thread);
+
+  // look for the given stack frame
+  StackFrameStream fst(thread);
+  intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
+  while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
+    fst.next();
+  }
+  if (fst.current()->sp() != stack_pointer) {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
+  }
+
+  if (invalidate) {
+    if (!fst.current()->is_compiled_frame()) {
+      THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+    }
+    assert(fst.current()->cb()->is_nmethod(), "nmethod expected");
+    ((nmethod*) fst.current()->cb())->make_not_entrant();
+  }
+  Deoptimization::deoptimize(thread, *fst.current(), fst.register_map(), Deoptimization::Reason_none);
+  // look for the frame again as it has been updated by deopt (pc, deopt state...)
+  StackFrameStream fstAfterDeopt(thread);
+  while (fstAfterDeopt.current()->sp() != stack_pointer && !fstAfterDeopt.is_done()) {
+    fstAfterDeopt.next();
+  }
+  if (fstAfterDeopt.current()->sp() != stack_pointer) {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found after deopt")
+  }
+
+  vframe* vf = vframe::new_vframe(fstAfterDeopt.current(), fstAfterDeopt.register_map(), thread);
+  if (!vf->is_compiled_frame()) {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+  }
+
+  GrowableArray<compiledVFrame*>* virtualFrames = new GrowableArray<compiledVFrame*>(10);
+  while (true) {
+    assert(vf->is_compiled_frame(), "Wrong frame type");
+    virtualFrames->push(compiledVFrame::cast(vf));
+    if (vf->is_top()) {
+      break;
+    }
+    vf = vf->sender();
+  }
+
+  int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
+  if (last_frame_number >= virtualFrames->length()) {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
+  }
+
+  // Reallocate the non-escaping objects and restore their fields.
+  assert (virtualFrames->at(last_frame_number)->scope() != NULL,"invalid scope");
+  GrowableArray<ScopeValue*>* objects = virtualFrames->at(last_frame_number)->scope()->objects();
+
+  if (objects == NULL) {
+    // no objects to materialize
+    return;
+  }
+
+  bool realloc_failures = Deoptimization::realloc_objects(thread, fstAfterDeopt.current(), objects, THREAD);
+  Deoptimization::reassign_fields(fstAfterDeopt.current(), fstAfterDeopt.register_map(), objects, realloc_failures, false);
+
+  for (int frame_index = 0; frame_index < virtualFrames->length(); frame_index++) {
+    compiledVFrame* cvf = virtualFrames->at(frame_index);
+
+    GrowableArray<ScopeValue*>* scopeLocals = cvf->scope()->locals();
+    StackValueCollection* locals = cvf->locals();
+
+    if (locals != NULL) {
+      for (int i2 = 0; i2 < locals->size(); i2++) {
+        StackValue* var = locals->at(i2);
+        if (var->type() == T_OBJECT && scopeLocals->at(i2)->is_object()) {
+          jvalue val;
+          val.l = (jobject) locals->at(i2)->get_obj()();
+          cvf->update_local(T_OBJECT, i2, val);
+        }
+      }
+    }
+  }
+
+  // all locals are materialized by now
+  HotSpotStackFrameReference::set_localIsVirtual(hs_frame, NULL);
+
+  // update the locals array
+  objArrayHandle array = HotSpotStackFrameReference::locals(hs_frame);
+  StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals();
+  for (int i = 0; i < locals->size(); i++) {
+    StackValue* var = locals->at(i);
+    if (var->type() == T_OBJECT) {
+      array->obj_at_put(i, locals->at(i)->get_obj()());
+    }
+  }
+C2V_END
+
+C2V_VMENTRY(void, writeDebugOutput, (JNIEnv*, jobject, jbyteArray bytes, jint offset, jint length))
+  if (bytes == NULL) {
+    THROW(vmSymbols::java_lang_NullPointerException());
+  }
+  typeArrayOop array = (typeArrayOop) JNIHandles::resolve(bytes);
+
+  // Check if offset and length are non negative.
+  if (offset < 0 || length < 0) {
+    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
+  }
+  // Check if the range is valid.
+  if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array->length())) {
+    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
+  }
+  while (length > 0) {
+    jbyte* start = array->byte_at_addr(offset);
+    tty->write((char*) start, MIN2(length, O_BUFLEN));
+    length -= O_BUFLEN;
+    offset += O_BUFLEN;
+  }
+C2V_END
+
+C2V_VMENTRY(void, flushDebugOutput, (JNIEnv*, jobject))
+  tty->flush();
+C2V_END
+
+C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv*, jobject, jlong metaspace_method_data, jint position))
+  ResourceMark rm;
+  MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data);
+  ProfileData* profile_data = mdo->data_at(position);
+  if (mdo->is_valid(profile_data)) {
+    return profile_data->size_in_bytes();
+  }
+  DataLayout* data    = mdo->extra_data_base();
+  DataLayout* end   = mdo->extra_data_limit();
+  for (;; data = mdo->next_extra(data)) {
+    assert(data < end, "moved past end of extra data");
+    profile_data = data->data_in();
+    if (mdo->dp_to_di(profile_data->dp()) == position) {
+      return profile_data->size_in_bytes();
+    }
+  }
+  THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Invalid profile data position %d", position));
+C2V_END
+
+C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv*, jobject, jobject bytecode_frame_handle))
+  if (bytecode_frame_handle == NULL) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+
+  oop top_bytecode_frame = JNIHandles::resolve_non_null(bytecode_frame_handle);
+  oop bytecode_frame = top_bytecode_frame;
+  int size = 0;
+  int callee_parameters = 0;
+  int callee_locals = 0;
+  Method* method = getMethodFromHotSpotMethod(BytecodePosition::method(bytecode_frame));
+  int extra_args = method->max_stack() - BytecodeFrame::numStack(bytecode_frame);
+
+  while (bytecode_frame != NULL) {
+    int locks = BytecodeFrame::numLocks(bytecode_frame);
+    int temps = BytecodeFrame::numStack(bytecode_frame);
+    bool is_top_frame = (bytecode_frame == top_bytecode_frame);
+    Method* method = getMethodFromHotSpotMethod(BytecodePosition::method(bytecode_frame));
+
+    int frame_size = BytesPerWord * Interpreter::size_activation(method->max_stack(),
+                                                                 temps + callee_parameters,
+                                                                 extra_args,
+                                                                 locks,
+                                                                 callee_parameters,
+                                                                 callee_locals,
+                                                                 is_top_frame);
+    size += frame_size;
+
+    callee_parameters = method->size_of_parameters();
+    callee_locals = method->max_locals();
+    extra_args = 0;
+    bytecode_frame = BytecodePosition::caller(bytecode_frame);
+  }
+  return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord;
+C2V_END
+
+C2V_VMENTRY(void, compileToBytecode, (JNIEnv*, jobject, jobject lambda_form_handle))
+  Handle lambda_form = JNIHandles::resolve_non_null(lambda_form_handle);
+  if (lambda_form->is_a(SystemDictionary::LambdaForm_klass())) {
+    TempNewSymbol compileToBytecode = SymbolTable::new_symbol("compileToBytecode", CHECK);
+    JavaValue result(T_VOID);
+    JavaCalls::call_special(&result, lambda_form, SystemDictionary::LambdaForm_klass(), compileToBytecode, vmSymbols::void_method_signature(), CHECK);
+  } else {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Unexpected type: %s", lambda_form->klass()->external_name()));
+  }
+C2V_END
+
+#define CC (char*)  /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
+
+#define STRING                "Ljava/lang/String;"
+#define OBJECT                "Ljava/lang/Object;"
+#define CLASS                 "Ljava/lang/Class;"
+#define EXECUTABLE            "Ljava/lang/reflect/Executable;"
+#define STACK_TRACE_ELEMENT   "Ljava/lang/StackTraceElement;"
+#define INSTALLED_CODE        "Ljdk/vm/ci/code/InstalledCode;"
+#define TARGET_DESCRIPTION    "Ljdk/vm/ci/code/TargetDescription;"
+#define BYTECODE_FRAME        "Ljdk/vm/ci/code/BytecodeFrame;"
+#define RESOLVED_METHOD       "Ljdk/vm/ci/meta/ResolvedJavaMethod;"
+#define HS_RESOLVED_METHOD    "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;"
+#define HS_RESOLVED_KLASS     "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;"
+#define HS_CONSTANT_POOL      "Ljdk/vm/ci/hotspot/HotSpotConstantPool;"
+#define HS_COMPILED_CODE      "Ljdk/vm/ci/hotspot/HotSpotCompiledCode;"
+#define HS_STACK_FRAME_REF    "Ljdk/vm/ci/hotspot/HotSpotStackFrameReference;"
+#define HS_SPECULATION_LOG    "Ljdk/vm/ci/hotspot/HotSpotSpeculationLog;"
+#define METASPACE_METHOD_DATA "J"
+
+JNINativeMethod CompilerToVM::methods[] = {
+  {CC"getBytecode",                                  CC"("HS_RESOLVED_METHOD")[B",                                                     FN_PTR(getBytecode)},
+  {CC"getExceptionTableStart",                       CC"("HS_RESOLVED_METHOD")J",                                                      FN_PTR(getExceptionTableStart)},
+  {CC"getExceptionTableLength",                      CC"("HS_RESOLVED_METHOD")I",                                                      FN_PTR(getExceptionTableLength)},
+  {CC"findUniqueConcreteMethod",                     CC"("HS_RESOLVED_KLASS HS_RESOLVED_METHOD")"HS_RESOLVED_METHOD,                   FN_PTR(findUniqueConcreteMethod)},
+  {CC"getImplementor",                               CC"("HS_RESOLVED_KLASS")"HS_RESOLVED_KLASS,                                       FN_PTR(getImplementor)},
+  {CC"getStackTraceElement",                         CC"("HS_RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT,                                   FN_PTR(getStackTraceElement)},
+  {CC"methodIsIgnoredBySecurityStackWalk",           CC"("HS_RESOLVED_METHOD")Z",                                                      FN_PTR(methodIsIgnoredBySecurityStackWalk)},
+  {CC"doNotInlineOrCompile",                         CC"("HS_RESOLVED_METHOD")V",                                                      FN_PTR(doNotInlineOrCompile)},
+  {CC"isCompilable",                                 CC"("HS_RESOLVED_METHOD")Z",                                                      FN_PTR(isCompilable)},
+  {CC"hasNeverInlineDirective",                      CC"("HS_RESOLVED_METHOD")Z",                                                      FN_PTR(hasNeverInlineDirective)},
+  {CC"shouldInlineMethod",                           CC"("HS_RESOLVED_METHOD")Z",                                                      FN_PTR(shouldInlineMethod)},
+  {CC"lookupType",                                   CC"("STRING CLASS"Z)"HS_RESOLVED_KLASS,                                           FN_PTR(lookupType)},
+  {CC"lookupNameInPool",                             CC"("HS_CONSTANT_POOL"I)"STRING,                                                  FN_PTR(lookupNameInPool)},
+  {CC"lookupNameAndTypeRefIndexInPool",              CC"("HS_CONSTANT_POOL"I)I",                                                       FN_PTR(lookupNameAndTypeRefIndexInPool)},
+  {CC"lookupSignatureInPool",                        CC"("HS_CONSTANT_POOL"I)"STRING,                                                  FN_PTR(lookupSignatureInPool)},
+  {CC"lookupKlassRefIndexInPool",                    CC"("HS_CONSTANT_POOL"I)I",                                                       FN_PTR(lookupKlassRefIndexInPool)},
+  {CC"lookupKlassInPool",                            CC"("HS_CONSTANT_POOL"I)Ljava/lang/Object;",                                      FN_PTR(lookupKlassInPool)},
+  {CC"lookupAppendixInPool",                         CC"("HS_CONSTANT_POOL"I)"OBJECT,                                                  FN_PTR(lookupAppendixInPool)},
+  {CC"lookupMethodInPool",                           CC"("HS_CONSTANT_POOL"IB)"HS_RESOLVED_METHOD,                                     FN_PTR(lookupMethodInPool)},
+  {CC"constantPoolRemapInstructionOperandFromCache", CC"("HS_CONSTANT_POOL"I)I",                                                       FN_PTR(constantPoolRemapInstructionOperandFromCache)},
+  {CC"resolveConstantInPool",                        CC"("HS_CONSTANT_POOL"I)"OBJECT,                                                  FN_PTR(resolveConstantInPool)},
+  {CC"resolvePossiblyCachedConstantInPool",          CC"("HS_CONSTANT_POOL"I)"OBJECT,                                                  FN_PTR(resolvePossiblyCachedConstantInPool)},
+  {CC"resolveTypeInPool",                            CC"("HS_CONSTANT_POOL"I)"HS_RESOLVED_KLASS,                                       FN_PTR(resolveTypeInPool)},
+  {CC"resolveFieldInPool",                           CC"("HS_CONSTANT_POOL"IB[I)"HS_RESOLVED_KLASS,                                    FN_PTR(resolveFieldInPool)},
+  {CC"resolveInvokeDynamicInPool",                   CC"("HS_CONSTANT_POOL"I)V",                                                       FN_PTR(resolveInvokeDynamicInPool)},
+  {CC"resolveInvokeHandleInPool",                    CC"("HS_CONSTANT_POOL"I)V",                                                       FN_PTR(resolveInvokeHandleInPool)},
+  {CC"resolveMethod",                                CC"("HS_RESOLVED_KLASS HS_RESOLVED_METHOD HS_RESOLVED_KLASS")"HS_RESOLVED_METHOD, FN_PTR(resolveMethod)},
+  {CC"getSignaturePolymorphicHolders",               CC"()[" STRING,                                                                   FN_PTR(getSignaturePolymorphicHolders)},
+  {CC"getVtableIndexForInterfaceMethod",             CC"("HS_RESOLVED_KLASS HS_RESOLVED_METHOD")I",                                    FN_PTR(getVtableIndexForInterfaceMethod)},
+  {CC"getClassInitializer",                          CC"("HS_RESOLVED_KLASS")"HS_RESOLVED_METHOD,                                      FN_PTR(getClassInitializer)},
+  {CC"hasFinalizableSubclass",                       CC"("HS_RESOLVED_KLASS")Z",                                                       FN_PTR(hasFinalizableSubclass)},
+  {CC"getMaxCallTargetOffset",                       CC"(J)J",                                                                         FN_PTR(getMaxCallTargetOffset)},
+  {CC"asResolvedJavaMethod",                         CC"(" EXECUTABLE ")" HS_RESOLVED_METHOD,                                          FN_PTR(asResolvedJavaMethod)},
+  {CC"getResolvedJavaMethod",                        CC"(Ljava/lang/Object;J)"HS_RESOLVED_METHOD,                                      FN_PTR(getResolvedJavaMethod)},
+  {CC"getConstantPool",                              CC"(Ljava/lang/Object;)"HS_CONSTANT_POOL,                                         FN_PTR(getConstantPool)},
+  {CC"getResolvedJavaType",                          CC"(Ljava/lang/Object;JZ)"HS_RESOLVED_KLASS,                                      FN_PTR(getResolvedJavaType)},
+  {CC"readConfiguration",                            CC"()[Ljava/lang/Object;",                                                        FN_PTR(readConfiguration)},
+  {CC"installCode",                                  CC"("TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE HS_SPECULATION_LOG")I",   FN_PTR(installCode)},
+  {CC"resetCompilationStatistics",                   CC"()V",                                                                          FN_PTR(resetCompilationStatistics)},
+  {CC"disassembleCodeBlob",                          CC"("INSTALLED_CODE")"STRING,                                                     FN_PTR(disassembleCodeBlob)},
+  {CC"executeInstalledCode",                         CC"(["OBJECT INSTALLED_CODE")"OBJECT,                                             FN_PTR(executeInstalledCode)},
+  {CC"getLineNumberTable",                           CC"("HS_RESOLVED_METHOD")[J",                                                     FN_PTR(getLineNumberTable)},
+  {CC"getLocalVariableTableStart",                   CC"("HS_RESOLVED_METHOD")J",                                                      FN_PTR(getLocalVariableTableStart)},
+  {CC"getLocalVariableTableLength",                  CC"("HS_RESOLVED_METHOD")I",                                                      FN_PTR(getLocalVariableTableLength)},
+  {CC"reprofile",                                    CC"("HS_RESOLVED_METHOD")V",                                                      FN_PTR(reprofile)},
+  {CC"invalidateInstalledCode",                      CC"("INSTALLED_CODE")V",                                                          FN_PTR(invalidateInstalledCode)},
+  {CC"readUncompressedOop",                          CC"(J)"OBJECT,                                                                    FN_PTR(readUncompressedOop)},
+  {CC"collectCounters",                              CC"()[J",                                                                         FN_PTR(collectCounters)},
+  {CC"allocateCompileId",                            CC"("HS_RESOLVED_METHOD"I)I",                                                     FN_PTR(allocateCompileId)},
+  {CC"isMature",                                     CC"("METASPACE_METHOD_DATA")Z",                                                   FN_PTR(isMature)},
+  {CC"hasCompiledCodeForOSR",                        CC"("HS_RESOLVED_METHOD"II)Z",                                                    FN_PTR(hasCompiledCodeForOSR)},
+  {CC"getSymbol",                                    CC"(J)"STRING,                                                                    FN_PTR(getSymbol)},
+  {CC"getNextStackFrame",                            CC"("HS_STACK_FRAME_REF "["RESOLVED_METHOD"I)"HS_STACK_FRAME_REF,                 FN_PTR(getNextStackFrame)},
+  {CC"materializeVirtualObjects",                    CC"("HS_STACK_FRAME_REF"Z)V",                                                     FN_PTR(materializeVirtualObjects)},
+  {CC"shouldDebugNonSafepoints",                     CC"()Z",                                                                          FN_PTR(shouldDebugNonSafepoints)},
+  {CC"writeDebugOutput",                             CC"([BII)V",                                                                      FN_PTR(writeDebugOutput)},
+  {CC"flushDebugOutput",                             CC"()V",                                                                          FN_PTR(flushDebugOutput)},
+  {CC"methodDataProfileDataSize",                    CC"(JI)I",                                                                        FN_PTR(methodDataProfileDataSize)},
+  {CC"interpreterFrameSize",                         CC"("BYTECODE_FRAME")I",                                                          FN_PTR(interpreterFrameSize)},
+  {CC"compileToBytecode",                            CC"("OBJECT")V",                                                                  FN_PTR(compileToBytecode)},
+  {CC"getFlagValue",                                 CC"("STRING")"OBJECT,                                                             FN_PTR(getFlagValue)},
+};
+
+int CompilerToVM::methods_count() {
+  return sizeof(methods) / sizeof(JNINativeMethod);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_COMPILER_TO_VM_HPP
+#define SHARE_VM_JVMCI_JVMCI_COMPILER_TO_VM_HPP
+
+#include "prims/jni.h"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+
+class CompilerToVM {
+ public:
+   class Data {
+     friend class VMStructs;
+
+    private:
+     static int Klass_vtable_start_offset;
+     static int Klass_vtable_length_offset;
+
+     static int Method_extra_stack_entries;
+
+     static address SharedRuntime_ic_miss_stub;
+     static address SharedRuntime_handle_wrong_method_stub;
+     static address SharedRuntime_deopt_blob_unpack;
+     static address SharedRuntime_deopt_blob_uncommon_trap;
+
+     static size_t ThreadLocalAllocBuffer_alignment_reserve;
+
+     static CollectedHeap* Universe_collectedHeap;
+     static int Universe_base_vtable_size;
+     static address Universe_narrow_oop_base;
+     static int Universe_narrow_oop_shift;
+     static address Universe_narrow_klass_base;
+     static int Universe_narrow_klass_shift;
+     static uintptr_t Universe_verify_oop_mask;
+     static uintptr_t Universe_verify_oop_bits;
+     static void* Universe_non_oop_bits;
+
+     static bool _supports_inline_contig_alloc;
+     static HeapWord** _heap_end_addr;
+     static HeapWord** _heap_top_addr;
+     static int _max_oop_map_stack_offset;
+
+     static jbyte* cardtable_start_address;
+     static int cardtable_shift;
+     static int g1_young_card;
+     static int dirty_card;
+
+     static int vm_page_size;
+
+     static int sizeof_vtableEntry;
+     static int sizeof_ExceptionTableElement;
+     static int sizeof_LocalVariableTableElement;
+     static int sizeof_ConstantPool;
+     static int sizeof_SymbolPointer;
+     static int sizeof_narrowKlass;
+     static int sizeof_arrayOopDesc;
+     static int sizeof_BasicLock;
+
+     static address CodeCache_low_bound;
+     static address CodeCache_high_bound;
+
+     static address dsin;
+     static address dcos;
+     static address dtan;
+     static address dexp;
+     static address dlog;
+     static address dlog10;
+     static address dpow;
+
+     static address symbol_init;
+     static address symbol_clinit;
+
+    public:
+     static void initialize(TRAPS);
+
+    static int max_oop_map_stack_offset() {
+      assert(_max_oop_map_stack_offset > 0, "must be initialized");
+      return Data::_max_oop_map_stack_offset;
+    }
+   };
+
+  static bool cstring_equals(const char* const& s0, const char* const& s1) {
+    return strcmp(s0, s1) == 0;
+  }
+
+  static unsigned cstring_hash(const char* const& s) {
+    int h = 0;
+    const char* p = s;
+    while (*p != '\0') {
+      h = 31 * h + *p;
+      p++;
+    }
+    return h;
+  }
+
+  static JNINativeMethod methods[];
+
+  static objArrayHandle initialize_intrinsics(TRAPS);
+
+  static int methods_count();
+
+  static inline Method* asMethod(jobject jvmci_method) {
+    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
+  }
+
+  static inline Method* asMethod(Handle jvmci_method) {
+    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
+  }
+
+  static inline Method* asMethod(oop jvmci_method) {
+    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
+  }
+
+  static inline ConstantPool* asConstantPool(jobject jvmci_constant_pool) {
+    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
+  }
+
+  static inline ConstantPool* asConstantPool(Handle jvmci_constant_pool) {
+    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
+  }
+
+  static inline ConstantPool* asConstantPool(oop jvmci_constant_pool) {
+    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
+  }
+
+  static inline Klass* asKlass(jobject jvmci_type) {
+    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
+  }
+
+  static inline Klass* asKlass(Handle jvmci_type) {
+    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
+  }
+
+  static inline Klass* asKlass(oop jvmci_type) {
+    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
+  }
+
+  static inline MethodData* asMethodData(jlong metaspaceMethodData) {
+    return (MethodData*) (address) metaspaceMethodData;
+  }
+
+  static oop get_jvmci_method(const methodHandle& method, TRAPS);
+
+  static oop get_jvmci_type(KlassHandle klass, TRAPS);
+};
+
+class JavaArgumentUnboxer : public SignatureIterator {
+ protected:
+  JavaCallArguments*  _jca;
+  arrayOop _args;
+  int _index;
+
+  oop next_arg(BasicType expectedType) {
+    assert(_index < _args->length(), "out of bounds");
+    oop arg=((objArrayOop) (_args))->obj_at(_index++);
+    assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
+    return arg;
+  }
+
+ public:
+  JavaArgumentUnboxer(Symbol* signature, JavaCallArguments*  jca, arrayOop args, bool is_static) : SignatureIterator(signature) {
+    this->_return_type = T_ILLEGAL;
+    _jca = jca;
+    _index = 0;
+    _args = args;
+    if (!is_static) {
+      _jca->push_oop(next_arg(T_OBJECT));
+    }
+    iterate();
+    assert(_index == args->length(), "arg count mismatch with signature");
+  }
+
+  inline void do_bool()   { if (!is_return_type()) _jca->push_int(next_arg(T_BOOLEAN)->bool_field(java_lang_boxing_object::value_offset_in_bytes(T_BOOLEAN))); }
+  inline void do_char()   { if (!is_return_type()) _jca->push_int(next_arg(T_CHAR)->char_field(java_lang_boxing_object::value_offset_in_bytes(T_CHAR))); }
+  inline void do_short()  { if (!is_return_type()) _jca->push_int(next_arg(T_SHORT)->short_field(java_lang_boxing_object::value_offset_in_bytes(T_SHORT))); }
+  inline void do_byte()   { if (!is_return_type()) _jca->push_int(next_arg(T_BYTE)->byte_field(java_lang_boxing_object::value_offset_in_bytes(T_BYTE))); }
+  inline void do_int()    { if (!is_return_type()) _jca->push_int(next_arg(T_INT)->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT))); }
+
+  inline void do_long()   { if (!is_return_type()) _jca->push_long(next_arg(T_LONG)->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); }
+  inline void do_float()  { if (!is_return_type()) _jca->push_float(next_arg(T_FLOAT)->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT))); }
+  inline void do_double() { if (!is_return_type()) _jca->push_double(next_arg(T_DOUBLE)->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); }
+
+  inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_array(int begin, int end)  { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_void()                     { }
+};
+
+#endif // SHARE_VM_JVMCI_JVMCI_COMPILER_TO_VM_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciEnv.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "classfile/javaAssertions.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/codeCache.hpp"
+#include "code/scopeDesc.hpp"
+#include "runtime/sweeper.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/compileLog.hpp"
+#include "compiler/compilerOracle.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/oopFactory.hpp"
+#include "memory/universe.inline.hpp"
+#include "oops/methodData.hpp"
+#include "oops/objArrayKlass.hpp"
+#include "oops/oop.inline.hpp"
+#include "prims/jvmtiExport.hpp"
+#include "runtime/init.hpp"
+#include "runtime/reflection.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "utilities/dtrace.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+
+JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter):
+  _task(task),
+  _system_dictionary_modification_counter(system_dictionary_modification_counter),
+  _failure_reason(NULL),
+  _retryable(true)
+{
+  // Get Jvmti capabilities under lock to get consistent values.
+  MutexLocker mu(JvmtiThreadState_lock);
+  _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
+  _jvmti_can_access_local_variables     = JvmtiExport::can_access_local_variables();
+  _jvmti_can_post_on_exceptions         = JvmtiExport::can_post_on_exceptions();
+}
+
+// ------------------------------------------------------------------
+// Note: the logic of this method should mirror the logic of
+// constantPoolOopDesc::verify_constant_pool_resolve.
+bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass) {
+  if (accessing_klass->oop_is_objArray()) {
+    accessing_klass = ObjArrayKlass::cast(accessing_klass())->bottom_klass();
+  }
+  if (!accessing_klass->oop_is_instance()) {
+    return true;
+  }
+
+  if (resolved_klass->oop_is_objArray()) {
+    // Find the element klass, if this is an array.
+    resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
+  }
+  if (resolved_klass->oop_is_instance()) {
+    return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
+  }
+  return true;
+}
+
+// ------------------------------------------------------------------
+KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass,
+                                          const constantPoolHandle& cpool,
+                                          Symbol* sym,
+                                          bool require_local) {
+  JVMCI_EXCEPTION_CONTEXT;
+
+  // Now we need to check the SystemDictionary
+  if (sym->byte_at(0) == 'L' &&
+    sym->byte_at(sym->utf8_length()-1) == ';') {
+    // This is a name from a signature.  Strip off the trimmings.
+    // Call recursive to keep scope of strippedsym.
+    TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,
+                    sym->utf8_length()-2,
+                    CHECK_(KlassHandle()));
+    return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local);
+  }
+
+  Handle loader(THREAD, (oop)NULL);
+  Handle domain(THREAD, (oop)NULL);
+  if (!accessing_klass.is_null()) {
+    loader = Handle(THREAD, accessing_klass->class_loader());
+    domain = Handle(THREAD, accessing_klass->protection_domain());
+  }
+
+  KlassHandle found_klass;
+  {
+    ttyUnlocker ttyul;  // release tty lock to avoid ordering problems
+    MutexLocker ml(Compile_lock);
+    Klass*  kls;
+    if (!require_local) {
+      kls = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_(KlassHandle()));
+    } else {
+      kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_(KlassHandle()));
+    }
+    found_klass = KlassHandle(THREAD, kls);
+  }
+
+  // If we fail to find an array klass, look again for its element type.
+  // The element type may be available either locally or via constraints.
+  // In either case, if we can find the element type in the system dictionary,
+  // we must build an array type around it.  The CI requires array klasses
+  // to be loaded if their element klasses are loaded, except when memory
+  // is exhausted.
+  if (sym->byte_at(0) == '[' &&
+      (sym->byte_at(1) == '[' || sym->byte_at(1) == 'L')) {
+    // We have an unloaded array.
+    // Build it on the fly if the element class exists.
+    TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
+                                                 sym->utf8_length()-1,
+                                                 CHECK_(KlassHandle()));
+
+    // Get element Klass recursively.
+    KlassHandle elem_klass =
+      get_klass_by_name_impl(accessing_klass,
+                             cpool,
+                             elem_sym,
+                             require_local);
+    if (!elem_klass.is_null()) {
+      // Now make an array for it
+      return elem_klass->array_klass(CHECK_(KlassHandle()));
+    }
+  }
+
+  if (found_klass.is_null() && !cpool.is_null() && cpool->has_preresolution()) {
+    // Look inside the constant pool for pre-resolved class entries.
+    for (int i = cpool->length() - 1; i >= 1; i--) {
+      if (cpool->tag_at(i).is_klass()) {
+        Klass*  kls = cpool->resolved_klass_at(i);
+        if (kls->name() == sym) {
+          return kls;
+        }
+      }
+    }
+  }
+
+  return found_klass();
+}
+
+// ------------------------------------------------------------------
+KlassHandle JVMCIEnv::get_klass_by_name(KlassHandle accessing_klass,
+                                  Symbol* klass_name,
+                                  bool require_local) {
+  ResourceMark rm;
+  constantPoolHandle cpool;
+  return get_klass_by_name_impl(accessing_klass,
+                                                 cpool,
+                                                 klass_name,
+                                                 require_local);
+}
+
+// ------------------------------------------------------------------
+// Implementation of get_klass_by_index.
+KlassHandle JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool,
+                                        int index,
+                                        bool& is_accessible,
+                                        KlassHandle accessor) {
+  JVMCI_EXCEPTION_CONTEXT;
+  KlassHandle klass (THREAD, ConstantPool::klass_at_if_loaded(cpool, index));
+  Symbol* klass_name = NULL;
+  if (klass.is_null()) {
+    klass_name = cpool->klass_name_at(index);
+  }
+
+  if (klass.is_null()) {
+    // Not found in constant pool.  Use the name to do the lookup.
+    KlassHandle k = get_klass_by_name_impl(accessor,
+                                        cpool,
+                                        klass_name,
+                                        false);
+    // Calculate accessibility the hard way.
+    if (k.is_null()) {
+      is_accessible = false;
+    } else if (k->class_loader() != accessor->class_loader() &&
+               get_klass_by_name_impl(accessor, cpool, k->name(), true).is_null()) {
+      // Loaded only remotely.  Not linked yet.
+      is_accessible = false;
+    } else {
+      // Linked locally, and we must also check public/private, etc.
+      is_accessible = check_klass_accessibility(accessor, k);
+    }
+    if (!is_accessible) {
+      return KlassHandle();
+    }
+    return k;
+  }
+
+  // It is known to be accessible, since it was found in the constant pool.
+  is_accessible = true;
+  return klass;
+}
+
+// ------------------------------------------------------------------
+// Get a klass from the constant pool.
+KlassHandle JVMCIEnv::get_klass_by_index(const constantPoolHandle& cpool,
+                                   int index,
+                                   bool& is_accessible,
+                                   KlassHandle accessor) {
+  ResourceMark rm;
+  KlassHandle result = get_klass_by_index_impl(cpool, index, is_accessible, accessor);
+  return result;
+}
+
+// ------------------------------------------------------------------
+// Implementation of get_field_by_index.
+//
+// Implementation note: the results of field lookups are cached
+// in the accessor klass.
+void JVMCIEnv::get_field_by_index_impl(instanceKlassHandle klass, fieldDescriptor& field_desc,
+                                        int index) {
+  JVMCI_EXCEPTION_CONTEXT;
+
+  assert(klass->is_linked(), "must be linked before using its constant-pool");
+
+  constantPoolHandle cpool(thread, klass->constants());
+
+  // Get the field's name, signature, and type.
+  Symbol* name  = cpool->name_ref_at(index);
+
+  int nt_index = cpool->name_and_type_ref_index_at(index);
+  int sig_index = cpool->signature_ref_index_at(nt_index);
+  Symbol* signature = cpool->symbol_at(sig_index);
+
+  // Get the field's declared holder.
+  int holder_index = cpool->klass_ref_index_at(index);
+  bool holder_is_accessible;
+  KlassHandle declared_holder = get_klass_by_index(cpool, holder_index,
+                                               holder_is_accessible,
+                                               klass);
+
+  // The declared holder of this field may not have been loaded.
+  // Bail out with partial field information.
+  if (!holder_is_accessible) {
+    return;
+  }
+
+
+  // Perform the field lookup.
+  Klass*  canonical_holder =
+    InstanceKlass::cast(declared_holder())->find_field(name, signature, &field_desc);
+  if (canonical_holder == NULL) {
+    return;
+  }
+
+  assert(canonical_holder == field_desc.field_holder(), "just checking");
+}
+
+// ------------------------------------------------------------------
+// Get a field by index from a klass's constant pool.
+void JVMCIEnv::get_field_by_index(instanceKlassHandle accessor, fieldDescriptor& fd, int index) {
+  ResourceMark rm;
+  return get_field_by_index_impl(accessor, fd, index);
+}
+
+// ------------------------------------------------------------------
+// Perform an appropriate method lookup based on accessor, holder,
+// name, signature, and bytecode.
+methodHandle JVMCIEnv::lookup_method(instanceKlassHandle h_accessor,
+                               instanceKlassHandle h_holder,
+                               Symbol*       name,
+                               Symbol*       sig,
+                               Bytecodes::Code bc) {
+  JVMCI_EXCEPTION_CONTEXT;
+  LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
+  methodHandle dest_method;
+  switch (bc) {
+  case Bytecodes::_invokestatic:
+    dest_method =
+      LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor);
+    break;
+  case Bytecodes::_invokespecial:
+    dest_method =
+      LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor);
+    break;
+  case Bytecodes::_invokeinterface:
+    dest_method =
+      LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig,
+                                                              h_accessor, true);
+    break;
+  case Bytecodes::_invokevirtual:
+    dest_method =
+      LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig,
+                                                            h_accessor, true);
+    break;
+  default: ShouldNotReachHere();
+  }
+
+  return dest_method;
+}
+
+
+// ------------------------------------------------------------------
+methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
+                                          int index, Bytecodes::Code bc,
+                                          instanceKlassHandle accessor) {
+  if (bc == Bytecodes::_invokedynamic) {
+    ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
+    bool is_resolved = !cpce->is_f1_null();
+    if (is_resolved) {
+      // Get the invoker Method* from the constant pool.
+      // (The appendix argument, if any, will be noted in the method's signature.)
+      Method* adapter = cpce->f1_as_method();
+      return methodHandle(adapter);
+    }
+
+    return NULL;
+  }
+
+  int holder_index = cpool->klass_ref_index_at(index);
+  bool holder_is_accessible;
+  KlassHandle holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
+
+  // Get the method's name and signature.
+  Symbol* name_sym = cpool->name_ref_at(index);
+  Symbol* sig_sym  = cpool->signature_ref_at(index);
+
+  if (cpool->has_preresolution()
+      || (holder() == SystemDictionary::MethodHandle_klass() &&
+          MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) {
+    // Short-circuit lookups for JSR 292-related call sites.
+    // That is, do not rely only on name-based lookups, because they may fail
+    // if the names are not resolvable in the boot class loader (7056328).
+    switch (bc) {
+    case Bytecodes::_invokevirtual:
+    case Bytecodes::_invokeinterface:
+    case Bytecodes::_invokespecial:
+    case Bytecodes::_invokestatic:
+      {
+        Method* m = ConstantPool::method_at_if_loaded(cpool, index);
+        if (m != NULL) {
+          return m;
+        }
+      }
+      break;
+    }
+  }
+
+  if (holder_is_accessible) { // Our declared holder is loaded.
+    instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder);
+    methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc);
+    if (!m.is_null() &&
+        (bc == Bytecodes::_invokestatic
+         ?  InstanceKlass::cast(m->method_holder())->is_not_initialized()
+         : !InstanceKlass::cast(m->method_holder())->is_loaded())) {
+      m = NULL;
+    }
+    if (!m.is_null()) {
+      // We found the method.
+      return m;
+    }
+  }
+
+  // Either the declared holder was not loaded, or the method could
+  // not be found.
+
+  return NULL;
+}
+
+// ------------------------------------------------------------------
+instanceKlassHandle JVMCIEnv::get_instance_klass_for_declared_method_holder(KlassHandle method_holder) {
+  // For the case of <array>.clone(), the method holder can be an ArrayKlass*
+  // instead of an InstanceKlass*.  For that case simply pretend that the
+  // declared holder is Object.clone since that's where the call will bottom out.
+  if (method_holder->oop_is_instance()) {
+    return instanceKlassHandle(method_holder());
+  } else if (method_holder->oop_is_array()) {
+    return instanceKlassHandle(SystemDictionary::Object_klass());
+  } else {
+    ShouldNotReachHere();
+  }
+  return NULL;
+}
+
+
+// ------------------------------------------------------------------
+methodHandle JVMCIEnv::get_method_by_index(const constantPoolHandle& cpool,
+                                     int index, Bytecodes::Code bc,
+                                     instanceKlassHandle accessor) {
+  ResourceMark rm;
+  return get_method_by_index_impl(cpool, index, bc, accessor);
+}
+
+// ------------------------------------------------------------------
+// Check for changes to the system dictionary during compilation
+// class loads, evolution, breakpoints
+JVMCIEnv::CodeInstallResult JVMCIEnv::check_for_system_dictionary_modification(Dependencies* dependencies, Handle compiled_code,
+                                                                               JVMCIEnv* env, char** failure_detail) {
+  // If JVMTI capabilities were enabled during compile, the compilation is invalidated.
+  if (env != NULL) {
+    if (!env->_jvmti_can_hotswap_or_post_breakpoint && JvmtiExport::can_hotswap_or_post_breakpoint()) {
+      *failure_detail = (char*) "Hotswapping or breakpointing was enabled during compilation";
+      return JVMCIEnv::dependencies_failed;
+    }
+  }
+
+  // Dependencies must be checked when the system dictionary changes
+  // or if we don't know whether it has changed (i.e., env == NULL).
+  // In debug mode, always check dependencies.
+  bool counter_changed = env != NULL && env->_system_dictionary_modification_counter != SystemDictionary::number_of_modifications();
+  bool verify_deps = env == NULL || trueInDebug || JavaAssertions::enabled(SystemDictionary::HotSpotInstalledCode_klass()->name()->as_C_string(), true);
+  if (!counter_changed && !verify_deps) {
+    return JVMCIEnv::ok;
+  }
+
+  for (Dependencies::DepStream deps(dependencies); deps.next(); ) {
+    Klass* witness = deps.check_dependency();
+    if (witness != NULL) {
+      // Use a fixed size buffer to prevent the string stream from
+      // resizing in the context of an inner resource mark.
+      char* buffer = NEW_RESOURCE_ARRAY(char, O_BUFLEN);
+      stringStream st(buffer, O_BUFLEN);
+      deps.print_dependency(witness, true, &st);
+      *failure_detail = st.as_string();
+      if (env == NULL || counter_changed || deps.type() == Dependencies::evol_method) {
+        return JVMCIEnv::dependencies_failed;
+      } else {
+        // The dependencies were invalid at the time of installation
+        // without any intervening modification of the system
+        // dictionary.  That means they were invalidly constructed.
+        return JVMCIEnv::dependencies_invalid;
+      }
+    }
+    if (LogCompilation) {
+      deps.log_dependency();
+    }
+  }
+
+  return JVMCIEnv::ok;
+}
+
+// ------------------------------------------------------------------
+JVMCIEnv::CodeInstallResult JVMCIEnv::register_method(
+                                const methodHandle& method,
+                                nmethod*& nm,
+                                int entry_bci,
+                                CodeOffsets* offsets,
+                                int orig_pc_offset,
+                                CodeBuffer* code_buffer,
+                                int frame_words,
+                                OopMapSet* oop_map_set,
+                                ExceptionHandlerTable* handler_table,
+                                AbstractCompiler* compiler,
+                                DebugInformationRecorder* debug_info,
+                                Dependencies* dependencies,
+                                JVMCIEnv* env,
+                                int compile_id,
+                                bool has_unsafe_access,
+                                bool has_wide_vector,
+                                Handle installed_code,
+                                Handle compiled_code,
+                                Handle speculation_log) {
+  JVMCI_EXCEPTION_CONTEXT;
+  NMethodSweeper::possibly_sweep();
+  nm = NULL;
+  int comp_level = CompLevel_full_optimization;
+  char* failure_detail = NULL;
+  JVMCIEnv::CodeInstallResult result;
+  {
+    // To prevent compile queue updates.
+    MutexLocker locker(MethodCompileQueue_lock, THREAD);
+
+    // Prevent SystemDictionary::add_to_hierarchy from running
+    // and invalidating our dependencies until we install this method.
+    MutexLocker ml(Compile_lock);
+
+    // Encode the dependencies now, so we can check them right away.
+    dependencies->encode_content_bytes();
+
+    // Check for {class loads, evolution, breakpoints} during compilation
+    result = check_for_system_dictionary_modification(dependencies, compiled_code, env, &failure_detail);
+    if (result != JVMCIEnv::ok) {
+      // While not a true deoptimization, it is a preemptive decompile.
+      MethodData* mdp = method()->method_data();
+      if (mdp != NULL) {
+        mdp->inc_decompile_count();
+#ifdef DEBUG
+        if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) {
+          ResourceMark m;
+          tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string());
+        }
+#endif
+      }
+
+      // All buffers in the CodeBuffer are allocated in the CodeCache.
+      // If the code buffer is created on each compile attempt
+      // as in C2, then it must be freed.
+      //code_buffer->free_blob();
+    } else {
+      ImplicitExceptionTable implicit_tbl;
+      nm =  nmethod::new_nmethod(method,
+                                 compile_id,
+                                 entry_bci,
+                                 offsets,
+                                 orig_pc_offset,
+                                 debug_info, dependencies, code_buffer,
+                                 frame_words, oop_map_set,
+                                 handler_table, &implicit_tbl,
+                                 compiler, comp_level, installed_code, speculation_log);
+
+      // Free codeBlobs
+      //code_buffer->free_blob();
+      if (nm == NULL) {
+        // The CodeCache is full.  Print out warning and disable compilation.
+        {
+          MutexUnlocker ml(Compile_lock);
+          MutexUnlocker locker(MethodCompileQueue_lock);
+          CompileBroker::handle_full_code_cache();
+        }
+      } else {
+        nm->set_has_unsafe_access(has_unsafe_access);
+        nm->set_has_wide_vectors(has_wide_vector);
+
+        // Record successful registration.
+        // (Put nm into the task handle *before* publishing to the Java heap.)
+        CompileTask* task = env == NULL ? NULL : env->task();
+        if (task != NULL) {
+          task->set_code(nm);
+        }
+
+        if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) {
+          if (entry_bci == InvocationEntryBci) {
+            if (TieredCompilation) {
+              // If there is an old version we're done with it
+              nmethod* old = method->code();
+              if (TraceMethodReplacement && old != NULL) {
+                ResourceMark rm;
+                char *method_name = method->name_and_sig_as_C_string();
+                tty->print_cr("Replacing method %s", method_name);
+              }
+              if (old != NULL ) {
+                old->make_not_entrant();
+              }
+            }
+            if (TraceNMethodInstalls) {
+              ResourceMark rm;
+              char *method_name = method->name_and_sig_as_C_string();
+              ttyLocker ttyl;
+              tty->print_cr("Installing method (%d) %s [entry point: %p]",
+                            comp_level,
+                            method_name, nm->entry_point());
+            }
+            // Allow the code to be executed
+            method->set_code(method, nm);
+          } else {
+            if (TraceNMethodInstalls ) {
+              ResourceMark rm;
+              char *method_name = method->name_and_sig_as_C_string();
+              ttyLocker ttyl;
+              tty->print_cr("Installing osr method (%d) %s @ %d",
+                            comp_level,
+                            method_name,
+                            entry_bci);
+            }
+            InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
+          }
+        }
+      }
+      result = nm != NULL ? JVMCIEnv::ok :JVMCIEnv::cache_full;
+    }
+  }
+
+  // String creation must be done outside lock
+  if (failure_detail != NULL) {
+    // A failure to allocate the string is silently ignored.
+    Handle message = java_lang_String::create_from_str(failure_detail, THREAD);
+    HotSpotCompiledNmethod::set_installationFailureMessage(compiled_code, message());
+  }
+
+  // JVMTI -- compiled method notification (must be done outside lock)
+  if (nm != NULL) {
+    nm->post_compiled_method_load_event();
+  }
+
+  return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciEnv.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCIENV_HPP
+#define SHARE_VM_JVMCI_JVMCIENV_HPP
+
+#include "classfile/systemDictionary.hpp"
+#include "code/debugInfoRec.hpp"
+#include "code/dependencies.hpp"
+#include "code/exceptionHandlerTable.hpp"
+#include "compiler/oopMap.hpp"
+#include "runtime/thread.hpp"
+
+class CompileTask;
+
+// Bring the JVMCI compiler thread into the VM state.
+#define JVMCI_VM_ENTRY_MARK                       \
+  JavaThread* thread = JavaThread::current(); \
+  ThreadInVMfromNative __tiv(thread);       \
+  ResetNoHandleMark rnhm;                   \
+  HandleMarkCleaner __hm(thread);           \
+  Thread* THREAD = thread;                  \
+  debug_only(VMNativeEntryWrapper __vew;)
+
+#define JVMCI_EXCEPTION_CONTEXT \
+  JavaThread* thread=JavaThread::current(); \
+  Thread* THREAD = thread;
+
+//
+// This class is the top level broker for requests from the compiler
+// to the VM.
+class JVMCIEnv : StackObj {
+  CI_PACKAGE_ACCESS_TO
+
+  friend class CompileBroker;
+  friend class Dependencies;  // for get_object, during logging
+
+public:
+
+  enum CodeInstallResult {
+     ok,
+     dependencies_failed,
+     dependencies_invalid,
+     cache_full,
+     code_too_large
+  };
+
+  // Look up a klass by name from a particular class loader (the accessor's).
+  // If require_local, result must be defined in that class loader, or NULL.
+  // If !require_local, a result from remote class loader may be reported,
+  // if sufficient class loader constraints exist such that initiating
+  // a class loading request from the given loader is bound to return
+  // the class defined in the remote loader (or throw an error).
+  //
+  // Return an unloaded klass if !require_local and no class at all is found.
+  //
+  // The CI treats a klass as loaded if it is consistently defined in
+  // another loader, even if it hasn't yet been loaded in all loaders
+  // that could potentially see it via delegation.
+  static KlassHandle get_klass_by_name(KlassHandle accessing_klass,
+                             Symbol* klass_name,
+                             bool require_local);
+
+  // Constant pool access.
+  static KlassHandle   get_klass_by_index(const constantPoolHandle& cpool,
+                                int klass_index,
+                                bool& is_accessible,
+                                KlassHandle loading_klass);
+  static void   get_field_by_index(instanceKlassHandle loading_klass, fieldDescriptor& fd,
+                                int field_index);
+  static methodHandle  get_method_by_index(const constantPoolHandle& cpool,
+                                 int method_index, Bytecodes::Code bc,
+                                 instanceKlassHandle loading_klass);
+
+  JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter);
+
+private:
+  CompileTask*     _task;
+  int              _system_dictionary_modification_counter;
+
+  // Compilation result values
+  const char*      _failure_reason;
+  bool             _retryable;
+
+  // Cache JVMTI state
+  bool  _jvmti_can_hotswap_or_post_breakpoint;
+  bool  _jvmti_can_access_local_variables;
+  bool  _jvmti_can_post_on_exceptions;
+
+  // Implementation methods for loading and constant pool access.
+  static KlassHandle get_klass_by_name_impl(KlassHandle& accessing_klass,
+                                  const constantPoolHandle& cpool,
+                                  Symbol* klass_name,
+                                  bool require_local);
+  static KlassHandle   get_klass_by_index_impl(const constantPoolHandle& cpool,
+                                     int klass_index,
+                                     bool& is_accessible,
+                                     KlassHandle loading_klass);
+  static void   get_field_by_index_impl(instanceKlassHandle loading_klass, fieldDescriptor& fd,
+                                     int field_index);
+  static methodHandle  get_method_by_index_impl(const constantPoolHandle& cpool,
+                                      int method_index, Bytecodes::Code bc,
+                                      instanceKlassHandle loading_klass);
+
+  // Helper methods
+  static bool       check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass);
+  static methodHandle  lookup_method(instanceKlassHandle  accessor,
+                           instanceKlassHandle  holder,
+                           Symbol*         name,
+                           Symbol*         sig,
+                           Bytecodes::Code bc);
+
+  private:
+
+  // Is this thread currently in the VM state?
+  static bool is_in_vm();
+
+  // Helper routine for determining the validity of a compilation
+  // with respect to concurrent class loading.
+  static JVMCIEnv::CodeInstallResult check_for_system_dictionary_modification(Dependencies* target, Handle compiled_code,
+                                                                              JVMCIEnv* env, char** failure_detail);
+
+public:
+  CompileTask* task() { return _task; }
+
+  const char* failure_reason() { return _failure_reason; }
+  bool retryable() { return _retryable; }
+
+  void set_failure(const char* reason, bool retryable) {
+    _failure_reason = reason;
+    _retryable = retryable;
+  }
+
+  // Register the result of a compilation.
+  static JVMCIEnv::CodeInstallResult register_method(
+                       const methodHandle&       target,
+                       nmethod*&                 nm,
+                       int                       entry_bci,
+                       CodeOffsets*              offsets,
+                       int                       orig_pc_offset,
+                       CodeBuffer*               code_buffer,
+                       int                       frame_words,
+                       OopMapSet*                oop_map_set,
+                       ExceptionHandlerTable*    handler_table,
+                       AbstractCompiler*         compiler,
+                       DebugInformationRecorder* debug_info,
+                       Dependencies*             dependencies,
+                       JVMCIEnv*                 env,
+                       int                       compile_id,
+                       bool                      has_unsafe_access,
+                       bool                      has_wide_vector,
+                       Handle                    installed_code,
+                       Handle                    compiled_code,
+                       Handle                    speculation_log);
+
+  // converts the Klass* representing the holder of a method into a
+  // InstanceKlass*.  This is needed since the holder of a method in
+  // the bytecodes could be an array type.  Basically this converts
+  // array types into java/lang/Object and other types stay as they are.
+  static instanceKlassHandle get_instance_klass_for_declared_method_holder(KlassHandle klass);
+};
+
+#endif // SHARE_VM_JVMCI_JVMCIENV_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciJavaClasses.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+#include "precompiled.hpp"
+#include "utilities/exceptions.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "runtime/jniHandles.hpp"
+#include "classfile/symbolTable.hpp"
+
+// This function is similar to javaClasses.cpp, it computes the field offset of a (static or instance) field.
+// It looks up the name and signature symbols without creating new ones, all the symbols of these classes need to be already loaded.
+
+void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS) {
+  InstanceKlass* ik = InstanceKlass::cast(klass);
+  Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name));
+  Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature));
+  if (name_symbol == NULL || signature_symbol == NULL) {
+#ifndef PRODUCT
+    ik->print_on(tty);
+#endif
+    fatal(err_msg("symbol with name %s and signature %s was not found in symbol table (klass=%s)", name, signature, klass->name()->as_C_string()));
+  }
+
+  fieldDescriptor fd;
+  if (!ik->find_field(name_symbol, signature_symbol, &fd)) {
+    ResourceMark rm;
+    fatal(err_msg("Invalid layout of %s at %s", name_symbol->as_C_string(), ik->external_name()));
+  }
+  guarantee(fd.is_static() == static_field, "static/instance mismatch");
+  dest_offset = fd.offset();
+  assert(dest_offset != 0, "must be valid offset");
+  if (static_field) {
+    // Must ensure classes for static fields are initialized as the
+    // accessor itself does not include a class initialization check.
+    ik->initialize(CHECK);
+  }
+}
+
+// This piece of macro magic creates the contents of the jvmci_compute_offsets method that initializes the field indices of all the access classes.
+
+#define START_CLASS(name) { Klass* k = SystemDictionary::name##_klass(); assert(k != NULL, "Could not find class " #name "");
+
+#define END_CLASS }
+
+#define FIELD(klass, name, signature, static_field) compute_offset(klass::_##name##_offset, k, #name, signature, static_field, CHECK);
+#define CHAR_FIELD(klass, name) FIELD(klass, name, "C", false)
+#define INT_FIELD(klass, name) FIELD(klass, name, "I", false)
+#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", false)
+#define LONG_FIELD(klass, name) FIELD(klass, name, "J", false)
+#define FLOAT_FIELD(klass, name) FIELD(klass, name, "F", false)
+#define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false)
+#define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true)
+#define STATIC_INT_FIELD(klass, name) FIELD(klass, name, "I", true)
+#define STATIC_BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", true)
+
+
+void JVMCIJavaClasses::compute_offsets(TRAPS) {
+  COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, OOP_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
+}
+
+#define EMPTY0
+#define EMPTY1(x)
+#define EMPTY2(x,y)
+#define FIELD2(klass, name) int klass::_##name##_offset = 0;
+#define FIELD3(klass, name, sig) FIELD2(klass, name)
+
+COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD3, FIELD3, FIELD3, FIELD2, FIELD2)
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciJavaClasses.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCIJAVACLASSES_HPP
+#define SHARE_VM_JVMCI_JVMCIJAVACLASSES_HPP
+
+#include "classfile/systemDictionary.hpp"
+#include "oops/instanceMirrorKlass.hpp"
+
+class JVMCIJavaClasses : AllStatic {
+ public:
+  static void compute_offsets(TRAPS);
+};
+
+/* This macro defines the structure of the JVMCI classes accessed from VM code.
+ * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles.
+ *
+ * The public interface of these classes will look like this:
+
+ * class StackSlot : AllStatic {
+ * public:
+ *   static Klass* klass();
+ *   static jint  index(oop obj);
+ *   static jint  index(Handle obj);
+ *   static jint  index(jobject obj);
+ *   static void set_index(oop obj, jint x);
+ *   static void set_index(Handle obj, jint x);
+ *   static void set_index(jobject obj, jint x);
+ * };
+ *
+ */
+
+#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, typeArrayOop_field, objArrayOop_field, static_oop_field, static_objArrayOop_field, static_int_field, static_boolean_field) \
+  start_class(Architecture)                                                                                                                                    \
+    oop_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;")                                                                                         \
+  end_class                                                                                                                                                    \
+  start_class(TargetDescription)                                                                                                                               \
+    oop_field(TargetDescription, arch, "Ljdk/vm/ci/code/Architecture;")                                                                                        \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotResolvedObjectTypeImpl)                                                                                                                   \
+    oop_field(HotSpotResolvedObjectTypeImpl, javaClass, "Ljava/lang/Class;")                                                                                   \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotResolvedJavaMethodImpl)                                                                                                                   \
+    long_field(HotSpotResolvedJavaMethodImpl, metaspaceMethod)                                                                                                 \
+  end_class                                                                                                                                                    \
+  start_class(InstalledCode)                                                                                                                                   \
+    long_field(InstalledCode, address)                                                                                                                         \
+    long_field(InstalledCode, entryPoint)                                                                                                                      \
+    long_field(InstalledCode, version)                                                                                                                         \
+    oop_field(InstalledCode, name, "Ljava/lang/String;")                                                                                                       \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotInstalledCode)                                                                                                                            \
+    int_field(HotSpotInstalledCode, size)                                                                                                                      \
+    long_field(HotSpotInstalledCode, codeStart)                                                                                                                \
+    int_field(HotSpotInstalledCode, codeSize)                                                                                                                  \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotNmethod)                                                                                                                                  \
+    boolean_field(HotSpotNmethod, isDefault)                                                                                                                   \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotCompiledCode)                                                                                                                             \
+    oop_field(HotSpotCompiledCode, name, "Ljava/lang/String;")                                                                                                        \
+    typeArrayOop_field(HotSpotCompiledCode, targetCode, "[B")                                                                                                         \
+    int_field(HotSpotCompiledCode, targetCodeSize)                                                                                                                    \
+    objArrayOop_field(HotSpotCompiledCode, sites, "[Ljdk/vm/ci/code/site/Site;")                                                                                      \
+    objArrayOop_field(HotSpotCompiledCode, assumptions, "[Ljdk/vm/ci/meta/Assumptions$Assumption;")                                                                   \
+    objArrayOop_field(HotSpotCompiledCode, methods, "[Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                           \
+    objArrayOop_field(HotSpotCompiledCode, comments, "[Ljdk/vm/ci/hotspot/HotSpotCompiledCode$Comment;")                                                       \
+    typeArrayOop_field(HotSpotCompiledCode, dataSection, "[B")                                                                                                 \
+    int_field(HotSpotCompiledCode, dataSectionAlignment)                                                                                                       \
+    objArrayOop_field(HotSpotCompiledCode, dataSectionPatches, "[Ljdk/vm/ci/code/site/DataPatch;")                                                             \
+    int_field(HotSpotCompiledCode, totalFrameSize)                                                                                                             \
+    oop_field(HotSpotCompiledCode, deoptRescueSlot, "Ljdk/vm/ci/code/StackSlot;")                                                                              \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotCompiledCode_Comment)                                                                                                                     \
+    oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;")                                                                                         \
+    int_field(HotSpotCompiledCode_Comment, pcOffset)                                                                                                           \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotCompiledNmethod)                                                                                                                          \
+    oop_field(HotSpotCompiledNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                                                                 \
+    oop_field(HotSpotCompiledNmethod, installationFailureMessage, "Ljava/lang/String;")                                                                        \
+    int_field(HotSpotCompiledNmethod, entryBCI)                                                                                                                \
+    int_field(HotSpotCompiledNmethod, id)                                                                                                                      \
+    long_field(HotSpotCompiledNmethod, jvmciEnv)                                                                                                               \
+    boolean_field(HotSpotCompiledNmethod, hasUnsafeAccess)                                                                                                     \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotJVMCIMetaAccessContext)                                                                                                                   \
+    static_objArrayOop_field(HotSpotJVMCIMetaAccessContext, allContexts, "[Ljava/lang/ref/WeakReference;")                                                     \
+    objArrayOop_field(HotSpotJVMCIMetaAccessContext, metadataRoots, "[Ljava/lang/Object;")                                                                     \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotForeignCallTarget)                                                                                                                        \
+    long_field(HotSpotForeignCallTarget, address)                                                                                                              \
+  end_class                                                                                                                                                    \
+  start_class(VMField)                                                                                                                                         \
+    oop_field(VMField, name, "Ljava/lang/String;")                                                                                                             \
+    oop_field(VMField, type, "Ljava/lang/String;")                                                                                                             \
+    long_field(VMField, offset)                                                                                                                                \
+    long_field(VMField, address)                                                                                                                               \
+    oop_field(VMField, value, "Ljava/lang/Long;")                                                                                                              \
+  end_class                                                                                                                                                    \
+  start_class(VMFlag)                                                                                                                                          \
+    oop_field(VMFlag, name, "Ljava/lang/String;")                                                                                                              \
+    oop_field(VMFlag, type, "Ljava/lang/String;")                                                                                                              \
+    oop_field(VMFlag, value, "Ljava/lang/Object;")                                                                                                             \
+  end_class                                                                                                                                                    \
+  start_class(VMIntrinsicMethod)                                                                                                                               \
+    oop_field(VMIntrinsicMethod, declaringClass, "Ljava/lang/String;")                                                                                         \
+    oop_field(VMIntrinsicMethod, name, "Ljava/lang/String;")                                                                                                   \
+    oop_field(VMIntrinsicMethod, descriptor, "Ljava/lang/String;")                                                                                             \
+    int_field(VMIntrinsicMethod, id)                                                                                                                           \
+  end_class                                                                                                                                                    \
+  start_class(Assumptions_NoFinalizableSubclass)                                                                                                               \
+    oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                            \
+  end_class                                                                                                                                                    \
+  start_class(Assumptions_ConcreteSubtype)                                                                                                                     \
+    oop_field(Assumptions_ConcreteSubtype, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                       \
+    oop_field(Assumptions_ConcreteSubtype, subtype, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                       \
+  end_class                                                                                                                                                    \
+  start_class(Assumptions_LeafType)                                                                                                                            \
+    oop_field(Assumptions_LeafType, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                              \
+  end_class                                                                                                                                                    \
+  start_class(Assumptions_ConcreteMethod)                                                                                                                      \
+    oop_field(Assumptions_ConcreteMethod, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                       \
+    oop_field(Assumptions_ConcreteMethod, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                        \
+    oop_field(Assumptions_ConcreteMethod, impl, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                         \
+  end_class                                                                                                                                                    \
+  start_class(Assumptions_CallSiteTargetValue)                                                                                                                 \
+    oop_field(Assumptions_CallSiteTargetValue, callSite, "Ljava/lang/invoke/CallSite;")                                                                        \
+    oop_field(Assumptions_CallSiteTargetValue, methodHandle, "Ljava/lang/invoke/MethodHandle;")                                                                \
+  end_class                                                                                                                                                    \
+  start_class(site_Site)                                                                                                                                       \
+    int_field(site_Site, pcOffset)                                                                                                                             \
+  end_class                                                                                                                                                    \
+  start_class(site_Call)                                                                                                                                       \
+    oop_field(site_Call, target, "Ljdk/vm/ci/meta/InvokeTarget;")                                                                                              \
+    oop_field(site_Call, debugInfo, "Ljdk/vm/ci/code/DebugInfo;")                                                                                              \
+  end_class                                                                                                                                                    \
+  start_class(site_DataPatch)                                                                                                                                  \
+    oop_field(site_DataPatch, reference, "Ljdk/vm/ci/code/site/Reference;")                                                                                    \
+  end_class                                                                                                                                                    \
+  start_class(site_ConstantReference)                                                                                                                          \
+    oop_field(site_ConstantReference, constant, "Ljdk/vm/ci/meta/VMConstant;")                                                                                 \
+  end_class                                                                                                                                                    \
+  start_class(site_DataSectionReference)                                                                                                                       \
+    int_field(site_DataSectionReference, offset)                                                                                                               \
+  end_class                                                                                                                                                    \
+  start_class(site_InfopointReason)                                                                                                                            \
+    static_oop_field(site_InfopointReason, SAFEPOINT, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                 \
+    static_oop_field(site_InfopointReason, CALL, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                      \
+    static_oop_field(site_InfopointReason, IMPLICIT_EXCEPTION, "Ljdk/vm/ci/code/site/InfopointReason;")                                                        \
+  end_class                                                                                                                                                    \
+  start_class(site_Infopoint)                                                                                                                                  \
+    oop_field(site_Infopoint, debugInfo, "Ljdk/vm/ci/code/DebugInfo;")                                                                                         \
+    oop_field(site_Infopoint, reason, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                                 \
+  end_class                                                                                                                                                    \
+  start_class(site_ExceptionHandler)                                                                                                                           \
+    int_field(site_ExceptionHandler, handlerPos)                                                                                                               \
+  end_class                                                                                                                                                    \
+  start_class(site_Mark)                                                                                                                                       \
+    oop_field(site_Mark, id, "Ljava/lang/Object;")                                                                                                             \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotCompilationRequestResult)                                                                                                                 \
+    oop_field(HotSpotCompilationRequestResult, failureMessage, "Ljava/lang/String;")                                                                           \
+    boolean_field(HotSpotCompilationRequestResult, retry)                                                                                                      \
+    int_field(HotSpotCompilationRequestResult, inlinedBytecodes)                                                                                               \
+  end_class                                                                                                                                                    \
+  start_class(DebugInfo)                                                                                                                                       \
+    oop_field(DebugInfo, bytecodePosition, "Ljdk/vm/ci/code/BytecodePosition;")                                                                                \
+    oop_field(DebugInfo, referenceMap, "Ljdk/vm/ci/code/ReferenceMap;")                                                                                        \
+    oop_field(DebugInfo, calleeSaveInfo, "Ljdk/vm/ci/code/RegisterSaveLayout;")                                                                                \
+    objArrayOop_field(DebugInfo, virtualObjectMapping, "[Ljdk/vm/ci/code/VirtualObject;")                                                                      \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotReferenceMap)                                                                                                                             \
+    objArrayOop_field(HotSpotReferenceMap, objects, "[Ljdk/vm/ci/code/Location;")                                                                              \
+    objArrayOop_field(HotSpotReferenceMap, derivedBase, "[Ljdk/vm/ci/code/Location;")                                                                          \
+    typeArrayOop_field(HotSpotReferenceMap, sizeInBytes, "[I")                                                                                                 \
+    int_field(HotSpotReferenceMap, maxRegisterSize)                                                                                                            \
+  end_class                                                                                                                                                    \
+  start_class(RegisterSaveLayout)                                                                                                                              \
+    objArrayOop_field(RegisterSaveLayout, registers, "[Ljdk/vm/ci/code/Register;")                                                                             \
+    typeArrayOop_field(RegisterSaveLayout, slots, "[I")                                                                                                        \
+  end_class                                                                                                                                                    \
+  start_class(BytecodeFrame)                                                                                                                                   \
+    objArrayOop_field(BytecodeFrame, values, "[Ljdk/vm/ci/meta/JavaValue;")                                                                                    \
+    objArrayOop_field(BytecodeFrame, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                                                                  \
+    int_field(BytecodeFrame, numLocals)                                                                                                                        \
+    int_field(BytecodeFrame, numStack)                                                                                                                         \
+    int_field(BytecodeFrame, numLocks)                                                                                                                         \
+    boolean_field(BytecodeFrame, rethrowException)                                                                                                             \
+    boolean_field(BytecodeFrame, duringCall)                                                                                                                   \
+    static_int_field(BytecodeFrame, BEFORE_BCI)                                                                                                                \
+  end_class                                                                                                                                                    \
+  start_class(BytecodePosition)                                                                                                                                \
+    oop_field(BytecodePosition, caller, "Ljdk/vm/ci/code/BytecodePosition;")                                                                                   \
+    oop_field(BytecodePosition, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                                 \
+    int_field(BytecodePosition, bci)                                                                                                                           \
+  end_class                                                                                                                                                    \
+  start_class(JavaConstant)                                                                                                                                    \
+  end_class                                                                                                                                                    \
+  start_class(PrimitiveConstant)                                                                                                                               \
+    oop_field(PrimitiveConstant, kind, "Ljdk/vm/ci/meta/JavaKind;")                                                                                            \
+    long_field(PrimitiveConstant, primitive)                                                                                                                   \
+  end_class                                                                                                                                                    \
+  start_class(RawConstant)                                                                                                                                     \
+    long_field(RawConstant, primitive)                                                                                                                         \
+  end_class                                                                                                                                                    \
+  start_class(NullConstant)                                                                                                                                    \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotCompressedNullConstant)                                                                                                                   \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotObjectConstantImpl)                                                                                                                       \
+    oop_field(HotSpotObjectConstantImpl, object, "Ljava/lang/Object;")                                                                                         \
+    boolean_field(HotSpotObjectConstantImpl, compressed)                                                                                                       \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotMetaspaceConstantImpl)                                                                                                                    \
+    oop_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljdk/vm/ci/hotspot/MetaspaceWrapperObject;")                                                     \
+    boolean_field(HotSpotMetaspaceConstantImpl, compressed)                                                                                                    \
+  end_class                                                                                                                                                    \
+  start_class(JavaKind)                                                                                                                                        \
+    char_field(JavaKind, typeChar)                                                                                                                             \
+    static_oop_field(JavaKind, Boolean, "Ljdk/vm/ci/meta/JavaKind;");                                                                                          \
+    static_oop_field(JavaKind, Byte, "Ljdk/vm/ci/meta/JavaKind;");                                                                                             \
+    static_oop_field(JavaKind, Char, "Ljdk/vm/ci/meta/JavaKind;");                                                                                             \
+    static_oop_field(JavaKind, Short, "Ljdk/vm/ci/meta/JavaKind;");                                                                                            \
+    static_oop_field(JavaKind, Int, "Ljdk/vm/ci/meta/JavaKind;");                                                                                              \
+    static_oop_field(JavaKind, Long, "Ljdk/vm/ci/meta/JavaKind;");                                                                                             \
+  end_class                                                                                                                                                    \
+  start_class(ValueKind)                                                                                                                                       \
+    oop_field(ValueKind, platformKind, "Ljdk/vm/ci/meta/PlatformKind;")                                                                                        \
+  end_class                                                                                                                                                    \
+  start_class(Value)                                                                                                                                           \
+    oop_field(Value, valueKind, "Ljdk/vm/ci/meta/ValueKind;")                                                                                                  \
+    static_oop_field(Value, ILLEGAL, "Ljdk/vm/ci/meta/AllocatableValue;");                                                                                     \
+  end_class                                                                                                                                                    \
+  start_class(RegisterValue)                                                                                                                                   \
+    oop_field(RegisterValue, reg, "Ljdk/vm/ci/code/Register;")                                                                                                 \
+  end_class                                                                                                                                                    \
+  start_class(code_Location)                                                                                                                                   \
+    oop_field(code_Location, reg, "Ljdk/vm/ci/code/Register;")                                                                                                 \
+    int_field(code_Location, offset)                                                                                                                           \
+  end_class                                                                                                                                                    \
+  start_class(code_Register)                                                                                                                                   \
+    int_field(code_Register, number)                                                                                                                           \
+    int_field(code_Register, encoding)                                                                                                                         \
+  end_class                                                                                                                                                    \
+  start_class(StackSlot)                                                                                                                                       \
+    int_field(StackSlot, offset)                                                                                                                               \
+    boolean_field(StackSlot, addFrameSize)                                                                                                                     \
+  end_class                                                                                                                                                    \
+  start_class(VirtualObject)                                                                                                                                   \
+    int_field(VirtualObject, id)                                                                                                                               \
+    oop_field(VirtualObject, type, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                                        \
+    objArrayOop_field(VirtualObject, values, "[Ljdk/vm/ci/meta/JavaValue;")                                                                                    \
+    objArrayOop_field(VirtualObject, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                                                                  \
+  end_class                                                                                                                                                    \
+  start_class(StackLockValue)                                                                                                                                  \
+    oop_field(StackLockValue, owner, "Ljdk/vm/ci/meta/JavaValue;")                                                                                             \
+    oop_field(StackLockValue, slot, "Ljdk/vm/ci/meta/AllocatableValue;")                                                                                       \
+    boolean_field(StackLockValue, eliminated)                                                                                                                  \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotSpeculationLog)                                                                                                                           \
+    oop_field(HotSpotSpeculationLog, lastFailed, "Ljava/lang/Object;")                                                                                         \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotStackFrameReference)                                                                                                                      \
+    oop_field(HotSpotStackFrameReference, compilerToVM, "Ljdk/vm/ci/hotspot/CompilerToVM;")                                                                    \
+    long_field(HotSpotStackFrameReference, stackPointer)                                                                                                       \
+    int_field(HotSpotStackFrameReference, frameNumber)                                                                                                         \
+    int_field(HotSpotStackFrameReference, bci)                                                                                                                 \
+    oop_field(HotSpotStackFrameReference, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                                                             \
+    objArrayOop_field(HotSpotStackFrameReference, locals, "[Ljava/lang/Object;")                                                                               \
+    typeArrayOop_field(HotSpotStackFrameReference, localIsVirtual, "[Z")                                                                                       \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotConstantPool)                                                                                                                             \
+    long_field(HotSpotConstantPool, metaspaceConstantPool)                                                                                                     \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotJVMCIRuntime)                                                                                                                             \
+    objArrayOop_field(HotSpotJVMCIRuntime, trivialPrefixes, "[Ljava/lang/String;")                                                                             \
+    int_field(HotSpotJVMCIRuntime, compilationLevelAdjustment)                                                                                                 \
+  end_class                                                                                                                                                    \
+  /* end*/
+
+#define START_CLASS(name)                                                                                                                                      \
+class name : AllStatic {                                                                                                                                       \
+  private:                                                                                                                                                     \
+    friend class JVMCICompiler;                                                                                                                                \
+    static void check(oop obj, const char* field_name, int offset) {                                                                                           \
+        assert(obj != NULL, err_msg("NULL field access of %s.%s", #name, field_name));                                                                         \
+        assert(obj->is_a(SystemDictionary::name##_klass()), err_msg("wrong class, " #name " expected, found %s", obj->klass()->external_name())); \
+        assert(offset != 0, "must be valid offset");                                                                                                           \
+    }                                                                                                                                                          \
+    static void compute_offsets();                                                                                                                             \
+  public:                                                                                                                                                      \
+    static InstanceKlass* klass() { return SystemDictionary::name##_klass() == NULL ? NULL : InstanceKlass::cast(SystemDictionary::name##_klass()); }
+
+#define END_CLASS };
+
+#define FIELD(name, type, accessor, cast)                                                                                                                         \
+    static int _##name##_offset;                                                                                                                                  \
+    static type name(oop obj)                   { check(obj, #name, _##name##_offset); return cast obj->accessor(_##name##_offset); }                                               \
+    static type name(Handle obj)                { check(obj(), #name, _##name##_offset); return cast obj->accessor(_##name##_offset); }                                             \
+    static type name(jobject obj)               { check(JNIHandles::resolve(obj), #name, _##name##_offset); return cast JNIHandles::resolve(obj)->accessor(_##name##_offset); }     \
+    static void set_##name(oop obj, type x)     { check(obj, #name, _##name##_offset); obj->accessor##_put(_##name##_offset, x); }                                                  \
+    static void set_##name(Handle obj, type x)  { check(obj(), #name, _##name##_offset); obj->accessor##_put(_##name##_offset, x); }                                                \
+    static void set_##name(jobject obj, type x) { check(JNIHandles::resolve(obj), #name, _##name##_offset); JNIHandles::resolve(obj)->accessor##_put(_##name##_offset, x); }
+
+#define EMPTY_CAST 
+#define CHAR_FIELD(klass, name) FIELD(name, jchar, char_field, EMPTY_CAST)
+#define INT_FIELD(klass, name) FIELD(name, jint, int_field, EMPTY_CAST)
+#define BOOLEAN_FIELD(klass, name) FIELD(name, jboolean, bool_field, EMPTY_CAST)
+#define LONG_FIELD(klass, name) FIELD(name, jlong, long_field, EMPTY_CAST)
+#define FLOAT_FIELD(klass, name) FIELD(name, jfloat, float_field, EMPTY_CAST)
+#define OOP_FIELD(klass, name, signature) FIELD(name, oop, obj_field, EMPTY_CAST)
+#define OBJARRAYOOP_FIELD(klass, name, signature) FIELD(name, objArrayOop, obj_field, (objArrayOop))
+#define TYPEARRAYOOP_FIELD(klass, name, signature) FIELD(name, typeArrayOop, obj_field, (typeArrayOop))
+#define STATIC_OOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, oop, signature)
+#define STATIC_OBJARRAYOOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, objArrayOop, signature)
+#define STATIC_OOPISH_FIELD(klassName, name, type, signature)                                                  \
+    static int _##name##_offset;                                                                               \
+    static type name() {                                                                                       \
+      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
+      InstanceKlass* ik = klassName::klass();                                                                  \
+      address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
+      if (UseCompressedOops) {                                                                                 \
+        return (type) oopDesc::load_decode_heap_oop((narrowOop *)addr);                                        \
+      } else {                                                                                                 \
+        return (type) oopDesc::load_decode_heap_oop((oop*)addr);                                               \
+      }                                                                                                        \
+    }                                                                                                          \
+    static void set_##name(type x) {                                                                           \
+      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
+      assert(klassName::klass() != NULL, "Class not yet loaded: " #klassName);                                 \
+      InstanceKlass* ik = klassName::klass();                                                                  \
+      address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
+      if (UseCompressedOops) {                                                                                 \
+        oop_store((narrowOop *)addr, x);                                                                       \
+      } else {                                                                                                 \
+        oop_store((oop*)addr, x);                                                                              \
+      }                                                                                                        \
+    }
+#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename)                                                     \
+    static int _##name##_offset;                                                                               \
+    static jtypename name() {                                                                                  \
+      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
+      InstanceKlass* ik = klassName::klass();                                                                  \
+      address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
+      return *((jtypename *)addr);                                                                             \
+    }                                                                                                          \
+    static void set_##name(jtypename x) {                                                                      \
+      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
+      InstanceKlass* ik = klassName::klass();                                                                  \
+      address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
+      *((jtypename *)addr) = x;                                                                                \
+    }
+
+#define STATIC_INT_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jint)
+#define STATIC_BOOLEAN_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jboolean)
+
+COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, TYPEARRAYOOP_FIELD, OBJARRAYOOP_FIELD, STATIC_OOP_FIELD, STATIC_OBJARRAYOOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
+#undef START_CLASS
+#undef END_CLASS
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OOP_FIELD
+#undef TYPEARRAYOOP_FIELD
+#undef OBJARRAYOOP_FIELD
+#undef STATIC_OOPISH_FIELD
+#undef STATIC_OOP_FIELD
+#undef STATIC_OBJARRAYOOP_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
+
+void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS);
+
+#endif // SHARE_VM_JVMCI_JVMCIJAVACLASSES_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciRuntime.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,985 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "asm/codeBuffer.hpp"
+#include "code/codeCache.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/disassembler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/oop.inline.hpp"
+#include "prims/jvm.h"
+#include "runtime/biasedLocking.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/reflection.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/defaultStream.hpp"
+
+#if defined(_MSC_VER)
+#define strtoll _strtoi64
+#endif
+
+jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
+bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false;
+int JVMCIRuntime::_trivial_prefixes_count = 0;
+char** JVMCIRuntime::_trivial_prefixes = NULL;
+JVMCIRuntime::CompLevelAdjustment JVMCIRuntime::_comp_level_adjustment = JVMCIRuntime::none;
+bool JVMCIRuntime::_shutdown_called = false;
+
+BasicType JVMCIRuntime::kindToBasicType(Handle kind, TRAPS) {
+  if (kind.is_null()) {
+    THROW_(vmSymbols::java_lang_NullPointerException(), T_ILLEGAL);
+  }
+  jchar ch = JavaKind::typeChar(kind);
+  switch(ch) {
+    case 'Z': return T_BOOLEAN;
+    case 'B': return T_BYTE;
+    case 'S': return T_SHORT;
+    case 'C': return T_CHAR;
+    case 'I': return T_INT;
+    case 'F': return T_FLOAT;
+    case 'J': return T_LONG;
+    case 'D': return T_DOUBLE;
+    case 'A': return T_OBJECT;
+    case '-': return T_ILLEGAL;
+    default:
+      JVMCI_ERROR_(T_ILLEGAL, "unexpected Kind: %c", ch);
+  }
+}
+
+// Simple helper to see if the caller of a runtime stub which
+// entered the VM has been deoptimized
+
+static bool caller_is_deopted() {
+  JavaThread* thread = JavaThread::current();
+  RegisterMap reg_map(thread, false);
+  frame runtime_frame = thread->last_frame();
+  frame caller_frame = runtime_frame.sender(&reg_map);
+  assert(caller_frame.is_compiled_frame(), "must be compiled");
+  return caller_frame.is_deoptimized_frame();
+}
+
+// Stress deoptimization
+static void deopt_caller() {
+  if ( !caller_is_deopted()) {
+    JavaThread* thread = JavaThread::current();
+    RegisterMap reg_map(thread, false);
+    frame runtime_frame = thread->last_frame();
+    frame caller_frame = runtime_frame.sender(&reg_map);
+    Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
+    assert(caller_is_deopted(), "Must be deoptimized");
+  }
+}
+
+JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance(JavaThread* thread, Klass* klass))
+  JRT_BLOCK;
+  assert(klass->is_klass(), "not a class");
+  Handle holder(THREAD, klass->klass_holder()); // keep the klass alive
+  instanceKlassHandle h(thread, klass);
+  h->check_valid_for_instantiation(true, CHECK);
+  // make sure klass is initialized
+  h->initialize(CHECK);
+  // allocate instance and return via TLS
+  oop obj = h->allocate_instance(CHECK);
+  thread->set_vm_result(obj);
+  JRT_BLOCK_END;
+
+  if (ReduceInitialCardMarks) {
+    new_store_pre_barrier(thread);
+  }
+JRT_END
+
+JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_klass, jint length))
+  JRT_BLOCK;
+  // Note: no handle for klass needed since they are not used
+  //       anymore after new_objArray() and no GC can happen before.
+  //       (This may have to change if this code changes!)
+  assert(array_klass->is_klass(), "not a class");
+  oop obj;
+  if (array_klass->oop_is_typeArray()) {
+    BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type();
+    obj = oopFactory::new_typeArray(elt_type, length, CHECK);
+  } else {
+    Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive
+    Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass();
+    obj = oopFactory::new_objArray(elem_klass, length, CHECK);
+  }
+  thread->set_vm_result(obj);
+  // This is pretty rare but this runtime patch is stressful to deoptimization
+  // if we deoptimize here so force a deopt to stress the path.
+  if (DeoptimizeALot) {
+    static int deopts = 0;
+    // Alternate between deoptimizing and raising an error (which will also cause a deopt)
+    if (deopts++ % 2 == 0) {
+      ResourceMark rm(THREAD);
+      THROW(vmSymbols::java_lang_OutOfMemoryError());
+    } else {
+      deopt_caller();
+    }
+  }
+  JRT_BLOCK_END;
+
+  if (ReduceInitialCardMarks) {
+    new_store_pre_barrier(thread);
+  }
+JRT_END
+
+void JVMCIRuntime::new_store_pre_barrier(JavaThread* thread) {
+  // After any safepoint, just before going back to compiled code,
+  // we inform the GC that we will be doing initializing writes to
+  // this object in the future without emitting card-marks, so
+  // GC may take any compensating steps.
+  // NOTE: Keep this code consistent with GraphKit::store_barrier.
+
+  oop new_obj = thread->vm_result();
+  if (new_obj == NULL)  return;
+
+  assert(Universe::heap()->can_elide_tlab_store_barriers(),
+         "compiler must check this first");
+  // GC may decide to give back a safer copy of new_obj.
+  new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj);
+  thread->set_vm_result(new_obj);
+}
+
+JRT_ENTRY(void, JVMCIRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims))
+  assert(klass->is_klass(), "not a class");
+  assert(rank >= 1, "rank must be nonzero");
+  Handle holder(THREAD, klass->klass_holder()); // keep the klass alive
+  oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK);
+  thread->set_vm_result(obj);
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length))
+  oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK);
+  thread->set_vm_result(obj);
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance(JavaThread* thread, oopDesc* type_mirror))
+  instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(type_mirror));
+
+  if (klass == NULL) {
+    ResourceMark rm(THREAD);
+    THROW(vmSymbols::java_lang_InstantiationException());
+  }
+
+  // Create new instance (the receiver)
+  klass->check_valid_for_instantiation(false, CHECK);
+
+  // Make sure klass gets initialized
+  klass->initialize(CHECK);
+
+  oop obj = klass->allocate_instance(CHECK);
+  thread->set_vm_result(obj);
+JRT_END
+
+extern void vm_exit(int code);
+
+// Enter this method from compiled code handler below. This is where we transition
+// to VM mode. This is done as a helper routine so that the method called directly
+// from compiled code does not have to transition to VM. This allows the entry
+// method to see if the nmethod that we have just looked up a handler for has
+// been deoptimized while we were in the vm. This simplifies the assembly code
+// cpu directories.
+//
+// We are entering here from exception stub (via the entry method below)
+// If there is a compiled exception handler in this method, we will continue there;
+// otherwise we will unwind the stack and continue at the caller of top frame method
+// Note: we enter in Java using a special JRT wrapper. This wrapper allows us to
+// control the area where we can allow a safepoint. After we exit the safepoint area we can
+// check to see if the handler we are going to return is now in a nmethod that has
+// been deoptimized. If that is the case we return the deopt blob
+// unpack_with_exception entry instead. This makes life for the exception blob easier
+// because making that same check and diverting is painful from assembly language.
+JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* thread, oopDesc* ex, address pc, nmethod*& nm))
+  // Reset method handle flag.
+  thread->set_is_method_handle_return(false);
+
+  Handle exception(thread, ex);
+  nm = CodeCache::find_nmethod(pc);
+  assert(nm != NULL, "this is not a compiled method");
+  // Adjust the pc as needed/
+  if (nm->is_deopt_pc(pc)) {
+    RegisterMap map(thread, false);
+    frame exception_frame = thread->last_frame().sender(&map);
+    // if the frame isn't deopted then pc must not correspond to the caller of last_frame
+    assert(exception_frame.is_deoptimized_frame(), "must be deopted");
+    pc = exception_frame.pc();
+  }
+#ifdef ASSERT
+  assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");
+  assert(exception->is_oop(), "just checking");
+  // Check that exception is a subclass of Throwable, otherwise we have a VerifyError
+  if (!(exception->is_a(SystemDictionary::Throwable_klass()))) {
+    if (ExitVMOnVerifyError) vm_exit(-1);
+    ShouldNotReachHere();
+  }
+#endif
+
+  // Check the stack guard pages and reenable them if necessary and there is
+  // enough space on the stack to do so.  Use fast exceptions only if the guard
+  // pages are enabled.
+  bool guard_pages_enabled = thread->stack_yellow_zone_enabled();
+  if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack();
+
+  if (JvmtiExport::can_post_on_exceptions()) {
+    // To ensure correct notification of exception catches and throws
+    // we have to deoptimize here.  If we attempted to notify the
+    // catches and throws during this exception lookup it's possible
+    // we could deoptimize on the way out of the VM and end back in
+    // the interpreter at the throw site.  This would result in double
+    // notifications since the interpreter would also notify about
+    // these same catches and throws as it unwound the frame.
+
+    RegisterMap reg_map(thread);
+    frame stub_frame = thread->last_frame();
+    frame caller_frame = stub_frame.sender(&reg_map);
+
+    // We don't really want to deoptimize the nmethod itself since we
+    // can actually continue in the exception handler ourselves but I
+    // don't see an easy way to have the desired effect.
+    Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
+    assert(caller_is_deopted(), "Must be deoptimized");
+
+    return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
+  }
+
+  // ExceptionCache is used only for exceptions at call sites and not for implicit exceptions
+  if (guard_pages_enabled) {
+    address fast_continuation = nm->handler_for_exception_and_pc(exception, pc);
+    if (fast_continuation != NULL) {
+      // Set flag if return address is a method handle call site.
+      thread->set_is_method_handle_return(nm->is_method_handle_return(pc));
+      return fast_continuation;
+    }
+  }
+
+  // If the stack guard pages are enabled, check whether there is a handler in
+  // the current method.  Otherwise (guard pages disabled), force an unwind and
+  // skip the exception cache update (i.e., just leave continuation==NULL).
+  address continuation = NULL;
+  if (guard_pages_enabled) {
+
+    // New exception handling mechanism can support inlined methods
+    // with exception handlers since the mappings are from PC to PC
+
+    // debugging support
+    // tracing
+    if (TraceExceptions) {
+      ttyLocker ttyl;
+      ResourceMark rm;
+      tty->print_cr("Exception <%s> (" INTPTR_FORMAT ") thrown in compiled method <%s> at PC " INTPTR_FORMAT " for thread " INTPTR_FORMAT "",
+                    exception->print_value_string(), p2i((address)exception()), nm->method()->print_value_string(), p2i(pc), p2i(thread));
+    }
+    // for AbortVMOnException flag
+    NOT_PRODUCT(Exceptions::debug_check_abort(exception));
+
+    // Clear out the exception oop and pc since looking up an
+    // exception handler can cause class loading, which might throw an
+    // exception and those fields are expected to be clear during
+    // normal bytecode execution.
+    thread->clear_exception_oop_and_pc();
+
+    bool recursive_exception = false;
+    continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false, recursive_exception);
+    // If an exception was thrown during exception dispatch, the exception oop may have changed
+    thread->set_exception_oop(exception());
+    thread->set_exception_pc(pc);
+
+    // The exception cache is used only for non-implicit exceptions
+    // Update the exception cache only when another exception did
+    // occur during the computation of the compiled exception handler
+    // (e.g., when loading the class of the catch type).
+    // Checking for exception oop equality is not
+    // sufficient because some exceptions are pre-allocated and reused.
+    if (continuation != NULL && !recursive_exception && !SharedRuntime::deopt_blob()->contains(continuation)) {
+      nm->add_handler_for_exception_and_pc(exception, pc, continuation);
+    }
+  }
+
+  // Set flag if return address is a method handle call site.
+  thread->set_is_method_handle_return(nm->is_method_handle_return(pc));
+
+  if (TraceExceptions) {
+    ttyLocker ttyl;
+    ResourceMark rm;
+    tty->print_cr("Thread " PTR_FORMAT " continuing at PC " PTR_FORMAT " for exception thrown at PC " PTR_FORMAT,
+                  p2i(thread), p2i(continuation), p2i(pc));
+  }
+
+  return continuation;
+JRT_END
+
+// Enter this method from compiled code only if there is a Java exception handler
+// in the method handling the exception.
+// We are entering here from exception stub. We don't do a normal VM transition here.
+// We do it in a helper. This is so we can check to see if the nmethod we have just
+// searched for an exception handler has been deoptimized in the meantime.
+address JVMCIRuntime::exception_handler_for_pc(JavaThread* thread) {
+  oop exception = thread->exception_oop();
+  address pc = thread->exception_pc();
+  // Still in Java mode
+  DEBUG_ONLY(ResetNoHandleMark rnhm);
+  nmethod* nm = NULL;
+  address continuation = NULL;
+  {
+    // Enter VM mode by calling the helper
+    ResetNoHandleMark rnhm;
+    continuation = exception_handler_for_pc_helper(thread, exception, pc, nm);
+  }
+  // Back in JAVA, use no oops DON'T safepoint
+
+  // Now check to see if the compiled method we were called from is now deoptimized.
+  // If so we must return to the deopt blob and deoptimize the nmethod
+  if (nm != NULL && caller_is_deopted()) {
+    continuation = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
+  }
+
+  assert(continuation != NULL, "no handler found");
+  return continuation;
+}
+
+JRT_ENTRY_NO_ASYNC(void, JVMCIRuntime::monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock))
+  IF_TRACE_jvmci_3 {
+    char type[O_BUFLEN];
+    obj->klass()->name()->as_C_string(type, O_BUFLEN);
+    markOop mark = obj->mark();
+    TRACE_jvmci_3("%s: entered locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), p2i(obj), type, p2i(mark), p2i(lock));
+    tty->flush();
+  }
+  if (PrintBiasedLockingStatistics) {
+    Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
+  }
+  Handle h_obj(thread, obj);
+  assert(h_obj()->is_oop(), "must be NULL or an object");
+  if (UseBiasedLocking) {
+    // Retry fast entry if bias is revoked to avoid unnecessary inflation
+    ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
+  } else {
+    if (JVMCIUseFastLocking) {
+      // When using fast locking, the compiled code has already tried the fast case
+      ObjectSynchronizer::slow_enter(h_obj, lock, THREAD);
+    } else {
+      ObjectSynchronizer::fast_enter(h_obj, lock, false, THREAD);
+    }
+  }
+  TRACE_jvmci_3("%s: exiting locking slow with obj=" INTPTR_FORMAT, thread->name(), p2i(obj));
+JRT_END
+
+JRT_LEAF(void, JVMCIRuntime::monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock))
+  assert(thread == JavaThread::current(), "threads must correspond");
+  assert(thread->last_Java_sp(), "last_Java_sp must be set");
+  // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown
+  EXCEPTION_MARK;
+
+#ifdef DEBUG
+  if (!obj->is_oop()) {
+    ResetNoHandleMark rhm;
+    nmethod* method = thread->last_frame().cb()->as_nmethod_or_null();
+    if (method != NULL) {
+      tty->print_cr("ERROR in monitorexit in method %s wrong obj " INTPTR_FORMAT, method->name(), p2i(obj));
+    }
+    thread->print_stack_on(tty);
+    assert(false, "invalid lock object pointer dected");
+  }
+#endif
+
+  if (JVMCIUseFastLocking) {
+    // When using fast locking, the compiled code has already tried the fast case
+    ObjectSynchronizer::slow_exit(obj, lock, THREAD);
+  } else {
+    ObjectSynchronizer::fast_exit(obj, lock, THREAD);
+  }
+  IF_TRACE_jvmci_3 {
+    char type[O_BUFLEN];
+    obj->klass()->name()->as_C_string(type, O_BUFLEN);
+    TRACE_jvmci_3("%s: exited locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), p2i(obj), type, p2i(obj->mark()), p2i(lock));
+    tty->flush();
+  }
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message))
+  TempNewSymbol symbol = SymbolTable::new_symbol(exception, CHECK);
+  SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass))
+  ResourceMark rm(thread);
+  TempNewSymbol symbol = SymbolTable::new_symbol(exception, CHECK);
+  SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, klass->external_name());
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass))
+  ResourceMark rm(thread);
+  const char* message = SharedRuntime::generate_class_cast_message(caster_klass->external_name(), target_klass->external_name());
+  TempNewSymbol symbol = SymbolTable::new_symbol(exception, CHECK);
+  SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
+JRT_END
+
+JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, bool as_string, bool newline))
+  ttyLocker ttyl;
+
+  if (obj == NULL) {
+    tty->print("NULL");
+  } else if (obj->is_oop_or_null(true) && (!as_string || !java_lang_String::is_instance(obj))) {
+    if (obj->is_oop_or_null(true)) {
+      char buf[O_BUFLEN];
+      tty->print("%s@" INTPTR_FORMAT, obj->klass()->name()->as_C_string(buf, O_BUFLEN), p2i(obj));
+    } else {
+      tty->print(INTPTR_FORMAT, p2i(obj));
+    }
+  } else {
+    ResourceMark rm;
+    assert(obj != NULL && java_lang_String::is_instance(obj), "must be");
+    char *buf = java_lang_String::as_utf8_string(obj);
+    tty->print_raw(buf);
+  }
+  if (newline) {
+    tty->cr();
+  }
+JRT_END
+
+JRT_LEAF(void, JVMCIRuntime::write_barrier_pre(JavaThread* thread, oopDesc* obj))
+  thread->satb_mark_queue().enqueue(obj);
+JRT_END
+
+JRT_LEAF(void, JVMCIRuntime::write_barrier_post(JavaThread* thread, void* card_addr))
+  thread->dirty_card_queue().enqueue(card_addr);
+JRT_END
+
+JRT_LEAF(jboolean, JVMCIRuntime::validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child))
+  bool ret = true;
+  if(!Universe::heap()->is_in_closed_subset(parent)) {
+    tty->print_cr("Parent Object " INTPTR_FORMAT " not in heap", p2i(parent));
+    parent->print();
+    ret=false;
+  }
+  if(!Universe::heap()->is_in_closed_subset(child)) {
+    tty->print_cr("Child Object " INTPTR_FORMAT " not in heap", p2i(child));
+    child->print();
+    ret=false;
+  }
+  return (jint)ret;
+JRT_END
+
+JRT_ENTRY(void, JVMCIRuntime::vm_error(JavaThread* thread, jlong where, jlong format, jlong value))
+  ResourceMark rm;
+  const char *error_msg = where == 0L ? "<internal JVMCI error>" : (char*) (address) where;
+  char *detail_msg = NULL;
+  if (format != 0L) {
+    const char* buf = (char*) (address) format;
+    size_t detail_msg_length = strlen(buf) * 2;
+    detail_msg = (char *) NEW_RESOURCE_ARRAY(u_char, detail_msg_length);
+    jio_snprintf(detail_msg, detail_msg_length, buf, value);
+  }
+  report_vm_error(__FILE__, __LINE__, error_msg, detail_msg);
+JRT_END
+
+JRT_LEAF(oopDesc*, JVMCIRuntime::load_and_clear_exception(JavaThread* thread))
+  oop exception = thread->exception_oop();
+  assert(exception != NULL, "npe");
+  thread->set_exception_oop(NULL);
+  thread->set_exception_pc(0);
+  return exception;
+JRT_END
+
+PRAGMA_DIAG_PUSH
+PRAGMA_FORMAT_NONLITERAL_IGNORED
+JRT_LEAF(void, JVMCIRuntime::log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3))
+  ResourceMark rm;
+  assert(format != NULL && java_lang_String::is_instance(format), "must be");
+  char *buf = java_lang_String::as_utf8_string(format);
+  tty->print((const char*)buf, v1, v2, v3);
+JRT_END
+PRAGMA_DIAG_POP
+
+static void decipher(jlong v, bool ignoreZero) {
+  if (v != 0 || !ignoreZero) {
+    void* p = (void *)(address) v;
+    CodeBlob* cb = CodeCache::find_blob(p);
+    if (cb) {
+      if (cb->is_nmethod()) {
+        char buf[O_BUFLEN];
+        tty->print("%s [" INTPTR_FORMAT "+" JLONG_FORMAT "]", cb->as_nmethod_or_null()->method()->name_and_sig_as_C_string(buf, O_BUFLEN), p2i(cb->code_begin()), (jlong)((address)v - cb->code_begin()));
+        return;
+      }
+      cb->print_value_on(tty);
+      return;
+    }
+    if (Universe::heap()->is_in(p)) {
+      oop obj = oop(p);
+      obj->print_value_on(tty);
+      return;
+    }
+    tty->print(INTPTR_FORMAT " [long: " JLONG_FORMAT ", double %lf, char %c]",p2i((void *)v), (jlong)v, (jdouble)v, (char)v);
+  }
+}
+
+PRAGMA_DIAG_PUSH
+PRAGMA_FORMAT_NONLITERAL_IGNORED
+JRT_LEAF(void, JVMCIRuntime::vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3))
+  ResourceMark rm;
+  const char *buf = (const char*) (address) format;
+  if (vmError) {
+    if (buf != NULL) {
+      fatal(err_msg(buf, v1, v2, v3));
+    } else {
+      fatal("<anonymous error>");
+    }
+  } else if (buf != NULL) {
+    tty->print(buf, v1, v2, v3);
+  } else {
+    assert(v2 == 0, "v2 != 0");
+    assert(v3 == 0, "v3 != 0");
+    decipher(v1, false);
+  }
+JRT_END
+PRAGMA_DIAG_POP
+
+JRT_LEAF(void, JVMCIRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
+  union {
+      jlong l;
+      jdouble d;
+      jfloat f;
+  } uu;
+  uu.l = value;
+  switch (typeChar) {
+    case 'Z': tty->print(value == 0 ? "false" : "true"); break;
+    case 'B': tty->print("%d", (jbyte) value); break;
+    case 'C': tty->print("%c", (jchar) value); break;
+    case 'S': tty->print("%d", (jshort) value); break;
+    case 'I': tty->print("%d", (jint) value); break;
+    case 'F': tty->print("%f", uu.f); break;
+    case 'J': tty->print(JLONG_FORMAT, value); break;
+    case 'D': tty->print("%lf", uu.d); break;
+    default: assert(false, "unknown typeChar"); break;
+  }
+  if (newline) {
+    tty->cr();
+  }
+JRT_END
+
+JRT_ENTRY(jint, JVMCIRuntime::identity_hash_code(JavaThread* thread, oopDesc* obj))
+  return (jint) obj->identity_hash();
+JRT_END
+
+JRT_ENTRY(jboolean, JVMCIRuntime::thread_is_interrupted(JavaThread* thread, oopDesc* receiver, jboolean clear_interrupted))
+  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate.
+  // This locking requires thread_in_vm which is why this method cannot be JRT_LEAF.
+  Handle receiverHandle(thread, receiver);
+  MutexLockerEx ml(thread->threadObj() == (void*)receiver ? NULL : Threads_lock);
+  JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle());
+  if (receiverThread == NULL) {
+    // The other thread may exit during this process, which is ok so return false.
+    return JNI_FALSE;
+  } else {
+    return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
+  }
+JRT_END
+
+JRT_ENTRY(jint, JVMCIRuntime::test_deoptimize_call_int(JavaThread* thread, int value))
+  deopt_caller();
+  return value;
+JRT_END
+
+// private static void JVMCIClassLoaderFactory.init(ClassLoader loader)
+JVM_ENTRY(void, JVM_InitJVMCIClassLoader(JNIEnv *env, jclass c, jobject loader_handle))
+  SystemDictionary::init_jvmci_loader(JNIHandles::resolve(loader_handle));
+  SystemDictionary::WKID scan = SystemDictionary::FIRST_JVMCI_WKID;
+  SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_JVMCI_WKID, scan, CHECK);
+JVM_END
+
+// private static JVMCIRuntime JVMCI.initializeRuntime()
+JVM_ENTRY(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
+  if (!EnableJVMCI) {
+    THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
+  }
+  JVMCIRuntime::initialize_HotSpotJVMCIRuntime(CHECK_NULL);
+  return JVMCIRuntime::get_HotSpotJVMCIRuntime_jobject(CHECK_NULL);
+JVM_END
+
+// private static ClassLoader Services.getJVMCIClassLoader()
+JVM_ENTRY(jobject, JVM_GetJVMCIClassLoader(JNIEnv *env, jclass c))
+  if (!EnableJVMCI) {
+    // This message must not change - it is used by the Java code to
+    // distinguish an InternalError due to -EnableJVMCI from other
+    // InternalErrors that may be raised below.
+    THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
+  }
+  JVMCIRuntime::ensure_jvmci_class_loader_is_initialized();
+  return JNIHandles::make_local(THREAD, SystemDictionary::jvmci_loader());
+JVM_END
+
+Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, const char* signature, JavaCallArguments* args, TRAPS) {
+  TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_(Handle()));
+  KlassHandle klass = resolve_or_fail(name, CHECK_(Handle()));
+  TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_(Handle()));
+  TempNewSymbol sig = SymbolTable::new_symbol(signature, CHECK_(Handle()));
+  JavaValue result(T_OBJECT);
+  if (args == NULL) {
+    JavaCalls::call_static(&result, klass, runtime, sig, CHECK_(Handle()));
+  } else {
+    JavaCalls::call_static(&result, klass, runtime, sig, args, CHECK_(Handle()));
+  }
+  return Handle((oop)result.get_jobject());
+}
+
+void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) {
+  guarantee(!_HotSpotJVMCIRuntime_initialized, "cannot reinitialize HotSpotJVMCIRuntime");
+  JVMCIRuntime::ensure_jvmci_class_loader_is_initialized();
+  // This should only be called in the context of the JVMCI class being initialized
+  instanceKlassHandle klass = InstanceKlass::cast(SystemDictionary::JVMCI_klass());
+  guarantee(klass->is_being_initialized() && klass->is_reentrant_initialization(THREAD),
+         "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization");
+
+  Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime",
+                             "runtime",
+                             "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK);
+  objArrayOop trivial_prefixes = HotSpotJVMCIRuntime::trivialPrefixes(result);
+  if (trivial_prefixes != NULL) {
+    char** prefixes = NEW_C_HEAP_ARRAY(char*, trivial_prefixes->length(), mtCompiler);
+    for (int i = 0; i < trivial_prefixes->length(); i++) {
+      oop str = trivial_prefixes->obj_at(i);
+      if (str == NULL) {
+        THROW(vmSymbols::java_lang_NullPointerException());
+      } else {
+        prefixes[i] = strdup(java_lang_String::as_utf8_string(str));
+      }
+    }
+    _trivial_prefixes = prefixes;
+    _trivial_prefixes_count = trivial_prefixes->length();
+  }
+  int adjustment = HotSpotJVMCIRuntime::compilationLevelAdjustment(result);
+  assert(adjustment >= JVMCIRuntime::none &&
+         adjustment <= JVMCIRuntime::by_full_signature,
+         "compilation level adjustment out of bounds");
+  _comp_level_adjustment = (CompLevelAdjustment) adjustment;
+  _HotSpotJVMCIRuntime_initialized = true;
+  _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result());
+}
+
+void JVMCIRuntime::initialize_JVMCI(TRAPS) {
+  if (JNIHandles::resolve(_HotSpotJVMCIRuntime_instance) == NULL) {
+    callStatic("jdk/vm/ci/runtime/JVMCI",
+               "getRuntime",
+               "()Ljdk/vm/ci/runtime/JVMCIRuntime;", NULL, CHECK);
+  }
+  assert(_HotSpotJVMCIRuntime_initialized == true, "what?");
+}
+
+void JVMCIRuntime::metadata_do(void f(Metadata*)) {
+  // For simplicity, the existence of HotSpotJVMCIMetaAccessContext in
+  // the SystemDictionary well known classes should ensure the other
+  // classes have already been loaded, so make sure their order in the
+  // table enforces that.
+  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl) <
+         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
+  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotConstantPool) <
+         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
+  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl) <
+         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
+
+  if (HotSpotJVMCIMetaAccessContext::klass() == NULL ||
+      !HotSpotJVMCIMetaAccessContext::klass()->is_linked()) {
+    // Nothing could be registered yet
+    return;
+  }
+
+  // WeakReference<HotSpotJVMCIMetaAccessContext>[]
+  objArrayOop allContexts = HotSpotJVMCIMetaAccessContext::allContexts();
+  if (allContexts == NULL) {
+    return;
+  }
+
+  // These must be loaded at this point but the linking state doesn't matter.
+  assert(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass() != NULL, "must be loaded");
+  assert(SystemDictionary::HotSpotConstantPool_klass() != NULL, "must be loaded");
+  assert(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass() != NULL, "must be loaded");
+
+  for (int i = 0; i < allContexts->length(); i++) {
+    oop ref = allContexts->obj_at(i);
+    if (ref != NULL) {
+      oop referent = java_lang_ref_Reference::referent(ref);
+      if (referent != NULL) {
+        // Chunked Object[] with last element pointing to next chunk
+        objArrayOop metadataRoots = HotSpotJVMCIMetaAccessContext::metadataRoots(referent);
+        while (metadataRoots != NULL) {
+          for (int typeIndex = 0; typeIndex < metadataRoots->length() - 1; typeIndex++) {
+            oop reference = metadataRoots->obj_at(typeIndex);
+            if (reference == NULL) {
+              continue;
+            }
+            oop metadataRoot = java_lang_ref_Reference::referent(reference);
+            if (metadataRoot == NULL) {
+              continue;
+            }
+            if (metadataRoot->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+              Method* method = CompilerToVM::asMethod(metadataRoot);
+              f(method);
+            } else if (metadataRoot->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
+              ConstantPool* constantPool = CompilerToVM::asConstantPool(metadataRoot);
+              f(constantPool);
+            } else if (metadataRoot->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
+              Klass* klass = CompilerToVM::asKlass(metadataRoot);
+              f(klass);
+            } else {
+              metadataRoot->print();
+              ShouldNotReachHere();
+            }
+          }
+          metadataRoots = (objArrayOop)metadataRoots->obj_at(metadataRoots->length() - 1);
+          assert(metadataRoots == NULL || metadataRoots->is_objArray(), "wrong type");
+        }
+      }
+    }
+  }
+}
+
+// private static void CompilerToVM.registerNatives()
+JVM_ENTRY(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
+  if (!EnableJVMCI) {
+    THROW_MSG(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled");
+  }
+
+#ifdef _LP64
+#ifndef TARGET_ARCH_sparc
+  uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
+  uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
+  guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)");
+#endif // TARGET_ARCH_sparc
+#else
+  fatal("check TLAB allocation code for address space conflicts");
+#endif
+
+  JVMCIRuntime::ensure_jvmci_class_loader_is_initialized();
+
+  {
+    ThreadToNativeFromVM trans(thread);
+
+    ResourceMark rm;
+    HandleMark hm;
+
+    // Ensure _non_oop_bits is initialized
+    Universe::non_oop_word();
+
+    env->RegisterNatives(c2vmClass, CompilerToVM::methods, CompilerToVM::methods_count());
+  }
+JVM_END
+
+void JVMCIRuntime::ensure_jvmci_class_loader_is_initialized() {
+  // This initialization code is guarded by a static pointer to the Factory class.
+  // Once it is non-null, the JVMCI class loader and well known JVMCI classes are
+  // guaranteed to have been initialized. By going through the static
+  // initializer of Factory, we can rely on class initialization semantics to
+  // synchronize threads racing to do the initialization.
+  static Klass* _FactoryKlass = NULL;
+  if (_FactoryKlass == NULL) {
+    Thread* THREAD = Thread::current();
+    TempNewSymbol name = SymbolTable::new_symbol("jdk/vm/ci/services/JVMCIClassLoaderFactory", CHECK_EXIT);
+    KlassHandle klass = SystemDictionary::resolve_or_fail(name, true, CHECK_EXIT);
+
+    // We cannot use jvmciJavaClasses for this because we are currently in the
+    // process of initializing that mechanism.
+    TempNewSymbol field_name = SymbolTable::new_symbol("useJVMCIClassLoader", CHECK_EXIT);
+    fieldDescriptor field_desc;
+    if (klass->find_field(field_name, vmSymbols::bool_signature(), &field_desc) == NULL) {
+      ResourceMark rm;
+      fatal(err_msg("Invalid layout of %s at %s", field_name->as_C_string(), klass->external_name()));
+    }
+
+    InstanceKlass* ik = InstanceKlass::cast(klass());
+    address addr = ik->static_field_addr(field_desc.offset() - InstanceMirrorKlass::offset_of_static_fields());
+    *((jboolean *) addr) = (jboolean) UseJVMCIClassLoader;
+    klass->initialize(CHECK_EXIT);
+    _FactoryKlass = klass();
+    assert(!UseJVMCIClassLoader || SystemDictionary::jvmci_loader() != NULL, "JVMCI classloader should have been initialized");
+
+    JVMCIJavaClasses::compute_offsets(THREAD);
+  }
+}
+
+void JVMCIRuntime::shutdown(TRAPS) {
+  if (_HotSpotJVMCIRuntime_instance != NULL) {
+    _shutdown_called = true;
+    HandleMark hm(THREAD);
+    Handle receiver = get_HotSpotJVMCIRuntime(CHECK);
+    JavaValue result(T_VOID);
+    JavaCallArguments args;
+    args.push_oop(receiver);
+    JavaCalls::call_special(&result, receiver->klass(), vmSymbols::shutdown_method_name(), vmSymbols::void_method_signature(), &args, CHECK);
+  }
+}
+
+void JVMCIRuntime::bootstrap_finished(TRAPS) {
+  if (_HotSpotJVMCIRuntime_instance != NULL) {
+    HandleMark hm(THREAD);
+    Handle receiver = get_HotSpotJVMCIRuntime(CHECK_EXIT);
+    JavaValue result(T_VOID);
+    JavaCallArguments args;
+    args.push_oop(receiver);
+    JavaCalls::call_special(&result, receiver->klass(), vmSymbols::bootstrapFinished_method_name(), vmSymbols::void_method_signature(), &args, CHECK_EXIT);
+  }
+}
+
+bool JVMCIRuntime::treat_as_trivial(Method* method) {
+  if (_HotSpotJVMCIRuntime_initialized) {
+    oop loader = method->method_holder()->class_loader();
+    if (loader == NULL || loader == SystemDictionary::jvmci_loader()) {
+      for (int i = 0; i < _trivial_prefixes_count; i++) {
+        if (method->method_holder()->name()->starts_with(_trivial_prefixes[i])) {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
+CompLevel JVMCIRuntime::adjust_comp_level(methodHandle method, bool is_osr, CompLevel level, JavaThread* thread) {
+  if (!thread->adjusting_comp_level()) {
+    thread->set_adjusting_comp_level(true);
+    level = adjust_comp_level_inner(method, is_osr, level, thread);
+    thread->set_adjusting_comp_level(false);
+  }
+  return level;
+}
+
+CompLevel JVMCIRuntime::adjust_comp_level_inner(methodHandle method, bool is_osr, CompLevel level, JavaThread* thread) {
+  JVMCICompiler* compiler = JVMCICompiler::instance(thread);
+  if (compiler != NULL && compiler->is_bootstrapping()) {
+    return level;
+  }
+  if (!is_HotSpotJVMCIRuntime_initialized() || !_comp_level_adjustment) {
+    // JVMCI cannot participate in compilation scheduling until
+    // JVMCI is initialized and indicates it wants to participate.
+    return level;
+  }
+
+#define CHECK_RETURN THREAD); \
+if (HAS_PENDING_EXCEPTION) { \
+  Handle exception(THREAD, PENDING_EXCEPTION); \
+  CLEAR_PENDING_EXCEPTION; \
+\
+  java_lang_Throwable::print(exception, tty); \
+  tty->cr(); \
+  java_lang_Throwable::print_stack_trace(exception(), tty); \
+  if (HAS_PENDING_EXCEPTION) { \
+    CLEAR_PENDING_EXCEPTION; \
+  } \
+  return level; \
+} \
+(void)(0
+
+
+  Thread* THREAD = thread;
+  HandleMark hm;
+  Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_RETURN);
+  Handle name;
+  Handle sig;
+  if (_comp_level_adjustment == JVMCIRuntime::by_full_signature) {
+    name = java_lang_String::create_from_symbol(method->name(), CHECK_RETURN);
+    sig = java_lang_String::create_from_symbol(method->signature(), CHECK_RETURN);
+  } else {
+    name = Handle();
+    sig = Handle();
+  }
+
+  JavaValue result(T_INT);
+  JavaCallArguments args;
+  args.push_oop(receiver);
+  args.push_oop(method->method_holder()->java_mirror());
+  args.push_oop(name());
+  args.push_oop(sig());
+  args.push_int(is_osr);
+  args.push_int(level);
+  JavaCalls::call_special(&result, receiver->klass(), vmSymbols::adjustCompilationLevel_name(),
+                          vmSymbols::adjustCompilationLevel_signature(), &args, CHECK_RETURN);
+
+  // An uncaught exception was thrown. Generally these
+  // should be handled by the Java code in some useful way but if they leak
+  // through to here report them instead of dying or silently ignoring them.
+  if (HAS_PENDING_EXCEPTION) {
+    Handle throwable = PENDING_EXCEPTION;
+    CLEAR_PENDING_EXCEPTION;
+
+    java_lang_Throwable::print(throwable, tty);
+    tty->cr();
+    java_lang_Throwable::print_stack_trace(throwable(), tty);
+    return level;
+  }
+  int comp_level = result.get_jint();
+  if (comp_level < CompLevel_none || comp_level > CompLevel_full_optimization) {
+    assert(false, "compilation level out of bounds");
+    return level;
+  }
+  return (CompLevel) comp_level;
+#undef CHECK_RETURN
+}
+
+void JVMCIRuntime::exit_on_pending_exception(Handle exception, const char* message) {
+  JavaThread* THREAD = JavaThread::current();
+  CLEAR_PENDING_EXCEPTION;
+
+  static volatile int report_error = 0;
+  if (!report_error && Atomic::cmpxchg(1, &report_error, 0) == 0) {
+    // Only report an error once
+    tty->print_raw_cr(message);
+    java_lang_Throwable::print(exception, tty);
+    tty->cr();
+    java_lang_Throwable::print_stack_trace(exception(), tty);
+  } else {
+    // Allow error reporting thread to print the stack trace.
+    os::sleep(THREAD, 200, false);
+  }
+
+  before_exit(THREAD);
+  vm_exit(-1);
+}
+
+void JVMCIRuntime::fthrow_error(Thread* thread, const char* file, int line, const char* format, ...) {
+  const int max_msg_size = 1024;
+  va_list ap;
+  va_start(ap, format);
+  char msg[max_msg_size];
+  vsnprintf(msg, max_msg_size, format, ap);
+  msg[max_msg_size-1] = '\0';
+  va_end(ap);
+  Handle h_loader = Handle(thread, SystemDictionary::jvmci_loader());
+  Handle h_protection_domain = Handle();
+  Exceptions::_throw_msg(thread, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader, h_protection_domain);
+}
+
+Klass* JVMCIRuntime::resolve_or_null(Symbol* name, TRAPS) {
+  assert(!UseJVMCIClassLoader || SystemDictionary::jvmci_loader() != NULL, "JVMCI classloader should have been initialized");
+  return SystemDictionary::resolve_or_null(name, SystemDictionary::jvmci_loader(), Handle(), CHECK_NULL);
+}
+
+Klass* JVMCIRuntime::resolve_or_fail(Symbol* name, TRAPS) {
+  assert(!UseJVMCIClassLoader || SystemDictionary::jvmci_loader() != NULL, "JVMCI classloader should have been initialized");
+  return SystemDictionary::resolve_or_fail(name, SystemDictionary::jvmci_loader(), Handle(), true, CHECK_NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmciRuntime.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_RUNTIME_HPP
+#define SHARE_VM_JVMCI_JVMCI_RUNTIME_HPP
+
+#include "interpreter/interpreter.hpp"
+#include "memory/allocation.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/deoptimization.hpp"
+
+#define JVMCI_ERROR(...)       \
+  { JVMCIRuntime::fthrow_error(THREAD_AND_LOCATION, __VA_ARGS__); return; }
+
+#define JVMCI_ERROR_(ret, ...) \
+  { JVMCIRuntime::fthrow_error(THREAD_AND_LOCATION, __VA_ARGS__); return ret; }
+
+#define JVMCI_ERROR_0(...)    JVMCI_ERROR_(0, __VA_ARGS__)
+#define JVMCI_ERROR_NULL(...) JVMCI_ERROR_(NULL, __VA_ARGS__)
+#define JVMCI_ERROR_OK(...)   JVMCI_ERROR_(JVMCIEnv::ok, __VA_ARGS__)
+#define CHECK_OK              CHECK_(JVMCIEnv::ok)
+
+class JVMCIRuntime: public AllStatic {
+ public:
+  // Constants describing whether JVMCI wants to be able to adjust the compilation
+  // level selected for a method by the VM compilation policy and if so, based on
+  // what information about the method being schedule for compilation.
+  enum CompLevelAdjustment {
+     none = 0,             // no adjustment
+     by_holder = 1,        // adjust based on declaring class of method
+     by_full_signature = 2 // adjust based on declaring class, name and signature of method
+  };
+
+ private:
+  static jobject _HotSpotJVMCIRuntime_instance;
+  static bool _HotSpotJVMCIRuntime_initialized;
+
+  static int _trivial_prefixes_count;
+  static char** _trivial_prefixes;
+
+  static CompLevelAdjustment _comp_level_adjustment;
+
+  static bool _shutdown_called;
+
+  static CompLevel adjust_comp_level_inner(methodHandle method, bool is_osr, CompLevel level, JavaThread* thread);
+
+ public:
+
+  /**
+   * Ensures that the JVMCI class loader is initialized and the well known JVMCI classes are loaded.
+   */
+  static void ensure_jvmci_class_loader_is_initialized();
+
+  static bool is_HotSpotJVMCIRuntime_initialized() {
+    return _HotSpotJVMCIRuntime_initialized;
+  }
+
+  /**
+   * Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary
+   */
+  static Handle get_HotSpotJVMCIRuntime(TRAPS) {
+    initialize_JVMCI(CHECK_(Handle()));
+    return Handle(JNIHandles::resolve_non_null(_HotSpotJVMCIRuntime_instance));
+  }
+
+  static jobject get_HotSpotJVMCIRuntime_jobject(TRAPS) {
+    initialize_JVMCI(CHECK_NULL);
+    assert(_HotSpotJVMCIRuntime_initialized, "must be");
+    return _HotSpotJVMCIRuntime_instance;
+  }
+
+  static Handle callStatic(const char* className, const char* methodName, const char* returnType, JavaCallArguments* args, TRAPS);
+
+  /**
+   * Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime()
+   */
+  static void initialize_JVMCI(TRAPS);
+
+  /**
+   * Explicitly initialize HotSpotJVMCIRuntime itself
+   */
+  static void initialize_HotSpotJVMCIRuntime(TRAPS);
+
+  static void metadata_do(void f(Metadata*));
+
+  static void shutdown(TRAPS);
+
+  static void bootstrap_finished(TRAPS);
+
+  static bool shutdown_called() {
+    return _shutdown_called;
+  }
+
+  static bool treat_as_trivial(Method* method);
+
+  /**
+   * Lets JVMCI modify the compilation level currently selected for a method by
+   * the VM compilation policy.
+   *
+   * @param method the method being scheduled for compilation
+   * @param is_osr specifies if the compilation is an OSR compilation
+   * @param level the compilation level currently selected by the VM compilation policy
+   * @param thread the current thread
+   * @return the compilation level to use for the compilation
+   */
+  static CompLevel adjust_comp_level(methodHandle method, bool is_osr, CompLevel level, JavaThread* thread);
+
+  /**
+   * Throws a JVMCIError with a formatted error message. Ideally we would use
+   * a variation of Exceptions::fthrow that takes a class loader argument but alas,
+   * no such variation exists.
+   */
+  static void fthrow_error(Thread* thread, const char* file, int line, const char* format, ...) ATTRIBUTE_PRINTF(4, 5);
+
+  /**
+   * Exits the VM due to an unexpected exception.
+   */
+  static void exit_on_pending_exception(Handle exception, const char* message);
+
+#define CHECK_EXIT THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(PENDING_EXCEPTION, buf); \
+    return; \
+  } \
+  (void)(0
+
+#define CHECK_EXIT_(result) THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(PENDING_EXCEPTION, buf); \
+    return result; \
+  } \
+  (void)(0
+
+  /**
+   * Same as SystemDictionary::resolve_or_null but uses the JVMCI loader.
+   */
+  static Klass* resolve_or_null(Symbol* name, TRAPS);
+
+  /**
+   * Same as SystemDictionary::resolve_or_fail but uses the JVMCI loader.
+   */
+  static Klass* resolve_or_fail(Symbol* name, TRAPS);
+
+  static BasicType kindToBasicType(Handle kind, TRAPS);
+
+  // The following routines are all called from compiled JVMCI code
+
+  static void new_instance(JavaThread* thread, Klass* klass);
+  static void new_array(JavaThread* thread, Klass* klass, jint length);
+  static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims);
+  static void dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length);
+  static void dynamic_new_instance(JavaThread* thread, oopDesc* type_mirror);
+  static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupted);
+  static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3);
+  static jint identity_hash_code(JavaThread* thread, oopDesc* obj);
+  static address exception_handler_for_pc(JavaThread* thread);
+  static void monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
+  static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
+  static void vm_error(JavaThread* thread, jlong where, jlong format, jlong value);
+  static oopDesc* load_and_clear_exception(JavaThread* thread);
+  static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3);
+  static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
+  // Print the passed in object, optionally followed by a newline.  If
+  // as_string is true and the object is a java.lang.String then it
+  // printed as a string, otherwise the type of the object is printed
+  // followed by its address.
+  static void log_object(JavaThread* thread, oopDesc* object, bool as_string, bool newline);
+  static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
+  static void write_barrier_post(JavaThread* thread, void* card);
+  static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);
+  static void new_store_pre_barrier(JavaThread* thread);
+
+  // used to throw exceptions from compiled JVMCI code
+  static void throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message);
+  // helper methods to throw exception with complex messages
+  static void throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass);
+  static void throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass);
+
+  // Test only function
+  static int test_deoptimize_call_int(JavaThread* thread, int value);
+};
+
+// Tracing macros.
+
+#define IF_TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1)) ; else
+#define IF_TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2)) ; else
+#define IF_TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3)) ; else
+#define IF_TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4)) ; else
+#define IF_TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5)) ; else
+
+#define TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1 && (tty->print("JVMCITrace-1: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2 && (tty->print("   JVMCITrace-2: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3 && (tty->print("      JVMCITrace-3: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4 && (tty->print("         JVMCITrace-4: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5 && (tty->print("            JVMCITrace-5: "), true))) ; else tty->print_cr
+
+#endif // SHARE_VM_JVMCI_JVMCI_RUNTIME_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmci_globals.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "jvmci/jvmci_globals.hpp"
+#include "utilities/defaultStream.hpp"
+#include "runtime/globals_extension.hpp"
+
+JVMCI_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
+
+bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
+#ifndef PRODUCT
+#define APPLY_JVMCI_FLAGS(params3, params4) \
+  JVMCI_FLAGS(params4, params3, params4, params3, params4)
+#define JVMCI_DECLARE_CHECK4(type, name, value, doc) bool name##checked = false;
+#define JVMCI_DECLARE_CHECK3(type, name, doc)        bool name##checked = false;
+#define JVMCI_FLAG_CHECKED(name)                          name##checked = true;
+  APPLY_JVMCI_FLAGS(JVMCI_DECLARE_CHECK3, JVMCI_DECLARE_CHECK4)
+#else
+#define JVMCI_FLAG_CHECKED(name)
+#endif
+
+  // Checks that a given flag is not set if a given guard flag is false.
+#define CHECK_NOT_SET(FLAG, GUARD)                     \
+  JVMCI_FLAG_CHECKED(FLAG)                             \
+  if (!GUARD && !FLAG_IS_DEFAULT(FLAG)) {              \
+    jio_fprintf(defaultStream::error_stream(),         \
+        "Improperly specified VM option '%s': '%s' must be enabled\n", #FLAG, #GUARD); \
+    return false;                                      \
+  }
+
+  JVMCI_FLAG_CHECKED(UseJVMCICompiler)
+  JVMCI_FLAG_CHECKED(EnableJVMCI)
+
+  CHECK_NOT_SET(BootstrapJVMCI,   UseJVMCICompiler)
+  CHECK_NOT_SET(PrintBootstrap,   UseJVMCICompiler)
+  CHECK_NOT_SET(JVMCIThreads,     UseJVMCICompiler)
+  CHECK_NOT_SET(JVMCIHostThreads, UseJVMCICompiler)
+
+  if (UseJVMCICompiler) {
+    if (!FLAG_IS_DEFAULT(EnableJVMCI) && !EnableJVMCI) {
+      jio_fprintf(defaultStream::error_stream(),
+          "Improperly specified VM option UseJVMCICompiler: EnableJVMCI cannot be disabled\n");
+      return false;
+    }
+    FLAG_SET_DEFAULT(EnableJVMCI, true);
+  }
+  CHECK_NOT_SET(UseJVMCIClassLoader,          EnableJVMCI)
+  CHECK_NOT_SET(CodeInstallSafepointChecks,   EnableJVMCI)
+  CHECK_NOT_SET(JVMCITraceLevel,              EnableJVMCI)
+  CHECK_NOT_SET(JVMCICounterSize,             EnableJVMCI)
+  CHECK_NOT_SET(JVMCICountersExcludeCompiler, EnableJVMCI)
+  CHECK_NOT_SET(JVMCIUseFastLocking,          EnableJVMCI)
+  CHECK_NOT_SET(JVMCINMethodSizeLimit,        EnableJVMCI)
+  CHECK_NOT_SET(MethodProfileWidth,           EnableJVMCI)
+  CHECK_NOT_SET(JVMCIPrintProperties,         EnableJVMCI)
+  CHECK_NOT_SET(TraceUncollectedSpeculations, EnableJVMCI)
+
+#ifndef PRODUCT
+#define JVMCI_CHECK4(type, name, value, doc) assert(name##checked, #name " flag not checked");
+#define JVMCI_CHECK3(type, name, doc)        assert(name##checked, #name " flag not checked");
+  // Ensures that all JVMCI flags are checked by this method.
+  APPLY_JVMCI_FLAGS(JVMCI_CHECK3, JVMCI_CHECK4)
+#undef APPLY_JVMCI_FLAGS
+#undef JVMCI_DECLARE_CHECK3
+#undef JVMCI_DECLARE_CHECK4
+#undef JVMCI_CHECK3
+#undef JVMCI_CHECK4
+#undef JVMCI_FLAG_CHECKED
+#endif
+#undef CHECK_NOT_SET
+  if (UseJVMCICompiler) {
+    if(JVMCIThreads < 1) {
+      // Check the minimum number of JVMCI compiler threads
+      jio_fprintf(defaultStream::error_stream(), "JVMCIThreads of " INTX_FORMAT " is invalid; must be at least 1\n", JVMCIThreads);
+      return false;
+    }
+  }
+  return true;
+}
+
+void JVMCIGlobals::set_jvmci_specific_flags() {
+  if (UseJVMCICompiler) {
+    if (FLAG_IS_DEFAULT(TypeProfileWidth)) {
+      FLAG_SET_DEFAULT(TypeProfileWidth, 8);
+    }
+    // Adjust the on stack replacement percentage to avoid early
+    // OSR compilations while JVMCI itself is warming up
+    if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
+      FLAG_SET_DEFAULT(OnStackReplacePercentage, 933);
+    }
+    if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
+      FLAG_SET_DEFAULT(ReservedCodeCacheSize, 64*M);
+    }
+    if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
+      FLAG_SET_DEFAULT(InitialCodeCacheSize, 16*M);
+    }
+    if (FLAG_IS_DEFAULT(MetaspaceSize)) {
+      FLAG_SET_DEFAULT(MetaspaceSize, 12*M);
+    }
+    if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
+      FLAG_SET_DEFAULT(NewSizeThreadIncrease, 4*K);
+    }
+  }
+  if (!ScavengeRootsInCode) {
+    warning("forcing ScavengeRootsInCode non-zero because JVMCI is enabled");
+    ScavengeRootsInCode = 1;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/jvmci_globals.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_JVMCI_JVMCI_GLOBALS_HPP
+#define SHARE_VM_JVMCI_JVMCI_GLOBALS_HPP
+
+#include "runtime/globals.hpp"
+#ifdef TARGET_ARCH_x86
+# include "jvmci_globals_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "jvmci_globals_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "jvmci_globals_arm.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "jvmci_globals_ppc.hpp"
+#endif
+
+//
+// Defines all global flags used by the JVMCI compiler. Only flags that need
+// to be accessible to the JVMCI C++ code should be defined here. All other
+// JVMCI flags should be defined in JVMCIOptions.java.
+//
+#define JVMCI_FLAGS(develop, develop_pd, product, product_pd, notproduct)   \
+                                                                            \
+  product(bool, EnableJVMCI, true,                                          \
+          "Enable JVMCI")                                                   \
+                                                                            \
+  product(bool, UseJVMCICompiler, false,                                    \
+          "Use JVMCI as the default compiler")                              \
+                                                                            \
+  product(bool, JVMCIPrintProperties, false,                                \
+          "Prints properties used by the JVMCI compiler and exits")         \
+                                                                            \
+  product(bool, UseJVMCIClassLoader, true,                                  \
+          "Load JVMCI classes with separate class loader")                  \
+                                                                            \
+  product(bool, BootstrapJVMCI, false,                                      \
+          "Bootstrap JVMCI before running Java main method")                \
+                                                                            \
+  product(bool, PrintBootstrap, true,                                       \
+          "Print JVMCI bootstrap progress and summary")                     \
+                                                                            \
+  product(intx, JVMCIThreads, 1,                                            \
+          "Force number of JVMCI compiler threads to use")                  \
+                                                                            \
+  product(intx, JVMCIHostThreads, 1,                                        \
+          "Force number of compiler threads for JVMCI host compiler")       \
+                                                                            \
+  product(bool, CodeInstallSafepointChecks, true,                           \
+          "Perform explicit safepoint checks while installing code")        \
+                                                                            \
+  NOT_COMPILER2(product_pd(intx, MaxVectorSize,                             \
+          "Max vector size in bytes, "                                      \
+          "actual size could be less depending on elements type"))          \
+                                                                            \
+  NOT_COMPILER2(product(bool, ReduceInitialCardMarks, true,                 \
+          "Defer write barriers of young objects"))                         \
+                                                                            \
+  product(intx, JVMCITraceLevel, 0,                                         \
+          "Trace level for JVMCI: "                                         \
+          "1 means emit a message for each CompilerToVM call,"              \
+          "levels greater than 1 provide progressively greater detail")     \
+                                                                            \
+  product(intx, JVMCICounterSize, 0,                                        \
+          "Reserved size for benchmark counters")                           \
+                                                                            \
+  product(bool, JVMCICountersExcludeCompiler, true,                         \
+          "Exclude JVMCI compiler threads from benchmark counters")         \
+                                                                            \
+  develop(bool, JVMCIUseFastLocking, true,                                  \
+          "Use fast inlined locking code")                                  \
+                                                                            \
+  product(intx, JVMCINMethodSizeLimit, (80*K)*wordSize,                     \
+          "Maximum size of a compiled method.")                             \
+                                                                            \
+  product(intx, MethodProfileWidth, 0,                                      \
+          "Number of methods to record in call profile")                    \
+                                                                            \
+  develop(bool, TraceUncollectedSpeculations, false,                        \
+          "Print message when a failed speculation was not collected")
+
+
+// Read default values for JVMCI globals
+
+JVMCI_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_NOTPRODUCT_FLAG)
+
+
+class JVMCIGlobals {
+ public:
+  static void set_jvmci_specific_flags();
+  // Return true if jvmci flags are consistent. If not consistent,
+  // an error message describing the inconsistency is printed before
+  // returning false.
+  static bool check_jvmci_flags_are_consistent();
+};
+
+#endif // SHARE_VM_JVMCI_JVMCI_GLOBALS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/systemDictionary_jvmci.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
+#define SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
+
+#if !INCLUDE_JVMCI
+#define JVMCI_WK_KLASSES_DO(do_klass)
+#else
+#define JVMCI_WK_KLASSES_DO(do_klass)                                                                                  \
+  /* JVMCI classes. These are loaded on-demand. */                                                                     \
+  do_klass(JVMCI_klass,                                  jdk_vm_ci_runtime_JVMCI,                               Jvmci) \
+  do_klass(HotSpotCompiledCode_klass,                    jdk_vm_ci_hotspot_HotSpotCompiledCode,                 Jvmci) \
+  do_klass(HotSpotCompiledCode_Comment_klass,            jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment,         Jvmci) \
+  do_klass(HotSpotCompiledNmethod_klass,                 jdk_vm_ci_hotspot_HotSpotCompiledNmethod,              Jvmci) \
+  do_klass(HotSpotForeignCallTarget_klass,               jdk_vm_ci_hotspot_HotSpotForeignCallTarget,            Jvmci) \
+  do_klass(HotSpotReferenceMap_klass,                    jdk_vm_ci_hotspot_HotSpotReferenceMap,                 Jvmci) \
+  do_klass(HotSpotInstalledCode_klass,                   jdk_vm_ci_hotspot_HotSpotInstalledCode,                Jvmci) \
+  do_klass(HotSpotNmethod_klass,                         jdk_vm_ci_hotspot_HotSpotNmethod,                      Jvmci) \
+  do_klass(HotSpotResolvedJavaMethodImpl_klass,          jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl,       Jvmci) \
+  do_klass(HotSpotResolvedObjectTypeImpl_klass,          jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl,       Jvmci) \
+  do_klass(HotSpotCompressedNullConstant_klass,          jdk_vm_ci_hotspot_HotSpotCompressedNullConstant,       Jvmci) \
+  do_klass(HotSpotObjectConstantImpl_klass,              jdk_vm_ci_hotspot_HotSpotObjectConstantImpl,           Jvmci) \
+  do_klass(HotSpotMetaspaceConstantImpl_klass,           jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl,        Jvmci) \
+  do_klass(HotSpotStackFrameReference_klass,             jdk_vm_ci_hotspot_HotSpotStackFrameReference,          Jvmci) \
+  do_klass(HotSpotConstantPool_klass,                    jdk_vm_ci_hotspot_HotSpotConstantPool,                 Jvmci) \
+  do_klass(HotSpotJVMCIMetaAccessContext_klass,          jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext,       Jvmci) \
+  do_klass(HotSpotJVMCIRuntime_klass,                    jdk_vm_ci_hotspot_HotSpotJVMCIRuntime,                 Jvmci) \
+  do_klass(HotSpotSpeculationLog_klass,                  jdk_vm_ci_hotspot_HotSpotSpeculationLog,               Jvmci) \
+  do_klass(HotSpotCompilationRequestResult_klass,        jdk_vm_ci_hotspot_HotSpotCompilationRequestResult,     Jvmci) \
+  do_klass(VMField_klass,                                jdk_vm_ci_hotspot_VMField,                             Jvmci) \
+  do_klass(VMFlag_klass,                                 jdk_vm_ci_hotspot_VMFlag,                              Jvmci) \
+  do_klass(VMIntrinsicMethod_klass,                      jdk_vm_ci_hotspot_VMIntrinsicMethod,                   Jvmci) \
+  do_klass(Assumptions_ConcreteMethod_klass,             jdk_vm_ci_meta_Assumptions_ConcreteMethod,             Jvmci) \
+  do_klass(Assumptions_NoFinalizableSubclass_klass,      jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass,      Jvmci) \
+  do_klass(Assumptions_ConcreteSubtype_klass,            jdk_vm_ci_meta_Assumptions_ConcreteSubtype,            Jvmci) \
+  do_klass(Assumptions_LeafType_klass,                   jdk_vm_ci_meta_Assumptions_LeafType,                   Jvmci) \
+  do_klass(Assumptions_CallSiteTargetValue_klass,        jdk_vm_ci_meta_Assumptions_CallSiteTargetValue,        Jvmci) \
+  do_klass(Architecture_klass,                           jdk_vm_ci_code_Architecture,                           Jvmci) \
+  do_klass(TargetDescription_klass,                      jdk_vm_ci_code_TargetDescription,                      Jvmci) \
+  do_klass(BytecodePosition_klass,                       jdk_vm_ci_code_BytecodePosition,                       Jvmci) \
+  do_klass(DebugInfo_klass,                              jdk_vm_ci_code_DebugInfo,                              Jvmci) \
+  do_klass(RegisterSaveLayout_klass,                     jdk_vm_ci_code_RegisterSaveLayout,                     Jvmci) \
+  do_klass(BytecodeFrame_klass,                          jdk_vm_ci_code_BytecodeFrame,                          Jvmci) \
+  do_klass(InstalledCode_klass,                          jdk_vm_ci_code_InstalledCode,                          Jvmci) \
+  do_klass(code_Location_klass,                          jdk_vm_ci_code_Location,                               Jvmci) \
+  do_klass(code_Register_klass,                          jdk_vm_ci_code_Register,                               Jvmci) \
+  do_klass(RegisterValue_klass,                          jdk_vm_ci_code_RegisterValue,                          Jvmci) \
+  do_klass(StackSlot_klass,                              jdk_vm_ci_code_StackSlot,                              Jvmci) \
+  do_klass(StackLockValue_klass,                         jdk_vm_ci_code_StackLockValue,                         Jvmci) \
+  do_klass(VirtualObject_klass,                          jdk_vm_ci_code_VirtualObject,                          Jvmci) \
+  do_klass(site_Call_klass,                              jdk_vm_ci_code_site_Call,                              Jvmci) \
+  do_klass(site_ConstantReference_klass,                 jdk_vm_ci_code_site_ConstantReference,                 Jvmci) \
+  do_klass(site_DataPatch_klass,                         jdk_vm_ci_code_site_DataPatch,                         Jvmci) \
+  do_klass(site_DataSectionReference_klass,              jdk_vm_ci_code_site_DataSectionReference,              Jvmci) \
+  do_klass(site_ExceptionHandler_klass,                  jdk_vm_ci_code_site_ExceptionHandler,                  Jvmci) \
+  do_klass(site_Mark_klass,                              jdk_vm_ci_code_site_Mark,                              Jvmci) \
+  do_klass(site_Infopoint_klass,                         jdk_vm_ci_code_site_Infopoint,                         Jvmci) \
+  do_klass(site_Site_klass,                              jdk_vm_ci_code_site_Site,                              Jvmci) \
+  do_klass(site_InfopointReason_klass,                   jdk_vm_ci_code_site_InfopointReason,                   Jvmci) \
+  do_klass(JavaConstant_klass,                           jdk_vm_ci_meta_JavaConstant,                           Jvmci) \
+  do_klass(PrimitiveConstant_klass,                      jdk_vm_ci_meta_PrimitiveConstant,                      Jvmci) \
+  do_klass(RawConstant_klass,                            jdk_vm_ci_meta_RawConstant,                            Jvmci) \
+  do_klass(NullConstant_klass,                           jdk_vm_ci_meta_NullConstant,                           Jvmci) \
+  do_klass(ExceptionHandler_klass,                       jdk_vm_ci_meta_ExceptionHandler,                       Jvmci) \
+  do_klass(JavaKind_klass,                               jdk_vm_ci_meta_JavaKind,                               Jvmci) \
+  do_klass(ValueKind_klass,                              jdk_vm_ci_meta_ValueKind,                              Jvmci) \
+  do_klass(Value_klass,                                  jdk_vm_ci_meta_Value,                                  Jvmci)
+#endif
+
+#endif // SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/vmStructs_jvmci.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_JVMCI_VMSTRUCTS_JVMCI_HPP
+#define SHARE_VM_JVMCI_VMSTRUCTS_JVMCI_HPP
+
+#include "compiler/abstractCompiler.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciEnv.hpp"
+
+#define VM_STRUCTS_JVMCI(nonstatic_field, static_field, volatile_nonstatic_field)                                                    \
+  static_field(CompilerToVM::Data,             Klass_vtable_start_offset,              int)                                          \
+  static_field(CompilerToVM::Data,             Klass_vtable_length_offset,             int)                                          \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             Method_extra_stack_entries,             int)                                          \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             SharedRuntime_ic_miss_stub,             address)                                      \
+  static_field(CompilerToVM::Data,             SharedRuntime_handle_wrong_method_stub, address)                                      \
+  static_field(CompilerToVM::Data,             SharedRuntime_deopt_blob_unpack,        address)                                      \
+  static_field(CompilerToVM::Data,             SharedRuntime_deopt_blob_uncommon_trap, address)                                      \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             ThreadLocalAllocBuffer_alignment_reserve, size_t)                                     \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             Universe_collectedHeap,                 CollectedHeap*)                               \
+  static_field(CompilerToVM::Data,             Universe_base_vtable_size,              int)                                          \
+  static_field(CompilerToVM::Data,             Universe_narrow_oop_base,               address)                                      \
+  static_field(CompilerToVM::Data,             Universe_narrow_oop_shift,              int)                                          \
+  static_field(CompilerToVM::Data,             Universe_narrow_klass_base,             address)                                      \
+  static_field(CompilerToVM::Data,             Universe_narrow_klass_shift,            int)                                          \
+  static_field(CompilerToVM::Data,             Universe_non_oop_bits,                  void*)                                        \
+  static_field(CompilerToVM::Data,             Universe_verify_oop_mask,               uintptr_t)                                    \
+  static_field(CompilerToVM::Data,             Universe_verify_oop_bits,               uintptr_t)                                    \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             _supports_inline_contig_alloc,          bool)                                         \
+  static_field(CompilerToVM::Data,             _heap_end_addr,                         HeapWord**)                                   \
+  static_field(CompilerToVM::Data,             _heap_top_addr,                         HeapWord**)                                   \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             _max_oop_map_stack_offset,              int)                                          \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             cardtable_start_address,                jbyte*)                                       \
+  static_field(CompilerToVM::Data,             cardtable_shift,                        int)                                          \
+  static_field(CompilerToVM::Data,             g1_young_card,                          int)                                          \
+  static_field(CompilerToVM::Data,             dirty_card,                             int)                                          \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             vm_page_size,                           int)                                          \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             sizeof_vtableEntry,                     int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_ExceptionTableElement,           int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_LocalVariableTableElement,       int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_ConstantPool,                    int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_SymbolPointer,                   int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_narrowKlass,                     int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_arrayOopDesc,                    int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_BasicLock,                       int)                                          \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             CodeCache_low_bound,                    address)                                      \
+  static_field(CompilerToVM::Data,             CodeCache_high_bound,                   address)                                      \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             dsin,                                   address)                                      \
+  static_field(CompilerToVM::Data,             dcos,                                   address)                                      \
+  static_field(CompilerToVM::Data,             dtan,                                   address)                                      \
+  static_field(CompilerToVM::Data,             dexp,                                   address)                                      \
+  static_field(CompilerToVM::Data,             dlog,                                   address)                                      \
+  static_field(CompilerToVM::Data,             dlog10,                                 address)                                      \
+  static_field(CompilerToVM::Data,             dpow,                                   address)                                      \
+                                                                                                                                     \
+  static_field(CompilerToVM::Data,             symbol_init,                            address)                                      \
+  static_field(CompilerToVM::Data,             symbol_clinit,                          address)                                      \
+                                                                                                                                     \
+  static_field(StubRoutines,                   _sha1_implCompress,                     address)                                      \
+  static_field(StubRoutines,                   _sha1_implCompressMB,                   address)                                      \
+  static_field(StubRoutines,                   _sha256_implCompress,                   address)                                      \
+  static_field(StubRoutines,                   _sha256_implCompressMB,                 address)                                      \
+  static_field(StubRoutines,                   _sha512_implCompress,                   address)                                      \
+  static_field(StubRoutines,                   _sha512_implCompressMB,                 address)                                      \
+  static_field(StubRoutines,                   _montgomeryMultiply,                    address)                                      \
+  static_field(StubRoutines,                   _montgomerySquare,                      address)                                      \
+                                                                                                                                     \
+  volatile_nonstatic_field(ObjectMonitor,      _cxq,                                   ObjectWaiter*)                                \
+  volatile_nonstatic_field(ObjectMonitor,      _EntryList,                             ObjectWaiter*)                                \
+                                                                                                                                     \
+  nonstatic_field(JavaThread,                  _pending_deoptimization,                int)                                          \
+  nonstatic_field(JavaThread,                  _pending_failed_speculation,            oop)                                          \
+  nonstatic_field(JavaThread,                  _pending_transfer_to_interpreter,       bool)                                         \
+  nonstatic_field(JavaThread,                  _jvmci_counters,                        jlong*)                                       \
+  nonstatic_field(MethodData,                  _jvmci_ir_size,                         int)                                          \
+  nonstatic_field(JVMCIEnv,                    _task,                                  CompileTask*)                                 \
+  nonstatic_field(JVMCIEnv,                    _jvmti_can_hotswap_or_post_breakpoint,  bool)                                         \
+
+#define VM_TYPES_JVMCI(declare_type, declare_toplevel_type)                   \
+  declare_toplevel_type(narrowKlass)                                          \
+  declare_toplevel_type(JVMCIEnv)                                             \
+  declare_toplevel_type(CompilerToVM::Data)                                   \
+  declare_toplevel_type(ObjectWaiter)                                         \
+
+#define VM_INT_CONSTANTS_JVMCI(declare_constant, declare_preprocessor_constant)                   \
+  declare_constant(Deoptimization::Reason_unreached0)                                             \
+  declare_constant(Deoptimization::Reason_type_checked_inlining)                                  \
+  declare_constant(Deoptimization::Reason_optimized_type_check)                                   \
+  declare_constant(Deoptimization::Reason_aliasing)                                               \
+  declare_constant(Deoptimization::Reason_transfer_to_interpreter)                                \
+  declare_constant(Deoptimization::Reason_not_compiled_exception_handler)                         \
+  declare_constant(Deoptimization::Reason_unresolved)                                             \
+  declare_constant(Deoptimization::Reason_jsr_mismatch)                                           \
+  declare_constant(JVMCIEnv::ok)                                                                  \
+  declare_constant(JVMCIEnv::dependencies_failed)                                                 \
+  declare_constant(JVMCIEnv::dependencies_invalid)                                                \
+  declare_constant(JVMCIEnv::cache_full)                                                          \
+  declare_constant(JVMCIEnv::code_too_large)                                                      \
+  declare_constant(JVMCIRuntime::none)                                                            \
+  declare_constant(JVMCIRuntime::by_holder)                                                       \
+  declare_constant(JVMCIRuntime::by_full_signature)                                               \
+                                                                                                  \
+  declare_preprocessor_constant("JVM_ACC_VARARGS", JVM_ACC_VARARGS)                               \
+  declare_preprocessor_constant("JVM_ACC_BRIDGE", JVM_ACC_BRIDGE)                                 \
+  declare_preprocessor_constant("JVM_ACC_ANNOTATION", JVM_ACC_ANNOTATION)                         \
+  declare_preprocessor_constant("JVM_ACC_ENUM", JVM_ACC_ENUM)                                     \
+  declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC)                           \
+                                                                                                  \
+  declare_constant(BitData::exception_seen_flag)                                                  \
+  declare_constant(BitData::null_seen_flag)                                                       \
+  declare_constant(CounterData::count_off)                                                        \
+  declare_constant(JumpData::taken_off_set)                                                       \
+  declare_constant(JumpData::displacement_off_set)                                                \
+  declare_constant(ReceiverTypeData::nonprofiled_count_off_set)                                   \
+  declare_constant(ReceiverTypeData::receiver_type_row_cell_count)                                \
+  declare_constant(ReceiverTypeData::receiver0_offset)                                            \
+  declare_constant(ReceiverTypeData::count0_offset)                                               \
+  declare_constant(BranchData::not_taken_off_set)                                                 \
+  declare_constant(ArrayData::array_len_off_set)                                                  \
+  declare_constant(ArrayData::array_start_off_set)                                                \
+  declare_constant(MultiBranchData::per_case_cell_count)                                          \
+                                                                                                  \
+  declare_constant(CodeInstaller::VERIFIED_ENTRY)                                                 \
+  declare_constant(CodeInstaller::UNVERIFIED_ENTRY)                                               \
+  declare_constant(CodeInstaller::OSR_ENTRY)                                                      \
+  declare_constant(CodeInstaller::EXCEPTION_HANDLER_ENTRY)                                        \
+  declare_constant(CodeInstaller::DEOPT_HANDLER_ENTRY)                                            \
+  declare_constant(CodeInstaller::INVOKEINTERFACE)                                                \
+  declare_constant(CodeInstaller::INVOKEVIRTUAL)                                                  \
+  declare_constant(CodeInstaller::INVOKESTATIC)                                                   \
+  declare_constant(CodeInstaller::INVOKESPECIAL)                                                  \
+  declare_constant(CodeInstaller::INLINE_INVOKE)                                                  \
+  declare_constant(CodeInstaller::POLL_NEAR)                                                      \
+  declare_constant(CodeInstaller::POLL_RETURN_NEAR)                                               \
+  declare_constant(CodeInstaller::POLL_FAR)                                                       \
+  declare_constant(CodeInstaller::POLL_RETURN_FAR)                                                \
+  declare_constant(CodeInstaller::CARD_TABLE_SHIFT)                                               \
+  declare_constant(CodeInstaller::CARD_TABLE_ADDRESS)                                             \
+  declare_constant(CodeInstaller::INVOKE_INVALID)                                                 \
+                                                                                                  \
+  declare_constant(Method::invalid_vtable_index)                                                  \
+
+#define VM_ADDRESSES_JVMCI(declare_address, declare_preprocessor_address, declare_function) \
+  declare_function(SharedRuntime::register_finalizer)                     \
+  declare_function(SharedRuntime::exception_handler_for_return_address)   \
+  declare_function(SharedRuntime::OSR_migration_end)                      \
+  declare_function(SharedRuntime::frem)                                   \
+  declare_function(SharedRuntime::drem)                                   \
+                                                                          \
+  declare_function(os::dll_load)                                          \
+  declare_function(os::dll_lookup)                                        \
+  declare_function(os::javaTimeMillis)                                    \
+  declare_function(os::javaTimeNanos)                                     \
+                                                                          \
+  declare_function(Deoptimization::fetch_unroll_info)                     \
+  declare_function(Deoptimization::uncommon_trap)                         \
+  declare_function(Deoptimization::unpack_frames)                         \
+                                                                          \
+  declare_function(JVMCIRuntime::new_instance) \
+  declare_function(JVMCIRuntime::new_array) \
+  declare_function(JVMCIRuntime::new_multi_array) \
+  declare_function(JVMCIRuntime::dynamic_new_array) \
+  declare_function(JVMCIRuntime::dynamic_new_instance) \
+  \
+  declare_function(JVMCIRuntime::thread_is_interrupted) \
+  declare_function(JVMCIRuntime::vm_message) \
+  declare_function(JVMCIRuntime::identity_hash_code) \
+  declare_function(JVMCIRuntime::exception_handler_for_pc) \
+  declare_function(JVMCIRuntime::monitorenter) \
+  declare_function(JVMCIRuntime::monitorexit) \
+  declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \
+  declare_function(JVMCIRuntime::throw_klass_external_name_exception) \
+  declare_function(JVMCIRuntime::throw_class_cast_exception) \
+  declare_function(JVMCIRuntime::log_primitive) \
+  declare_function(JVMCIRuntime::log_object) \
+  declare_function(JVMCIRuntime::log_printf) \
+  declare_function(JVMCIRuntime::vm_error) \
+  declare_function(JVMCIRuntime::load_and_clear_exception) \
+  declare_function(JVMCIRuntime::write_barrier_pre) \
+  declare_function(JVMCIRuntime::write_barrier_post) \
+  declare_function(JVMCIRuntime::validate_object) \
+  \
+  declare_function(JVMCIRuntime::test_deoptimize_call_int)
+
+#ifdef TARGET_OS_FAMILY_linux
+
+#define VM_ADDRESSES_JVMCI_OS(declare_address, declare_preprocessor_address, declare_function) \
+  declare_preprocessor_address("RTLD_DEFAULT", RTLD_DEFAULT)
+
+#endif // TARGET_OS_FAMILY_linux
+
+
+#ifdef TARGET_OS_FAMILY_bsd
+
+#define VM_ADDRESSES_JVMCI_OS(declare_address, declare_preprocessor_address, declare_function) \
+  declare_preprocessor_address("RTLD_DEFAULT", RTLD_DEFAULT)
+
+#endif // TARGET_OS_FAMILY_bsd
+
+#ifndef VM_ADDRESSES_JVMCI_OS
+#define VM_ADDRESSES_JVMCI_OS(declare_address, declare_preprocessor_address, declare_function)
+#endif
+
+#endif // SHARE_VM_JVMCI_VMSTRUCTS_JVMCI_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/jvmci/vmSymbols_jvmci.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_VM_JVMCI_VMSYMBOLS_JVMCI_HPP
+#define SHARE_VM_JVMCI_VMSYMBOLS_JVMCI_HPP
+
+
+#if !INCLUDE_JVMCI
+#define JVMCI_VM_SYMBOLS_DO(template, do_alias)
+#else
+#define JVMCI_VM_SYMBOLS_DO(template, do_alias)                                                                                           \
+  template(jdk_vm_ci_runtime_JVMCI,                               "jdk/vm/ci/runtime/JVMCI")                                              \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledCode,                 "jdk/vm/ci/hotspot/HotSpotCompiledCode")                                \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment,         "jdk/vm/ci/hotspot/HotSpotCompiledCode$Comment")                        \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledNmethod,              "jdk/vm/ci/hotspot/HotSpotCompiledNmethod")                             \
+  template(jdk_vm_ci_hotspot_HotSpotForeignCallTarget,            "jdk/vm/ci/hotspot/HotSpotForeignCallTarget")                           \
+  template(jdk_vm_ci_hotspot_HotSpotReferenceMap,                 "jdk/vm/ci/hotspot/HotSpotReferenceMap")                                \
+  template(jdk_vm_ci_hotspot_CompilerToVM,                        "jdk/vm/ci/hotspot/CompilerToVM")                                       \
+  template(jdk_vm_ci_hotspot_HotSpotInstalledCode,                "jdk/vm/ci/hotspot/HotSpotInstalledCode")                               \
+  template(jdk_vm_ci_hotspot_HotSpotNmethod,                      "jdk/vm/ci/hotspot/HotSpotNmethod")                                     \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl")                      \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl")                      \
+  template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant,       "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant")                      \
+  template(jdk_vm_ci_hotspot_HotSpotObjectConstantImpl,           "jdk/vm/ci/hotspot/HotSpotObjectConstantImpl")                          \
+  template(jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl,        "jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl")                       \
+  template(jdk_vm_ci_hotspot_HotSpotStackFrameReference,          "jdk/vm/ci/hotspot/HotSpotStackFrameReference")                         \
+  template(jdk_vm_ci_hotspot_HotSpotConstantPool,                 "jdk/vm/ci/hotspot/HotSpotConstantPool")                                \
+  template(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext,       "jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext")                      \
+  template(jdk_vm_ci_hotspot_HotSpotJVMCIRuntime,                 "jdk/vm/ci/hotspot/HotSpotJVMCIRuntime")                                \
+  template(jdk_vm_ci_hotspot_HotSpotSpeculationLog,               "jdk/vm/ci/hotspot/HotSpotSpeculationLog")                              \
+  template(jdk_vm_ci_hotspot_HotSpotCompilationRequestResult,     "jdk/vm/ci/hotspot/HotSpotCompilationRequestResult")                    \
+  template(jdk_vm_ci_hotspot_VMField,                             "jdk/vm/ci/hotspot/VMField")                                            \
+  template(jdk_vm_ci_hotspot_VMFlag,                              "jdk/vm/ci/hotspot/VMFlag")                                             \
+  template(jdk_vm_ci_hotspot_VMIntrinsicMethod,                   "jdk/vm/ci/hotspot/VMIntrinsicMethod")                                  \
+  template(jdk_vm_ci_meta_JavaConstant,                           "jdk/vm/ci/meta/JavaConstant")                                          \
+  template(jdk_vm_ci_meta_PrimitiveConstant,                      "jdk/vm/ci/meta/PrimitiveConstant")                                     \
+  template(jdk_vm_ci_meta_RawConstant,                            "jdk/vm/ci/meta/RawConstant")                                           \
+  template(jdk_vm_ci_meta_NullConstant,                           "jdk/vm/ci/meta/NullConstant")                                          \
+  template(jdk_vm_ci_meta_ExceptionHandler,                       "jdk/vm/ci/meta/ExceptionHandler")                                      \
+  template(jdk_vm_ci_meta_JavaKind,                               "jdk/vm/ci/meta/JavaKind")                                              \
+  template(jdk_vm_ci_meta_ValueKind,                              "jdk/vm/ci/meta/ValueKind")                                             \
+  template(jdk_vm_ci_meta_Value,                                  "jdk/vm/ci/meta/Value")                                                 \
+  template(jdk_vm_ci_meta_Assumptions_ConcreteSubtype,            "jdk/vm/ci/meta/Assumptions$ConcreteSubtype")                           \
+  template(jdk_vm_ci_meta_Assumptions_LeafType,                   "jdk/vm/ci/meta/Assumptions$LeafType")                                  \
+  template(jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass,      "jdk/vm/ci/meta/Assumptions$NoFinalizableSubclass")                     \
+  template(jdk_vm_ci_meta_Assumptions_ConcreteMethod,             "jdk/vm/ci/meta/Assumptions$ConcreteMethod")                            \
+  template(jdk_vm_ci_meta_Assumptions_CallSiteTargetValue,        "jdk/vm/ci/meta/Assumptions$CallSiteTargetValue")                       \
+  template(jdk_vm_ci_code_Architecture,                           "jdk/vm/ci/code/Architecture")                                          \
+  template(jdk_vm_ci_code_BytecodeFrame,                          "jdk/vm/ci/code/BytecodeFrame")                                         \
+  template(jdk_vm_ci_code_BytecodePosition,                       "jdk/vm/ci/code/BytecodePosition")                                      \
+  template(jdk_vm_ci_code_DebugInfo,                              "jdk/vm/ci/code/DebugInfo")                                             \
+  template(jdk_vm_ci_code_InstalledCode,                          "jdk/vm/ci/code/InstalledCode")                                         \
+  template(jdk_vm_ci_code_Location,                               "jdk/vm/ci/code/Location")                                              \
+  template(jdk_vm_ci_code_Register,                               "jdk/vm/ci/code/Register")                                              \
+  template(jdk_vm_ci_code_RegisterValue,                          "jdk/vm/ci/code/RegisterValue")                                         \
+  template(jdk_vm_ci_code_StackSlot,                              "jdk/vm/ci/code/StackSlot")                                             \
+  template(jdk_vm_ci_code_StackLockValue,                         "jdk/vm/ci/code/StackLockValue")                                        \
+  template(jdk_vm_ci_code_TargetDescription,                      "jdk/vm/ci/code/TargetDescription")                                     \
+  template(jdk_vm_ci_code_VirtualObject,                          "jdk/vm/ci/code/VirtualObject")                                         \
+  template(jdk_vm_ci_code_RegisterSaveLayout,                     "jdk/vm/ci/code/RegisterSaveLayout")                                    \
+  template(jdk_vm_ci_code_InvalidInstalledCodeException,          "jdk/vm/ci/code/InvalidInstalledCodeException")                         \
+  template(jdk_vm_ci_code_site_Call,                              "jdk/vm/ci/code/site/Call")                                             \
+  template(jdk_vm_ci_code_site_ConstantReference,                 "jdk/vm/ci/code/site/ConstantReference")                                \
+  template(jdk_vm_ci_code_site_DataPatch,                         "jdk/vm/ci/code/site/DataPatch")                                        \
+  template(jdk_vm_ci_code_site_DataSectionReference,              "jdk/vm/ci/code/site/DataSectionReference")                             \
+  template(jdk_vm_ci_code_site_ExceptionHandler,                  "jdk/vm/ci/code/site/ExceptionHandler")                                 \
+  template(jdk_vm_ci_code_site_Mark,                              "jdk/vm/ci/code/site/Mark")                                             \
+  template(jdk_vm_ci_code_site_Infopoint,                         "jdk/vm/ci/code/site/Infopoint")                                        \
+  template(jdk_vm_ci_code_site_Site,                              "jdk/vm/ci/code/site/Site")                                             \
+  template(jdk_vm_ci_code_site_InfopointReason,                   "jdk/vm/ci/code/site/InfopointReason")                                  \
+  template(jdk_vm_ci_common_JVMCIError,                           "jdk/vm/ci/common/JVMCIError")                                          \
+  template(adjustCompilationLevel_name,                           "adjustCompilationLevel")                                               \
+  template(adjustCompilationLevel_signature,                      "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;ZI)I")           \
+  template(compileMethod_name,                                    "compileMethod")                                                        \
+  template(compileMethod_signature,                               "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/hotspot/HotSpotCompilationRequestResult;") \
+  template(fromMetaspace_name,                                    "fromMetaspace")                                                        \
+  template(method_fromMetaspace_signature,                        "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                     \
+  template(constantPool_fromMetaspace_signature,                  "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;")                           \
+  template(klass_fromMetaspace_signature,                         "(Ljava/lang/Class;)Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;") \
+  template(jdk_vm_ci_hotspot_Stable_signature,                    "Ljdk/vm/ci/hotspot/Stable;")
+#endif
+
+#endif // SHARE_VM_JVMCI_VMSYMBOLS_JVMCI_HPP
--- a/src/share/vm/memory/barrierSet.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/memory/barrierSet.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -145,6 +145,9 @@
   static void static_write_ref_array_pre(HeapWord* start, size_t count);
   static void static_write_ref_array_post(HeapWord* start, size_t count);
 
+  virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm) {}
+  virtual void write_ref_nmethod_post(oop* dst, nmethod* nm) {}
+
 protected:
   virtual void write_ref_array_work(MemRegion mr) = 0;
 public:
--- a/src/share/vm/memory/cardTableRS.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/memory/cardTableRS.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -352,15 +352,22 @@
                    "[_begin, _end) = [" PTR_FORMAT "," PTR_FORMAT ")",
                    p2i(jp), p2i(_begin), p2i(_end)));
     oop obj = oopDesc::load_decode_heap_oop(p);
-    guarantee(obj == NULL || (HeapWord*)obj >= _boundary,
-              err_msg("pointer " PTR_FORMAT " at " PTR_FORMAT " on "
-                      "clean card crosses boundary" PTR_FORMAT,
-                      p2i((HeapWord*)obj), p2i(jp), p2i(_boundary)));
+    if (!(obj == NULL || (HeapWord*)obj >= _boundary)) {
+      tty->print_cr("pointer " PTR_FORMAT " at " PTR_FORMAT " on "
+                    "clean card crosses boundary" PTR_FORMAT,
+                    p2i((HeapWord*)obj), p2i(jp), p2i(_boundary));
+#ifndef PRODUCT
+      obj->print();
+#endif
+      had_error = true;
+    }
   }
 
 public:
+  bool had_error;
+  
   VerifyCleanCardClosure(HeapWord* b, HeapWord* begin, HeapWord* end) :
-    _boundary(b), _begin(begin), _end(end) {
+    _boundary(b), _begin(begin), _end(end), had_error(false) {
     assert(b <= begin,
            err_msg("Error: boundary " PTR_FORMAT " should be at or below begin " PTR_FORMAT,
                    p2i(b), p2i(begin)));
@@ -400,6 +407,7 @@
   // We don't need to do young-gen spaces.
   if (s->end() <= gen_boundary) return;
   MemRegion used = s->used_region();
+  bool had_error = false;
 
   jbyte* cur_entry = byte_for(used.start());
   jbyte* limit = byte_after(used.last());
@@ -438,6 +446,13 @@
         for (HeapWord* cur = start_block; cur < end; cur += s->block_size(cur)) {
           if (s->block_is_obj(cur) && s->obj_is_alive(cur)) {
             oop(cur)->oop_iterate_no_header(&verify_blk, mr);
+            had_error |= verify_blk.had_error;
+            if (verify_blk.had_error) {
+              verify_blk.had_error = false;
+#ifndef PRODUCT
+              oop(cur)->print();
+#endif
+            }
           }
         }
       }
@@ -598,6 +613,7 @@
       cur_entry++;
     }
   }
+  guarantee(!had_error, "Card table errors found");
 }
 
 void CardTableRS::verify() {
--- a/src/share/vm/memory/genCollectedHeap.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -457,7 +457,9 @@
           }
           Universe::verify(" VerifyBeforeGC:");
         }
-        COMPILER2_PRESENT(DerivedPointerTable::clear());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+        DerivedPointerTable::clear();
+#endif
 
         if (!must_restore_marks_for_biased_locking &&
             _gens[i]->performs_in_place_marking()) {
@@ -517,7 +519,9 @@
           }
         }
 
-        COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+        DerivedPointerTable::update_pointers();
+#endif
 
         _gens[i]->stat_record()->accumulated_time.stop();
 
@@ -1308,7 +1312,7 @@
 };
 
 void GenCollectedHeap::gc_epilogue(bool full) {
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   assert(DerivedPointerTable::is_empty(), "derived pointer present");
   size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
   guarantee(actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
--- a/src/share/vm/memory/genMarkSweep.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/memory/genMarkSweep.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -96,8 +96,10 @@
   mark_sweep_phase2();
 
   // Don't add any more derived pointers during phase3
-  COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
-  COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  assert(DerivedPointerTable::is_active(), "Sanity");
+  DerivedPointerTable::set_active(false);
+#endif
 
   mark_sweep_phase3(level);
 
--- a/src/share/vm/memory/referenceProcessor.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/memory/referenceProcessor.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -57,8 +57,11 @@
   java_lang_ref_SoftReference::set_clock(_soft_ref_timestamp_clock);
 
   _always_clear_soft_ref_policy = new AlwaysClearPolicy();
-  _default_soft_ref_policy      = new COMPILER2_PRESENT(LRUMaxHeapPolicy())
-                                      NOT_COMPILER2(LRUCurrentHeapPolicy());
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  _default_soft_ref_policy      = new LRUMaxHeapPolicy();
+#else
+  _default_soft_ref_policy      = new LRUCurrentHeapPolicy();
+#endif
   if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
     vm_exit_during_initialization("Could not allocate reference policy object");
   }
--- a/src/share/vm/memory/threadLocalAllocBuffer.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -42,6 +42,9 @@
 
 void ThreadLocalAllocBuffer::clear_before_allocation() {
   _slow_refill_waste += (unsigned)remaining();
+  // In debug mode we expect the storage above top to be uninitialized
+  // or filled with a padding object.
+  assert(!ZapUnusedHeapArea || VM_Version::reserve_for_allocation_prefetch() > 0 || top() == NULL || *(intptr_t*)top() != 0, "overzeroing detected");
   make_parsable(true);   // also retire the TLAB
 }
 
--- a/src/share/vm/oops/constantPool.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/constantPool.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -676,6 +676,8 @@
   int klass_ref_index_at(int which)               { return impl_klass_ref_index_at(which, false); }
   int name_and_type_ref_index_at(int which)       { return impl_name_and_type_ref_index_at(which, false); }
 
+  int remap_instruction_operand_from_cache(int operand);  // operand must be biased by CPCACHE_INDEX_TAG
+
   // Lookup for entries consisting of (name_index, signature_index)
   int name_ref_index_at(int which_nt);            // ==  low-order jshort of name_and_type_at(which_nt)
   int signature_ref_index_at(int which_nt);       // == high-order jshort of name_and_type_at(which_nt)
@@ -797,8 +799,6 @@
   int       impl_klass_ref_index_at(int which, bool uncached);
   int       impl_name_and_type_ref_index_at(int which, bool uncached);
 
-  int remap_instruction_operand_from_cache(int operand);  // operand must be biased by CPCACHE_INDEX_TAG
-
   // Used while constructing constant pool (only by ClassFileParser)
   jint klass_index_at(int which) {
     assert(tag_at(which).is_klass_index(), "Corrupted constant pool");
--- a/src/share/vm/oops/cpCache.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/cpCache.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -192,7 +192,7 @@
     field_index_mask           = right_n_bits(field_index_bits),
     parameter_size_bits        = 8,  // subset of field_index_mask, range is 0..255
     parameter_size_mask        = right_n_bits(parameter_size_bits),
-    option_bits_mask           = ~(((-1) << tos_state_shift) | (field_index_mask | parameter_size_mask))
+    option_bits_mask           = ~(((~0u) << tos_state_shift) | (field_index_mask | parameter_size_mask))
   };
 
   // specific bit definitions for the indices field:
--- a/src/share/vm/oops/generateOopMap.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/generateOopMap.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2080,6 +2080,7 @@
   _ret_adr_tos    = new GrowableArray<intptr_t>(5);  // 5 seems like a good number;
   _did_rewriting  = false;
   _did_relocation = false;
+  _monitor_safe = true;
 
   if (TraceNewOopMapGeneration) {
     tty->print("Method name: %s\n", method()->name()->as_C_string());
--- a/src/share/vm/oops/instanceKlass.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/instanceKlass.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -63,6 +63,10 @@
 #include "services/threadService.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/macros.hpp"
+#if INCLUDE_JVMCI
+#include "classfile/javaAssertions.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
@@ -324,7 +328,6 @@
   set_layout_helper(Klass::instance_layout_helper(0, true));
 }
 
-
 void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
                                        Array<Method*>* methods) {
   if (methods != NULL && methods != Universe::the_empty_method_array() &&
@@ -1238,6 +1241,7 @@
     JavaValue result(T_VOID);
     JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)
   }
+
 }
 
 
@@ -3207,9 +3211,9 @@
   if (this == SystemDictionary::String_klass()) {
     typeArrayOop value  = java_lang_String::value(obj);
     juint        offset = java_lang_String::offset(obj);
+    if (value != NULL) {
     juint        length = java_lang_String::length(obj);
-    if (value != NULL &&
-        value->is_typeArray() &&
+      if (value->is_typeArray() &&
         offset          <= (juint) value->length() &&
         offset + length <= (juint) value->length()) {
       st->print(BULLET"string: ");
@@ -3218,6 +3222,7 @@
       if (!WizardMode)  return;  // that is enough
     }
   }
+  }
 
   st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj));
   FieldPrinter print_field(st, obj);
@@ -3635,6 +3640,10 @@
               ("purge: %s(%s): prev method @%d in version @%d is alive",
               method->name()->as_C_string(),
               method->signature()->as_C_string(), j, i));
+            if (method->method_data() != NULL) {
+              // Clean out any weak method links
+              method->method_data()->clean_weak_method_links();
+            }
           }
         }
       }
@@ -3644,6 +3653,14 @@
       ("purge: previous version stats: live=%d, deleted=%d", live_count,
       deleted_count));
   }
+
+  Array<Method*>* methods = ik->methods();
+  int num_methods = methods->length();
+  for (int index2 = 0; index2 < num_methods; ++index2) {
+    if (methods->at(index2)->method_data() != NULL) {
+      methods->at(index2)->method_data()->clean_weak_method_links();
+    }
+  }
 }
 
 // External interface for use during class unloading.
--- a/src/share/vm/oops/klass.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/klass.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -352,11 +352,11 @@
   }
   static bool layout_helper_is_typeArray(jint lh) {
     // _lh_array_tag_type_value == (lh >> _lh_array_tag_shift);
-    return (juint)lh >= (juint)(_lh_array_tag_type_value << _lh_array_tag_shift);
+    return (juint)lh >= (juint)((unsigned)_lh_array_tag_type_value << _lh_array_tag_shift);
   }
   static bool layout_helper_is_objArray(jint lh) {
     // _lh_array_tag_obj_value == (lh >> _lh_array_tag_shift);
-    return (jint)lh < (jint)(_lh_array_tag_type_value << _lh_array_tag_shift);
+    return (jint)lh < (jint)((unsigned)_lh_array_tag_type_value << _lh_array_tag_shift);
   }
   static int layout_helper_header_size(jint lh) {
     assert(lh < (jint)_lh_neutral_value, "must be array");
--- a/src/share/vm/oops/method.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/method.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -218,7 +218,7 @@
 
   Thread* myThread    = Thread::current();
   methodHandle h_this(myThread, this);
-#ifdef ASSERT
+#if defined(ASSERT) && !INCLUDE_JVMCI
   bool has_capability = myThread->is_VM_thread() ||
                         myThread->is_ConcurrentGC_thread() ||
                         myThread->is_GC_task_thread();
@@ -1355,7 +1355,7 @@
 
 // These two methods are static since a GC may move the Method
 bool Method::load_signature_classes(methodHandle m, TRAPS) {
-  if (THREAD->is_Compiler_thread()) {
+  if (!THREAD->can_call_java()) {
     // There is nothing useful this routine can do from within the Compile thread.
     // Hopefully, the signature contains only well-known classes.
     // We could scan for this and return true/false, but the caller won't care.
--- a/src/share/vm/oops/method.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/method.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -107,13 +107,17 @@
                                                  // note: can have vtables with >2**16 elements (because of inheritance)
   u2                _method_size;                // size of this object
   u1                _intrinsic_id;               // vmSymbols::intrinsic_id (0 == _none)
-  u1                _jfr_towrite          : 1,   // Flags
-                    _caller_sensitive     : 1,
-                    _force_inline         : 1,
-                    _hidden               : 1,
-                    _dont_inline          : 1,
-                    _has_injected_profile : 1,
-                                          : 2;
+
+  // Flags
+  enum Flags {
+    _jfr_towrite          = 1 << 0,
+    _caller_sensitive     = 1 << 1,
+    _force_inline         = 1 << 2,
+    _dont_inline          = 1 << 3,
+    _hidden               = 1 << 4,
+    _has_injected_profile = 1 << 5
+  };
+  u1 _flags;
 
 #ifndef PRODUCT
   int               _compiled_invocation_count;  // Number of nmethod invocations so far (for perf. debugging)
@@ -772,18 +776,47 @@
 
   static vmSymbols::SID klass_id_for_intrinsics(Klass* holder);
 
-  bool     jfr_towrite()                { return _jfr_towrite;              }
-  void set_jfr_towrite(bool x)          {        _jfr_towrite = x;          }
-  bool     caller_sensitive()           { return _caller_sensitive;         }
-  void set_caller_sensitive(bool x)     {        _caller_sensitive = x;     }
-  bool     force_inline()               { return _force_inline;             }
-  void set_force_inline(bool x)         {        _force_inline = x;         }
-  bool     dont_inline()                { return _dont_inline;              }
-  void set_dont_inline(bool x)          {        _dont_inline = x;          }
-  bool  is_hidden()                     { return _hidden;                   }
-  void set_hidden(bool x)               {        _hidden = x;               }
-  bool     has_injected_profile()       { return _has_injected_profile;     }
-  void set_has_injected_profile(bool x) {        _has_injected_profile = x; }
+  bool jfr_towrite() {
+    return (_flags & _jfr_towrite) != 0;
+  }
+  void set_jfr_towrite(bool x) {
+    _flags = x ? (_flags | _jfr_towrite) : (_flags & ~_jfr_towrite);
+  }
+
+  bool caller_sensitive() {
+    return (_flags & _caller_sensitive) != 0;
+  }
+  void set_caller_sensitive(bool x) {
+    _flags = x ? (_flags | _caller_sensitive) : (_flags & ~_caller_sensitive);
+  }
+
+  bool force_inline() {
+    return (_flags & _force_inline) != 0;
+  }
+  void set_force_inline(bool x) {
+    _flags = x ? (_flags | _force_inline) : (_flags & ~_force_inline);
+  }
+
+  bool dont_inline() {
+    return (_flags & _dont_inline) != 0;
+  }
+  void set_dont_inline(bool x) {
+    _flags = x ? (_flags | _dont_inline) : (_flags & ~_dont_inline);
+  }
+
+  bool is_hidden() {
+    return (_flags & _hidden) != 0;
+  }
+  void set_hidden(bool x) {
+    _flags = x ? (_flags | _hidden) : (_flags & ~_hidden);
+  }
+
+  bool has_injected_profile() {
+    return (_flags & _has_injected_profile) != 0;
+  }
+  void set_has_injected_profile(bool x) {
+    _flags = x ? (_flags | _has_injected_profile) : (_flags & ~_has_injected_profile);
+  }
 
   ConstMethod::MethodType method_type() const {
       return _constMethod->method_type();
--- a/src/share/vm/oops/methodData.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/methodData.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -420,6 +420,28 @@
   }
 }
 
+#if INCLUDE_JVMCI
+void VirtualCallData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
+  ReceiverTypeData::clean_weak_klass_links(is_alive_cl);
+  for (uint row = 0; row < method_row_limit(); row++) {
+    Method* p = method(row);
+    if (p != NULL && !p->method_holder()->is_loader_alive(is_alive_cl)) {
+      clear_method_row(row);
+    }
+  }
+}
+
+void VirtualCallData::clean_weak_method_links() {
+  ReceiverTypeData::clean_weak_method_links();
+  for (uint row = 0; row < method_row_limit(); row++) {
+    Method* p = method(row);
+    if (p != NULL && !p->on_stack()) {
+      clear_method_row(row);
+    }
+  }
+}
+#endif // INCLUDE_JVMCI
+
 #ifndef PRODUCT
 void ReceiverTypeData::print_receiver_data_on(outputStream* st) const {
   uint row;
@@ -427,7 +449,11 @@
   for (row = 0; row < row_limit(); row++) {
     if (receiver(row) != NULL)  entries++;
   }
+#if INCLUDE_JVMCI
+  st->print_cr("count(%u) nonprofiled_count(%u) entries(%u)", count(), nonprofiled_count(), entries);
+#else
   st->print_cr("count(%u) entries(%u)", count(), entries);
+#endif
   int total = count();
   for (row = 0; row < row_limit(); row++) {
     if (receiver(row) != NULL) {
@@ -446,9 +472,38 @@
   print_shared(st, "ReceiverTypeData", extra);
   print_receiver_data_on(st);
 }
+
+#if INCLUDE_JVMCI
+void VirtualCallData::print_method_data_on(outputStream* st) const {
+  uint row;
+  int entries = 0;
+  for (row = 0; row < method_row_limit(); row++) {
+    if (method(row) != NULL) entries++;
+  }
+  tab(st);
+  st->print_cr("method_entries(%u)", entries);
+  int total = count();
+  for (row = 0; row < method_row_limit(); row++) {
+    if (method(row) != NULL) {
+      total += method_count(row);
+    }
+  }
+  for (row = 0; row < method_row_limit(); row++) {
+    if (method(row) != NULL) {
+      tab(st);
+      method(row)->print_value_on(st);
+      st->print_cr("(%u %4.2f)", method_count(row), (float) method_count(row) / (float) total);
+    }
+  }
+}
+#endif
+
 void VirtualCallData::print_data_on(outputStream* st, const char* extra) const {
   print_shared(st, "VirtualCallData", extra);
   print_receiver_data_on(st);
+#if INCLUDE_JVMCI
+  print_method_data_on(st);
+#endif
 }
 #endif // !PRODUCT
 
@@ -685,7 +740,7 @@
 }
 
 int MethodData::bytecode_cell_count(Bytecodes::Code code) {
-#if defined(COMPILER1) && !defined(COMPILER2)
+#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
   return no_profile_data;
 #else
   switch (code) {
@@ -814,6 +869,26 @@
   return false;
 }
 
+#if INCLUDE_JVMCI
+int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) {
+  if (!ProfileTraps) return 0;
+
+  // Assume that up to 30% of the possibly trapping BCIs with no MDP will need to allocate one.
+  int extra_data_count = MIN2(empty_bc_count, MAX2(4, (empty_bc_count * 30) / 100));
+
+  // Make sure we have a minimum number of extra data slots to
+  // allocate SpeculativeTrapData entries. We would want to have one
+  // entry per compilation that inlines this method and for which
+  // some type speculation assumption fails. So the room we need for
+  // the SpeculativeTrapData entries doesn't directly depend on the
+  // size of the method. Because it's hard to estimate, we reserve
+  // space for an arbitrary number of entries.
+  int spec_data_count = (needs_speculative_traps ? SpecTrapLimitExtraEntries : 0) *
+    (SpeculativeTrapData::static_cell_count() + DataLayout::header_size_in_cells());
+
+  return MAX2(extra_data_count, spec_data_count);
+}
+#else
 int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) {
   if (ProfileTraps) {
     // Assume that up to 3% of BCIs with no MDP will need to allocate one.
@@ -841,6 +916,7 @@
     return 0;
   }
 }
+#endif
 
 // Compute the size of the MethodData* necessary to store
 // profiling information about a given method.  Size is in bytes.
@@ -853,7 +929,7 @@
   while ((c = stream.next()) >= 0) {
     int size_in_bytes = compute_data_size(&stream);
     data_size += size_in_bytes;
-    if (size_in_bytes == 0)  empty_bc_count += 1;
+    if (size_in_bytes == 0 JVMCI_ONLY(&& Bytecodes::can_trap(c)))  empty_bc_count += 1;
     needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c);
   }
   int object_size = in_bytes(data_offset()) + data_size;
@@ -887,7 +963,7 @@
 // the segment in bytes.
 int MethodData::initialize_data(BytecodeStream* stream,
                                        int data_index) {
-#if defined(COMPILER1) && !defined(COMPILER2)
+#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
   return 0;
 #else
   int cell_count = -1;
@@ -1048,7 +1124,9 @@
     return new VirtualCallTypeData(this);
   case DataLayout::parameters_type_data_tag:
     return new ParametersTypeData(this);
-  };
+  case DataLayout::speculative_trap_data_tag:
+    return new SpeculativeTrapData(this);
+  }
 }
 
 // Iteration over data.
@@ -1077,10 +1155,14 @@
 // Initialize the MethodData* corresponding to a given method.
 MethodData::MethodData(methodHandle method, int size, TRAPS)
   : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {
+  // Set the method back-pointer.
+  _method = method();
+  initialize();
+}
+
+void MethodData::initialize() {
   No_Safepoint_Verifier no_safepoint;  // init function atomic wrt GC
   ResourceMark rm;
-  // Set the method back-pointer.
-  _method = method();
 
   init();
   set_creation_mileage(mileage_of(method()));
@@ -1090,13 +1172,13 @@
   int data_size = 0;
   int empty_bc_count = 0;  // number of bytecodes lacking data
   _data[0] = 0;  // apparently not set below.
-  BytecodeStream stream(method);
+  BytecodeStream stream(method());
   Bytecodes::Code c;
   bool needs_speculative_traps = false;
   while ((c = stream.next()) >= 0) {
     int size_in_bytes = initialize_data(&stream, data_size);
     data_size += size_in_bytes;
-    if (size_in_bytes == 0)  empty_bc_count += 1;
+    if (size_in_bytes == 0 JVMCI_ONLY(&& Bytecodes::can_trap(c)))  empty_bc_count += 1;
     needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c);
   }
   _data_size = data_size;
@@ -1114,7 +1196,7 @@
   // the code for traps cells works.
   DataLayout *dp = data_layout_at(data_size + extra_size);
 
-  int arg_size = method->size_of_parameters();
+  int arg_size = method()->size_of_parameters();
   dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
 
   int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1);
@@ -1143,6 +1225,7 @@
 
   post_initialize(&stream);
 
+  assert(object_size == compute_allocation_size_in_bytes(methodHandle(_method)), "MethodData: computed size != initialized size");
   set_size(object_size);
 }
 
@@ -1155,6 +1238,10 @@
   _num_blocks = 0;
   _would_profile = unknown;
 
+#if INCLUDE_JVMCI
+  _jvmci_ir_size = 0;
+#endif
+
 #if INCLUDE_RTM_OPT
   _rtm_state = NoRTM; // No RTM lock eliding by default
   if (UseRTMLocking &&
@@ -1644,3 +1731,11 @@
   clean_extra_data(is_alive);
   verify_extra_data_clean(is_alive);
 }
+
+void MethodData::clean_weak_method_links() {
+  for (ProfileData* data = first_data();
+       is_valid(data);
+       data = next_data(data)) {
+    data->clean_weak_method_links();
+  }
+}
--- a/src/share/vm/oops/methodData.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/oops/methodData.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -251,6 +251,9 @@
 
   // GC support
   void clean_weak_klass_links(BoolObjectClosure* cl);
+
+  // Redefinition support
+  void clean_weak_method_links();
 };
 
 
@@ -508,6 +511,9 @@
   // GC support
   virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {}
 
+  // Redefinition support
+  virtual void clean_weak_method_links() {}
+
   // CI translation: ProfileData can represent both MethodDataOop data
   // as well as CIMethodData data. This function is provided for translating
   // an oop in a ProfileData to the ci equivalent. Generally speaking,
@@ -531,11 +537,17 @@
 //
 // A BitData holds a flag or two in its header.
 class BitData : public ProfileData {
+  friend class VMStructs;
 protected:
   enum {
     // null_seen:
     //  saw a null operand (cast/aastore/instanceof)
-    null_seen_flag              = DataLayout::first_flag + 0
+      null_seen_flag              = DataLayout::first_flag + 0
+
+#if INCLUDE_JVMCI
+    // bytecode threw any exception
+    , exception_seen_flag         = null_seen_flag + 1
+#endif
   };
   enum { bit_cell_count = 0 };  // no additional data fields needed.
 public:
@@ -559,6 +571,11 @@
   bool null_seen()     { return flag_at(null_seen_flag); }
   void set_null_seen()    { set_flag_at(null_seen_flag); }
 
+#if INCLUDE_JVMCI
+  // true if an exception was thrown at the specific BCI
+  bool exception_seen() { return flag_at(exception_seen_flag); }
+  void set_exception_seen() { set_flag_at(exception_seen_flag); }
+#endif
 
   // Code generation support
   static int null_seen_byte_constant() {
@@ -592,6 +609,7 @@
 //
 // A CounterData corresponds to a simple counter.
 class CounterData : public BitData {
+  friend class VMStructs;
 protected:
   enum {
     count_off,
@@ -658,6 +676,7 @@
 // plus a data displacement, used for realigning the data pointer to
 // the corresponding target bci.
 class JumpData : public ProfileData {
+  friend class VMStructs;
 protected:
   enum {
     taken_off_set,
@@ -1161,9 +1180,24 @@
 // that the check is reached, and a series of (Klass*, count) pairs
 // which are used to store a type profile for the receiver of the check.
 class ReceiverTypeData : public CounterData {
+  friend class VMStructs;
 protected:
   enum {
+#if INCLUDE_JVMCI
+    // Description of the different counters
+    // ReceiverTypeData for instanceof/checkcast/aastore:
+    //   count is decremented for failed type checks
+    //   JVMCI only: nonprofiled_count is incremented on type overflow
+    // VirtualCallData for invokevirtual/invokeinterface:
+    //   count is incremented on type overflow
+    //   JVMCI only: nonprofiled_count is incremented on method overflow
+
+    // JVMCI is interested in knowing the percentage of type checks involving a type not explicitly in the profile
+    nonprofiled_count_off_set = counter_cell_count,
+    receiver0_offset,
+#else
     receiver0_offset = counter_cell_count,
+#endif
     count0_offset,
     receiver_type_row_cell_count = (count0_offset + 1) - receiver0_offset
   };
@@ -1178,7 +1212,7 @@
   virtual bool is_ReceiverTypeData() const { return true; }
 
   static int static_cell_count() {
-    return counter_cell_count + (uint) TypeProfileWidth * receiver_type_row_cell_count;
+    return counter_cell_count + (uint) TypeProfileWidth * receiver_type_row_cell_count JVMCI_ONLY(+ 1);
   }
 
   virtual int cell_count() const {
@@ -1240,6 +1274,13 @@
     set_count(0);
     set_receiver(row, NULL);
     set_receiver_count(row, 0);
+#if INCLUDE_JVMCI
+    if (!this->is_VirtualCallData()) {
+      // if this is a ReceiverTypeData for JVMCI, the nonprofiled_count
+      // must also be reset (see "Description of the different counters" above)
+      set_nonprofiled_count(0);
+    }
+#endif
   }
 
   // Code generation support
@@ -1249,6 +1290,17 @@
   static ByteSize receiver_count_offset(uint row) {
     return cell_offset(receiver_count_cell_index(row));
   }
+#if INCLUDE_JVMCI
+  static ByteSize nonprofiled_receiver_count_offset() {
+    return cell_offset(nonprofiled_count_off_set);
+  }
+  uint nonprofiled_count() const {
+    return uint_at(nonprofiled_count_off_set);
+  }
+  void set_nonprofiled_count(uint count) {
+    set_uint_at(nonprofiled_count_off_set, count);
+  }
+#endif
   static ByteSize receiver_type_data_size() {
     return cell_offset(static_cell_count());
   }
@@ -1304,6 +1356,7 @@
 // A VirtualCallData is used to access profiling information about a
 // virtual call.  For now, it has nothing more than a ReceiverTypeData.
 class VirtualCallData : public ReceiverTypeData {
+  friend class VMStructs;
 public:
   VirtualCallData(DataLayout* layout) : ReceiverTypeData(layout) {
     assert(layout->tag() == DataLayout::virtual_call_data_tag ||
@@ -1315,7 +1368,7 @@
   static int static_cell_count() {
     // At this point we could add more profile state, e.g., for arguments.
     // But for now it's the same size as the base record type.
-    return ReceiverTypeData::static_cell_count();
+    return ReceiverTypeData::static_cell_count() JVMCI_ONLY(+ (uint) MethodProfileWidth * receiver_type_row_cell_count);
   }
 
   virtual int cell_count() const {
@@ -1337,7 +1390,65 @@
   }
 #endif // CC_INTERP
 
+#if INCLUDE_JVMCI
+  static ByteSize method_offset(uint row) {
+    return cell_offset(method_cell_index(row));
+  }
+  static ByteSize method_count_offset(uint row) {
+    return cell_offset(method_count_cell_index(row));
+  }
+  static int method_cell_index(uint row) {
+    return receiver0_offset + (row + TypeProfileWidth) * receiver_type_row_cell_count;
+  }
+  static int method_count_cell_index(uint row) {
+    return count0_offset + (row + TypeProfileWidth) * receiver_type_row_cell_count;
+  }
+  static uint method_row_limit() {
+    return MethodProfileWidth;
+  }
+
+  Method* method(uint row) const {
+    assert(row < method_row_limit(), "oob");
+
+    Method* method = (Method*)intptr_at(method_cell_index(row));
+    assert(method == NULL || method->is_method(), "must be");
+    return method;
+  }
+
+  uint method_count(uint row) const {
+    assert(row < method_row_limit(), "oob");
+    return uint_at(method_count_cell_index(row));
+  }
+
+  void set_method(uint row, Method* m) {
+    assert((uint)row < method_row_limit(), "oob");
+    set_intptr_at(method_cell_index(row), (uintptr_t)m);
+  }
+
+  void set_method_count(uint row, uint count) {
+    assert(row < method_row_limit(), "oob");
+    set_uint_at(method_count_cell_index(row), count);
+  }
+
+  void clear_method_row(uint row) {
+    assert(row < method_row_limit(), "oob");
+    // Clear total count - indicator of polymorphic call site (see comment for clear_row() in ReceiverTypeData).
+    set_nonprofiled_count(0);
+    set_method(row, NULL);
+    set_method_count(row, 0);
+  }
+
+  // GC support
+  virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+
+  // Redefinition support
+  virtual void clean_weak_method_links();
+#endif
+
 #ifndef PRODUCT
+#if INCLUDE_JVMCI
+  void print_method_data_on(outputStream* st) const;
+#endif
   void print_data_on(outputStream* st, const char* extra = NULL) const;
 #endif
 };
@@ -1348,6 +1459,7 @@
 // a virtual call for which we collect type information about
 // arguments and return value.
 class VirtualCallTypeData : public VirtualCallData {
+  friend class VMStructs;
 private:
   // entries for arguments if any
   TypeStackSlotEntries _args;
@@ -1577,6 +1689,7 @@
 // It consists of taken and not_taken counts as well as a data displacement
 // for the taken case.
 class BranchData : public JumpData {
+  friend class VMStructs;
 protected:
   enum {
     not_taken_off_set = jump_cell_count,
@@ -1655,6 +1768,7 @@
 // not have a statically known size.  It consists of an array length
 // and an array start.
 class ArrayData : public ProfileData {
+  friend class VMStructs;
 protected:
   friend class DataLayout;
 
@@ -1732,6 +1846,7 @@
 // of (count, displacement) pairs, which count the number of times each
 // case was taken and specify the data displacment for each branch target.
 class MultiBranchData : public ArrayData {
+  friend class VMStructs;
 protected:
   enum {
     default_count_off_set,
@@ -2054,10 +2169,11 @@
   MethodData() : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {}; // For ciMethodData
 
   bool is_methodData() const volatile { return true; }
+  void initialize();
 
   // Whole-method sticky bits and flags
   enum {
-    _trap_hist_limit    = 20,   // decoupled from Deoptimization::Reason_LIMIT
+    _trap_hist_limit    = 20 JVMCI_ONLY(+5),   // decoupled from Deoptimization::Reason_LIMIT
     _trap_hist_mask     = max_jubyte,
     _extra_data_count   = 4     // extra DataLayout headers, for trap history
   }; // Public flag values
@@ -2067,7 +2183,7 @@
   uint _nof_overflow_traps;         // trap count, excluding _trap_hist
   union {
     intptr_t _align;
-    u1 _array[_trap_hist_limit];
+    u1 _array[JVMCI_ONLY(2 *) _trap_hist_limit];
   } _trap_hist;
 
   // Support for interprocedural escape analysis, from Thomas Kotzmann.
@@ -2102,6 +2218,11 @@
   enum WouldProfile {unknown, no_profile, profile};
   WouldProfile      _would_profile;
 
+#if INCLUDE_JVMCI
+  // Support for HotSpotMethodData.setCompiledIRSize(int)
+  int               _jvmci_ir_size;
+#endif
+
   // Size of _data array in bytes.  (Excludes header and extra_data fields.)
   int _data_size;
 
@@ -2378,7 +2499,7 @@
 
   // Return (uint)-1 for overflow.
   uint trap_count(int reason) const {
-    assert((uint)reason < _trap_hist_limit, "oob");
+    assert((uint)reason < JVMCI_ONLY(2*) _trap_hist_limit, "oob");
     return (int)((_trap_hist._array[reason]+1) & _trap_hist_mask) - 1;
   }
   // For loops:
@@ -2387,17 +2508,13 @@
   uint inc_trap_count(int reason) {
     // Count another trap, anywhere in this method.
     assert(reason >= 0, "must be single trap");
-    if ((uint)reason < _trap_hist_limit) {
-      uint cnt1 = 1 + _trap_hist._array[reason];
-      if ((cnt1 & _trap_hist_mask) != 0) {  // if no counter overflow...
-        _trap_hist._array[reason] = cnt1;
-        return cnt1;
-      } else {
-        return _trap_hist_mask + (++_nof_overflow_traps);
-      }
+    assert((uint)reason < JVMCI_ONLY(2*) _trap_hist_limit, "oob");
+    uint cnt1 = 1 + _trap_hist._array[reason];
+    if ((cnt1 & _trap_hist_mask) != 0) {  // if no counter overflow...
+      _trap_hist._array[reason] = cnt1;
+      return cnt1;
     } else {
-      // Could not represent the count in the histogram.
-      return (++_nof_overflow_traps);
+      return _trap_hist_mask + (++_nof_overflow_traps);
     }
   }
 
@@ -2435,6 +2552,10 @@
     return byte_offset_of(MethodData, _data[0]);
   }
 
+  static ByteSize trap_history_offset() {
+    return byte_offset_of(MethodData, _trap_hist._array);
+  }
+
   static ByteSize invocation_counter_offset() {
     return byte_offset_of(MethodData, _invocation_counter);
   }
@@ -2477,6 +2598,8 @@
   static bool profile_return_jsr292_only();
 
   void clean_method_data(BoolObjectClosure* is_alive);
+
+  void clean_weak_method_links();
 };
 
 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
--- a/src/share/vm/opto/c2compiler.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/c2compiler.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -32,6 +32,8 @@
   static bool init_c2_runtime();
 
 public:
+  C2Compiler() : AbstractCompiler(c2) {}
+
   // Name
   const char *name() { return "C2"; }
 
--- a/src/share/vm/opto/compile.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/compile.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2240,6 +2240,8 @@
       if (failing())  return;
     }
   }
+  // Ensure that major progress is now clear
+  C->clear_major_progress();
 
   {
     // Verify that all previous optimizations produced a valid graph
--- a/src/share/vm/opto/library_call.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/library_call.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -3788,7 +3788,7 @@
   }
   // Now test the correct condition.
   jint  nval = (obj_array
-                ? ((jint)Klass::_lh_array_tag_type_value
+                ? (jint)((unsigned)Klass::_lh_array_tag_type_value
                    <<    Klass::_lh_array_tag_shift)
                 : Klass::_lh_neutral_value);
   Node* cmp = _gvn.transform(new(C) CmpINode(layout_val, intcon(nval)));
--- a/src/share/vm/opto/node.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/node.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -286,6 +286,10 @@
 #ifdef _MSC_VER // the IDX_INIT hack falls foul of warning C4355
 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
 #endif
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
 
 // Out-of-line code from node constructors.
 // Executed only when extra debug info. is being passed around.
@@ -493,6 +497,10 @@
   _in[6] = n6; if (n6 != NULL) n6->add_out((Node *)this);
 }
 
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
 
 //------------------------------clone------------------------------------------
 // Clone a Node.
--- a/src/share/vm/opto/output.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/output.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -971,7 +971,9 @@
     assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI");
     assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest");
     // Now we can describe the scope.
-    debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+    methodHandle null_mh;
+    bool rethrow_exception = false;
+    debug_info()->describe_scope(safepoint_pc_offset, null_mh, scope_method, jvms->bci(), jvms->should_reexecute(), rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
   } // End jvms loop
 
   // Mark the end of the scope set.
@@ -1054,7 +1056,8 @@
     JVMState* jvms = youngest_jvms->of_depth(depth);
     ciMethod* method = jvms->has_method() ? jvms->method() : NULL;
     assert(!jvms->should_reexecute() || depth==max_depth, "reexecute allowed only for the youngest");
-    debug_info->describe_scope(pc_offset, method, jvms->bci(), jvms->should_reexecute());
+    methodHandle null_mh;
+    debug_info->describe_scope(pc_offset, null_mh, method, jvms->bci(), jvms->should_reexecute());
   }
 
   // Mark the end of the scope set.
--- a/src/share/vm/opto/runtime.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/runtime.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1218,17 +1218,22 @@
         force_unwind ? NULL : nm->handler_for_exception_and_pc(exception, pc);
 
       if (handler_address == NULL) {
-        Handle original_exception(thread, exception());
-        handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true);
+        bool recursive_exception = false;
+        handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true, recursive_exception);
         assert (handler_address != NULL, "must have compiled handler");
         // Update the exception cache only when the unwind was not forced
         // and there didn't happen another exception during the computation of the
-        // compiled exception handler.
-        if (!force_unwind && original_exception() == exception()) {
+        // compiled exception handler. Checking for exception oop equality is not
+        // sufficient because some exceptions are pre-allocated and reused.
+        if (!force_unwind && recursive_exception) {
           nm->add_handler_for_exception_and_pc(exception,pc,handler_address);
         }
       } else {
-        assert(handler_address == SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true), "Must be the same");
+#ifdef ASSERT
+        bool recursive_exception = false;
+        address computed_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true, recursive_exception);
+        assert(recursive_exception || (handler_address == computed_address), "Handler address inconsistency");
+#endif
       }
     }
 
--- a/src/share/vm/opto/superword.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/superword.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -201,6 +201,31 @@
   static const SWNodeInfo initial;
 };
 
+// JVMCI: OrderedPair is moved up to deal with compilation issues on Windows
+//------------------------------OrderedPair---------------------------
+// Ordered pair of Node*.
+class OrderedPair VALUE_OBJ_CLASS_SPEC {
+ protected:
+  Node* _p1;
+  Node* _p2;
+ public:
+  OrderedPair() : _p1(NULL), _p2(NULL) {}
+  OrderedPair(Node* p1, Node* p2) {
+    if (p1->_idx < p2->_idx) {
+      _p1 = p1; _p2 = p2;
+    } else {
+      _p1 = p2; _p2 = p1;
+    }
+  }
+
+  bool operator==(const OrderedPair &rhs) {
+    return _p1 == rhs._p1 && _p2 == rhs._p2;
+  }
+  void print() { tty->print("  (%d, %d)", _p1->_idx, _p2->_idx); }
+
+  static const OrderedPair initial;
+};
+
 // -----------------------------SuperWord---------------------------------
 // Transforms scalar operations into packed (superword) operations.
 class SuperWord : public ResourceObj {
@@ -505,29 +530,4 @@
   void print();
 };
 
-
-//------------------------------OrderedPair---------------------------
-// Ordered pair of Node*.
-class OrderedPair VALUE_OBJ_CLASS_SPEC {
- protected:
-  Node* _p1;
-  Node* _p2;
- public:
-  OrderedPair() : _p1(NULL), _p2(NULL) {}
-  OrderedPair(Node* p1, Node* p2) {
-    if (p1->_idx < p2->_idx) {
-      _p1 = p1; _p2 = p2;
-    } else {
-      _p1 = p2; _p2 = p1;
-    }
-  }
-
-  bool operator==(const OrderedPair &rhs) {
-    return _p1 == rhs._p1 && _p2 == rhs._p2;
-  }
-  void print() { tty->print("  (%d, %d)", _p1->_idx, _p2->_idx); }
-
-  static const OrderedPair initial;
-};
-
 #endif // SHARE_VM_OPTO_SUPERWORD_HPP
--- a/src/share/vm/opto/type.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/type.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1119,8 +1119,10 @@
 bool TypeD::eq( const Type *t ) const {
   if( g_isnan(_d) ||
       g_isnan(t->getd()) ) {
-    // One or both are NANs.  If both are NANs return true, else false.
-    return (g_isnan(_d) && g_isnan(t->getd()));
+    // it is important, when two different NaNs are used in one method, the NaNs are treated
+    // as different NaNs (as C1 does)
+    jdouble td = t->getd();
+    return *((jlong*)(&_d)) == *(jlong*)(&td);
   }
   if (_d == t->getd()) {
     // (NaN is impossible at this point, since it is not equal even to itself)
@@ -2008,7 +2010,7 @@
 
 //----------------------interface_vs_oop---------------------------------------
 #ifdef ASSERT
-bool TypeAry::interface_vs_oop(const Type *t) const {
+bool TypeAry::interface_vs_oop_helper(const Type *t) const {
   const TypeAry* t_ary = t->is_ary();
   if (t_ary) {
     const TypePtr* this_ptr = _elem->make_ptr(); // In case we have narrow_oops
@@ -2017,7 +2019,7 @@
       return this_ptr->interface_vs_oop(t_ptr);
     }
   }
-  return false;
+  return Type::interface_vs_oop_helper(t);
 }
 #endif
 
@@ -4100,12 +4102,12 @@
 
 //----------------------interface_vs_oop---------------------------------------
 #ifdef ASSERT
-bool TypeAryPtr::interface_vs_oop(const Type *t) const {
+bool TypeAryPtr::interface_vs_oop_helper(const Type *t) const {
   const TypeAryPtr* t_aryptr = t->isa_aryptr();
   if (t_aryptr) {
     return _ary->interface_vs_oop(t_aryptr->_ary);
   }
-  return false;
+  return Type::interface_vs_oop_helper(t);
 }
 #endif
 
--- a/src/share/vm/opto/type.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/opto/type.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -159,11 +159,6 @@
   // Table for efficient dualing of base types
   static const TYPES dual_type[lastype];
 
-#ifdef ASSERT
-  // One type is interface, the other is oop
-  virtual bool interface_vs_oop_helper(const Type *t) const;
-#endif
-
   const Type *meet_helper(const Type *t, bool include_speculative) const;
 
 protected:
@@ -178,6 +173,12 @@
     return dual()->meet_helper(t->dual(), include_speculative)->dual();
   }
 
+#ifdef ASSERT
+  // One type is interface, the other is oop.  Override to perform subtype specific
+  // interface_vs_oop checking.
+  virtual bool interface_vs_oop_helper(const Type *t) const;
+#endif
+
 public:
 
   inline void* operator new( size_t x ) throw() {
@@ -686,7 +687,7 @@
   virtual const Type* remove_speculative() const;
 #ifdef ASSERT
   // One type is interface, the other is oop
-  virtual bool interface_vs_oop(const Type *t) const;
+  virtual bool interface_vs_oop_helper(const Type *t) const;
 #endif
 #ifndef PRODUCT
   virtual void dump2( Dict &d, uint, outputStream *st  ) const; // Specialized per-Type dumping
@@ -1172,7 +1173,7 @@
   // sharpen the type of an int which is used as an array size
 #ifdef ASSERT
   // One type is interface, the other is oop
-  virtual bool interface_vs_oop(const Type *t) const;
+  virtual bool interface_vs_oop_helper(const Type *t) const;
 #endif
 #ifndef PRODUCT
   virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
--- a/src/share/vm/precompiled/precompiled.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/precompiled/precompiled.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -295,6 +295,9 @@
 # include "c1/c1_ValueType.hpp"
 # include "c1/c1_globals.hpp"
 #endif // COMPILER1
+#if INCLUDE_JVMCI
+# include "jvmci/jvmci_globals.hpp"
+#endif // INCLUDE_JVMCI
 #if INCLUDE_ALL_GCS
 # include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
 # include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
--- a/src/share/vm/prims/forte.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/prims/forte.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -625,7 +625,7 @@
 #ifdef __APPLE__
 // XXXDARWIN: Link errors occur even when __attribute__((weak_import))
 // is added
-#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) (0)
+#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) ((void) 0)
 #else
 void    collector_func_load(char* name,
                             void* null_argument_1,
--- a/src/share/vm/prims/jni.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/prims/jni.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -33,6 +33,10 @@
 #include "classfile/vmSymbols.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "utilities/macros.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #endif // INCLUDE_ALL_GCS
@@ -1405,6 +1409,10 @@
 
 static instanceOop alloc_object(jclass clazz, TRAPS) {
   KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
+  if (k == NULL) {
+    ResourceMark rm(THREAD);
+    THROW_(vmSymbols::java_lang_InstantiationException(), NULL);
+  }
   k()->check_valid_for_instantiation(false, CHECK_NULL);
   InstanceKlass::cast(k())->initialize(CHECK_NULL);
   instanceOop ih = InstanceKlass::cast(k())->allocate_instance(THREAD);
@@ -5224,6 +5232,21 @@
     *vm = (JavaVM *)(&main_vm);
     *(JNIEnv**)penv = thread->jni_environment();
 
+#if INCLUDE_JVMCI
+    if (UseJVMCICompiler) {
+      // JVMCI is initialized on a CompilerThread
+      if (BootstrapJVMCI) {
+        JavaThread* THREAD = thread;
+        JVMCICompiler* compiler = JVMCICompiler::instance(CATCH);
+        compiler->bootstrap(THREAD);
+        if (HAS_PENDING_EXCEPTION) {
+          HandleMark hm;
+          vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
+        }
+      }
+    }
+#endif
+
     // Tracks the time application was running before GC
     RuntimeService::record_application_start();
 
--- a/src/share/vm/prims/jvm.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/prims/jvm.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -383,6 +383,8 @@
     const char* compiler_name = "HotSpot " CSIZE "Client Compiler";
 #elif defined(COMPILER2)
     const char* compiler_name = "HotSpot " CSIZE "Server Compiler";
+#elif defined(INCLUDE_JVMCI)
+    const char* compiler_name = "HotSpot " CSIZE "JVMCI Compiler";
 #else
     const char* compiler_name = "";
 #endif // compilers
@@ -2368,7 +2370,7 @@
 
   ResourceMark rm(THREAD);
   const char* name = k->name()->as_C_string();
-  bool system_class = k->class_loader() == NULL;
+  bool system_class = k->class_loader() == NULL JVMCI_ONLY(|| SystemDictionary::jvmci_loader() == k->class_loader());
   return JavaAssertions::enabled(name, system_class);
 
 JVM_END
--- a/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -268,7 +268,7 @@
 
     address scopes_data = nm->scopes_data_begin();
     for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
-      ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop());
+      ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->rethrow_exception(), pcd->return_oop());
       ScopeDesc *sd  = &sc0;
       while( !sd->is_top() ) { sd = sd->sender(); }
       int bci = sd->bci();
--- a/src/share/vm/prims/jvmtiEnv.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -226,6 +226,7 @@
                             NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count);
   NULL_CHECK(class_definitions, JVMTI_ERROR_OUT_OF_MEMORY);
 
+  int redef_index = 0;
   for (index = 0; index < class_count; index++) {
     HandleMark hm(current_thread);
 
@@ -253,6 +254,11 @@
       return JVMTI_ERROR_UNMODIFIABLE_CLASS;
     }
 
+    if (klass->oop_is_instance() && InstanceKlass::cast(klass())->is_anonymous()) {
+      // return JVMTI_ERROR_UNMODIFIABLE_CLASS;
+      continue;
+    }
+
     instanceKlassHandle ikh(current_thread, k_oop);
     if (ikh->get_cached_class_file_bytes() == NULL) {
       // Not cached, we need to reconstitute the class file from the
@@ -267,19 +273,24 @@
         return reconstituter.get_error();
       }
 
-      class_definitions[index].class_byte_count = (jint)reconstituter.class_file_size();
-      class_definitions[index].class_bytes      = (unsigned char*)
+      class_definitions[redef_index].class_byte_count = (jint)reconstituter.class_file_size();
+      class_definitions[redef_index].class_bytes      = (unsigned char*)
                                                        reconstituter.class_file_bytes();
     } else {
       // it is cached, get it from the cache
-      class_definitions[index].class_byte_count = ikh->get_cached_class_file_len();
-      class_definitions[index].class_bytes      = ikh->get_cached_class_file_bytes();
+      class_definitions[redef_index].class_byte_count = ikh->get_cached_class_file_len();
+      class_definitions[redef_index].class_bytes      = ikh->get_cached_class_file_bytes();
     }
-    class_definitions[index].klass              = jcls;
+    class_definitions[redef_index].klass              = jcls;
+    redef_index++;
   }
-  VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
-  VMThread::execute(&op);
-  return (op.check_error());
+  if (redef_index > 0) {
+    VM_RedefineClasses op(redef_index, class_definitions, jvmti_class_load_kind_retransform);
+    VMThread::execute(&op);
+    return (op.check_error());
+  } else {
+    return JVMTI_ERROR_NONE;
+  }
 } /* end RetransformClasses */
 
 
--- a/src/share/vm/prims/jvmtiTagMap.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/prims/jvmtiTagMap.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -2796,6 +2796,7 @@
   return true;
 }
 
+#ifdef ASSERT
 // verify that a static oop field is in range
 static inline bool verify_static_oop(InstanceKlass* ik,
                                      oop mirror, int offset) {
@@ -2810,6 +2811,7 @@
     return false;
   }
 }
+#endif // #ifdef ASSERT
 
 // a class references its super class, interfaces, class loader, ...
 // and finally its static fields
--- a/src/share/vm/prims/methodHandles.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/prims/methodHandles.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -331,7 +331,7 @@
 
 
 Symbol* MethodHandles::signature_polymorphic_intrinsic_name(vmIntrinsics::ID iid) {
-  assert(is_signature_polymorphic_intrinsic(iid), err_msg("iid=%d", iid));
+  assert(is_signature_polymorphic_intrinsic(iid), err_msg("%d %s", iid, vmIntrinsics::name_at(iid)));
   switch (iid) {
   case vmIntrinsics::_invokeBasic:      return vmSymbols::invokeBasic_name();
   case vmIntrinsics::_linkToVirtual:    return vmSymbols::linkToVirtual_name();
@@ -339,7 +339,7 @@
   case vmIntrinsics::_linkToSpecial:    return vmSymbols::linkToSpecial_name();
   case vmIntrinsics::_linkToInterface:  return vmSymbols::linkToInterface_name();
   }
-  assert(false, "");
+  fatal(err_msg("unexpected intrinsic id: %d %s", iid, vmIntrinsics::name_at(iid)));
   return 0;
 }
 
@@ -351,7 +351,7 @@
   case vmIntrinsics::_linkToSpecial:    return JVM_REF_invokeSpecial;
   case vmIntrinsics::_linkToInterface:  return JVM_REF_invokeInterface;
   }
-  assert(false, err_msg("iid=%d", iid));
+  fatal(err_msg("unexpected intrinsic id: %d %s", iid, vmIntrinsics::name_at(iid)));
   return 0;
 }
 
--- a/src/share/vm/prims/nativeLookup.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/prims/nativeLookup.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -126,6 +126,12 @@
   void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
   void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
   void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
+#if INCLUDE_JVMCI
+  void     JNICALL JVM_InitJVMCIClassLoader(JNIEnv *env, jclass c, jobject loader);
+  void     JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
+  jobject  JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
+  jobject  JNICALL JVM_GetJVMCIClassLoader(JNIEnv *env, jclass c);
+#endif
 }
 
 #define CC (char*)  /* cast a literal from (const char*) */
@@ -136,6 +142,12 @@
   { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
   { CC"Java_sun_misc_Perf_registerNatives",                        NULL, FN_PTR(JVM_RegisterPerfMethods)         },
   { CC"Java_sun_hotspot_WhiteBox_registerNatives",                 NULL, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
+#if INCLUDE_JVMCI
+  { CC"Java_jdk_vm_ci_services_JVMCIClassLoaderFactory_init", NULL, FN_PTR(JVM_InitJVMCIClassLoader)     },
+  { CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime",       NULL, FN_PTR(JVM_GetJVMCIRuntime)          },
+  { CC"Java_jdk_vm_ci_services_Services_getJVMCIClassLoader", NULL, FN_PTR(JVM_GetJVMCIClassLoader)      },
+  { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives",  NULL, FN_PTR(JVM_RegisterJVMCINatives)     },
+#endif
 };
 
 static address lookup_special_native(char* jni_name) {
@@ -165,7 +177,7 @@
   // gets found the first time around - otherwise an infinite loop can occure. This is
   // another VM/library dependency
   Handle loader(THREAD, method->method_holder()->class_loader());
-  if (loader.is_null()) {
+  if (loader.is_null() JVMCI_ONLY(|| loader() == SystemDictionary::jvmci_loader())) {
     entry = lookup_special_native(jni_name);
     if (entry == NULL) {
        entry = (address) os::dll_lookup(os::native_java_library(), jni_name);
--- a/src/share/vm/runtime/advancedThresholdPolicy.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -25,6 +25,9 @@
 #include "precompiled.hpp"
 #include "runtime/advancedThresholdPolicy.hpp"
 #include "runtime/simpleThresholdPolicy.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 
 #ifdef TIERED
 // Print an event.
@@ -161,6 +164,7 @@
 
 // Called with the queue locked and with at least one element
 CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) {
+  CompileTask *max_blocking_task = NULL;
   CompileTask *max_task = NULL;
   Method* max_method = NULL;
   jlong t = os::javaTimeMillis();
@@ -178,6 +182,7 @@
         if (PrintTieredEvents) {
           print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level());
         }
+        task->log_task_dequeued("stale");
         compile_queue->remove_and_mark_stale(task);
         method->clear_queued_for_compilation();
         task = next_task;
@@ -190,9 +195,24 @@
         max_method = method;
       }
     }
+    if (task->is_blocking()) {
+      if (max_blocking_task == NULL || compare_methods(method, max_blocking_task->method())) {
+        max_blocking_task = task;
+      }
+    }
     task = next_task;
   }
 
+  if (max_blocking_task != NULL) {
+    // In blocking compilation mode, the CompileBroker will make
+    // compilations submitted by a JVMCI compiler thread non-blocking. These
+    // compilations should be scheduled after all blocking compilations
+    // to service non-compiler related compilations sooner and reduce the
+    // chance of such compilations timing out.
+    max_task = max_blocking_task;
+    max_method = max_task->method();
+  }
+
   if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile
       && is_method_profiled(max_method)) {
     max_task->set_comp_level(CompLevel_limited_profile);
@@ -348,6 +368,14 @@
       if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
         next_level = CompLevel_full_optimization;
       } else if ((this->*p)(i, b, cur_level)) {
+#if INCLUDE_JVMCI
+        if (UseJVMCICompiler) {
+          // Since JVMCI takes a while to warm up, its queue inevitably backs up during
+          // early VM execution.
+          next_level = CompLevel_full_profile;
+          break;
+        }
+#endif
         // C1-generated fully profiled code is about 30% slower than the limited profile
         // code that has only invocation and backedge counters. The observation is that
         // if C2 queue is large enough we can spend too much time in the fully profiled code
@@ -404,7 +432,7 @@
 }
 
 // Determine if a method should be compiled with a normal entry point at a different level.
-CompLevel AdvancedThresholdPolicy::call_event(Method* method, CompLevel cur_level) {
+CompLevel AdvancedThresholdPolicy::call_event(Method* method, CompLevel cur_level, JavaThread * thread) {
   CompLevel osr_level = MIN2((CompLevel) method->highest_osr_comp_level(),
                              common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level, true));
   CompLevel next_level = common(&AdvancedThresholdPolicy::call_predicate, method, cur_level);
@@ -421,11 +449,16 @@
   } else {
     next_level = MAX2(osr_level, next_level);
   }
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler) {
+    next_level = JVMCIRuntime::adjust_comp_level(method, false, next_level, thread);
+  }
+#endif
   return next_level;
 }
 
 // Determine if we should do an OSR compilation of a given method.
-CompLevel AdvancedThresholdPolicy::loop_event(Method* method, CompLevel cur_level) {
+CompLevel AdvancedThresholdPolicy::loop_event(Method* method, CompLevel cur_level, JavaThread * thread) {
   CompLevel next_level = common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level, true);
   if (cur_level == CompLevel_none) {
     // If there is a live OSR method that means that we deopted to the interpreter
@@ -435,6 +468,11 @@
       return osr_level;
     }
   }
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler) {
+    next_level = JVMCIRuntime::adjust_comp_level(method, true, next_level, thread);
+  }
+#endif
   return next_level;
 }
 
@@ -452,7 +490,7 @@
     create_mdo(mh, thread);
   }
   if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) {
-    CompLevel next_level = call_event(mh(), level);
+    CompLevel next_level = call_event(mh(), level, thread);
     if (next_level != level) {
       compile(mh, InvocationEntryBci, next_level, thread);
     }
@@ -472,7 +510,7 @@
   }
 
   if (is_compilation_enabled()) {
-    CompLevel next_osr_level = loop_event(imh(), level);
+    CompLevel next_osr_level = loop_event(imh(), level, thread);
     CompLevel max_osr_level = (CompLevel)imh->highest_osr_comp_level();
     // At the very least compile the OSR version
     if (!CompileBroker::compilation_is_in_queue(imh) && (next_osr_level != level)) {
@@ -485,7 +523,7 @@
     if (mh() != imh()) { // If there is an enclosing method
       guarantee(nm != NULL, "Should have nmethod here");
       cur_level = comp_level(mh());
-      next_level = call_event(mh(), cur_level);
+      next_level = call_event(mh(), cur_level, thread);
 
       if (max_osr_level == CompLevel_full_optimization) {
         // The inlinee OSRed to full opt, we need to modify the enclosing method to avoid deopts
@@ -520,7 +558,7 @@
       }
     } else {
       cur_level = comp_level(imh());
-      next_level = call_event(imh(), cur_level);
+      next_level = call_event(imh(), cur_level, thread);
       if (!CompileBroker::compilation_is_in_queue(imh) && (next_level != cur_level)) {
         compile(imh, InvocationEntryBci, next_level, thread);
       }
--- a/src/share/vm/runtime/advancedThresholdPolicy.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/advancedThresholdPolicy.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -172,10 +172,10 @@
   // Transition functions.
   // call_event determines if a method should be compiled at a different
   // level with a regular invocation entry.
-  CompLevel call_event(Method* method, CompLevel cur_level);
+  CompLevel call_event(Method* method, CompLevel cur_level, JavaThread * thread);
   // loop_event checks if a method should be OSR compiled at a different
   // level.
-  CompLevel loop_event(Method* method, CompLevel cur_level);
+  CompLevel loop_event(Method* method, CompLevel cur_level, JavaThread * thread);
   // Has a method been long around?
   // We don't remove old methods from the compile queue even if they have
   // very low activity (see select_task()).
--- a/src/share/vm/runtime/arguments.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/arguments.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1115,7 +1115,7 @@
   }
 }
 
-#if defined(COMPILER2) || defined(_LP64) || !INCLUDE_CDS
+#if defined(COMPILER2) || INCLUDE_JVMCI || defined(_LP64) || !INCLUDE_CDS
 // Conflict: required to use shared spaces (-Xshare:on), but
 // incompatible command line options were chosen.
 
@@ -1165,7 +1165,7 @@
  *    the minimum number of compiler threads is 2.
  */
 int Arguments::get_min_number_of_compiler_threads() {
-#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
+#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK) && !INCLUDE_JVMCI
   return 0;   // case 1
 #else
   if (!TieredCompilation || (TieredStopAtLevel < CompLevel_full_optimization)) {
@@ -1586,10 +1586,12 @@
   }
 }
 
+
+
 void Arguments::set_ergonomics_flags() {
   select_gc();
 
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   // Shared spaces work fine with other GCs but causes bytecode rewriting
   // to be disabled, which hurts interpreter performance and decreases
   // server performance.  When -server is specified, keep the default off
@@ -1673,7 +1675,7 @@
 
 void Arguments::set_g1_gc_flags() {
   assert(UseG1GC, "Error");
-#ifdef COMPILER1
+#if defined(COMPILER1) || INCLUDE_JVMCI
   FastTLABRefill = false;
 #endif
   FLAG_SET_DEFAULT(ParallelGCThreads,
@@ -2439,6 +2441,9 @@
     }
 #endif
   }
+#if INCLUDE_JVMCI
+  status = status && JVMCIGlobals::check_jvmci_flags_are_consistent();
+#endif
 
   // Need to limit the extent of the padding to reasonable size.
   // 8K is well beyond the reasonable HW cache line size, even with the
@@ -2502,7 +2507,6 @@
   assert(min_number_of_compiler_threads <= CI_COMPILER_COUNT, "minimum should be less or equal default number");
   // Check the minimum number of compiler threads
   status &=verify_min_value(CICompilerCount, min_number_of_compiler_threads, "CICompilerCount");
-
   return status;
 }
 
@@ -3353,8 +3357,8 @@
           return JNI_EINVAL;
         }
       }
-    // Unknown option
-    } else if (is_bad_option(option, args->ignoreUnrecognized)) {
+    }
+    else if (is_bad_option(option, args->ignoreUnrecognized)) {
       return JNI_ERR;
     }
   }
@@ -3569,6 +3573,37 @@
   // This must be done after all -D arguments have been processed.
   scp_p->expand_endorsed();
 
+#if INCLUDE_JVMCI
+  if (!UseJVMCIClassLoader) {
+    // Append lib/jvmci/*.jar to boot class path
+    char jvmciDir[JVM_MAXPATHLEN];
+    const char* fileSep = os::file_separator();
+    jio_snprintf(jvmciDir, sizeof(jvmciDir), "%s%slib%sjvmci", Arguments::get_java_home(), fileSep, fileSep);
+    DIR* dir = os::opendir(jvmciDir);
+    if (dir != NULL) {
+      struct dirent *entry;
+      char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(jvmciDir), mtInternal);
+      while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+        const char* name = entry->d_name;
+        const char* ext = name + strlen(name) - 4;
+        if (ext > name && strcmp(ext, ".jar") == 0) {
+          char fileName[JVM_MAXPATHLEN];
+          jio_snprintf(fileName, sizeof(fileName), "%s%s%s", jvmciDir, fileSep, name);
+          scp_p->add_suffix(fileName);
+          scp_assembly_required = true;
+        }
+      }
+      FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
+      os::closedir(dir);
+    }
+    const char* path = Arguments::get_property("jvmci.class.path.append");
+    if (path != NULL) {
+      scp_p->add_suffix(path);
+      scp_assembly_required = true;
+    }
+  }
+#endif
+
   if (scp_assembly_required || scp_p->get_endorsed() != NULL) {
     // Assemble the bootclasspath elements into the final path.
     Arguments::set_sysclasspath(scp_p->combined_path());
@@ -3595,7 +3630,7 @@
     FLAG_SET_ERGO(uintx, InitialTenuringThreshold, MaxTenuringThreshold);
   }
 
-#ifndef COMPILER2
+#if !defined(COMPILER2) && !INCLUDE_JVMCI
   // Don't degrade server performance for footprint
   if (FLAG_IS_DEFAULT(UseLargePages) &&
       MaxHeapSize < LargePageHeapSizeThreshold) {
@@ -3605,7 +3640,7 @@
     FLAG_SET_DEFAULT(UseLargePages, false);
   }
 
-#else
+#elif defined(COMPILER2)
   if (!FLAG_IS_DEFAULT(OptoLoopAlignment) && FLAG_IS_DEFAULT(MaxLoopPad)) {
     FLAG_SET_DEFAULT(MaxLoopPad, OptoLoopAlignment-1);
   }
@@ -3853,6 +3888,12 @@
     if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) {
       IgnoreUnrecognizedVMOptions = false;
     }
+    if (match_option(option, "-XX:+UnlockDiagnosticVMOptions", &tail)) {
+      UnlockDiagnosticVMOptions = true;
+    }
+    if (match_option(option, "-XX:-UnlockDiagnosticVMOptions", &tail)) {
+      UnlockDiagnosticVMOptions = false;
+    }
     if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) {
       CommandLineFlags::printFlags(tty, false);
       vm_exit(0);
@@ -4027,6 +4068,11 @@
   // Set flags based on ergonomics.
   set_ergonomics_flags();
 
+#if INCLUDE_JVMCI
+  // Set flags specific to JVMCI. This is done prior to computing NMethodSweepFraction.
+  JVMCIGlobals::set_jvmci_specific_flags();
+#endif
+
   set_shared_spaces_flags();
 
   // Check the GC selections again.
@@ -4070,6 +4116,9 @@
 #ifdef COMPILER1
       || !UseFastLocking
 #endif // COMPILER1
+#if INCLUDE_JVMCI
+      || !JVMCIUseFastLocking
+#endif
     ) {
     if (!FLAG_IS_DEFAULT(UseBiasedLocking) && UseBiasedLocking) {
       // flag set to true on command line; warn the user that they
@@ -4146,7 +4195,7 @@
     }
   }
 #ifdef COMPILER2
-  if (!UseBiasedLocking || EmitSync != 0) {
+  if (!UseBiasedLocking || (EmitSync & ~(2 | 8)) != 0) {
     UseOptoBiasInlining = false;
   }
 #endif
--- a/src/share/vm/runtime/compilationPolicy.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -107,6 +107,33 @@
          (UseCompiler && AlwaysCompileLoopMethods && m->has_loops() && CompileBroker::should_compile_new_jobs()); // eagerly compile loop methods
 }
 
+void CompilationPolicy::compile_if_required(methodHandle selected_method, TRAPS) {
+  if (must_be_compiled(selected_method)) {
+    // This path is unusual, mostly used by the '-Xcomp' stress test mode.
+
+    // Note: with several active threads, the must_be_compiled may be true
+    //       while can_be_compiled is false; remove assert
+    // assert(CompilationPolicy::can_be_compiled(selected_method), "cannot compile");
+    if (!THREAD->can_call_java() || THREAD->is_Compiler_thread()) {
+      // don't force compilation, resolve was on behalf of compiler
+      return;
+    }
+    if (selected_method->method_holder()->is_not_initialized()) {
+      // 'is_not_initialized' means not only '!is_initialized', but also that
+      // initialization has not been started yet ('!being_initialized')
+      // Do not force compilation of methods in uninitialized classes.
+      // Note that doing this would throw an assert later,
+      // in CompileBroker::compile_method.
+      // We sometimes use the link resolver to do reflective lookups
+      // even before classes are initialized.
+      return;
+    }
+    CompileBroker::compile_method(selected_method, InvocationEntryBci,
+        CompilationPolicy::policy()->initial_compile_level(),
+        methodHandle(), 0, "must_be_compiled", CHECK);
+  }
+}
+
 // Returns true if m is allowed to be compiled
 bool CompilationPolicy::can_be_compiled(methodHandle m, int comp_level) {
   // allow any levels for WhiteBox
@@ -160,6 +187,26 @@
   return !delay_compilation_during_startup() && CompileBroker::should_compile_new_jobs();
 }
 
+CompileTask* CompilationPolicy::select_task_helper(CompileQueue* compile_queue) {
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler && !BackgroundCompilation) {
+    /*
+     * In blocking compilation mode, the CompileBroker will make
+     * compilations submitted by a JVMCI compiler thread non-blocking. These
+     * compilations should be scheduled after all blocking compilations
+     * to service non-compiler related compilations sooner and reduce the
+     * chance of such compilations timing out.
+     */
+    for (CompileTask* task = compile_queue->first(); task != NULL; task = task->next()) {
+      if (task->is_blocking()) {
+        return task;
+      }
+    }
+  }
+#endif
+  return compile_queue->first();
+}
+
 #ifndef PRODUCT
 void CompilationPolicy::print_time() {
   tty->print_cr ("Accumulated compilationPolicy times:");
@@ -340,7 +387,7 @@
 }
 
 CompileTask* NonTieredCompPolicy::select_task(CompileQueue* compile_queue) {
-  return compile_queue->first();
+  return select_task_helper(compile_queue);
 }
 
 bool NonTieredCompPolicy::is_mature(Method* method) {
--- a/src/share/vm/runtime/compilationPolicy.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -43,13 +43,19 @@
   static elapsedTimer       _accumulated_time;
 
   static bool               _in_vm_startup;
+
+  // m must be compiled before executing it
+  static bool must_be_compiled(methodHandle m, int comp_level = CompLevel_all);
+
 public:
   static  void set_in_vm_startup(bool in_vm_startup) { _in_vm_startup = in_vm_startup; }
   static  void completed_vm_startup();
   static  bool delay_compilation_during_startup()    { return _in_vm_startup; }
 
-  // m must be compiled before executing it
-  static bool must_be_compiled(methodHandle m, int comp_level = CompLevel_all);
+  // If m must_be_compiled then request a compilation from the CompileBroker.
+  // This supports the -Xcomp option.
+  static void compile_if_required(methodHandle m, TRAPS);
+
   // m is allowed to be compiled
   static bool can_be_compiled(methodHandle m, int comp_level = CompLevel_all);
   // m is allowed to be osr compiled
@@ -58,6 +64,8 @@
   static void set_policy(CompilationPolicy* policy) { _policy = policy; }
   static CompilationPolicy* policy()                { return _policy; }
 
+  static CompileTask* select_task_helper(CompileQueue* compile_queue);
+
   // Profiling
   elapsedTimer* accumulated_time() { return &_accumulated_time; }
   void print_time() PRODUCT_RETURN;
--- a/src/share/vm/runtime/deoptimization.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/deoptimization.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -36,6 +36,7 @@
 #include "memory/resourceArea.hpp"
 #include "oops/method.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/fieldStreams.hpp"
 #include "prims/jvmtiThreadState.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/compilationPolicy.hpp"
@@ -83,6 +84,12 @@
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
+
+
 bool DeoptimizationMarker::_is_active = false;
 
 Deoptimization::UnrollBlock::UnrollBlock(int  size_of_deoptimized_frame,
@@ -91,7 +98,8 @@
                                          int  number_of_frames,
                                          intptr_t* frame_sizes,
                                          address* frame_pcs,
-                                         BasicType return_type) {
+                                         BasicType return_type,
+                                         int exec_mode) {
   _size_of_deoptimized_frame = size_of_deoptimized_frame;
   _caller_adjustment         = caller_adjustment;
   _caller_actual_parameters  = caller_actual_parameters;
@@ -103,10 +111,11 @@
   _initial_info              = 0;
   // PD (x86 only)
   _counter_temp              = 0;
-  _unpack_kind               = 0;
+  _unpack_kind               = exec_mode;
   _sender_sp_temp            = 0;
 
   _total_frame_sizes         = size_of_frames();
+  assert(exec_mode >= 0 && exec_mode < Unpack_LIMIT, "Unexpected exec_mode");
 }
 
 
@@ -151,7 +160,7 @@
 // ResetNoHandleMark and HandleMark were removed from it. The actual reallocation
 // of previously eliminated objects occurs in realloc_objects, which is
 // called from the method fetch_unroll_info_helper below.
-JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info(JavaThread* thread))
+JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info(JavaThread* thread, int exec_mode))
   // It is actually ok to allocate handles in a leaf method. It causes no safepoints,
   // but makes the entry a little slower. There is however a little dance we have to
   // do in debug mode to get around the NoHandleMark code in the JRT_LEAF macro
@@ -160,14 +169,17 @@
   // handler. Note this fact before we start generating temporary frames
   // that can confuse an asynchronous stack walker. This counter is
   // decremented at the end of unpack_frames().
+  if (TraceDeoptimization) {
+    tty->print_cr("Deoptimizing thread " INTPTR_FORMAT, thread);
+  }
   thread->inc_in_deopt_handler();
 
-  return fetch_unroll_info_helper(thread);
+  return fetch_unroll_info_helper(thread, exec_mode);
 JRT_END
 
 
 // This is factored, since it is both called from a JRT_LEAF (deoptimization) and a JRT_ENTRY (uncommon_trap)
-Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread* thread) {
+Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread* thread, int exec_mode) {
 
   // Note: there is a safepoint safety issue here. No matter whether we enter
   // via vanilla deopt or uncommon trap we MUST NOT stop at a safepoint once
@@ -187,6 +199,7 @@
   // Set the deoptee nmethod
   assert(thread->deopt_nmethod() == NULL, "Pending deopt!");
   thread->set_deopt_nmethod(deoptee.cb()->as_nmethod_or_null());
+  bool skip_internal = thread->deopt_nmethod() != NULL && !thread->deopt_nmethod()->compiler()->is_jvmci();
 
   if (VerifyStack) {
     thread->validate_frame_layout();
@@ -205,13 +218,28 @@
   assert(vf->is_compiled_frame(), "Wrong frame type");
   chunk->push(compiledVFrame::cast(vf));
 
+  ScopeDesc* trap_scope = chunk->at(0)->scope();
+  Handle exceptionObject;
+  if (trap_scope->rethrow_exception()) {
+    if (PrintDeoptimizationDetails) {
+      tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", trap_scope->method()->method_holder()->name()->as_C_string(), trap_scope->method()->name()->as_C_string(), trap_scope->bci());
+    }
+    GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
+    guarantee(expressions != NULL && expressions->length() > 0, "must have exception to throw");
+    ScopeValue* topOfStack = expressions->top();
+    exceptionObject = StackValue::create_stack_value(&deoptee, &map, topOfStack)->get_obj();
+    assert(exceptionObject() != NULL, "exception oop can not be null");
+  }
+
   bool realloc_failures = false;
 
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   // Reallocate the non-escaping objects and restore their fields. Then
   // relock objects if synchronization on them was eliminated.
+#ifndef INCLUDE_JVMCI
   if (DoEscapeAnalysis || EliminateNestedLocks) {
     if (EliminateAllocations) {
+#endif // INCLUDE_JVMCI
       assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames");
       GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
 
@@ -222,8 +250,9 @@
       // It is not guaranteed that we can get such information here only
       // by analyzing bytecode in deoptimized frames. This is why this flag
       // is set during method compilation (see Compile::Process_OopMap_Node()).
-      // If the previous frame was popped, we don't have a result.
-      bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution();
+      // If the previous frame was popped or if we are dispatching an exception,
+      // we don't have an oop result.
+      bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution() && (exec_mode == Unpack_deopt);
       Handle return_value;
       if (save_oop_result) {
         // Reallocation may trigger GC. If deoptimization happened on return from
@@ -241,7 +270,7 @@
         JRT_BLOCK
           realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD);
         JRT_END
-        reassign_fields(&deoptee, &map, objects, realloc_failures);
+        reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal);
 #ifndef PRODUCT
         if (TraceDeoptimization) {
           ttyLocker ttyl;
@@ -254,8 +283,10 @@
         // Restore result.
         deoptee.set_saved_oop_result(&map, return_value());
       }
+#ifndef INCLUDE_JVMCI
     }
     if (EliminateLocks) {
+#endif // INCLUDE_JVMCI
 #ifndef PRODUCT
       bool first = true;
 #endif
@@ -266,7 +297,7 @@
         if (monitors->is_nonempty()) {
           relock_objects(monitors, thread, realloc_failures);
 #ifndef PRODUCT
-          if (TraceDeoptimization) {
+          if (PrintDeoptimizationDetails) {
             ttyLocker ttyl;
             for (int j = 0; j < monitors->length(); j++) {
               MonitorInfo* mi = monitors->at(j);
@@ -287,16 +318,19 @@
 #endif
         }
       }
+#ifndef INCLUDE_JVMCI
     }
   }
-#endif // COMPILER2
+#endif // INCLUDE_JVMCI
+#endif // COMPILER2 || INCLUDE_JVMCI
+
   // Ensure that no safepoint is taken after pointers have been stored
   // in fields of rematerialized objects.  If a safepoint occurs from here on
   // out the java state residing in the vframeArray will be missed.
   No_Safepoint_Verifier no_safepoint;
 
   vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures);
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   if (realloc_failures) {
     pop_frames_failed_reallocs(thread, array);
   }
@@ -346,7 +380,11 @@
     unpack_sp = deoptee.unextended_sp();
 
 #ifdef ASSERT
-  assert(cb->is_deoptimization_stub() || cb->is_uncommon_trap_stub(), "just checking");
+  assert(cb->is_deoptimization_stub() ||
+         cb->is_uncommon_trap_stub() ||
+         strcmp("Stub<DeoptimizationStub.deoptimizationHandler>", cb->name()) == 0 ||
+         strcmp("Stub<UncommonTrapStub.uncommonTrapHandler>", cb->name()) == 0,
+         err_msg("unexpected code blob: %s", cb->name()));
 #endif
 #else
   intptr_t* unpack_sp = stub_frame.sender(&dummy_map).unextended_sp();
@@ -482,13 +520,21 @@
   assert(CodeCache::find_blob_unsafe(frame_pcs[0]) != NULL, "bad pc");
 #endif // SHARK
 
+#if INCLUDE_JVMCI
+  if (exceptionObject() != NULL) {
+    thread->set_exception_oop(exceptionObject());
+    exec_mode = Unpack_exception;
+  }
+#endif
+
   UnrollBlock* info = new UnrollBlock(array->frame_size() * BytesPerWord,
                                       caller_adjustment * BytesPerWord,
                                       caller_was_method_handle ? 0 : callee_parameters,
                                       number_of_frames,
                                       frame_sizes,
                                       frame_pcs,
-                                      return_type);
+                                      return_type,
+                                      exec_mode);
   // On some platforms, we need a way to pass some platform dependent
   // information to the unpacking code so the skeletal frames come out
   // correct (initial fp value, unextended sp, ...)
@@ -747,7 +793,7 @@
 }
 
 
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
 bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS) {
   Handle pending_exception(thread->pending_exception());
   const char* exception_file = thread->exception_file();
@@ -795,89 +841,6 @@
   return failures;
 }
 
-// This assumes that the fields are stored in ObjectValue in the same order
-// they are yielded by do_nonstatic_fields.
-class FieldReassigner: public FieldClosure {
-  frame* _fr;
-  RegisterMap* _reg_map;
-  ObjectValue* _sv;
-  InstanceKlass* _ik;
-  oop _obj;
-
-  int _i;
-public:
-  FieldReassigner(frame* fr, RegisterMap* reg_map, ObjectValue* sv, oop obj) :
-    _fr(fr), _reg_map(reg_map), _sv(sv), _obj(obj), _i(0) {}
-
-  int i() const { return _i; }
-
-
-  void do_field(fieldDescriptor* fd) {
-    intptr_t val;
-    StackValue* value =
-      StackValue::create_stack_value(_fr, _reg_map, _sv->field_at(i()));
-    int offset = fd->offset();
-    switch (fd->field_type()) {
-    case T_OBJECT: case T_ARRAY:
-      assert(value->type() == T_OBJECT, "Agreement.");
-      _obj->obj_field_put(offset, value->get_obj()());
-      break;
-
-    case T_LONG: case T_DOUBLE: {
-      assert(value->type() == T_INT, "Agreement.");
-      StackValue* low =
-        StackValue::create_stack_value(_fr, _reg_map, _sv->field_at(++_i));
-#ifdef _LP64
-      jlong res = (jlong)low->get_int();
-#else
-#ifdef SPARC
-      // For SPARC we have to swap high and low words.
-      jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
-#else
-      jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
-#endif //SPARC
-#endif
-      _obj->long_field_put(offset, res);
-      break;
-    }
-    // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
-    case T_INT: case T_FLOAT: // 4 bytes.
-      assert(value->type() == T_INT, "Agreement.");
-      val = value->get_int();
-      _obj->int_field_put(offset, (jint)*((jint*)&val));
-      break;
-
-    case T_SHORT:
-      assert(value->type() == T_INT, "Agreement.");
-      val = value->get_int();
-      _obj->short_field_put(offset, (jshort)*((jint*)&val));
-      break;
-
-    case T_CHAR:
-      assert(value->type() == T_INT, "Agreement.");
-      val = value->get_int();
-      _obj->char_field_put(offset, (jchar)*((jint*)&val));
-      break;
-
-    case T_BYTE:
-      assert(value->type() == T_INT, "Agreement.");
-      val = value->get_int();
-      _obj->byte_field_put(offset, (jbyte)*((jint*)&val));
-      break;
-
-    case T_BOOLEAN:
-      assert(value->type() == T_INT, "Agreement.");
-      val = value->get_int();
-      _obj->bool_field_put(offset, (jboolean)*((jint*)&val));
-      break;
-
-    default:
-      ShouldNotReachHere();
-    }
-    _i++;
-  }
-};
-
 // restore elements of an eliminated type array
 void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type) {
   int index = 0;
@@ -905,11 +868,43 @@
     }
 
     // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
-    case T_INT: case T_FLOAT: // 4 bytes.
+    case T_INT: case T_FLOAT: { // 4 bytes.
       assert(value->type() == T_INT, "Agreement.");
-      val = value->get_int();
-      obj->int_at_put(index, (jint)*((jint*)&val));
+      bool big_value = false;
+      if (i + 1 < sv->field_size() && type == T_INT) {
+        if (sv->field_at(i)->is_location()) {
+          Location::Type type = ((LocationValue*) sv->field_at(i))->location().type();
+          if (type == Location::dbl || type == Location::lng) {
+            big_value = true;
+          }
+        } else if (sv->field_at(i)->is_constant_int()) {
+          ScopeValue* next_scope_field = sv->field_at(i + 1);
+          if (next_scope_field->is_constant_long() || next_scope_field->is_constant_double()) {
+            big_value = true;
+          }
+        }
+      }
+
+      if (big_value) {
+        StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++i));
+  #ifdef _LP64
+        jlong res = (jlong)low->get_int();
+  #else
+  #ifdef SPARC
+        // For SPARC we have to swap high and low words.
+        jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
+  #else
+        jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
+  #endif //SPARC
+  #endif
+        obj->int_at_put(index, (jint)*((jint*)&res));
+        obj->int_at_put(++index, (jint)*(((jint*)&res) + 1));
+      } else {
+        val = value->get_int();
+        obj->int_at_put(index, (jint)*((jint*)&val));
+      }
       break;
+    }
 
     case T_SHORT:
       assert(value->type() == T_INT, "Agreement.");
@@ -952,9 +947,132 @@
   }
 }
 
+class ReassignedField {
+public:
+  int _offset;
+  BasicType _type;
+public:
+  ReassignedField() {
+    _offset = 0;
+    _type = T_ILLEGAL;
+  }
+};
+
+int compare(ReassignedField* left, ReassignedField* right) {
+  return left->_offset - right->_offset;
+}
+
+// Restore fields of an eliminated instance object using the same field order
+// returned by HotSpotResolvedObjectTypeImpl.getInstanceFields(true)
+static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj, bool skip_internal) {
+  if (klass->superklass() != NULL) {
+    svIndex = reassign_fields_by_klass(klass->superklass(), fr, reg_map, sv, svIndex, obj, skip_internal);
+  }
+
+  GrowableArray<ReassignedField>* fields = new GrowableArray<ReassignedField>();
+  for (AllFieldStream fs(klass); !fs.done(); fs.next()) {
+    if (!fs.access_flags().is_static() && (!skip_internal || !fs.access_flags().is_internal())) {
+      ReassignedField field;
+      field._offset = fs.offset();
+      field._type = FieldType::basic_type(fs.signature());
+      fields->append(field);
+    }
+  }
+  fields->sort(compare);
+  for (int i = 0; i < fields->length(); i++) {
+    intptr_t val;
+    ScopeValue* scope_field = sv->field_at(svIndex);
+    StackValue* value = StackValue::create_stack_value(fr, reg_map, scope_field);
+    int offset = fields->at(i)._offset;
+    BasicType type = fields->at(i)._type;
+    switch (type) {
+      case T_OBJECT: case T_ARRAY:
+        assert(value->type() == T_OBJECT, "Agreement.");
+        obj->obj_field_put(offset, value->get_obj()());
+        break;
+
+      // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
+      case T_INT: case T_FLOAT: { // 4 bytes.
+        assert(value->type() == T_INT, "Agreement.");
+        bool big_value = false;
+        if (i+1 < fields->length() && fields->at(i+1)._type == T_INT) {
+          if (scope_field->is_location()) {
+            Location::Type type = ((LocationValue*) scope_field)->location().type();
+            if (type == Location::dbl || type == Location::lng) {
+              big_value = true;
+            }
+          }
+          if (scope_field->is_constant_int()) {
+            ScopeValue* next_scope_field = sv->field_at(svIndex + 1);
+            if (next_scope_field->is_constant_long() || next_scope_field->is_constant_double()) {
+              big_value = true;
+            }
+          }
+        }
+
+        if (big_value) {
+          i++;
+          assert(i < fields->length(), "second T_INT field needed");
+          assert(fields->at(i)._type == T_INT, "T_INT field needed");
+        } else {
+          val = value->get_int();
+          obj->int_field_put(offset, (jint)*((jint*)&val));
+          break;
+        }
+      }
+        /* no break */
+
+      case T_LONG: case T_DOUBLE: {
+        assert(value->type() == T_INT, "Agreement.");
+        StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++svIndex));
+#ifdef _LP64
+        jlong res = (jlong)low->get_int();
+#else
+#ifdef SPARC
+        // For SPARC we have to swap high and low words.
+        jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
+#else
+        jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
+#endif //SPARC
+#endif
+        obj->long_field_put(offset, res);
+        break;
+      }
+
+    case T_SHORT:
+      assert(value->type() == T_INT, "Agreement.");
+      val = value->get_int();
+      obj->short_field_put(offset, (jshort)*((jint*)&val));
+      break;
+
+    case T_CHAR:
+      assert(value->type() == T_INT, "Agreement.");
+      val = value->get_int();
+      obj->char_field_put(offset, (jchar)*((jint*)&val));
+      break;
+
+    case T_BYTE:
+      assert(value->type() == T_INT, "Agreement.");
+      val = value->get_int();
+      obj->byte_field_put(offset, (jbyte)*((jint*)&val));
+      break;
+
+    case T_BOOLEAN:
+      assert(value->type() == T_INT, "Agreement.");
+      val = value->get_int();
+      obj->bool_field_put(offset, (jboolean)*((jint*)&val));
+      break;
+
+      default:
+        ShouldNotReachHere();
+    }
+    svIndex++;
+  }
+  return svIndex;
+}
 
 // restore fields of all eliminated objects and arrays
-void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
+void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures, bool skip_internal) {
   for (int i = 0; i < objects->length(); i++) {
     ObjectValue* sv = (ObjectValue*) objects->at(i);
     KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()));
@@ -963,11 +1081,13 @@
     if (obj.is_null()) {
       continue;
     }
+    if (PrintDeoptimizationDetails) {
+      tty->print_cr("reassign fields for object of type %s!", k->name()->as_C_string());
+    }
 
     if (k->oop_is_instance()) {
       InstanceKlass* ik = InstanceKlass::cast(k());
-      FieldReassigner reassign(fr, reg_map, sv, obj());
-      ik->do_nonstatic_fields(&reassign);
+      reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal);
     } else if (k->oop_is_typeArray()) {
       TypeArrayKlass* ak = TypeArrayKlass::cast(k());
       reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type());
@@ -1032,13 +1152,13 @@
   }
 }
 #endif
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
 
 vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
   Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, fr.pc(), fr.sp());
 
 #ifndef PRODUCT
-  if (TraceDeoptimization) {
+  if (PrintDeoptimizationDetails) {
     ttyLocker ttyl;
     tty->print("DEOPT PACKING thread " INTPTR_FORMAT " ", thread);
     fr.print_on(tty);
@@ -1083,7 +1203,7 @@
   assert(array->structural_compare(thread, chunk), "just checking");
 
 #ifndef PRODUCT
-  if (TraceDeoptimization) {
+  if (PrintDeoptimizationDetails) {
     ttyLocker ttyl;
     tty->print_cr("     Created vframeArray " INTPTR_FORMAT, array);
   }
@@ -1092,7 +1212,7 @@
   return array;
 }
 
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
 void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) {
   // Reallocation of some scalar replaced objects failed. Record
   // that we need to pop all the interpreter frames for the
@@ -1200,10 +1320,27 @@
 }
 
 
-void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr) {
+void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr, Deoptimization::DeoptReason reason) {
   assert(fr.can_be_deoptimized(), "checking frame type");
 
-  gather_statistics(Reason_constraint, Action_none, Bytecodes::_illegal);
+  gather_statistics(reason, Action_none, Bytecodes::_illegal);
+
+  if (LogCompilation && xtty != NULL) {
+    nmethod* nm = fr.cb()->as_nmethod_or_null();
+    assert(nm != NULL, "only nmethods can deopt");
+
+    ttyLocker ttyl;
+    xtty->begin_head("deoptimized thread='" UINTX_FORMAT "' pc='" UINTX_FORMAT "'", thread->osthread()->thread_id(), fr.pc());
+    nm->log_identity(xtty);
+    xtty->end_head();
+    for (ScopeDesc* sd = nm->scope_desc_at(fr.pc()); ; sd = sd->sender()) {
+      xtty->begin_elem("jvms bci='%d'", sd->bci());
+      xtty->method(sd->method());
+      xtty->end_elem();
+      if (sd->is_top())  break;
+    }
+    xtty->tail("deoptimized");
+  }
 
   // Patch the nmethod so that when execution returns to it we will
   // deopt the execution state and return to the interpreter.
@@ -1211,6 +1348,10 @@
 }
 
 void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map) {
+  deoptimize(thread, fr, map, Reason_constraint);
+}
+
+void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map, DeoptReason reason) {
   // Deoptimize only if the frame comes from compile code.
   // Do not deoptimize the frame which is already patched
   // during the execution of the loops below.
@@ -1222,12 +1363,12 @@
   if (UseBiasedLocking) {
     revoke_biases_of_monitors(thread, fr, map);
   }
-  deoptimize_single_frame(thread, fr);
+  deoptimize_single_frame(thread, fr, reason);
 
 }
 
 
-void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id) {
+void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason) {
   assert(thread == Thread::current() || SafepointSynchronize::is_at_safepoint(),
          "can only deoptimize other thread at a safepoint");
   // Compute frame and register map based on thread and sp.
@@ -1236,19 +1377,22 @@
   while (fr.id() != id) {
     fr = fr.sender(&reg_map);
   }
-  deoptimize(thread, fr, &reg_map);
+  deoptimize(thread, fr, &reg_map, reason);
 }
 
 
-void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id) {
+void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id, DeoptReason reason) {
   if (thread == Thread::current()) {
-    Deoptimization::deoptimize_frame_internal(thread, id);
+    Deoptimization::deoptimize_frame_internal(thread, id, reason);
   } else {
-    VM_DeoptimizeFrame deopt(thread, id);
+    VM_DeoptimizeFrame deopt(thread, id, reason);
     VMThread::execute(&deopt);
   }
 }
 
+void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id) {
+  deoptimize_frame(thread, id, Reason_constraint);
+}
 
 // JVMTI PopFrame support
 JRT_LEAF(void, Deoptimization::popframe_preserve_args(JavaThread* thread, int bytes_to_save, void* start_address))
@@ -1258,7 +1402,7 @@
 JRT_END
 
 
-#if defined(COMPILER2) || defined(SHARK)
+#if defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI
 void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS) {
   // in case of an unresolved klass entry, load the class.
   if (constant_pool->tag_at(index).is_unresolved_klass()) {
@@ -1321,7 +1465,12 @@
   thread->inc_in_deopt_handler();
 
   // We need to update the map if we have biased locking.
+#if INCLUDE_JVMCI
+  // JVMCI might need to get an exception from the stack, which in turn requires the register map to be valid
+  RegisterMap reg_map(thread, true);
+#else
   RegisterMap reg_map(thread, UseBiasedLocking);
+#endif
   frame stub_frame = thread->last_frame();
   frame fr = stub_frame.sender(&reg_map);
   // Make sure the calling nmethod is not getting deoptimized and removed
@@ -1329,8 +1478,8 @@
   nmethodLocker nl(fr.pc());
 
   // Log a message
-  Events::log(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT,
-              trap_request, fr.pc());
+  Events::log(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT " relative=" INTPTR_FORMAT,
+              trap_request, fr.pc(), fr.pc() - fr.cb()->code_begin());
 
   {
     ResourceMark rm;
@@ -1340,6 +1489,9 @@
 
     DeoptReason reason = trap_request_reason(trap_request);
     DeoptAction action = trap_request_action(trap_request);
+#if INCLUDE_JVMCI
+    int debug_id = trap_request_debug_id(trap_request);
+#endif
     jint unloaded_class_index = trap_request_index(trap_request); // CP idx or -1
 
     vframe*  vf  = vframe::new_vframe(&fr, &reg_map, thread);
@@ -1348,8 +1500,58 @@
     nmethod* nm = cvf->code();
 
     ScopeDesc*      trap_scope  = cvf->scope();
+    
+    if (TraceDeoptimization) {
+      ttyLocker ttyl;
+      tty->print_cr("  bci=%d pc=" INTPTR_FORMAT ", relative_pc=%d, method=%s" JVMCI_ONLY(", debug_id=%d"), trap_scope->bci(), fr.pc(), fr.pc() - nm->code_begin(), trap_scope->method()->name_and_sig_as_C_string()
+#if INCLUDE_JVMCI
+          , debug_id
+#endif
+          );
+    }
+
     methodHandle    trap_method = trap_scope->method();
     int             trap_bci    = trap_scope->bci();
+#if INCLUDE_JVMCI
+    oop speculation = thread->pending_failed_speculation();
+    if (nm->is_compiled_by_jvmci()) {
+      if (speculation != NULL) {
+        oop speculation_log = nm->speculation_log();
+        if (speculation_log != NULL) {
+          if (TraceDeoptimization || TraceUncollectedSpeculations) {
+            if (HotSpotSpeculationLog::lastFailed(speculation_log) != NULL) {
+              tty->print_cr("A speculation that was not collected by the compiler is being overwritten");
+            }
+          }
+          if (TraceDeoptimization) {
+            tty->print_cr("Saving speculation to speculation log");
+          }
+          HotSpotSpeculationLog::set_lastFailed(speculation_log, speculation);
+        } else {
+          if (TraceDeoptimization) {
+            tty->print_cr("Speculation present but no speculation log");
+          }
+        }
+        thread->set_pending_failed_speculation(NULL);
+      } else {
+        if (TraceDeoptimization) {
+          tty->print_cr("No speculation");
+        }
+      }
+    } else {
+      assert(speculation == NULL, "There should not be a speculation for method compiled by non-JVMCI compilers");
+    }
+
+    if (trap_bci == SynchronizationEntryBCI) {
+      trap_bci = 0;
+      thread->set_pending_monitorenter(true);
+    }
+
+    if (reason == Deoptimization::Reason_transfer_to_interpreter) {
+      thread->set_pending_transfer_to_interpreter(true);
+    }
+#endif
+
     Bytecodes::Code trap_bc     = trap_method->java_code_at(trap_bci);
 
     // Record this event in the histogram.
@@ -1359,8 +1561,19 @@
     // Need MDO to record RTM code generation state.
     bool create_if_missing = ProfileTraps RTM_OPT_ONLY( || UseRTMLocking );
 
+    methodHandle profiled_method;
+#if INCLUDE_JVMCI
+    if (nm->is_compiled_by_jvmci()) {
+      profiled_method = nm->method();
+    } else {
+      profiled_method = trap_method;
+    }
+#else
+    profiled_method = trap_method;
+#endif
+
     MethodData* trap_mdo =
-      get_method_data(thread, trap_method, create_if_missing);
+      get_method_data(thread, profiled_method, create_if_missing);
 
     // Log a message
     Events::log_deopt_message(thread, "Uncommon trap: reason=%s action=%s pc=" INTPTR_FORMAT " method=%s @ %d",
@@ -1418,12 +1631,33 @@
       if (TraceDeoptimization) {  // make noise on the tty
         tty->print("Uncommon trap occurred in");
         nm->method()->print_short_name(tty);
-        tty->print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d",
+        tty->print(" compiler=%s compile_id=%d", nm->compiler() == NULL ? "" : nm->compiler()->name(), nm->compile_id());
+#if INCLUDE_JVMCI
+        oop installedCode = nm->jvmci_installed_code();
+        if (installedCode != NULL) {
+          oop installedCodeName = NULL;
+          if (installedCode->is_a(InstalledCode::klass())) {
+            installedCodeName = InstalledCode::name(installedCode);
+          }
+          if (installedCodeName != NULL) {
+            tty->print(" (JVMCI: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName));
+          } else {
+            tty->print(" (JVMCI: installed code has no name) ");
+          }
+        } else if (nm->is_compiled_by_jvmci()) {
+          tty->print(" (JVMCI: no installed code) ");
+        }
+#endif
+        tty->print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d" JVMCI_ONLY(" debug_id=%d"),
                    fr.pc(),
                    os::current_thread_id(),
                    trap_reason_name(reason),
                    trap_action_name(action),
-                   unloaded_class_index);
+                   unloaded_class_index
+#if INCLUDE_JVMCI
+                   , debug_id
+#endif
+                   );
         if (class_name != NULL) {
           tty->print(unresolved ? " unresolved class: " : " symbol: ");
           class_name->print_symbol_on(tty);
@@ -1556,11 +1790,14 @@
     bool inc_recompile_count = false;
     ProfileData* pdata = NULL;
     if (ProfileTraps && update_trap_state && trap_mdo != NULL) {
-      assert(trap_mdo == get_method_data(thread, trap_method, false), "sanity");
+      assert(trap_mdo == get_method_data(thread, profiled_method, false), "sanity");
       uint this_trap_count = 0;
       bool maybe_prior_trap = false;
       bool maybe_prior_recompile = false;
-      pdata = query_update_method_data(trap_mdo, trap_bci, reason,
+      pdata = query_update_method_data(trap_mdo, trap_bci, reason, true,
+#if INCLUDE_JVMCI
+                                   nm->is_compiled_by_jvmci() && nm->is_osr_method(),
+#endif
                                    nm->method(),
                                    //outputs:
                                    this_trap_count,
@@ -1706,26 +1943,42 @@
 Deoptimization::query_update_method_data(MethodData* trap_mdo,
                                          int trap_bci,
                                          Deoptimization::DeoptReason reason,
+                                         bool update_total_trap_count,
+#if INCLUDE_JVMCI
+                                         bool is_osr,
+#endif
                                          Method* compiled_method,
                                          //outputs:
                                          uint& ret_this_trap_count,
                                          bool& ret_maybe_prior_trap,
                                          bool& ret_maybe_prior_recompile) {
-  uint prior_trap_count = trap_mdo->trap_count(reason);
-  uint this_trap_count  = trap_mdo->inc_trap_count(reason);
+  bool maybe_prior_trap = false;
+  bool maybe_prior_recompile = false;
+  uint this_trap_count = 0;
+  if (update_total_trap_count) {
+    uint idx = reason;
+#if INCLUDE_JVMCI
+    if (is_osr) {
+      idx += Reason_LIMIT;
+    }
+#endif
+    uint prior_trap_count = trap_mdo->trap_count(idx);
+    this_trap_count  = trap_mdo->inc_trap_count(idx);
 
-  // If the runtime cannot find a place to store trap history,
-  // it is estimated based on the general condition of the method.
-  // If the method has ever been recompiled, or has ever incurred
-  // a trap with the present reason , then this BCI is assumed
-  // (pessimistically) to be the culprit.
-  bool maybe_prior_trap      = (prior_trap_count != 0);
-  bool maybe_prior_recompile = (trap_mdo->decompile_count() != 0);
+    // If the runtime cannot find a place to store trap history,
+    // it is estimated based on the general condition of the method.
+    // If the method has ever been recompiled, or has ever incurred
+    // a trap with the present reason , then this BCI is assumed
+    // (pessimistically) to be the culprit.
+    maybe_prior_trap      = (prior_trap_count != 0);
+    maybe_prior_recompile = (trap_mdo->decompile_count() != 0);
+  }
   ProfileData* pdata = NULL;
 
 
   // For reasons which are recorded per bytecode, we check per-BCI data.
   DeoptReason per_bc_reason = reason_recorded_per_bytecode_if_any(reason);
+  assert(per_bc_reason != Reason_none || update_total_trap_count, "must be");
   if (per_bc_reason != Reason_none) {
     // Find the profile data for this BCI.  If there isn't one,
     // try to allocate one from the MDO's set of spares.
@@ -1778,22 +2031,30 @@
   bool ignore_maybe_prior_trap;
   bool ignore_maybe_prior_recompile;
   assert(!reason_is_speculate(reason), "reason speculate only used by compiler");
+  // JVMCI uses the total counts to determine if deoptimizations are happening too frequently -> do not adjust total counts
+  bool update_total_counts = JVMCI_ONLY(false) NOT_JVMCI(true);
   query_update_method_data(trap_mdo, trap_bci,
                            (DeoptReason)reason,
+                           update_total_counts,
+#if INCLUDE_JVMCI
+                           false,
+#endif
                            NULL,
                            ignore_this_trap_count,
                            ignore_maybe_prior_trap,
                            ignore_maybe_prior_recompile);
 }
 
-Deoptimization::UnrollBlock* Deoptimization::uncommon_trap(JavaThread* thread, jint trap_request) {
-
+Deoptimization::UnrollBlock* Deoptimization::uncommon_trap(JavaThread* thread, jint trap_request, jint exec_mode) {
+  if (TraceDeoptimization) {
+    tty->print("Uncommon trap "); 
+  }
   // Still in Java no safepoints
   {
     // This enters VM and may safepoint
     uncommon_trap_inner(thread, trap_request);
   }
-  return fetch_unroll_info_helper(thread);
+  return fetch_unroll_info_helper(thread, exec_mode);
 }
 
 // Local derived constants.
@@ -1888,16 +2149,16 @@
 //--------------------------------statics--------------------------------------
 Deoptimization::DeoptAction Deoptimization::_unloaded_action
   = Deoptimization::Action_reinterpret;
-const char* Deoptimization::_trap_reason_name[Reason_LIMIT] = {
+const char* Deoptimization::_trap_reason_name[] = {
   // Note:  Keep this in sync. with enum DeoptReason.
   "none",
   "null_check",
-  "null_assert",
+  "null_assert" JVMCI_ONLY("_or_unreached0"),
   "range_check",
   "class_check",
   "array_check",
-  "intrinsic",
-  "bimorphic",
+  "intrinsic" JVMCI_ONLY("_or_type_checked_inlining"),
+  "bimorphic" JVMCI_ONLY("_or_optimized_type_check"),
   "unloaded",
   "uninitialized",
   "unreached",
@@ -1909,9 +2170,16 @@
   "loop_limit_check",
   "speculate_class_check",
   "rtm_state_change",
-  "unstable_if"
+  "unstable_if",
+#if INCLUDE_JVMCI
+  "aliasing",
+  "transfer_to_interpreter",
+  "not_compiled_exception_handler",
+  "unresolved",
+  "jsr_mismatch"
+#endif
 };
-const char* Deoptimization::_trap_action_name[Action_LIMIT] = {
+const char* Deoptimization::_trap_action_name[] = {
   // Note:  Keep this in sync. with enum DeoptAction.
   "none",
   "maybe_recompile",
@@ -1921,6 +2189,9 @@
 };
 
 const char* Deoptimization::trap_reason_name(int reason) {
+  // Check that every reason has a name
+  STATIC_ASSERT(sizeof(_trap_reason_name)/sizeof(const char*) == Reason_LIMIT);
+
   if (reason == Reason_many)  return "many";
   if ((uint)reason < Reason_LIMIT)
     return _trap_reason_name[reason];
@@ -1929,6 +2200,9 @@
   return buf;
 }
 const char* Deoptimization::trap_action_name(int action) {
+  // Check that every action has a name
+  STATIC_ASSERT(sizeof(_trap_action_name)/sizeof(const char*) == Action_LIMIT);
+
   if ((uint)action < Action_LIMIT)
     return _trap_action_name[action];
   static char buf[20];
@@ -1942,13 +2216,24 @@
   jint unloaded_class_index = trap_request_index(trap_request);
   const char* reason = trap_reason_name(trap_request_reason(trap_request));
   const char* action = trap_action_name(trap_request_action(trap_request));
+#if INCLUDE_JVMCI
+  int debug_id = trap_request_debug_id(trap_request);
+#endif
   size_t len;
   if (unloaded_class_index < 0) {
-    len = jio_snprintf(buf, buflen, "reason='%s' action='%s'",
-                       reason, action);
+    len = jio_snprintf(buf, buflen, "reason='%s' action='%s'" JVMCI_ONLY(" debug_id='%d'"),
+                       reason, action
+#if INCLUDE_JVMCI
+                       ,debug_id
+#endif
+                       );
   } else {
-    len = jio_snprintf(buf, buflen, "reason='%s' action='%s' index='%d'",
-                       reason, action, unloaded_class_index);
+    len = jio_snprintf(buf, buflen, "reason='%s' action='%s' index='%d'" JVMCI_ONLY(" debug_id='%d'"),
+                       reason, action, unloaded_class_index
+#if INCLUDE_JVMCI
+                       ,debug_id
+#endif
+                       );
   }
   return buf;
 }
@@ -2043,7 +2328,7 @@
     if (xtty != NULL)  xtty->tail("statistics");
   }
 }
-#else // COMPILER2 || SHARK
+#else // COMPILER2 || SHARK || INCLUDE_JVMCI
 
 
 // Stubs for C1 only system.
@@ -2079,4 +2364,4 @@
   return buf;
 }
 
-#endif // COMPILER2 || SHARK
+#endif // COMPILER2 || SHARK || INCLUDE_JVMCI
--- a/src/share/vm/runtime/deoptimization.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/deoptimization.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -41,7 +41,13 @@
   enum DeoptReason {
     Reason_many = -1,             // indicates presence of several reasons
     Reason_none = 0,              // indicates absence of a relevant deopt.
-    // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits
+    // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits.
+    // This is more complicated for JVMCI as JVMCI may deoptimize to *some* bytecode before the
+    // bytecode that actually caused the deopt (with inlining, JVMCI may even deoptimize to a
+    // bytecode in another method):
+    //  - bytecode y in method b() causes deopt
+    //  - JVMCI deoptimizes to bytecode x in method a()
+    // -> the deopt reason will be recorded for method a() at bytecode x
     Reason_null_check,            // saw unexpected null or zero divisor (@bci)
     Reason_null_assert,           // saw unexpected non-null or non-zero (@bci)
     Reason_range_check,           // saw unexpected array index (@bci)
@@ -50,6 +56,13 @@
     Reason_intrinsic,             // saw unexpected operand to intrinsic (@bci)
     Reason_bimorphic,             // saw unexpected object class in bimorphic inlining (@bci)
 
+#if INCLUDE_JVMCI
+    Reason_unreached0             = Reason_null_assert,
+    Reason_type_checked_inlining  = Reason_intrinsic,
+    Reason_optimized_type_check   = Reason_bimorphic,
+#endif
+
+    // recorded per method
     Reason_unloaded,              // unloaded class or constant pool entry
     Reason_uninitialized,         // bad class state (uninitialized)
     Reason_unreached,             // code is not reached, compiler
@@ -62,6 +75,13 @@
     Reason_speculate_class_check, // saw unexpected object class from type speculation
     Reason_rtm_state_change,      // rtm state change detected
     Reason_unstable_if,           // a branch predicted always false was taken
+#if INCLUDE_JVMCI
+    Reason_aliasing,              // optimistic assumption about aliasing failed
+    Reason_transfer_to_interpreter, // explicit transferToInterpreter()
+    Reason_not_compiled_exception_handler,
+    Reason_unresolved,
+    Reason_jsr_mismatch,
+#endif
     Reason_LIMIT,
     // Note:  Keep this enum in sync. with _trap_reason_name.
     Reason_RECORDED_LIMIT = Reason_bimorphic  // some are not recorded per bc
@@ -85,8 +105,10 @@
   enum {
     _action_bits = 3,
     _reason_bits = 5,
+    _debug_id_bits = 23,
     _action_shift = 0,
     _reason_shift = _action_shift+_action_bits,
+    _debug_id_shift = _reason_shift+_reason_bits,
     BC_CASE_LIMIT = PRODUCT_ONLY(1) NOT_PRODUCT(4) // for _deoptimization_hist
   };
 
@@ -94,7 +116,8 @@
     Unpack_deopt                = 0, // normal deoptimization, use pc computed in unpack_vframe_on_stack
     Unpack_exception            = 1, // exception is pending
     Unpack_uncommon_trap        = 2, // redo last byte code (C2 only)
-    Unpack_reexecute            = 3  // reexecute bytecode (C1 only)
+    Unpack_reexecute            = 3, // reexecute bytecode (C1 only)
+    Unpack_LIMIT                = 4
   };
 
   // Checks all compiled methods. Invalid methods are deleted and
@@ -103,10 +126,11 @@
 
   // Deoptimizes a frame lazily. nmethod gets patched deopt happens on return to the frame
   static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map);
+  static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map, DeoptReason reason);
 
   private:
   // Does the actual work for deoptimizing a single frame
-  static void deoptimize_single_frame(JavaThread* thread, frame fr);
+  static void deoptimize_single_frame(JavaThread* thread, frame fr, DeoptReason reason);
 
   // Helper function to revoke biases of all monitors in frame if UseBiasedLocking
   // is enabled
@@ -115,16 +139,18 @@
   // executing in a particular CodeBlob if UseBiasedLocking is enabled
   static void revoke_biases_of_monitors(CodeBlob* cb);
 
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
+JVMCI_ONLY(public:)
+
   // Support for restoring non-escaping objects
   static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
   static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
   static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj);
-  static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures);
+  static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures, bool skip_internal);
   static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures);
   static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array);
   NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures);)
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
 
   public:
   static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures);
@@ -134,6 +160,7 @@
   // UnrollBlock is returned by fetch_unroll_info() to the deoptimization handler (blob).
   // This is only a CheapObj to ease debugging after a deopt failure
   class UnrollBlock : public CHeapObj<mtCompiler> {
+    friend class VMStructs;
    private:
     int       _size_of_deoptimized_frame; // Size, in bytes, of current deoptimized frame
     int       _caller_adjustment;         // Adjustment, in bytes, to caller's SP by initial interpreted frame
@@ -146,13 +173,13 @@
     intptr_t  _initial_info;              // Platform dependent data for the sender frame (was FP on x86)
     int       _caller_actual_parameters;  // The number of actual arguments at the
                                           // interpreted caller of the deoptimized frame
+    int       _unpack_kind;               // exec_mode that can be changed during fetch_unroll_info
 
     // The following fields are used as temps during the unpacking phase
     // (which is tight on registers, especially on x86). They really ought
     // to be PD variables but that involves moving this class into its own
     // file to use the pd include mechanism. Maybe in a later cleanup ...
     intptr_t  _counter_temp;              // SHOULD BE PD VARIABLE (x86 frame count temp)
-    intptr_t  _unpack_kind;               // SHOULD BE PD VARIABLE (x86 unpack kind)
     intptr_t  _sender_sp_temp;            // SHOULD BE PD VARIABLE (x86 sender_sp)
    public:
     // Constructor
@@ -162,7 +189,8 @@
                 int  number_of_frames,
                 intptr_t* frame_sizes,
                 address* frames_pcs,
-                BasicType return_type);
+                BasicType return_type,
+                int unpack_kind);
     ~UnrollBlock();
 
     // Returns where a register is located.
@@ -172,6 +200,7 @@
     intptr_t* frame_sizes()  const { return _frame_sizes; }
     int number_of_frames()  const { return _number_of_frames; }
     address*  frame_pcs()   const { return _frame_pcs ; }
+    int  unpack_kind()   const { return _unpack_kind; }
 
     // Returns the total size of frames
     int size_of_frames() const;
@@ -204,7 +233,7 @@
   // deoptimized frame.
   // @argument thread.     Thread where stub_frame resides.
   // @see OptoRuntime::deoptimization_fetch_unroll_info_C
-  static UnrollBlock* fetch_unroll_info(JavaThread* thread);
+  static UnrollBlock* fetch_unroll_info(JavaThread* thread, int exec_mode);
 
   //** Unpacks vframeArray onto execution stack
   // Called by assembly stub after execution has returned to
@@ -229,7 +258,7 @@
 
   //** Performs an uncommon trap for compiled code.
   // The top most compiler frame is converted into interpreter frames
-  static UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index);
+  static UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index, jint exec_mode);
   // Helper routine that enters the VM and may block
   static void uncommon_trap_inner(JavaThread* thread, jint unloaded_class_index);
 
@@ -237,10 +266,11 @@
   // Only called from VMDeoptimizeFrame
   // @argument thread.     Thread where stub_frame resides.
   // @argument id.         id of frame that should be deoptimized.
-  static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id);
+  static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason);
 
   // If thread is not the current thread then execute
   // VM_DeoptimizeFrame otherwise deoptimize directly.
+  static void deoptimize_frame(JavaThread* thread, intptr_t* id, DeoptReason reason);
   static void deoptimize_frame(JavaThread* thread, intptr_t* id);
 
   // Statistics
@@ -270,6 +300,13 @@
       // standard action for unloaded CP entry
       return _unloaded_action;
   }
+  static int trap_request_debug_id(int trap_request) {
+      if (trap_request < 0)
+        return ((~(trap_request) >> _debug_id_shift) & right_n_bits(_debug_id_bits));
+      else
+        // standard action for unloaded CP entry
+        return 0;
+    }
   static int trap_request_index(int trap_request) {
     if (trap_request < 0)
       return -1;
@@ -356,6 +393,10 @@
   static ProfileData* query_update_method_data(MethodData* trap_mdo,
                                                int trap_bci,
                                                DeoptReason reason,
+                                               bool update_total_trap_count,
+#if INCLUDE_JVMCI
+                                               bool is_osr,
+#endif
                                                Method* compiled_method,
                                                //outputs:
                                                uint& ret_this_trap_count,
@@ -365,11 +406,11 @@
   static void load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS);
   static void load_class_by_index(constantPoolHandle constant_pool, int index);
 
-  static UnrollBlock* fetch_unroll_info_helper(JavaThread* thread);
+  static UnrollBlock* fetch_unroll_info_helper(JavaThread* thread, int exec_mode);
 
   static DeoptAction _unloaded_action; // == Action_reinterpret;
-  static const char* _trap_reason_name[Reason_LIMIT];
-  static const char* _trap_action_name[Action_LIMIT];
+  static const char* _trap_reason_name[];
+  static const char* _trap_action_name[];
 
   static juint _deoptimization_hist[Reason_LIMIT][1+Action_LIMIT][BC_CASE_LIMIT];
   // Note:  Histogram array size is 1-2 Kb.
--- a/src/share/vm/runtime/frame.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/frame.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -734,6 +734,12 @@
                   nm->compile_id(), (nm->is_osr_method() ? "%" : ""),
                   ((nm->compiler() != NULL) ? nm->compiler()->name() : ""),
                   buf, m->code_size(), _pc, _cb->code_begin(), _pc - _cb->code_begin());
+#if INCLUDE_JVMCI
+        char* jvmciName = nm->jvmci_installed_code_name(buf, buflen);
+        if (jvmciName != NULL) {
+          st->print(" (%s)", jvmciName);
+        }
+#endif
       } else {
         st->print("J  " PTR_FORMAT, pc());
       }
@@ -1307,7 +1313,9 @@
       // make sure we have the right receiver type
     }
   }
-  COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), "must be empty before verify");)
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  assert(DerivedPointerTable::is_empty(), "must be empty before verify");
+#endif
   oops_do_internal(&VerifyOopClosure::verify_oop, NULL, NULL, (RegisterMap*)map, false);
 }
 
--- a/src/share/vm/runtime/globals.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/globals.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -38,6 +38,9 @@
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci_globals.hpp"
+#endif
 #ifdef COMPILER2
 #include "opto/c2_globals.hpp"
 #endif
@@ -355,6 +358,7 @@
 
   Data data[] = {
       { KIND_C1, "C1" },
+      { KIND_JVMCI, "JVMCI" },
       { KIND_C2, "C2" },
       { KIND_ARCH, "ARCH" },
       { KIND_SHARK, "SHARK" },
@@ -383,7 +387,7 @@
         } else {
           st->print(" ");
         }
-        st->print("%s", d.name);
+        st->print_raw(d.name);
       }
     }
 
@@ -454,6 +458,12 @@
 #define C1_PD_DEVELOP_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
 #define C1_NOTPRODUCT_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_NOT_PRODUCT) },
 
+#define JVMCI_PRODUCT_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_PRODUCT) },
+#define JVMCI_PD_PRODUCT_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) },
+#define JVMCI_DEVELOP_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_DEVELOP) },
+#define JVMCI_PD_DEVELOP_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
+#define JVMCI_NOTPRODUCT_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_JVMCI | Flag::KIND_NOT_PRODUCT) },
+
 #define C2_PRODUCT_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_PRODUCT) },
 #define C2_PD_PRODUCT_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) },
 #define C2_DIAGNOSTIC_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DIAGNOSTIC) },
@@ -484,6 +494,9 @@
 #ifdef COMPILER1
  C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_DIAGNOSTIC_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT)
 #endif
+#if INCLUDE_JVMCI
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_STRUCT, JVMCI_PD_DEVELOP_FLAG_STRUCT, JVMCI_PRODUCT_FLAG_STRUCT, JVMCI_PD_PRODUCT_FLAG_STRUCT, JVMCI_NOTPRODUCT_FLAG_STRUCT)
+#endif
 #ifdef COMPILER2
  C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, C2_PD_DEVELOP_FLAG_STRUCT, C2_PRODUCT_FLAG_STRUCT, C2_PD_PRODUCT_FLAG_STRUCT, C2_DIAGNOSTIC_FLAG_STRUCT, C2_EXPERIMENTAL_FLAG_STRUCT, C2_NOTPRODUCT_FLAG_STRUCT)
 #endif
--- a/src/share/vm/runtime/globals.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/globals.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -129,6 +129,20 @@
 # include "c1_globals_bsd.hpp"
 #endif
 #endif
+#if INCLUDE_JVMCI
+#ifdef TARGET_ARCH_x86
+# include "jvmci_globals_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "jvmci_globals_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "jvmci_globals_arm.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "jvmci_globals_ppc.hpp"
+#endif
+#endif // INCLUDE_JVMCI
 #ifdef COMPILER2
 #ifdef TARGET_ARCH_x86
 # include "c2_globals_x86.hpp"
@@ -164,7 +178,7 @@
 #endif
 #endif
 
-#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
+#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK) && !INCLUDE_JVMCI
 define_pd_global(bool, BackgroundCompilation,        false);
 define_pd_global(bool, UseTLAB,                      false);
 define_pd_global(bool, CICompileOSR,                 false);
@@ -196,7 +210,7 @@
 #define CI_COMPILER_COUNT 0
 #else
 
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
 #define CI_COMPILER_COUNT 2
 #else
 #define CI_COMPILER_COUNT 1
@@ -239,6 +253,7 @@
     KIND_SHARK              = 1 << 15,
     KIND_LP64_PRODUCT       = 1 << 16,
     KIND_COMMERCIAL         = 1 << 17,
+    KIND_JVMCI              = 1 << 18,
 
     KIND_MASK = ~VALUE_ORIGIN_MASK
   };
@@ -980,9 +995,18 @@
   diagnostic(ccstr, PrintAssemblyOptions, NULL,                             \
           "Print options string passed to disassembler.so")                 \
                                                                             \
+  product(bool, PrintNMethodStatistics, false,                              \
+          "Print a summary statistic for the generated nmethods")           \
+                                                                            \
+  product(bool, ShareDebugInfo, IS_JVMCI_DEFINED,                           \
+          "Always tries to share similar debug info inside a nmethod")      \
+                                                                            \
   diagnostic(bool, PrintNMethods, false,                                    \
           "Print assembly code for nmethods when generated")                \
                                                                             \
+  diagnostic(intx, PrintNMethodsAtLevel, -1,                                \
+          "Only print code for nmethods at the given compilation level")    \
+                                                                            \
   diagnostic(bool, PrintNativeNMethods, false,                              \
           "Print assembly code for native nmethods when generated")         \
                                                                             \
@@ -2703,7 +2727,7 @@
                                                                             \
   develop(bool, CompileTheWorld, false,                                     \
           "Compile all methods in all classes in bootstrap class path "     \
-          "(stress test)")                                                  \
+            "(stress test)")                                                \
                                                                             \
   develop(bool, CompileTheWorldPreloadClasses, true,                        \
           "Preload all classes used by a class before start loading")       \
@@ -2948,9 +2972,12 @@
           "Prefetch instruction to prefetch ahead of allocation pointer")   \
                                                                             \
   /* deoptimization */                                                      \
-  develop(bool, TraceDeoptimization, false,                                 \
+  product(bool, TraceDeoptimization, false,                                 \
           "Trace deoptimization")                                           \
                                                                             \
+  product(bool, PrintDeoptimizationDetails, false,                          \
+          "Print more information about deoptimization")                    \
+                                                                            \
   develop(bool, DebugDeoptimization, false,                                 \
           "Tracing various information while debugging deoptimization")     \
                                                                             \
@@ -3106,7 +3133,7 @@
           "If non-zero, maximum number of words that malloc/realloc can "   \
           "allocate (for testing only)")                                    \
                                                                             \
-  product(intx, TypeProfileWidth,     2,                                    \
+  product_pd(intx, TypeProfileWidth,                                        \
           "Number of receiver types to record in call/cast profile")        \
                                                                             \
   develop(intx, BciProfileWidth,      2,                                    \
--- a/src/share/vm/runtime/globals_extension.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/globals_extension.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -57,6 +57,12 @@
 #define C1_PD_DEVELOP_FLAG_MEMBER(type, name, doc)               FLAG_MEMBER(name),
 #define C1_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc)        FLAG_MEMBER(name),
 
+#define JVMCI_PRODUCT_FLAG_MEMBER(type, name, value, doc)           FLAG_MEMBER(name),
+#define JVMCI_PD_PRODUCT_FLAG_MEMBER(type, name, doc)               FLAG_MEMBER(name),
+#define JVMCI_DEVELOP_FLAG_MEMBER(type, name, value, doc)           FLAG_MEMBER(name),
+#define JVMCI_PD_DEVELOP_FLAG_MEMBER(type, name, doc)               FLAG_MEMBER(name),
+#define JVMCI_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc)        FLAG_MEMBER(name),
+
 #define C2_PRODUCT_FLAG_MEMBER(type, name, value, doc)           FLAG_MEMBER(name),
 #define C2_PD_PRODUCT_FLAG_MEMBER(type, name, doc)               FLAG_MEMBER(name),
 #define C2_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc)        FLAG_MEMBER(name),
@@ -80,6 +86,9 @@
 #ifdef COMPILER1
  C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_DIAGNOSTIC_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER)
 #endif
+#if INCLUDE_JVMCI
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_MEMBER, JVMCI_PD_DEVELOP_FLAG_MEMBER, JVMCI_PRODUCT_FLAG_MEMBER, JVMCI_PD_PRODUCT_FLAG_MEMBER, JVMCI_NOTPRODUCT_FLAG_MEMBER)
+#endif
 #ifdef COMPILER2
  C2_FLAGS(C2_DEVELOP_FLAG_MEMBER, C2_PD_DEVELOP_FLAG_MEMBER, C2_PRODUCT_FLAG_MEMBER, C2_PD_PRODUCT_FLAG_MEMBER, C2_DIAGNOSTIC_FLAG_MEMBER, C2_EXPERIMENTAL_FLAG_MEMBER, C2_NOTPRODUCT_FLAG_MEMBER)
 #endif
@@ -109,6 +118,12 @@
 #define C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc)               FLAG_MEMBER_WITH_TYPE(name,type),
 #define C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)        FLAG_MEMBER_WITH_TYPE(name,type),
 
+#define JVMCI_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)           FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc)               FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)           FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc)               FLAG_MEMBER_WITH_TYPE(name,type),
+#define JVMCI_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)        FLAG_MEMBER_WITH_TYPE(name,type),
+
 #ifdef _LP64
 #define RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type),
 #else
@@ -165,6 +180,13 @@
           C1_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
           C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE)
 #endif
+#if INCLUDE_JVMCI
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_MEMBER_WITH_TYPE,
+          JVMCI_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
+          JVMCI_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+          JVMCI_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+          JVMCI_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE)
+#endif
 #ifdef COMPILER2
  C2_FLAGS(C2_DEVELOP_FLAG_MEMBER_WITH_TYPE,
           C2_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
--- a/src/share/vm/runtime/java.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/java.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -30,6 +30,10 @@
 #include "compiler/compileBroker.hpp"
 #include "compiler/compilerOracle.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 #include "memory/genCollectedHeap.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/universe.hpp"
@@ -252,7 +256,6 @@
     Runtime1::print_statistics();
     Deoptimization::print_statistics();
     SharedRuntime::print_statistics();
-    nmethod::print_statistics();
   }
 #endif /* COMPILER1 */
 
@@ -262,7 +265,6 @@
     Compile::print_statistics();
 #ifndef COMPILER1
     Deoptimization::print_statistics();
-    nmethod::print_statistics();
     SharedRuntime::print_statistics();
 #endif //COMPILER1
     os::print_statistics();
@@ -280,7 +282,21 @@
     IndexSet::print_statistics();
   }
 #endif // ASSERT
-#endif // COMPILER2
+#else
+#if INCLUDE_JVMCI
+#ifndef COMPILER1
+  if ((TraceDeoptimization || LogVMOutput || LogCompilation) && UseCompiler) {
+    FlagSetting fs(DisplayVMOutput, DisplayVMOutput && TraceDeoptimization);
+    Deoptimization::print_statistics();
+    SharedRuntime::print_statistics();
+  }
+#endif
+#endif
+#endif
+
+  if (PrintNMethodStatistics) {
+    nmethod::print_statistics();
+  }
   if (CountCompiledCalls) {
     print_method_invocation_histogram();
   }
@@ -392,6 +408,9 @@
   if (PrintBiasedLockingStatistics) {
     BiasedLocking::print_counters();
   }
+  if (PrintNMethodStatistics) {
+    nmethod::print_statistics();
+  }
 
   // Native memory tracking data
   if (PrintNMTStatistics) {
@@ -471,6 +490,19 @@
     }
   }
 
+#if INCLUDE_JVMCI
+  // We are not using CATCH here because we want the exit to continue normally.
+  Thread* THREAD = thread;
+  JVMCIRuntime::shutdown(THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    Handle exception(THREAD, PENDING_EXCEPTION);
+    CLEAR_PENDING_EXCEPTION;
+    java_lang_Throwable::print(exception, tty);
+    tty->cr();
+    java_lang_Throwable::print_stack_trace(exception(), tty);
+  }
+#endif
+
   // The only difference between this and Win32's _onexit procs is that
   // this version is invoked before any threads get killed.
   ExitProc* current = exit_procs;
--- a/src/share/vm/runtime/javaCalls.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/javaCalls.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -40,6 +40,10 @@
 #include "runtime/signature.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 
 // -----------------------------------------------------
 // Implementation of JavaCallWrapper
@@ -50,7 +54,7 @@
 
   guarantee(thread->is_Java_thread(), "crucial check - the VM thread cannot and must not escape to Java code");
   assert(!thread->owns_locks(), "must release all locks when leaving VM");
-  guarantee(!thread->is_Compiler_thread(), "cannot make java calls from the compiler");
+  guarantee(thread->can_call_java(), "cannot make java calls from the native compiler");
   _result   = result;
 
   // Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java_or_stub,
@@ -302,7 +306,7 @@
   // Check if we need to wrap a potential OS exception handler around thread
   // This is used for e.g. Win32 structured exception handlers
   assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls");
-  // Need to wrap each and everytime, since there might be native code down the
+  // Need to wrap each and every time, since there might be native code down the
   // stack that has installed its own exception handlers
   os::os_exception_wrapper(call_helper, result, &method, args, THREAD);
 }
@@ -322,36 +326,38 @@
 
   CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)
 
-  // Verify the arguments
+#if INCLUDE_JVMCI
+  // Gets the nmethod (if any) that should be called instead of normal target
+  nmethod* alternative_target = args->alternative_target();
+  if (alternative_target == NULL) {
+#endif
+// Verify the arguments
 
   if (CheckJNICalls)  {
     args->verify(method, result->get_type(), thread);
   }
   else debug_only(args->verify(method, result->get_type(), thread));
+#if INCLUDE_JVMCI
+  }
+#else
 
   // Ignore call if method is empty
   if (method->is_empty_method()) {
     assert(result->get_type() == T_VOID, "an empty method must return a void value");
     return;
   }
-
+#endif
 
 #ifdef ASSERT
   { InstanceKlass* holder = method->method_holder();
     // A klass might not be initialized since JavaCall's might be used during the executing of
     // the <clinit>. For example, a Thread.start might start executing on an object that is
     // not fully initialized! (bad Java programming style)
-    assert(holder->is_linked(), "rewritting must have taken place");
+    assert(holder->is_linked(), "rewriting must have taken place");
   }
 #endif
 
-
-  assert(!thread->is_Compiler_thread(), "cannot compile from the compiler");
-  if (CompilationPolicy::must_be_compiled(method)) {
-    CompileBroker::compile_method(method, InvocationEntryBci,
-                                  CompilationPolicy::policy()->initial_compile_level(),
-                                  methodHandle(), 0, "must_be_compiled", CHECK);
-  }
+  CompilationPolicy::compile_if_required(method, CHECK);
 
   // Since the call stub sets up like the interpreter we call the from_interpreted_entry
   // so we can go compiled via a i2c. Otherwise initial entry method will always
@@ -390,6 +396,17 @@
     os::bang_stack_shadow_pages();
   }
 
+#if INCLUDE_JVMCI
+  if (alternative_target != NULL) {
+    if (alternative_target->is_alive()) {
+      thread->set_jvmci_alternate_call_target(alternative_target->verified_entry_point());
+      entry_point = method->adapter()->get_i2c_entry();
+    } else {
+      THROW(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException());
+    }
+  }
+#endif
+  
   // do call
   { JavaCallWrapper link(method, receiver, result, CHECK);
     { HandleMark hm(thread);  // HandleMark used by HandleMarkCleaner
--- a/src/share/vm/runtime/javaCalls.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/javaCalls.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -100,6 +100,9 @@
   int         _size;
   int         _max_size;
   bool        _start_at_zero;      // Support late setting of receiver
+#if INCLUDE_JVMCI
+  nmethod*    _alternative_target; // Nmethod that should be called instead of normal target
+#endif
 
   void initialize() {
     // Starts at first element to support set_receiver.
@@ -109,6 +112,7 @@
     _max_size = _default_size;
     _size = 0;
     _start_at_zero = false;
+    JVMCI_ONLY(_alternative_target = NULL;)
   }
 
  public:
@@ -130,11 +134,22 @@
       _max_size = max_size;
       _size = 0;
       _start_at_zero = false;
+      JVMCI_ONLY(_alternative_target = NULL;)
     } else {
       initialize();
     }
   }
 
+#if INCLUDE_JVMCI
+  void set_alternative_target(nmethod* target) {
+    _alternative_target = target;
+  }
+
+  nmethod* alternative_target() {
+    return _alternative_target;
+  }
+#endif
+
   inline void push_oop(Handle h)    { _is_oop[_size] = true;
                                JNITypes::put_obj((oop)h.raw_value(), _value, _size); }
 
--- a/src/share/vm/runtime/mutex.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/mutex.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -283,16 +283,6 @@
   return x & 0x7FFFFFFF ;
 }
 
-static inline jint MarsagliaXOR (jint * const a) {
-  jint x = *a ;
-  if (x == 0) x = UNS(a)|1 ;
-  x ^= x << 6;
-  x ^= ((unsigned)x) >> 21;
-  x ^= x << 7 ;
-  *a = x ;
-  return x & 0x7FFFFFFF ;
-}
-
 static int Stall (int its) {
   static volatile jint rv = 1 ;
   volatile int OnFrame = 0 ;
--- a/src/share/vm/runtime/os.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/os.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -1193,6 +1193,9 @@
         "%/lib/jce.jar:"
         "%/lib/charsets.jar:"
         "%/lib/jfr.jar:"
+#if INCLUDE_JVMCI
+        "%/lib/jvmci-services.jar:"
+#endif
         "%/classes";
     char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep);
     if (sysclasspath == NULL) return false;
--- a/src/share/vm/runtime/os.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/os.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -104,6 +104,10 @@
 class os: AllStatic {
   friend class VMStructs;
   friend class MallocTracker;
+#if INCLUDE_JVMCI
+  friend class Arguments; // need access to format_boot_path
+#endif
+
  public:
   enum { page_sizes_max = 9 }; // Size of _page_sizes array (8 plus a sentinel)
 
--- a/src/share/vm/runtime/rframe.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/rframe.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -152,7 +152,7 @@
 
 void RFrame::print(const char* kind) {
 #ifndef PRODUCT
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
   int cnt = top_method()->interpreter_invocation_count();
 #else
   int cnt = top_method()->invocation_count();
--- a/src/share/vm/runtime/sharedRuntime.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -111,9 +111,10 @@
   _resolve_virtual_call_blob           = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C),       "resolve_virtual_call");
   _resolve_static_call_blob            = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C),        "resolve_static_call");
 
-#ifdef COMPILER2
-  // Vectors are generated only by C2.
-  if (is_wide_vector(MaxVectorSize)) {
+#if defined(COMPILER2) || INCLUDE_JVMCI
+  // Vectors are generated only by C2 and JVMCI.
+  bool support_wide = is_wide_vector(MaxVectorSize);
+  if (support_wide) {
     _polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP);
   }
 #endif // COMPILER2
@@ -487,6 +488,12 @@
   // Reset method handle flag.
   thread->set_is_method_handle_return(false);
 
+#if INCLUDE_JVMCI
+  // JVMCI's ExceptionHandlerStub expects the thread local exception PC to be clear
+  // and other exception handler continuations do not read it
+  thread->set_exception_pc(NULL);
+#endif
+
   // The fastest case first
   CodeBlob* blob = CodeCache::find_blob(return_address);
   nmethod* nm = (blob != NULL) ? blob->as_nmethod_or_null() : NULL;
@@ -639,10 +646,37 @@
 // ret_pc points into caller; we are returning caller's exception handler
 // for given exception
 address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, Handle& exception,
-                                                    bool force_unwind, bool top_frame_only) {
+                                                    bool force_unwind, bool top_frame_only, bool& recursive_exception_occurred) {
   assert(nm != NULL, "must exist");
   ResourceMark rm;
 
+#if INCLUDE_JVMCI
+  if (nm->is_compiled_by_jvmci()) {
+    // lookup exception handler for this pc
+    int catch_pco = ret_pc - nm->code_begin();
+    ExceptionHandlerTable table(nm);
+    HandlerTableEntry *t = table.entry_for(catch_pco, -1, 0);
+    if (t != NULL) {
+      return nm->code_begin() + t->pco();
+    } else {
+      // there is no exception handler for this pc => deoptimize
+      nm->make_not_entrant();
+
+      // Use Deoptimization::deoptimize for all of its side-effects:
+      // revoking biases of monitors, gathering traps statistics, logging...
+      // it also patches the return pc but we do not care about that
+      // since we return a continuation to the deopt_blob below.
+      JavaThread* thread = JavaThread::current();
+      RegisterMap reg_map(thread, UseBiasedLocking);
+      frame runtime_frame = thread->last_frame();
+      frame caller_frame = runtime_frame.sender(&reg_map);
+      Deoptimization::deoptimize(thread, caller_frame, &reg_map, Deoptimization::Reason_not_compiled_exception_handler);
+
+      return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
+    }
+  }
+#endif
+
   ScopeDesc* sd = nm->scope_desc_at(ret_pc);
   // determine handler bci, if any
   EXCEPTION_MARK;
@@ -667,6 +701,7 @@
         // BCI of the exception handler which caused the exception to be
         // thrown (bugs 4307310 and 4546590). Set "exception" reference
         // argument to ensure that the correct exception is thrown (4870175).
+        recursive_exception_occurred = true;
         exception = Handle(THREAD, PENDING_EXCEPTION);
         CLEAR_PENDING_EXCEPTION;
         if (handler_bci >= 0) {
@@ -761,6 +796,15 @@
   throw_and_post_jvmti_exception(thread, exception);
 JRT_END
 
+#if INCLUDE_JVMCI
+address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason) {
+  assert(deopt_reason > Deoptimization::Reason_none && deopt_reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
+  thread->set_jvmci_implicit_exception_pc(pc);
+  thread->set_pending_deoptimization(Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret));
+  return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap());
+}
+#endif
+
 address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
                                                            address pc,
                                                            SharedRuntime::ImplicitExceptionKind exception_kind)
@@ -830,8 +874,8 @@
           if (!cb->is_nmethod()) {
             bool is_in_blob = cb->is_adapter_blob() || cb->is_method_handles_adapter_blob();
             if (!is_in_blob) {
-              cb->print();
-              fatal(err_msg("exception happened outside interpreter, nmethods and vtable stubs at pc " INTPTR_FORMAT, pc));
+              // Allow normal crash reporting to handle this
+              return NULL;
             }
             Events::log_exception(thread, "NullPointerException in code blob at " INTPTR_FORMAT, pc);
             // There is no handler here, so we will simply unwind.
@@ -858,7 +902,18 @@
 #ifndef PRODUCT
           _implicit_null_throws++;
 #endif
+#if INCLUDE_JVMCI
+          if (nm->is_compiled_by_jvmci() && nm->pc_desc_at(pc) != NULL) {
+            // If there's no PcDesc then we'll die way down inside of
+            // deopt instead of just getting normal error reporting,
+            // so only go there if it will succeed.
+            return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check);
+          } else {
+#endif
           target_pc = nm->continuation_for_implicit_exception(pc);
+#if INCLUDE_JVMCI
+          }
+#endif
           // If there's an unexpected fault, target_pc might be NULL,
           // in which case we want to fall through into the normal
           // error handling code.
@@ -874,7 +929,15 @@
 #ifndef PRODUCT
         _implicit_div0_throws++;
 #endif
+#if INCLUDE_JVMCI
+        if (nm->is_compiled_by_jvmci() && nm->pc_desc_at(pc) != NULL) {
+          return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check);
+        } else {
+#endif
         target_pc = nm->continuation_for_implicit_exception(pc);
+#if INCLUDE_JVMCI
+        }
+#endif
         // If there's an unexpected fault, target_pc might be NULL,
         // in which case we want to fall through into the normal
         // error handling code.
@@ -886,11 +949,17 @@
 
     assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind");
 
-    // for AbortVMOnException flag
-    NOT_PRODUCT(Exceptions::debug_check_abort("java.lang.NullPointerException"));
     if (exception_kind == IMPLICIT_NULL) {
+#ifndef PRODUCT
+      // for AbortVMOnException flag
+      Exceptions::debug_check_abort("java.lang.NullPointerException");
+#endif //PRODUCT
       Events::log_exception(thread, "Implicit null exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc);
     } else {
+#ifndef PRODUCT
+      // for AbortVMOnException flag
+      Exceptions::debug_check_abort("java.lang.ArithmeticException");
+#endif //PRODUCT
       Events::log_exception(thread, "Implicit division by zero exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc);
     }
     return target_pc;
@@ -946,6 +1015,16 @@
 
 JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
   assert(obj->is_oop(), "must be a valid oop");
+#if INCLUDE_JVMCI
+  // This removes the requirement for JVMCI compilers to emit code
+  // performing a dynamic check that obj has a finalizer before
+  // calling this routine. There should be no performance impact
+  // for C1 since it emits a dynamic check. C2 and the interpreter
+  // uses other runtime routines for registering finalizers.
+  if (!obj->klass()->has_finalizer()) {
+    return;
+  }
+#endif
   assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
   InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
 JRT_END
--- a/src/share/vm/runtime/sharedRuntime.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -184,7 +184,7 @@
 
   // exception handling and implicit exceptions
   static address compute_compiled_exc_handler(nmethod* nm, address ret_pc, Handle& exception,
-                                              bool force_unwind, bool top_frame_only);
+                                              bool force_unwind, bool top_frame_only, bool& recursive_exception_occurred);
   enum ImplicitExceptionKind {
     IMPLICIT_NULL,
     IMPLICIT_DIVIDE_BY_ZERO,
@@ -199,6 +199,9 @@
   static address continuation_for_implicit_exception(JavaThread* thread,
                                                      address faulting_pc,
                                                      ImplicitExceptionKind exception_kind);
+#if INCLUDE_JVMCI
+  static address deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason);
+#endif
 
   // Shared stub locations
   static address get_poll_stub(address pc);
@@ -349,6 +352,11 @@
   static address clean_opt_virtual_call_entry();
   static address clean_static_call_entry();
 
+#if defined(X86) && defined(COMPILER1)
+  // For Object.hashCode, System.identityHashCode try to pull hashCode from object header if available.
+  static void inline_check_hashcode_from_object_header(MacroAssembler* masm, methodHandle method, Register obj_reg, Register result);
+#endif // X86 && COMPILER1
+
  public:
 
   // Read the array of BasicTypes from a Java signature, and compute where
@@ -422,6 +430,12 @@
                                                       const VMRegPair *regs,
                                                       AdapterFingerPrint* fingerprint);
 
+  static void gen_i2c_adapter(MacroAssembler *_masm,
+                              int total_args_passed,
+                              int comp_args_on_stack,
+                              const BasicType *sig_bt,
+                              const VMRegPair *regs);
+
   // OSR support
 
   // OSR_migration_begin will extract the jvm state from an interpreter
--- a/src/share/vm/runtime/simpleThresholdPolicy.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/simpleThresholdPolicy.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -29,6 +29,9 @@
 #include "runtime/simpleThresholdPolicy.hpp"
 #include "runtime/simpleThresholdPolicy.inline.hpp"
 #include "code/scopeDesc.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 
 
 void SimpleThresholdPolicy::print_counters(const char* prefix, methodHandle mh) {
@@ -168,7 +171,7 @@
 
 // Called with the queue locked and with at least one element
 CompileTask* SimpleThresholdPolicy::select_task(CompileQueue* compile_queue) {
-  return compile_queue->first();
+  return select_task_helper(compile_queue);
 }
 
 void SimpleThresholdPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) {
@@ -340,7 +343,7 @@
 }
 
 // Determine if a method should be compiled with a normal entry point at a different level.
-CompLevel SimpleThresholdPolicy::call_event(Method* method,  CompLevel cur_level) {
+CompLevel SimpleThresholdPolicy::call_event(Method* method,  CompLevel cur_level, JavaThread* thread) {
   CompLevel osr_level = MIN2((CompLevel) method->highest_osr_comp_level(),
                              common(&SimpleThresholdPolicy::loop_predicate, method, cur_level));
   CompLevel next_level = common(&SimpleThresholdPolicy::call_predicate, method, cur_level);
@@ -357,12 +360,16 @@
   } else {
     next_level = MAX2(osr_level, next_level);
   }
-
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler) {
+    next_level = JVMCIRuntime::adjust_comp_level(method, false, next_level, thread);
+  }
+#endif
   return next_level;
 }
 
 // Determine if we should do an OSR compilation of a given method.
-CompLevel SimpleThresholdPolicy::loop_event(Method* method, CompLevel cur_level) {
+CompLevel SimpleThresholdPolicy::loop_event(Method* method, CompLevel cur_level, JavaThread* thread) {
   CompLevel next_level = common(&SimpleThresholdPolicy::loop_predicate, method, cur_level);
   if (cur_level == CompLevel_none) {
     // If there is a live OSR method that means that we deopted to the interpreter
@@ -372,6 +379,11 @@
       return osr_level;
     }
   }
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler) {
+    next_level = JVMCIRuntime::adjust_comp_level(method, true, next_level, thread);
+  }
+#endif
   return next_level;
 }
 
@@ -380,7 +392,7 @@
 void SimpleThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh,
                                               CompLevel level, nmethod* nm, JavaThread* thread) {
   if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) {
-    CompLevel next_level = call_event(mh(), level);
+    CompLevel next_level = call_event(mh(), level, thread);
     if (next_level != level) {
       compile(mh, InvocationEntryBci, next_level, thread);
     }
@@ -396,8 +408,8 @@
     // Use loop event as an opportunity to also check there's been
     // enough calls.
     CompLevel cur_level = comp_level(mh());
-    CompLevel next_level = call_event(mh(), cur_level);
-    CompLevel next_osr_level = loop_event(mh(), level);
+    CompLevel next_level = call_event(mh(), cur_level, thread);
+    CompLevel next_osr_level = loop_event(mh(), level, thread);
 
     next_level = MAX2(next_level,
                       next_osr_level < CompLevel_full_optimization ? next_osr_level : cur_level);
--- a/src/share/vm/runtime/simpleThresholdPolicy.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/simpleThresholdPolicy.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -51,10 +51,10 @@
   // Transition functions.
   // call_event determines if a method should be compiled at a different
   // level with a regular invocation entry.
-  CompLevel call_event(Method* method, CompLevel cur_level);
+  CompLevel call_event(Method* method, CompLevel cur_level, JavaThread* thread);
   // loop_event checks if a method should be OSR compiled at a different
   // level.
-  CompLevel loop_event(Method* method, CompLevel cur_level);
+  CompLevel loop_event(Method* method, CompLevel cur_level, JavaThread* thread);
   void print_counters(const char* prefix, methodHandle mh);
 protected:
   int c1_count() const     { return _c1_count; }
--- a/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -58,6 +58,14 @@
       method->is_constant_getter()) {
     return true;
   }
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler) {
+    if (TieredCompilation && CompileBroker::compiler(CompLevel_full_optimization) != NULL &&
+        CompileBroker::compiler(CompLevel_full_optimization)->is_trivial(method)) {
+      return true;
+    }
+  }
+#endif
   if (method->has_loops() || method->code_size() >= 15) {
     return false;
   }
--- a/src/share/vm/runtime/sweeper.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/sweeper.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -241,7 +241,7 @@
 void NMethodSweeper::possibly_sweep() {
   assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
   // Only compiler threads are allowed to sweep
-  if (!MethodFlushing || !sweep_in_progress() || !Thread::current()->is_Compiler_thread()) {
+  if (!MethodFlushing || !sweep_in_progress() NOT_JVMCI(|| !Thread::current()->is_Compiler_thread()) JVMCI_ONLY(|| !Thread::current()->is_Java_thread())) {
     return;
   }
 
@@ -458,10 +458,18 @@
 
 class NMethodMarker: public StackObj {
  private:
+#if INCLUDE_JVMCI
+  JavaThread* _thread;
+#else
   CompilerThread* _thread;
+#endif
  public:
   NMethodMarker(nmethod* nm) {
+#if INCLUDE_JVMCI
+    _thread = JavaThread::current();
+#else
     _thread = CompilerThread::current();
+#endif
     if (!nm->is_zombie() && !nm->is_unloaded()) {
       // Only expose live nmethods for scanning
       _thread->set_scanned_nmethod(nm);
--- a/src/share/vm/runtime/thread.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/thread.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -29,6 +29,10 @@
 #include "classfile/vmSymbols.hpp"
 #include "code/scopeDesc.hpp"
 #include "compiler/compileBroker.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "interpreter/oopMapCache.hpp"
@@ -1419,6 +1423,33 @@
 
 // ======= JavaThread ========
 
+#if INCLUDE_JVMCI
+
+jlong* JavaThread::_jvmci_old_thread_counters;
+
+bool jvmci_counters_include(JavaThread* thread) {
+  oop threadObj = thread->threadObj();
+  return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
+}
+
+void JavaThread::collect_counters(typeArrayOop array) {
+  if (JVMCICounterSize > 0) {
+    MutexLocker tl(Threads_lock);
+    for (int i = 0; i < array->length(); i++) {
+      array->long_at_put(i, _jvmci_old_thread_counters[i]);
+    }
+    for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
+      if (jvmci_counters_include(tp)) {
+        for (int i = 0; i < array->length(); i++) {
+          array->long_at_put(i, array->long_at(i) + tp->_jvmci_counters[i]);
+        }
+      }
+    }
+  }
+}
+
+#endif
+
 // A JavaThread is a normal Java thread
 
 void JavaThread::initialize() {
@@ -1451,6 +1482,21 @@
   _in_deopt_handler = 0;
   _doing_unsafe_access = false;
   _stack_guard_state = stack_guard_unused;
+#if INCLUDE_JVMCI
+  _pending_monitorenter = false;
+  _pending_deoptimization = -1;
+  _pending_failed_speculation = NULL;
+  _pending_transfer_to_interpreter = false;
+  _adjusting_comp_level = false;
+  _jvmci._alternate_call_target = NULL;
+  assert(_jvmci._implicit_exception_pc == NULL, "must be");
+  if (JVMCICounterSize > 0) {
+    _jvmci_counters = NEW_C_HEAP_ARRAY(jlong, JVMCICounterSize, mtInternal);
+    memset(_jvmci_counters, 0, sizeof(jlong) * JVMCICounterSize);
+  } else {
+    _jvmci_counters = NULL;
+  }
+#endif
   (void)const_cast<oop&>(_exception_oop = NULL);
   _exception_pc  = 0;
   _exception_handler_pc = 0;
@@ -1469,6 +1515,7 @@
   _do_not_unlock_if_synchronized = false;
   _cached_monitor_info = NULL;
   _parker = Parker::Allocate(this) ;
+  _scanned_nmethod = NULL;
 
 #ifndef PRODUCT
   _jmp_ring_index = 0;
@@ -1630,6 +1677,17 @@
   ThreadSafepointState::destroy(this);
   if (_thread_profiler != NULL) delete _thread_profiler;
   if (_thread_stat != NULL) delete _thread_stat;
+
+#if INCLUDE_JVMCI
+  if (JVMCICounterSize > 0) {
+    if (jvmci_counters_include(this)) {
+      for (int i = 0; i < JVMCICounterSize; i++) {
+        _jvmci_old_thread_counters[i] += _jvmci_counters[i];
+      }
+    }
+    FREE_C_HEAP_ARRAY(jlong, _jvmci_counters, mtInternal);
+  }
+#endif
 }
 
 
@@ -2194,7 +2252,7 @@
 
   // Do not throw asynchronous exceptions against the compiler thread
   // (the compiler thread should not be a Java thread -- fix in 1.4.2)
-  if (is_Compiler_thread()) return;
+  if (!can_call_java()) return;
 
   {
     // Actually throw the Throwable against the target Thread - however
@@ -2674,12 +2732,6 @@
   StackFrameStream fst(this, UseBiasedLocking);
   for(; !fst.is_done(); fst.next()) {
     if (fst.current()->should_be_deoptimized()) {
-      if (LogCompilation && xtty != NULL) {
-        nmethod* nm = fst.current()->cb()->as_nmethod_or_null();
-        xtty->elem("deoptimized thread='" UINTX_FORMAT "' compile_id='%d'",
-                   this->name(), nm != NULL ? nm->compile_id() : -1);
-      }
-
       Deoptimization::deoptimize(this, *fst.current(), fst.register_map());
     }
   }
@@ -2732,6 +2784,8 @@
   // Traverse the GCHandles
   Thread::oops_do(f, cld_f, cf);
 
+  JVMCI_ONLY(f->do_oop((oop*)&_pending_failed_speculation);)
+
   assert( (!has_last_Java_frame() && java_call_counter() == 0) ||
           (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!");
 
@@ -2787,6 +2841,13 @@
   if (jvmti_thread_state() != NULL) {
     jvmti_thread_state()->oops_do(f);
   }
+
+  if (_scanned_nmethod != NULL && cf != NULL) {
+    // Safepoints can occur when the sweeper is scanning an nmethod so
+    // process it here to make sure it isn't unloaded in the middle of
+    // a scan.
+    cf->do_code_blob(_scanned_nmethod);
+  }
 }
 
 void JavaThread::nmethods_do(CodeBlobClosure* cf) {
@@ -3247,6 +3308,12 @@
 #endif
 }
 
+#if INCLUDE_JVMCI
+bool CompilerThread::can_call_java() const {
+  return _compiler != NULL && _compiler->is_jvmci();
+}
+#endif // INCLUDE_JVMCI
+
 void CompilerThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
   JavaThread::oops_do(f, cld_f, cf);
   if (_scanned_nmethod != NULL && cf != NULL) {
@@ -3389,6 +3456,15 @@
   // Initialize global data structures and create system classes in heap
   vm_init_globals();
 
+#if INCLUDE_JVMCI
+  if (JVMCICounterSize > 0) {
+    JavaThread::_jvmci_old_thread_counters = NEW_C_HEAP_ARRAY(jlong, JVMCICounterSize, mtInternal);
+    memset(JavaThread::_jvmci_old_thread_counters, 0, sizeof(jlong) * JVMCICounterSize);
+  } else {
+    JavaThread::_jvmci_old_thread_counters = NULL;
+  }
+#endif
+
   // Attach the main thread to this os thread
   JavaThread* main_thread = new JavaThread();
   main_thread->set_thread_state(_thread_in_vm);
@@ -3634,8 +3710,11 @@
   }
 
   // initialize compiler(s)
-#if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK)
-  CompileBroker::compilation_init();
+#if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI
+  CompileBroker::compilation_init(THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
+  }
 #endif
 
   if (EnableInvokeDynamic) {
@@ -4049,6 +4128,12 @@
 
   delete thread;
 
+#if INCLUDE_JVMCI
+  if (JVMCICounterSize > 0) {
+    FREE_C_HEAP_ARRAY(jlong, JavaThread::_jvmci_old_thread_counters, mtInternal);
+  }
+#endif
+
   // exit_globals() will delete tty
   exit_globals();
 
@@ -4253,7 +4338,7 @@
   {
     MutexLockerEx ml(doLock ? Threads_lock : NULL);
     ALL_JAVA_THREADS(p) {
-      if (p->is_Compiler_thread()) continue;
+      if (!p->can_call_java()) continue;
 
       address pending = (address)p->current_pending_monitor();
       if (pending == monitor) {             // found a match
@@ -4309,7 +4394,7 @@
 // Threads::print_on() is called at safepoint by VM_PrintThreads operation.
 void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format, bool print_concurrent_locks) {
   char buf[32];
-  st->print_cr("%s", os::local_time_string(buf, sizeof(buf)));
+  st->print_raw_cr(os::local_time_string(buf, sizeof(buf)));
 
   st->print_cr("Full thread dump %s (%s %s):",
                 Abstract_VM_Version::vm_name(),
--- a/src/share/vm/runtime/thread.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/thread.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -323,6 +323,9 @@
   virtual bool is_Named_thread() const               { return false; }
   virtual bool is_Worker_thread() const              { return false; }
 
+  // Can this thread make Java upcalls
+  virtual bool can_call_java() const                 { return false; }
+
   // Casts
   virtual WorkerThread* as_Worker_thread() const     { return NULL; }
 
@@ -909,6 +912,48 @@
 
  private:
 
+#if INCLUDE_JVMCI
+  // The _pending_* fields below are used to communicate extra information
+  // from an uncommon trap in JVMCI compiled code to the uncommon trap handler.
+
+  // Communicates the DeoptReason and DeoptAction of the uncommon trap
+  int       _pending_deoptimization;
+
+  // Specifies whether the uncommon trap is to bci 0 of a synchronized method
+  // before the monitor has been acquired.
+  bool      _pending_monitorenter;
+
+  // Specifies if the DeoptReason for the last uncommon trap was Reason_transfer_to_interpreter
+  bool      _pending_transfer_to_interpreter;
+
+  // Guard for re-entrant call to JVMCIRuntime::adjust_comp_level
+  bool      _adjusting_comp_level;
+
+  // An object that JVMCI compiled code can use to further describe and
+  // uniquely identify the  speculative optimization guarded by the uncommon trap
+  oop       _pending_failed_speculation;
+
+  // These fields are mutually exclusive in terms of live ranges.
+  union {
+    // Communicates the pc at which the most recent implicit exception occurred
+    // from the signal handler to a deoptimization stub.
+    address   _implicit_exception_pc;
+
+    // Communicates an alternative call target to an i2c stub from a JavaCall .
+    address   _alternate_call_target;
+  } _jvmci;
+
+  // Support for high precision, thread sensitive counters in JVMCI compiled code.
+  jlong*    _jvmci_counters;
+
+ public:
+  static jlong* _jvmci_old_thread_counters;
+  static void collect_counters(typeArrayOop array);
+ private:
+#endif
+
+  nmethod*      _scanned_nmethod;  // nmethod being scanned by the sweeper
+
   StackGuardState  _stack_guard_state;
 
   // Precompute the limit of the stack as used in stack overflow checks.
@@ -923,6 +968,7 @@
   volatile address _exception_handler_pc;        // PC for handler of exception
   volatile int     _is_method_handle_return;     // true (== 1) if the current exception PC is a MethodHandle call site.
 
+ private:  
   // support for JNI critical regions
   jint    _jni_active_critical;                  // count of entries into JNI critical region
 
@@ -1008,8 +1054,15 @@
 
   void cleanup_failed_attach_current_thread();
 
+  // Track the nmethod currently being scanned by the sweeper
+  void set_scanned_nmethod(nmethod* nm) {
+    assert(_scanned_nmethod == NULL || nm == NULL, "should reset to NULL before writing a new value");
+    _scanned_nmethod = nm;
+  }
+
   // Testers
   virtual bool is_Java_thread() const            { return true;  }
+  virtual bool can_call_java() const             { return true; }
 
   // Thread chain operations
   JavaThread* next() const                       { return _next; }
@@ -1272,6 +1325,20 @@
   MemRegion deferred_card_mark() const           { return _deferred_card_mark; }
   void set_deferred_card_mark(MemRegion mr)      { _deferred_card_mark = mr;   }
 
+#if INCLUDE_JVMCI
+  int  pending_deoptimization() const             { return _pending_deoptimization; }
+  oop  pending_failed_speculation() const         { return _pending_failed_speculation; }
+  bool adjusting_comp_level() const               { return _adjusting_comp_level; }
+  void set_adjusting_comp_level(bool b)           { _adjusting_comp_level = b; }
+  bool has_pending_monitorenter() const           { return _pending_monitorenter; }
+  void set_pending_monitorenter(bool b)           { _pending_monitorenter = b; }
+  void set_pending_deoptimization(int reason)     { _pending_deoptimization = reason; }
+  void set_pending_failed_speculation(oop failed_speculation) { _pending_failed_speculation = failed_speculation; }
+  void set_pending_transfer_to_interpreter(bool b) { _pending_transfer_to_interpreter = b; }
+  void set_jvmci_alternate_call_target(address a) { assert(_jvmci._alternate_call_target == NULL, "must be"); _jvmci._alternate_call_target = a; }
+  void set_jvmci_implicit_exception_pc(address a) { assert(_jvmci._implicit_exception_pc == NULL, "must be"); _jvmci._implicit_exception_pc = a; }
+#endif
+
   // Exception handling for compiled methods
   oop      exception_oop() const                 { return _exception_oop; }
   address  exception_pc() const                  { return _exception_pc; }
@@ -1365,6 +1432,14 @@
   static ByteSize thread_state_offset()          { return byte_offset_of(JavaThread, _thread_state        ); }
   static ByteSize saved_exception_pc_offset()    { return byte_offset_of(JavaThread, _saved_exception_pc  ); }
   static ByteSize osthread_offset()              { return byte_offset_of(JavaThread, _osthread            ); }
+#if INCLUDE_JVMCI
+  static ByteSize pending_deoptimization_offset() { return byte_offset_of(JavaThread, _pending_deoptimization); }
+  static ByteSize pending_monitorenter_offset()  { return byte_offset_of(JavaThread, _pending_monitorenter); }
+  static ByteSize pending_failed_speculation_offset() { return byte_offset_of(JavaThread, _pending_failed_speculation); }
+  static ByteSize jvmci_alternate_call_target_offset() { return byte_offset_of(JavaThread, _jvmci._alternate_call_target); }
+  static ByteSize jvmci_implicit_exception_pc_offset() { return byte_offset_of(JavaThread, _jvmci._implicit_exception_pc); }
+  static ByteSize jvmci_counters_offset()        { return byte_offset_of(JavaThread, _jvmci_counters      ); }
+#endif
   static ByteSize exception_oop_offset()         { return byte_offset_of(JavaThread, _exception_oop       ); }
   static ByteSize exception_pc_offset()          { return byte_offset_of(JavaThread, _exception_pc        ); }
   static ByteSize exception_handler_pc_offset()  { return byte_offset_of(JavaThread, _exception_handler_pc); }
@@ -1841,8 +1916,15 @@
   CompilerThread(CompileQueue* queue, CompilerCounters* counters);
 
   bool is_Compiler_thread() const                { return true; }
-  // Hide this compiler thread from external view.
-  bool is_hidden_from_external_view() const      { return true; }
+
+#if INCLUDE_JVMCI
+  virtual bool can_call_java() const;
+#else
+  virtual bool can_call_java() const             { return false; }
+#endif
+
+  // Hide native compiler threads from external view.
+  bool is_hidden_from_external_view() const      { return !can_call_java(); }
 
   void set_compiler(AbstractCompiler* c)         { _compiler = c; }
   AbstractCompiler* compiler() const             { return _compiler; }
--- a/src/share/vm/runtime/timer.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/timer.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -48,6 +48,22 @@
   return counter/freq;
 }
 
+elapsedTimer::elapsedTimer(jlong time, jlong timeUnitsPerSecond) {
+  _active = false;
+  jlong osTimeUnitsPerSecond = os::elapsed_frequency();
+  assert(osTimeUnitsPerSecond % 1000 == 0, "must be");
+  assert(timeUnitsPerSecond % 1000 == 0, "must be");
+  while (osTimeUnitsPerSecond < timeUnitsPerSecond) {
+    timeUnitsPerSecond /= 1000;
+    time *= 1000;
+  }
+  while (osTimeUnitsPerSecond > timeUnitsPerSecond) {
+    timeUnitsPerSecond *= 1000;
+    time /= 1000;
+  }
+  _counter = time;
+}
+
 void elapsedTimer::add(elapsedTimer t) {
   _counter += t._counter;
 }
--- a/src/share/vm/runtime/timer.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/timer.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -37,6 +37,7 @@
   bool  _active;
  public:
   elapsedTimer()             { _active = false; reset(); }
+  elapsedTimer(jlong time, jlong timeUnitsPerSecond);
   void add(elapsedTimer t);
   void start();
   void stop();
--- a/src/share/vm/runtime/vframe.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vframe.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -366,7 +366,7 @@
 
   InterpreterOopMap oop_mask;
   // oopmap for current bci
-  if (TraceDeoptimization && Verbose) {
+  if ((TraceDeoptimization && Verbose) JVMCI_ONLY( || PrintDeoptimizationDetails)) {
     methodHandle m_h(Thread::current(), method());
     OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
   } else {
--- a/src/share/vm/runtime/vframeArray.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vframeArray.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -293,7 +293,7 @@
 
   _frame.patch_pc(thread, pc);
 
-  assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors");
+  assert (!method()->is_synchronized() || locks > 0 || _removed_monitors || raw_bci() == SynchronizationEntryBCI, "synchronized methods must have monitors");
 
   BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
   for (int index = 0; index < locks; index++) {
@@ -316,6 +316,10 @@
     }
   }
 
+  if (PrintDeoptimizationDetails) {
+    tty->print_cr("Expressions size: %d", expressions()->size());
+  }
+
   // Unpack expression stack
   // If this is an intermediate frame (i.e. not top frame) then this
   // only unpacks the part of the expression stack not used by callee
@@ -328,9 +332,26 @@
     switch(value->type()) {
       case T_INT:
         *addr = value->get_int();
+#ifndef PRODUCT
+        if (PrintDeoptimizationDetails) {
+          tty->print_cr("Reconstructed expression %d (INT): %d", i, (int)(*addr));
+        }
+#endif
         break;
       case T_OBJECT:
         *addr = value->get_int(T_OBJECT);
+#ifndef PRODUCT
+        if (PrintDeoptimizationDetails) {
+          tty->print("Reconstructed expression %d (OBJECT): ", i);
+          oop o = (oop)(address)(*addr);
+          if (o == NULL) {
+            tty->print_cr("NULL");
+          } else {
+            ResourceMark rm;
+            tty->print_raw_cr(o->klass()->name()->as_C_string());
+          }
+        }
+#endif
         break;
       case T_CONFLICT:
         // A dead stack slot.  Initialize to null in case it is an oop.
@@ -349,9 +370,26 @@
     switch(value->type()) {
       case T_INT:
         *addr = value->get_int();
+#ifndef PRODUCT
+        if (PrintDeoptimizationDetails) {
+          tty->print_cr("Reconstructed local %d (INT): %d", i, (int)(*addr));
+        }
+#endif
         break;
       case T_OBJECT:
         *addr = value->get_int(T_OBJECT);
+#ifndef PRODUCT
+        if (PrintDeoptimizationDetails) {
+          tty->print("Reconstructed local %d (OBJECT): ", i);
+          oop o = (oop)(address)(*addr);
+          if (o == NULL) {
+            tty->print_cr("NULL");
+          } else {
+            ResourceMark rm;
+            tty->print_raw_cr(o->klass()->name()->as_C_string());
+          }
+        }
+#endif
         break;
       case T_CONFLICT:
         // A dead location. If it is an oop then we need a NULL to prevent GC from following it
@@ -393,7 +431,7 @@
   }
 
 #ifndef PRODUCT
-  if (TraceDeoptimization && Verbose) {
+  if (PrintDeoptimizationDetails) {
     ttyLocker ttyl;
     tty->print_cr("[%d Interpreted Frame]", ++unpack_counter);
     iframe()->print_on(tty);
--- a/src/share/vm/runtime/vframe_hp.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vframe_hp.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -157,7 +157,7 @@
     deferred =  new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true);
     thread()->set_deferred_locals(deferred);
   }
-  deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id()));
+  deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id(), vframe_id()));
   assert(deferred->top()->id() == fr().id(), "Huh? Must match");
   deferred->top()->set_local_at(index, type, value);
 }
@@ -242,6 +242,7 @@
 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, nmethod* nm)
 : javaVFrame(fr, reg_map, thread) {
   _scope  = NULL;
+  _vframe_id = 0;
   // Compiled method (native stub or Java code)
   // native wrappers have no scope data, it is implied
   if (!nm->is_native_method()) {
@@ -249,9 +250,10 @@
   }
 }
 
-compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope)
+compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id)
 : javaVFrame(fr, reg_map, thread) {
   _scope  = scope;
+  _vframe_id = vframe_id;
   guarantee(_scope != NULL, "scope must be present");
 }
 
@@ -315,14 +317,15 @@
   } else {
     return scope()->is_top()
       ? vframe::sender()
-      : new compiledVFrame(&f, register_map(), thread(), scope()->sender());
+      : new compiledVFrame(&f, register_map(), thread(), scope()->sender(), vframe_id() + 1);
   }
 }
 
-jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id) {
+jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id, int vframe_id) {
   _method = method;
   _bci = bci;
   _id = id;
+  _vframe_id = vframe_id;
   // Alway will need at least one, must be on C heap
   _locals = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariable*> (1, true);
 }
@@ -338,7 +341,11 @@
 bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) {
   if (!vf->is_compiled_frame()) return false;
   compiledVFrame* cvf = (compiledVFrame*)vf;
-  return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci();
+  if (cvf->fr().id() == id() && cvf->vframe_id() == vframe_id()) {
+    assert(cvf->method() == method() && cvf->bci() == bci(), "must agree");
+    return true;
+  }
+  return false;
 }
 
 void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) {
--- a/src/share/vm/runtime/vframe_hp.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vframe_hp.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -36,6 +36,7 @@
   StackValueCollection*        locals()             const;
   StackValueCollection*        expressions()        const;
   GrowableArray<MonitorInfo*>* monitors()           const;
+  int                          vframe_id()          const { return _vframe_id; }
 
   void set_locals(StackValueCollection* values) const;
 
@@ -68,14 +69,14 @@
 
  protected:
   ScopeDesc* _scope;
-
+  int _vframe_id;
 
   //StackValue resolve(ScopeValue* sv) const;
   BasicLock* resolve_monitor_lock(Location location) const;
   StackValue *create_stack_value(ScopeValue *sv) const;
 
  private:
-  compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope);
+  compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id);
 
 #ifndef PRODUCT
  public:
@@ -95,6 +96,7 @@
   Method* _method;
   int       _bci;
   intptr_t* _id;
+  int _vframe_id;
   GrowableArray<jvmtiDeferredLocalVariable*>* _locals;
 
  public:
@@ -102,6 +104,7 @@
   Method*                           method()         const  { return _method; }
   int                               bci()            const  { return _bci; }
   intptr_t*                         id()             const  { return _id; }
+  int                               vframe_id()      const  { return _vframe_id; }
   GrowableArray<jvmtiDeferredLocalVariable*>* locals()         const  { return _locals; }
   void                              set_local_at(int idx, BasicType typ, jvalue val);
 
@@ -111,7 +114,7 @@
   void                              oops_do(OopClosure* f);
 
   // constructor
-  jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id);
+  jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id, int vframe_id);
 
   // destructor
   ~jvmtiDeferredLocalVariableSet();
--- a/src/share/vm/runtime/vmStructs.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vmStructs.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -70,6 +70,9 @@
 #include "oops/constMethod.hpp"
 #include "oops/constantPool.hpp"
 #include "oops/cpCache.hpp"
+#if INCLUDE_JVMCI
+#include "oops/fieldStreams.hpp"
+#endif
 #include "oops/instanceClassLoaderKlass.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/instanceMirrorKlass.hpp"
@@ -103,6 +106,10 @@
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/hashtable.hpp"
 #include "utilities/macros.hpp"
+#if INCLUDE_JVMCI
+# include "jvmci/jvmciRuntime.hpp"
+# include "jvmci/vmStructs_jvmci.hpp"
+#endif
 
 #ifdef TARGET_ARCH_x86
 # include "vmStructs_x86.hpp"
@@ -369,6 +376,7 @@
   nonstatic_field(Method,               _vtable_index,                                 int)                                   \
   nonstatic_field(Method,               _method_size,                                  u2)                                    \
   nonstatic_field(Method,               _intrinsic_id,                                 u1)                                    \
+  nonstatic_field(Method,               _flags,                                        u1)                                    \
   nonproduct_nonstatic_field(Method,    _compiled_invocation_count,                    int)                                   \
   volatile_nonstatic_field(Method,      _code,                                         nmethod*)                              \
   nonstatic_field(Method,               _i2i_entry,                                    address)                               \
@@ -393,6 +401,7 @@
   nonstatic_field(Symbol,                      _identity_hash,                                int)                                   \
   nonstatic_field(Symbol,                      _length,                                       unsigned short)                        \
   unchecked_nonstatic_field(Symbol,            _body,                                         sizeof(jbyte)) /* NOTE: no type */     \
+  nonstatic_field(Symbol,                      _body[0],                                      jbyte)                                 \
   nonstatic_field(TypeArrayKlass,              _max_length,                                   int)                                   \
                                                                                                                                      \
   /***********************/                                                                                                          \
@@ -570,6 +579,7 @@
   nonstatic_field(ThreadLocalAllocBuffer,      _start,                                        HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _top,                                          HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _end,                                          HeapWord*)                             \
+  nonstatic_field(ThreadLocalAllocBuffer,      _pf_top,                                       HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _desired_size,                                 size_t)                                \
   nonstatic_field(ThreadLocalAllocBuffer,      _refill_waste_limit,                           size_t)                                \
      static_field(ThreadLocalAllocBuffer,      _target_refills,                               unsigned)                              \
@@ -815,6 +825,34 @@
      static_field(StubRoutines,                _multiplyToLen,                                address)                               \
      static_field(StubRoutines,                _squareToLen,                                  address)                               \
      static_field(StubRoutines,                _mulAdd,                                       address)                               \
+     static_field(StubRoutines,                _jbyte_arraycopy,                              address)                               \
+     static_field(StubRoutines,                _jshort_arraycopy,                             address)                               \
+     static_field(StubRoutines,                _jint_arraycopy,                               address)                               \
+     static_field(StubRoutines,                _jlong_arraycopy,                              address)                               \
+     static_field(StubRoutines,                _oop_arraycopy,                                address)                               \
+     static_field(StubRoutines,                _oop_arraycopy_uninit,                         address)                               \
+     static_field(StubRoutines,                _jbyte_disjoint_arraycopy,                     address)                               \
+     static_field(StubRoutines,                _jshort_disjoint_arraycopy,                    address)                               \
+     static_field(StubRoutines,                _jint_disjoint_arraycopy,                      address)                               \
+     static_field(StubRoutines,                _jlong_disjoint_arraycopy,                     address)                               \
+     static_field(StubRoutines,                _oop_disjoint_arraycopy,                       address)                               \
+     static_field(StubRoutines,                _oop_disjoint_arraycopy_uninit,                address)                               \
+     static_field(StubRoutines,                _arrayof_jbyte_arraycopy,                      address)                               \
+     static_field(StubRoutines,                _arrayof_jshort_arraycopy,                     address)                               \
+     static_field(StubRoutines,                _arrayof_jint_arraycopy,                       address)                               \
+     static_field(StubRoutines,                _arrayof_jlong_arraycopy,                      address)                               \
+     static_field(StubRoutines,                _arrayof_oop_arraycopy,                        address)                               \
+     static_field(StubRoutines,                _arrayof_oop_arraycopy_uninit,                 address)                               \
+     static_field(StubRoutines,                _arrayof_jbyte_disjoint_arraycopy,             address)                               \
+     static_field(StubRoutines,                _arrayof_jshort_disjoint_arraycopy,            address)                               \
+     static_field(StubRoutines,                _arrayof_jint_disjoint_arraycopy,              address)                               \
+     static_field(StubRoutines,                _arrayof_jlong_disjoint_arraycopy,             address)                               \
+     static_field(StubRoutines,                _arrayof_oop_disjoint_arraycopy,               address)                               \
+     static_field(StubRoutines,                _arrayof_oop_disjoint_arraycopy_uninit,        address)                               \
+     static_field(StubRoutines,                _checkcast_arraycopy,                          address)                               \
+     static_field(StubRoutines,                _checkcast_arraycopy_uninit,                   address)                               \
+     static_field(StubRoutines,                _unsafe_arraycopy,                             address)                               \
+     static_field(StubRoutines,                _generic_arraycopy,                            address)                               \
                                                                                                                                      \
   /*****************/                                                                                                                \
   /* SharedRuntime */                                                                                                                \
@@ -882,7 +920,19 @@
   nonstatic_field(nmethod,             _exception_cache,                              ExceptionCache*)                       \
   nonstatic_field(nmethod,             _marked_for_deoptimization,                    bool)                                  \
                                                                                                                              \
-  unchecked_c2_static_field(Deoptimization,         _trap_reason_name,                   void*)                              \
+  unchecked_c2_static_field(Deoptimization, _trap_reason_name,                        void*)                                 \
+                                                                                                                             \
+  nonstatic_field(Deoptimization::UnrollBlock, _size_of_deoptimized_frame,            int)                                   \
+  nonstatic_field(Deoptimization::UnrollBlock, _caller_adjustment,                    int)                                   \
+  nonstatic_field(Deoptimization::UnrollBlock, _number_of_frames,                     int)                                   \
+  nonstatic_field(Deoptimization::UnrollBlock, _total_frame_sizes,                    int)                                   \
+  nonstatic_field(Deoptimization::UnrollBlock, _unpack_kind,                          int)                                   \
+  nonstatic_field(Deoptimization::UnrollBlock, _frame_sizes,                          intptr_t*)                             \
+  nonstatic_field(Deoptimization::UnrollBlock, _frame_pcs,                            address*)                              \
+  nonstatic_field(Deoptimization::UnrollBlock, _register_block,                       intptr_t*)                             \
+  nonstatic_field(Deoptimization::UnrollBlock, _return_type,                          BasicType)                             \
+  nonstatic_field(Deoptimization::UnrollBlock, _initial_info,                         intptr_t)                              \
+  nonstatic_field(Deoptimization::UnrollBlock, _caller_actual_parameters,             int)                                   \
                                                                                                                                      \
   /********************************/                                                                                                 \
   /* JavaCalls (NOTE: incomplete) */                                                                                                 \
@@ -1266,6 +1316,7 @@
   nonstatic_field(CompileTask,                 _osr_bci,                                     int)                                    \
   nonstatic_field(CompileTask,                 _comp_level,                                  int)                                    \
   nonstatic_field(CompileTask,                 _compile_id,                                  uint)                                   \
+  nonstatic_field(CompileTask,                 _num_inlined_bytecodes,                       int)                                    \
   nonstatic_field(CompileTask,                 _next,                                        CompileTask*)                           \
   nonstatic_field(CompileTask,                 _prev,                                        CompileTask*)                           \
                                                                                                                                      \
@@ -1665,6 +1716,7 @@
   declare_toplevel_type(Dependencies)                                     \
   declare_toplevel_type(CompileTask)                                      \
   declare_toplevel_type(Deoptimization)                                   \
+  declare_toplevel_type(Deoptimization::UnrollBlock)                      \
                                                                           \
   /************************/                                              \
   /* OopMap and OopMapSet */                                              \
@@ -2296,6 +2348,36 @@
   declare_constant(JVM_ACC_PROMOTED_FLAGS)                                \
   declare_constant(JVM_ACC_FIELD_ACCESS_WATCHED)                          \
   declare_constant(JVM_ACC_FIELD_MODIFICATION_WATCHED)                    \
+  declare_constant(JVM_ACC_FIELD_INTERNAL)                                \
+  declare_constant(JVM_ACC_FIELD_STABLE)                                  \
+  declare_constant(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE)                   \
+                                                                          \
+  declare_constant(JVM_CONSTANT_Utf8)                                     \
+  declare_constant(JVM_CONSTANT_Unicode)                                  \
+  declare_constant(JVM_CONSTANT_Integer)                                  \
+  declare_constant(JVM_CONSTANT_Float)                                    \
+  declare_constant(JVM_CONSTANT_Long)                                     \
+  declare_constant(JVM_CONSTANT_Double)                                   \
+  declare_constant(JVM_CONSTANT_Class)                                    \
+  declare_constant(JVM_CONSTANT_String)                                   \
+  declare_constant(JVM_CONSTANT_Fieldref)                                 \
+  declare_constant(JVM_CONSTANT_Methodref)                                \
+  declare_constant(JVM_CONSTANT_InterfaceMethodref)                       \
+  declare_constant(JVM_CONSTANT_NameAndType)                              \
+  declare_constant(JVM_CONSTANT_MethodHandle)                             \
+  declare_constant(JVM_CONSTANT_MethodType)                               \
+  declare_constant(JVM_CONSTANT_InvokeDynamic)                            \
+  declare_constant(JVM_CONSTANT_ExternalMax)                              \
+                                                                          \
+  declare_constant(JVM_CONSTANT_Invalid)                                  \
+  declare_constant(JVM_CONSTANT_InternalMin)                              \
+  declare_constant(JVM_CONSTANT_UnresolvedClass)                          \
+  declare_constant(JVM_CONSTANT_ClassIndex)                               \
+  declare_constant(JVM_CONSTANT_StringIndex)                              \
+  declare_constant(JVM_CONSTANT_UnresolvedClassInError)                   \
+  declare_constant(JVM_CONSTANT_MethodHandleInError)                      \
+  declare_constant(JVM_CONSTANT_MethodTypeInError)                        \
+  declare_constant(JVM_CONSTANT_InternalMax)                              \
                                                                           \
   /*****************************/                                         \
   /* Thread::SuspendFlags enum */                                         \
@@ -2326,6 +2408,7 @@
   /******************************/                                        \
                                                                           \
   declare_constant(Klass::_primary_super_limit)                           \
+  declare_constant(Klass::_lh_neutral_value)                              \
   declare_constant(Klass::_lh_instance_slow_path_bit)                     \
   declare_constant(Klass::_lh_log2_element_size_shift)                    \
   declare_constant(Klass::_lh_log2_element_size_mask)                     \
@@ -2341,6 +2424,13 @@
   /* ConstMethod anon-enum */                                             \
   /********************************/                                      \
                                                                           \
+  declare_constant(Method::_jfr_towrite)                                  \
+  declare_constant(Method::_caller_sensitive)                             \
+  declare_constant(Method::_force_inline)                                 \
+  declare_constant(Method::_dont_inline)                                  \
+  declare_constant(Method::_hidden)                                       \
+  declare_constant(Method::nonvirtual_vtable_index)                       \
+                                                                          \
   declare_constant(ConstMethod::_has_linenumber_table)                    \
   declare_constant(ConstMethod::_has_checked_exceptions)                  \
   declare_constant(ConstMethod::_has_localvariable_table)                 \
@@ -2357,6 +2447,20 @@
   /**************/                                                        \
                                                                           \
   declare_constant(DataLayout::cell_size)                                 \
+  declare_constant(DataLayout::no_tag)                                    \
+  declare_constant(DataLayout::bit_data_tag)                              \
+  declare_constant(DataLayout::counter_data_tag)                          \
+  declare_constant(DataLayout::jump_data_tag)                             \
+  declare_constant(DataLayout::receiver_type_data_tag)                    \
+  declare_constant(DataLayout::virtual_call_data_tag)                     \
+  declare_constant(DataLayout::ret_data_tag)                              \
+  declare_constant(DataLayout::branch_data_tag)                           \
+  declare_constant(DataLayout::multi_branch_data_tag)                     \
+  declare_constant(DataLayout::arg_info_data_tag)                         \
+  declare_constant(DataLayout::call_type_data_tag)                        \
+  declare_constant(DataLayout::virtual_call_type_data_tag)                \
+  declare_constant(DataLayout::parameters_type_data_tag)                  \
+  declare_constant(DataLayout::speculative_trap_data_tag)                 \
                                                                           \
   /*************************************/                                 \
   /* InstanceKlass enum                */                                 \
@@ -2410,13 +2514,14 @@
                                                                           \
   declare_constant(Symbol::max_symbol_length)                             \
                                                                           \
-  /*************************************************/                     \
-  /* ConstantPool* layout enum for InvokeDynamic */                     \
-  /*************************************************/                     \
+  /***********************************************/                       \
+  /* ConstantPool* layout enum for InvokeDynamic */                       \
+  /***********************************************/                       \
                                                                           \
-  declare_constant(ConstantPool::_indy_bsm_offset)                 \
-  declare_constant(ConstantPool::_indy_argc_offset)                \
-  declare_constant(ConstantPool::_indy_argv_offset)                \
+  declare_constant(ConstantPool::_indy_bsm_offset)                        \
+  declare_constant(ConstantPool::_indy_argc_offset)                       \
+  declare_constant(ConstantPool::_indy_argv_offset)                       \
+  declare_constant(ConstantPool::CPCACHE_INDEX_TAG)                       \
                                                                           \
   /********************************/                                      \
   /* ConstantPoolCacheEntry enums */                                      \
@@ -2500,6 +2605,18 @@
   declare_constant(Deoptimization::Action_make_not_compilable)            \
   declare_constant(Deoptimization::Action_LIMIT)                          \
                                                                           \
+  declare_constant(Deoptimization::Unpack_deopt)                          \
+  declare_constant(Deoptimization::Unpack_exception)                      \
+  declare_constant(Deoptimization::Unpack_uncommon_trap)                  \
+  declare_constant(Deoptimization::Unpack_reexecute)                      \
+                                                                          \
+  declare_constant(Deoptimization::_action_bits)                          \
+  declare_constant(Deoptimization::_reason_bits)                          \
+  declare_constant(Deoptimization::_debug_id_bits)                        \
+  declare_constant(Deoptimization::_action_shift)                         \
+  declare_constant(Deoptimization::_reason_shift)                         \
+  declare_constant(Deoptimization::_debug_id_shift)                       \
+                                                                          \
   /*********************/                                                 \
   /* Matcher (C2 only) */                                                 \
   /*********************/                                                 \
@@ -2513,6 +2630,18 @@
   declare_constant(InvocationEntryBci)                                    \
   declare_constant(InvalidOSREntryBci)                                    \
                                                                           \
+  /*************/                                                         \
+  /* CompLevel */                                                         \
+  /*************/                                                         \
+                                                                          \
+  declare_constant(CompLevel_any)                                         \
+  declare_constant(CompLevel_all)                                         \
+  declare_constant(CompLevel_none)                                        \
+  declare_constant(CompLevel_simple)                                      \
+  declare_constant(CompLevel_limited_profile)                             \
+  declare_constant(CompLevel_full_profile)                                \
+  declare_constant(CompLevel_full_optimization)                           \
+                                                                          \
   /***************/                                                       \
   /* OopMapValue */                                                       \
   /***************/                                                       \
@@ -2527,7 +2656,6 @@
   declare_constant(OopMapValue::register_mask_in_place)                   \
   declare_constant(OopMapValue::unused_value)                             \
   declare_constant(OopMapValue::oop_value)                                \
-  declare_constant(OopMapValue::value_value)                              \
   declare_constant(OopMapValue::narrowoop_value)                          \
   declare_constant(OopMapValue::callee_saved_value)                       \
   declare_constant(OopMapValue::derived_oop_value)                        \
@@ -2877,6 +3005,23 @@
 # define GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value)
 #endif /* COMPILER1 */
 
+//--------------------------------------------------------------------------------
+// VMAddressEntry macros
+//
+
+#define GENERATE_VM_ADDRESS_ENTRY(name) \
+  { QUOTE(name), (void*) (name) },
+
+#define GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY(name, value) \
+  { name, (void*) (value) },
+
+#define GENERATE_VM_FUNCTION_ENTRY(name) \
+  { QUOTE(name), CAST_FROM_FN_PTR(void*, &(name)) },
+
+// This macro generates the sentinel value indicating the end of the list
+#define GENERATE_VM_ADDRESS_LAST_ENTRY() \
+ { NULL, NULL }
+
 //
 // Instantiation of VMStructEntries, VMTypeEntries and VMIntConstantEntries
 //
@@ -2895,6 +3040,12 @@
              GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY,
              GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY)
 
+#if INCLUDE_JVMCI
+   VM_STRUCTS_JVMCI(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
+                    GENERATE_STATIC_VM_STRUCT_ENTRY,
+                    GENERATE_NONSTATIC_VM_STRUCT_ENTRY)
+#endif
+
 #if INCLUDE_ALL_GCS
   VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
                         GENERATE_STATIC_VM_STRUCT_ENTRY)
@@ -2944,6 +3095,11 @@
            GENERATE_C2_VM_TYPE_ENTRY,
            GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY)
 
+#if INCLUDE_JVMCI
+  VM_TYPES_JVMCI(GENERATE_VM_TYPE_ENTRY,
+                 GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
+#endif
+
 #if INCLUDE_ALL_GCS
   VM_TYPES_PARALLELGC(GENERATE_VM_TYPE_ENTRY,
                       GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
@@ -2991,6 +3147,12 @@
                    GENERATE_C2_VM_INT_CONSTANT_ENTRY,
                    GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
 
+#if INCLUDE_JVMCI
+  VM_INT_CONSTANTS_JVMCI(GENERATE_VM_INT_CONSTANT_ENTRY,
+                         GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
+
+#endif
+
 #if INCLUDE_ALL_GCS
   VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY)
 
@@ -3039,6 +3201,20 @@
   GENERATE_VM_LONG_CONSTANT_LAST_ENTRY()
 };
 
+VMAddressEntry VMStructs::localHotSpotVMAddresses[] = {
+#if INCLUDE_JVMCI
+    VM_ADDRESSES_JVMCI(GENERATE_VM_ADDRESS_ENTRY,
+                 GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY,
+                 GENERATE_VM_FUNCTION_ENTRY)
+
+    VM_ADDRESSES_JVMCI_OS(GENERATE_VM_ADDRESS_ENTRY,
+                 GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY,
+                 GENERATE_VM_FUNCTION_ENTRY)
+#endif
+
+  GENERATE_VM_ADDRESS_LAST_ENTRY()
+};
+
 // This is used both to check the types of referenced fields and, in
 // debug builds, to ensure that all of the field types are present.
 void
@@ -3355,5 +3531,39 @@
       }
     }
   }
+
+  // Check for duplicate entries in structs array
+  for (int i = 0; localHotSpotVMStructs[i].typeName != NULL; i++) {
+    for (int j = i + 1; localHotSpotVMStructs[j].typeName != NULL; j++) {
+      if (strcmp(localHotSpotVMStructs[i].typeName, localHotSpotVMStructs[j].typeName) == 0 &&
+          strcmp(localHotSpotVMStructs[i].fieldName, localHotSpotVMStructs[j].fieldName) == 0) {
+        tty->print_cr("Duplicate entries for '%s::%s'", localHotSpotVMStructs[i].typeName, localHotSpotVMStructs[i].fieldName);
+        assert(false, "Duplicate types in localHotSpotVMStructs array");
+      }
+    }
+  }
 }
 #endif
+
+#if INCLUDE_JVMCI
+int VMStructs::localHotSpotVMStructs_count() {
+  // Ignore sentinel entry at the end
+  return (sizeof(localHotSpotVMStructs) / sizeof(VMStructEntry)) - 1;
+}
+int VMStructs::localHotSpotVMTypes_count() {
+  // Ignore sentinel entry at the end
+  return (sizeof(localHotSpotVMTypes) / sizeof(VMTypeEntry)) - 1;
+}
+int VMStructs::localHotSpotVMIntConstants_count() {
+  // Ignore sentinel entry at the end
+  return (sizeof(localHotSpotVMIntConstants) / sizeof(VMIntConstantEntry)) - 1;
+}
+int VMStructs::localHotSpotVMLongConstants_count() {
+  // Ignore sentinel entry at the end
+  return (sizeof(localHotSpotVMLongConstants) / sizeof(VMLongConstantEntry)) - 1;
+}
+int VMStructs::localHotSpotVMAddresses_count() {
+  // Ignore sentinel entry at the end
+  return (sizeof(localHotSpotVMAddresses) / sizeof(VMAddressEntry)) - 1;
+}
+#endif
--- a/src/share/vm/runtime/vmStructs.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vmStructs.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -95,6 +95,11 @@
   uint64_t value;                  // Value of constant
 } VMLongConstantEntry;
 
+typedef struct {
+  const char* name;                // Name of address (example: "SharedRuntime::register_finalizer")
+  void* value;                     // Value of address
+} VMAddressEntry;
+
 // This class is a friend of most classes, to be able to access
 // private fields
 class VMStructs {
@@ -117,6 +122,11 @@
   // the fact that it has a NULL typeName
   static VMLongConstantEntry localHotSpotVMLongConstants[];
 
+  /**
+   * Table of addresses.
+   */
+  static VMAddressEntry localHotSpotVMAddresses[];
+
   // This is used to run any checking code necessary for validation of
   // the data structure (debug build only)
   static void init();
@@ -126,6 +136,14 @@
   static void test();
 #endif
 
+#if INCLUDE_JVMCI
+  static int localHotSpotVMStructs_count();
+  static int localHotSpotVMTypes_count();
+  static int localHotSpotVMIntConstants_count();
+  static int localHotSpotVMLongConstants_count();
+  static int localHotSpotVMAddresses_count();
+#endif
+
 private:
   // Look up a type in localHotSpotVMTypes using strcmp() (debug build only).
   // Returns 1 if found, 0 if not.
--- a/src/share/vm/runtime/vm_operations.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vm_operations.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -111,14 +111,16 @@
 }
 
 
-VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id) {
+VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason) {
   _thread = thread;
   _id     = id;
+  _reason = reason;
 }
 
 
 void VM_DeoptimizeFrame::doit() {
-  Deoptimization::deoptimize_frame_internal(_thread, _id);
+  assert(_reason > Deoptimization::Reason_none && _reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
+  Deoptimization::deoptimize_frame_internal(_thread, _id, (Deoptimization::DeoptReason)_reason);
 }
 
 
--- a/src/share/vm/runtime/vm_operations.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vm_operations.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -255,7 +255,8 @@
  private:
   JavaThread* _thread;
   intptr_t*   _id;
-  VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id);
+  int _reason;
+  VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason);
 
  public:
   VMOp_Type type() const                         { return VMOp_DeoptimizeFrame; }
--- a/src/share/vm/runtime/vm_version.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/runtime/vm_version.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -114,16 +114,16 @@
   #ifdef TIERED
     #define VMTYPE "Server"
   #else // TIERED
-  #ifdef ZERO
-  #ifdef SHARK
-    #define VMTYPE "Shark"
-  #else // SHARK
-    #define VMTYPE "Zero"
-  #endif // SHARK
-  #else // ZERO
-     #define VMTYPE COMPILER1_PRESENT("Client")   \
-                    COMPILER2_PRESENT("Server")
-  #endif // ZERO
+    #ifdef ZERO
+      #ifdef SHARK
+        #define VMTYPE "Shark"
+      #else // SHARK
+        #define VMTYPE "Zero"
+      #endif // SHARK
+    #else // ZERO
+      #define VMTYPE COMPILER1_PRESENT("Client")   \
+                     COMPILER2_PRESENT("Server")
+    #endif // ZERO
   #endif // TIERED
 #endif
 
--- a/src/share/vm/shark/sharkCacheDecache.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/shark/sharkCacheDecache.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -150,8 +150,10 @@
 
 void SharkDecacher::end_frame() {
   // Record the scope
+  methodHandle null_mh;
   debug_info()->describe_scope(
     pc_offset(),
+    null_mh,
     target(),
     bci(),
     true,
--- a/src/share/vm/shark/sharkCompiler.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/shark/sharkCompiler.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -58,7 +58,7 @@
 }
 
 SharkCompiler::SharkCompiler()
-  : AbstractCompiler() {
+  : AbstractCompiler(shark) {
   // Create the lock to protect the memory manager and execution engine
   _execution_engine_lock = new Monitor(Mutex::leaf, "SharkExecutionEngineLock");
   MutexLocker locker(execution_engine_lock());
--- a/src/share/vm/shark/sharkRuntime.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/shark/sharkRuntime.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -212,8 +212,9 @@
   // Initiate the trap
   thread->set_last_Java_frame();
   Deoptimization::UnrollBlock *urb =
-    Deoptimization::uncommon_trap(thread, trap_request);
+    Deoptimization::uncommon_trap(thread, trap_request, Deoptimization::Unpack_uncommon_trap);
   thread->reset_last_Java_frame();
+  assert(urb->unpack_kind() == Deoptimization::Unpack_uncommon_trap, "expected Unpack_uncommon_trap");
 
   // Pop our dummy frame and the frame being deoptimized
   thread->pop_zero_frame();
--- a/src/share/vm/utilities/exceptions.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/utilities/exceptions.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -85,7 +85,7 @@
 #endif // ASSERT
 
   if (thread->is_VM_thread()
-      || thread->is_Compiler_thread()
+      || !thread->can_call_java()
       || DumpSharedSpaces ) {
     // We do not care what kind of exception we get for the vm-thread or a thread which
     // is compiling.  We just install a dummy exception object
@@ -112,7 +112,7 @@
   }
 
   if (thread->is_VM_thread()
-      || thread->is_Compiler_thread()
+      || !thread->can_call_java()
       || DumpSharedSpaces ) {
     // We do not care what kind of exception we get for the vm-thread or a thread which
     // is compiling.  We just install a dummy exception object
--- a/src/share/vm/utilities/globalDefinitions.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -895,12 +895,12 @@
   CompLevel_simple            = 1,         // C1
   CompLevel_limited_profile   = 2,         // C1, invocation & backedge counters
   CompLevel_full_profile      = 3,         // C1, invocation & backedge counters + mdo
-  CompLevel_full_optimization = 4,         // C2 or Shark
+  CompLevel_full_optimization = 4,         // C2, Shark or JVMCI
 
 #if defined(COMPILER2) || defined(SHARK)
-  CompLevel_highest_tier      = CompLevel_full_optimization,  // pure C2 and tiered
+  CompLevel_highest_tier      = CompLevel_full_optimization,  // pure C2 and tiered or JVMCI and tiered
 #elif defined(COMPILER1)
-  CompLevel_highest_tier      = CompLevel_simple,             // pure C1
+  CompLevel_highest_tier      = CompLevel_simple,             // pure C1 or JVMCI
 #else
   CompLevel_highest_tier      = CompLevel_none,
 #endif
@@ -908,7 +908,7 @@
 #if defined(TIERED)
   CompLevel_initial_compile   = CompLevel_full_profile        // tiered
 #elif defined(COMPILER1)
-  CompLevel_initial_compile   = CompLevel_simple              // pure C1
+  CompLevel_initial_compile   = CompLevel_simple              // pure C1 or JVMCI
 #elif defined(COMPILER2) || defined(SHARK)
   CompLevel_initial_compile   = CompLevel_full_optimization   // pure C2
 #else
--- a/src/share/vm/utilities/growableArray.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/utilities/growableArray.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -372,6 +372,41 @@
   void sort(int f(E*,E*), int stride) {
     qsort(_data, length() / stride, sizeof(E) * stride, (_sort_Fn)f);
   }
+
+  // Binary search and insertion utility.  Search array for element
+  // matching key according to the static compare function.  Insert
+  // that element is not already in the list.  Assumes the list is
+  // already sorted according to compare function.
+  template <int compare(E&, E&)> E insert_sorted(E& key) {
+    bool found;
+    int location = find_sorted<E, compare>(key, found);
+    if (!found) {
+      assert(location <= length(), "out of range");
+      insert_before(location, key);
+    }
+    return at(location);
+  }
+
+  template <typename K, int compare(K&, E&)> int find_sorted(K& key, bool& found) {
+    found = false;
+    int min = 0;
+    int max = length() - 1;
+  
+    while (max >= min) {
+      int mid = (max + min) / 2;
+      E value = at(mid);
+      int diff = compare(key, value);
+      if (diff > 0) {
+        min = mid + 1;
+      } else if (diff < 0) {
+        max = mid - 1;
+      } else {
+        found = true;
+        return mid;
+      }
+    }
+    return min;
+  }
 };
 
 // Global GrowableArray methods (one instance in the library per each 'E' type).
--- a/src/share/vm/utilities/macros.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/utilities/macros.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -164,9 +164,23 @@
 #define INCLUDE_TRACE 1
 #endif // INCLUDE_TRACE
 
+#ifndef INCLUDE_JVMCI
+#define INCLUDE_JVMCI 1
+#endif
+
+#if INCLUDE_JVMCI
+#define JVMCI_ONLY(code) code
+#define NOT_JVMCI(code)
+#define IS_JVMCI_DEFINED true
+#else
+#define JVMCI_ONLY(code)
+#define NOT_JVMCI(code) code
+#define IS_JVMCI_DEFINED false
+#endif // INCLUDE_JVMCI
+
 // COMPILER1 variant
 #ifdef COMPILER1
-#ifdef COMPILER2
+#if defined(COMPILER2)
   #define TIERED
 #endif
 #define COMPILER1_PRESENT(code) code
@@ -183,10 +197,21 @@
 #define NOT_COMPILER2(code) code
 #endif // COMPILER2
 
+// COMPILER2 or JVMCI
+#if defined(COMPILER2) || INCLUDE_JVMCI
+#define COMPILER2_OR_JVMCI 1
+#define COMPILER2_OR_JVMCI_PRESENT(code) code
+#define NOT_COMPILER2_OR_JVMCI(code)
+#else
+#define COMPILER2_OR_JVMCI 0
+#define COMPILER2_OR_JVMCI_PRESENT(code)
+#define NOT_COMPILER2_OR_JVMCI(code) code
+#endif
+
 #ifdef TIERED
 #define TIERED_ONLY(code) code
 #define NOT_TIERED(code)
-#else
+#else // TIERED
 #define TIERED_ONLY(code)
 #define NOT_TIERED(code) code
 #endif // TIERED
--- a/src/share/vm/utilities/top.hpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/utilities/top.hpp	Mon Feb 06 17:18:57 2017 +0100
@@ -42,6 +42,9 @@
 #ifdef COMPILER2
 #include "opto/c2_globals.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci_globals.hpp"
+#endif
 
 // THIS FILE IS INTESIONALLY LEFT EMPTY
 // IT IS USED TO MINIMIZE THE NUMBER OF DEPENDENCIES IN includeDB
--- a/src/share/vm/utilities/vmError.cpp	Mon Dec 05 13:09:39 2016 -0800
+++ b/src/share/vm/utilities/vmError.cpp	Mon Feb 06 17:18:57 2017 +0100
@@ -25,6 +25,7 @@
 #include <fcntl.h>
 #include "precompiled.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/disassembler.hpp"
 #include "gc_interface/collectedHeap.hpp"
 #include "prims/whitebox.hpp"
 #include "runtime/arguments.hpp"
@@ -535,6 +536,31 @@
        st->cr();
      }
 
+  STEP(102, "(printing code blob if possible)")
+
+     if (_verbose && _context) {
+       CodeBlob* cb = CodeCache::find_blob(_pc);
+       if (cb != NULL) {
+         if (Interpreter::contains(_pc)) {
+           // The interpreter CodeBlob is very large so try to print the codelet instead.
+           InterpreterCodelet* codelet = Interpreter::codelet_containing(_pc);
+           if (codelet != NULL) {
+             codelet->print_on(st);
+             Disassembler::decode(codelet->code_begin(), codelet->code_end(), st);
+           }
+         } else {
+           StubCodeDesc* desc = StubCodeDesc::desc_for(_pc);
+           if (desc != NULL) {
+             desc->print_on(st);
+             Disassembler::decode(desc->begin(), desc->end(), st);
+           } else {
+             Disassembler::decode(cb, st);
+             st->cr();
+           }
+         }
+       }
+     }
+
   STEP(105, "(printing register info)")
 
      // decode register contents if possible
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/whitelist_shortunittest.txt	Mon Feb 06 17:18:57 2017 +0100
@@ -0,0 +1,3 @@
+com.oracle.graal.jtt.bytecode.*
+com.oracle.graal.jtt.loop.*
+com.oracle.graal.jtt.except.*