// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
/**
* <p>
* This package assembles proxy classes. You will probably like to keep out from this code:)
* </p>
* <h2>Replacements and modification rules</h2>
* <p>
* During creation of proxy methods, several replacement and modification happens in order to produce valid proxy subclass.
* Here is the list of all such rules.
* </p>
* <h3>Add all constructors [A1]</h3>
* <p>
* Proxy subclass must contain all constructors as target subclass. New constructors simply
* delegates invocation to the super class. All constructor annotations are copied.
* </p>
* <h3>Add the last method in chain [A2]</h3>
* <p>
* Last method in proxy chain is the one that simply delegates the invocation to the target method in super class.
* </p>
* <h3>Add all type annotations [A3]</h3>
* <p>
* Proxy subclass must contain all type annotations as the target one.
* </p>
* <h3>Copy all annotations to the first method in proxy method chain [A4]</h3>
* <p>
* Proxy methods must contain all type annotations as the target one.
* </p>
* <h3>Fix the offset of local variables [F1]</h3>
* <p>
* Offset of all local variables has to be incremented by the <em>size</em> of target method argument list.
* Size of arguments list is the number of 32bit words used by arguments on stack, which means that
* all types has length of 1 word, except <code>Long</code> and <code>Double</code> that weight 2 words
* (or one dword).
* </p>
* <div style="width:100px;float:left; border:1px solid gray; margin-right:10px">
* <pre>
* iconst_1
* istore_1
* </pre>
* </div>
* <div style="width:100px;float:left; border:1px solid gray;">
* <pre>
* iconst_1
* istore_13
* </pre>
* </div>
* <p style="clear:both">
* Here is the order of local variables:</p>
* <ul>
* <li>0 - always 'this'</li>
* <li>arguments (if exist)</li>
* <li>locals (if exist)</li>
* </ul>
* <p>
* Therefore, index 0 is left as it is and offset will not be added to it.
* </p>
* <br style="clear:both;">
* <h3>Replace ProxyTarget.argsCount [R2]</h3>
* <p>
* Call to <code>ProxyTarget.argsCount()</code> has to be replaces with hardcoded arguments count.
* Method call is simply replaces with appropriate load instruction: <code>iload_n</code> where n is in [0. 5];
* <code>bipush n</code> where n is in byte range; or <code>sipush n</code> when n is in integer range.
* </p>
* <br>
* <h3>Replace ProxyTarget.getArgType [R3]</h3>
* <p>
* Call to <code>ProxyTarget.getArgType(int )</code> has to be replaces with hardcoded argument Class, where argument
* index is provided as an argument for <code>ProxyTarget.getArgType(int )</code>.
* Method call is replaced with <code>getClass()</code> call on specified argument. If argument is an primitive
* then method is replaced with reading the <code>TYPE</code> attribute of appropriate wrapper.
* </p>
* <p>
* One caveat: opcode for pushing argument offset to stack is not removed from the bytecode,
* due to performance issues of class creation. Instead, this value is poped from the stack before method call is replaced.
* It is assumed that this value is an integer.
* </p>
* <div style="width:400px;float:left; border:1px solid gray; margin-right:10px">
* <pre>
* iconst_1
* invokestatic package/ProxyTarget.getArgClass
* astore_1
* iconst_2
* invokestatic package/ProxyTarget.getArgClass
* astore_2
* </pre>
* </div>
* <div style="width:400px;float:left; border:1px solid gray;">
* <pre>
* (iconst_1
* pop)
* aload_1
* invokevirtual java/lang/Object.getClass
* astore 13
* (iconst_2
* pop)
* getstatic java/lang/Byte.TYPE
* astore 14
* </pre>
* </div>
* <br style="clear:both;">
* <h3>Replace ProxyTarget.getArg [R4]</h3>
* <p>
* Call to <code>ProxyTarget.getArg(int )</code> has to be replaces with hardcoded argument value, where
* index is provided as an argument for <code>ProxyTarget.getArg(int )</code>.
* If argument is a primitive, its wrapper object will be created.
* </p>
* <div style="width:400px;float:left; border:1px solid gray; margin-right:10px">
* <pre>
* iconst_1
* invokestatic package/ProxyTarget.getArg
* astore_1
* bipush 6
* invokestatic package/ProxyTarget.getArg
* astore_3
* </pre>
* </div>
* <div style="width:400px;float:left; border:1px solid gray;">
* <pre>
* aload_1
* astore_13
* lload 6
* invokestatic java/lang/Long.<init>
* astore 14
* </pre>
* </div>
* <br style="clear:both;">
* <h3>Replace ProxyTarget.setArg [R5]</h3>
* <p>
* Call to <code>ProxyTarget.setArg(Object, int )</code> has to be replaces with hardcoded setting of the argument value,
* where index is provided as an argument for <code>ProxyTarget.setArg(Object, int )</code>.
* If argument is a primitive, its wrapper object must be provided.
* </p>
* <h3>Replace ProxyTarget.createArgsArray [R6]</h3>
* <p>
* Call to <code>ProxyTarget.createArgsArray()</code> has to be replaces with hardcoded creation of an object array,
* where elements are target method arguments. Primitive arguments are wrapped.
* </p>
* <h3>Replace ProxyTarget.invoke [R7]</h3>
* <p>
* Call to <code>ProxyTarget.invokeAndGetResult()</code> has to be replaced with call to super target method. Since target methods
* may have one or more arguments, it is required to push all arguments to the stack prior to call of super target method.
* Note that <code>aload_0</code> is always the first instruction (load <code>this</code>), no matter how many arguments there are.
* </p>
* <div style="width:400px;float:left; border:1px solid gray; margin-right:10px">
* <pre>
* invokestatic package/ProxyTarget.invoke
* </pre>
* </div>
* <div style="width:300px;float:left; border:1px solid gray;">
* <pre>
* aload_0
* aload_1
* iload_2
* ...
* invokespecial package/Target.method
* </pre>
* </div>
* <p>
* Situation here is a bit more complicated since return value must be provided, so the following fixes has to be
* applied, too.
* </p>
* <h3>Fix POP for ProxyTarget.invoke [F3]</h3>
* <p>
* When <code>ProxyTarget.invoke()</code> is invoked without assignment, <code>POP/POP2</code> instruction
* is added afterwards, to remove the value from the stack. For targets that do not return void, this opcode
* has to be fixed, i.e. removed. (Fact is that targets that return void, do not have POP:).
* </p>
* <h3>Fix return value and Fix ASTORE for ProxyTarget.invoke [F4]</h3>
* <p>
* When <code>ProxyTarget.invoke()</code> is invoked with assignment, <code>xSTORE</code> instruction
* is added afterwards, to assign return value to a local variable. Therefore, it has to be loaded again on stack
* before return.
* </p>
* <p>Creates all return values, performs casting for small types.</p>
* <h3>Replace ProxyTarget.getTargetClass [R9]</h3>
* <p>
* Returns the target class.
* </p>
* <h3>Replace ProxyTarget.getTargetMethodName [R10]</h3>
* <p>
* Returns target method name.
* </p>
* <h3>Replace ProxyTarget.getReturnType [R11]</h3>
* <p>
* Returns return type of the target method or <code>null</code> if metod returns void.
* </p>
* <h3>Fix field access [F5]</h3>
* <p>
* Access to advice's fields has to be replaced with access to local fields. In relation with [A5].
* </p>
* <h3>Copy advice's fields to proxy [A5]</h3>
* <p>
* All fields from advice has to be copied to proxy, with proxy index added to the name, to prevent duplicate names.
* </p>
* <h3>Copy and fix advice static constructor [A6/F6]</h3>
* <p>
* Static block of an advice should be copied to the proxy, with fixed field access (see F5).
* </p>
* <h3>Copy and fix advices default constructors [A7/F7]</h3>
* <p>
* Advice's constructor will be copied to regular methods, except first two instructions (calling super constructor) will be
* ignored. Field access will be fixed (see F5).
* </p>
*/
package jodd.proxetta.asm;