/*
* Copyright (c) 2007, 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.
*/
/**
* <h2>Management of Code Dependencies</h2>
* The Management of dependencies from compiled methods to classes, methods and
* other entities where such dependencies may change and result in some
* action (e.g. deoptimization) being applied to a compiled method.
* <h2>Overall Architecture</h2>
* A <i>dependency</i> is a relationship between a {@link com.sun.max.vm.compiler.target.TargetMethod}, that is, the result of a compilation,
* and an assumption that was made by the compiler during the compilation. The assumption may be any invariant
* that can be checked for validity at a future time.
* <p>
* Assumptions are specified by subclasses of {@link com.sun.cri.ci.CiAssumptions.Assumption}. Instances of such classes
* typically contain references to VM objects that, for example, represent methods, i.e., {@link com.sun.cri.ri.RiResolvedMethod}.
* Note that assumptions at this level are generally specified using compiler and VM independent types,
* and are defined in a compiler and VM independent project (package). However, there is nothing that prevents a VM specific assumption
* being defined using VM specific types.
* <p>
* Since an assumption has to be validated any time the global state of the VM changes, for example, a new class
* is loaded, it must persist as long as the associated {@link com.sun.max.vm.compiler.target.TargetMethod}.
* To minimize the amount of storage space occupied by assumptions, and to simplify analysis in a
* concrete VM, validated assumptions are converted to {@link com.sun.max.vm.compiler.deps.Dependencies dependencies}, which
* use a densely encoded form of the concrete VM types using small integers, such as {@link com.sun.max.vm.actor.holder.ClassID}.
* <p>
* All assumptions have an associated <i>context</i> class which identifies the class that
* the assumption affects. For example, the {@link com.sun.cri.ci.CiAssumptions.ConcreteSubtype concrete subtype}
* assumption specifies that a class {@code T} has a single unique subtype {@code U}. In this case,
* {@code T} is defined to be the context class.
* <p>
* The possible set of assumptions and associated dependencies is open-ended. In order to provide for easy extensibility
* while keeping the core of the system independent, the concept of a {@link com.sun.max.vm.compiler.deps.DependencyProcessor} is introduced.
* A {@link com.sun.max.vm.compiler.deps.DependencyProcessor} is responsible for the following:
* <ol>
* <li> the validation of the associated assumption.</li>
* <li> the encoding of the assumption into an efficient packed form</li>
* <li> the processing of the packed form, converting back to an object form for ease of analysis</li>
* <li> supporting the application of a {@link com.sun.max.vm.compiler.deps.DependencyProcessor dependency visitor} for analysis</li>
* <li> providing a string based representation of the dependency for tracing</li>
* </ol>
* <h2>Analysing Dependencies</h2>
* A {@link com.sun.max.vm.compiler.deps.Dependencies.DependencyVisitor visitor pattern} is used to support the analysis of a
* {@link com.sun.max.vm.compiler.deps.Dependencies} instance.
* Recall that each such instance relates to a single {@link com.sun.max.vm.compiler.target.TargetMethod}, may contain dependencies related to
* several context classes and each of these may contain dependencies corresponding to several
* {@linkplain com.sun.max.vm.compiler.deps.DependencyProcessor dependency processors}.
* <p>
* Since the set of {@linkplain com.sun.max.vm.compiler.deps.DependencyProcessor dependency processors} is open ended, and a visitor may want to visit
* the data corresponding to several dependency processors in one visit, implementation class inheritance cannot be used to
* create a specific visitor. Instead, a two-level type structure is used, with interfaces defined in the specific
* {@link com.sun.max.vm.compiler.deps.DependencyProcessor} class that declare the statically typed methods that result from decoding the packed
* form of the dependency. Note that these typically correspond closely to the original {@link com.sun.cri.ci.CiAssumptions.Assumption}
* but with compiler/VM independent types replaced with Maxine specific types. E.g., {@link com.sun.cri.ri.RiResolvedType} replaced with
* {@link com.sun.max.vm.actor.holder.ClassActor}.
* <h3>Dependencies Visitor</h3>
* {@link com.sun.max.vm.compiler.deps.Dependencies.DependencyVisitor} handles the aspects of the iteration that are independent of the
* {@link com.sun.max.vm.compiler.deps.DependencyProcessor dependency processors}.
* See {@link com.sun.max.vm.compiler.deps.Dependencies.DependencyVisitor} for more details.
* <p>
* The data for each {@linkplain com.sun.max.vm.compiler.deps.DependencyProcessor dependency processor} is visited by
* invoking {@link com.sun.max.vm.compiler.deps.Dependencies.DependencyVisitor#visit}
* for each individual dependency. This method is generic since it cannot know anything about the types
* of the data associated with the dependency. The default implementation handles this by calling
* {@link com.sun.max.vm.compiler.deps.DependencyProcessor#match} which returns {@code dependencyVisitor} if the visitor
* implements the {@link com.sun.max.vm.compiler.deps.DependencyProcessor} interface defined by the processor that specifies the types of the data in the dependency,
* or {@code null} if not. It then invokes {@link com.sun.max.vm.compiler.deps.DependencyProcessor#visit} with this value, which invokes the
* typed method in the interface if the value is non-null, and steps the index to the next dependency. Defining {@link com.sun.max.vm.compiler.deps.DependencyProcessor#visit}
* this way allows a different {@link com.sun.max.vm.compiler.deps.DependencyProcessor} to be called by an overriding implementation of
* {@link com.sun.max.vm.compiler.deps.Dependencies.DependencyVisitor#visit}. For example, a visitor that cannot know all the {@linkplain com.sun.max.vm.compiler.deps.DependencyProcessor dependency processors}
* in the system, yet wants to invoke the {@link com.sun.max.vm.compiler.deps.DependencyProcessor.ToStringDependencyProcessorVisitor}.
* <h2>Defining a new Dependency Processor</h2>
* The first step is to define a new subclass of {@link com.sun.cri.ci.CiAssumptions.Assumption}. If, as is typical, the dependency is
* used within the optimizing compiler, then this subclass should be defined by adding it to {@link com.sun.cri.ci.CiAssumptions}.
* <p>
* Next define a subclass of {@link com.sun.max.vm.compiler.deps.DependencyProcessor} that will handle this assumption in Maxine, and place it in the
* {@code com.sun.max.vm.compiler.deps} package. Define a nested interface that extends
* of {@link com.sun.max.vm.compiler.deps.DependencyProcessor} and defines a method with the same arguments as the method in the
* {@link com.sun.cri.ci.CiAssumptions.Assumption} subclass. To support generic tracing of dependencies you should also define
* a subclass of {@link com.sun.max.vm.compiler.deps.DependencyProcessor.ToStringDependencyProcessorVisitor} that implements your interface method(s) and appends appropriate
* tracing data to the {@link java.lang.StringBuilder} variable in {@link com.sun.max.vm.compiler.deps.DependencyProcessor.ToStringDependencyProcessorVisitor}.
* <p>
* Define a {@code static final} instance of the {@link com.sun.max.vm.compiler.deps.DependencyProcessor} subclass, which will cause it to be
* registered with {@link com.sun.max.vm.compiler.deps.DependenciesManager} during boot image generation.
* <p>
* Finally, implement the remaining abstract methods:
* <ul>
* <li>{@link com.sun.max.vm.compiler.deps.DependencyProcessor#match}</li>
* <li>{@link com.sun.max.vm.compiler.deps.DependencyProcessor#getToStringDependencyProcessorVisitor(StringBuilder)}</li>
* <li>{@link com.sun.max.vm.compiler.deps.DependencyProcessor#visit}</li>
* </ul>
* <p>
* The first two have trivial implementations. The {@code visit} method must step over the specific dependency
* data and, if the {@code dependencyProcessorVisitor} is not {@code null}, invoke the associated method,
* with the encoded data transformed into the appropriate argument types. Evidently, if the visitor is {@code null},
* processing related to transforming the encoded data should be avoided.
*
*/
package com.sun.max.vm.compiler.deps;