You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2018/11/29 00:33:48 UTC
[01/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Repository: tapestry-5
Updated Branches:
refs/heads/master cb3b34d4e -> 1c71aec76
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXModuleAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXModuleAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXModuleAdapter.java
deleted file mode 100644
index 39494d0..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXModuleAdapter.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/***
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.xml;
-
-import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.xml.sax.helpers.AttributesImpl;
-
-/**
- * Generate SAX event for a module description.
- *
- * @author Remi Forax
- */
-public final class SAXModuleAdapter extends ModuleVisitor {
-
- private final SAXAdapter sa;
-
- public SAXModuleAdapter(final SAXAdapter sa) {
- super(Opcodes.ASM6);
- this.sa = sa;
- }
-
- @Override
- public void visitMainClass(String mainClass) {
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "name", "name", "", mainClass);
- sa.addElement("main-class", att);
- }
-
- @Override
- public void visitPackage(String packaze) {
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "name", "name", "", packaze);
- sa.addElement("packages", att);
- }
-
- @Override
- public void visitRequire(String module, int access, String version) {
- AttributesImpl att = new AttributesImpl();
- StringBuilder sb = new StringBuilder();
- SAXClassAdapter.appendAccess(access | SAXClassAdapter.ACCESS_MODULE, sb);
- att.addAttribute("", "module", "module", "", module);
- att.addAttribute("", "access", "access", "", sb.toString());
- if (version != null) {
- att.addAttribute("", "access", "access", "", version);
- }
- sa.addElement("requires", att);
- }
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- AttributesImpl att = new AttributesImpl();
- StringBuilder sb = new StringBuilder();
- SAXClassAdapter.appendAccess(access | SAXClassAdapter.ACCESS_MODULE, sb);
- att.addAttribute("", "name", "name", "", packaze);
- att.addAttribute("", "access", "access", "", sb.toString());
- sa.addStart("exports", att);
- if (modules != null && modules.length > 0) {
- for (String to : modules) {
- AttributesImpl atts = new AttributesImpl();
- atts.addAttribute("", "module", "module", "", to);
- sa.addElement("to", atts);
- }
- }
- sa.addEnd("exports");
- }
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- AttributesImpl att = new AttributesImpl();
- StringBuilder sb = new StringBuilder();
- SAXClassAdapter.appendAccess(access | SAXClassAdapter.ACCESS_MODULE, sb);
- att.addAttribute("", "name", "name", "", packaze);
- att.addAttribute("", "access", "access", "", sb.toString());
- sa.addStart("opens", att);
- if (modules != null && modules.length > 0) {
- for (String to : modules) {
- AttributesImpl atts = new AttributesImpl();
- atts.addAttribute("", "module", "module", "", to);
- sa.addElement("to", atts);
- }
- }
- sa.addEnd("opens");
- }
-
- @Override
- public void visitUse(String service) {
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "service", "service", "", service);
- sa.addElement("uses", att);
- }
-
- @Override
- public void visitProvide(String service, String... providers) {
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "service", "service", "", service);
- sa.addStart("provides", att);
- for (String provider : providers) {
- AttributesImpl atts = new AttributesImpl();
- atts.addAttribute("", "provider", "provider", "", provider);
- sa.addElement("with", atts);
- }
- sa.addEnd("provides");
- }
-
- @Override
- public void visitEnd() {
- sa.addEnd("module");
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
deleted file mode 100644
index b2be0d9..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
+++ /dev/null
@@ -1,363 +0,0 @@
-<!--
- ASM XML Adapter
- Copyright (c) 2004-2011, Eugene Kuleshov
- 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.
- 3. Neither the name of the copyright holders nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- THE POSSIBILITY OF SUCH DAMAGE.
--->
-
-<!--
- This DTD must be used to create XML documents to be processed by
- org.objectweb.asm.xml.ASMContentHandler
--->
-
-<!--
- Root element used to aggregate multiple classes into single document.
--->
-<!ELEMENT classes ( class+ )>
-
-<!--
- Root element for a single class.
--->
-<!ELEMENT class ( interfaces, module?, ( field | innerclass | method )*)>
-<!ATTLIST class access CDATA #REQUIRED>
-<!ATTLIST class name CDATA #REQUIRED>
-<!ATTLIST class parent CDATA #REQUIRED>
-<!ATTLIST class major CDATA #REQUIRED>
-<!ATTLIST class minor CDATA #REQUIRED>
-<!ATTLIST class source CDATA #IMPLIED>
-
-<!ELEMENT interfaces ( interface* )>
-<!ELEMENT interface EMPTY>
-<!ATTLIST interface name CDATA #REQUIRED>
-
-<!ELEMENT module ( requires*, exports*, uses*, provides* )>
-<!ELEMENT requires EMPTY>
-<!ATTLIST requires module CDATA #REQUIRED>
-<!ATTLIST requires access CDATA #REQUIRED>
-<!ELEMENT exports ( to* )>
-<!ATTLIST exports name CDATA #REQUIRED>
-<!ELEMENT to EMPTY>
-<!ATTLIST to module CDATA #REQUIRED>
-<!ELEMENT uses EMPTY>
-<!ATTLIST uses service CDATA #REQUIRED>
-<!ELEMENT provides EMPTY>
-<!ATTLIST provides service CDATA #REQUIRED>
-<!ATTLIST provides impl CDATA #REQUIRED>
-
-<!ELEMENT field EMPTY>
-<!ATTLIST field access CDATA #REQUIRED>
-<!ATTLIST field desc CDATA #REQUIRED>
-<!ATTLIST field name CDATA #REQUIRED>
-<!--
- All characters out of interval 0x20 to 0x7f (inclusive) must
- be encoded (\uXXXX) and character '\' must be replaced by "\\"
--->
-<!ATTLIST field value CDATA #IMPLIED>
-
-<!ELEMENT innerclass EMPTY>
-<!ATTLIST innerclass access CDATA #REQUIRED>
-<!ATTLIST innerclass innerName CDATA #IMPLIED>
-<!ATTLIST innerclass name CDATA #REQUIRED>
-<!ATTLIST innerclass outerName CDATA #IMPLIED>
-
-<!--
- Root element for method definition.
--->
-<!ELEMENT method ( exceptions, code? )>
-<!ATTLIST method access CDATA #REQUIRED>
-<!ATTLIST method desc CDATA #REQUIRED>
-<!ATTLIST method name CDATA #REQUIRED>
-
-<!ELEMENT exceptions ( exception* )>
-<!ELEMENT exception EMPTY>
-<!ATTLIST exception name CDATA #REQUIRED>
-
-<!--
- code element contains bytecode instructions and definitions for labels, line numbers, try/catch and max
--->
-<!ELEMENT code (( AALOAD | AASTORE | ACONST_NULL | ALOAD | ANEWARRAY | ARETURN | ARRAYLENGTH | ASTORE | ATHROW | BALOAD | BASTORE | BIPUSH | CALOAD | CASTORE | CHECKCAST | D2F | D2I | D2L | DADD | DALOAD | DASTORE | DCMPG | DCMPL | DCONST_0 | DCONST_1 | DDIV | DLOAD | DMUL | DNEG | DREM | DRETURN | DSTORE | DSUB | DUP | DUP2 | DUP2_X1 | DUP2_X2 | DUP_X1 | DUP_X2 | SWAP | F2D | F2I | F2L | FADD | FALOAD | FASTORE | FCMPG | FCMPL | FCONST_0 | FCONST_1 | FCONST_2 | FDIV | FLOAD | FMUL | FNEG | FREM | FRETURN | FSTORE | FSUB | GETFIELD | GETSTATIC | GOTO | I2B | I2C | I2D | I2F | I2L | I2S | IADD | IALOAD | IAND | IASTORE | ICONST_0 | ICONST_1 | ICONST_2 | ICONST_3 | ICONST_4 | ICONST_5 | ICONST_M1 | IDIV | IFEQ | IFGE | IFGT | IFLE | IFLT | IFNE | IFNONNULL | IFNULL | IF_ACMPEQ | IF_ACMPNE | IF_ICMPEQ | IF_ICMPGE | IF_ICMPGT | IF_ICMPLE | IF_ICMPLT | IF_ICMPNE | IINC | ILOAD | IMUL | INEG | INSTANCEOF | INVOKEINTERFACE | INVOKESPECIAL | INVOKESTATIC | INVOKEVIRTUAL | IOR | IREM | IRETU
RN | ISHL | ISHR | ISTORE | ISUB | IUSHR | IXOR | JSR | L2D | L2F | L2I | LADD | LALOAD | LAND | LASTORE | LCMP | LCONST_0 | LCONST_1 | LDC | LDIV | LLOAD | LMUL | LNEG | LOOKUPSWITCH | LOR | LREM | LRETURN | LSHL | LSHR | LSTORE | LSUB | LUSHR | LXOR | MONITORENTER | MONITOREXIT | MULTIANEWARRAY | NEW | NEWARRAY | NOP | POP | POP2 | PUTFIELD | PUTSTATIC | RET | RETURN | SALOAD | SASTORE | SIPUSH | TABLESWITCH | Label | LineNumber | TryCatch )*, Max)>
-
-<!ELEMENT Label EMPTY>
-<!ATTLIST Label name CDATA #REQUIRED>
-
-<!ELEMENT TryCatch EMPTY>
-<!ATTLIST TryCatch end CDATA #REQUIRED>
-<!ATTLIST TryCatch handler CDATA #REQUIRED>
-<!ATTLIST TryCatch start CDATA #REQUIRED>
-<!ATTLIST TryCatch type CDATA #IMPLIED>
-
-<!ELEMENT LineNumber EMPTY>
-<!ATTLIST LineNumber line CDATA #REQUIRED>
-<!ATTLIST LineNumber start CDATA #REQUIRED>
-
-<!ELEMENT Max EMPTY>
-<!ATTLIST Max maxLocals CDATA #REQUIRED>
-<!ATTLIST Max maxStack CDATA #REQUIRED>
-
-<!ELEMENT AALOAD EMPTY>
-<!ELEMENT AASTORE EMPTY>
-<!ELEMENT ACONST_NULL EMPTY>
-<!ELEMENT ALOAD EMPTY>
-<!ATTLIST ALOAD var CDATA #REQUIRED>
-<!ELEMENT ANEWARRAY EMPTY>
-<!ATTLIST ANEWARRAY desc CDATA #REQUIRED>
-<!ELEMENT ARETURN EMPTY>
-<!ELEMENT ARRAYLENGTH EMPTY>
-<!ELEMENT ASTORE EMPTY>
-<!ATTLIST ASTORE var CDATA #REQUIRED>
-<!ELEMENT ATHROW EMPTY>
-<!ELEMENT BALOAD EMPTY>
-<!ELEMENT BASTORE EMPTY>
-<!ELEMENT BIPUSH EMPTY>
-<!ATTLIST BIPUSH value CDATA #REQUIRED>
-<!ELEMENT CALOAD EMPTY>
-<!ELEMENT CASTORE EMPTY>
-<!ELEMENT CHECKCAST EMPTY>
-<!ATTLIST CHECKCAST desc CDATA #REQUIRED>
-<!ELEMENT D2F EMPTY>
-<!ELEMENT D2I EMPTY>
-<!ELEMENT D2L EMPTY>
-<!ELEMENT DADD EMPTY>
-<!ELEMENT DALOAD EMPTY>
-<!ELEMENT DASTORE EMPTY>
-<!ELEMENT DCMPG EMPTY>
-<!ELEMENT DCMPL EMPTY>
-<!ELEMENT DCONST_0 EMPTY>
-<!ELEMENT DCONST_1 EMPTY>
-<!ELEMENT DDIV EMPTY>
-<!ELEMENT DLOAD EMPTY>
-<!ATTLIST DLOAD var CDATA #REQUIRED>
-<!ELEMENT DMUL EMPTY>
-<!ELEMENT DNEG EMPTY>
-<!ELEMENT DREM EMPTY>
-<!ELEMENT DRETURN EMPTY>
-<!ELEMENT DSTORE EMPTY>
-<!ATTLIST DSTORE var CDATA #REQUIRED>
-<!ELEMENT DSUB EMPTY>
-<!ELEMENT DUP EMPTY>
-<!ELEMENT DUP2 EMPTY>
-<!ELEMENT DUP2_X1 EMPTY>
-<!ELEMENT DUP2_X2 EMPTY>
-<!ELEMENT DUP_X1 EMPTY>
-<!ELEMENT DUP_X2 EMPTY>
-<!ELEMENT SWAP EMPTY>
-<!ELEMENT F2D EMPTY>
-<!ELEMENT F2I EMPTY>
-<!ELEMENT F2L EMPTY>
-<!ELEMENT FADD EMPTY>
-<!ELEMENT FALOAD EMPTY>
-<!ELEMENT FASTORE EMPTY>
-<!ELEMENT FCMPG EMPTY>
-<!ELEMENT FCMPL EMPTY>
-<!ELEMENT FCONST_0 EMPTY>
-<!ELEMENT FCONST_1 EMPTY>
-<!ELEMENT FCONST_2 EMPTY>
-<!ELEMENT FDIV EMPTY>
-<!ELEMENT FLOAD EMPTY>
-<!ATTLIST FLOAD var CDATA #REQUIRED>
-<!ELEMENT FMUL EMPTY>
-<!ELEMENT FNEG EMPTY>
-<!ELEMENT FREM EMPTY>
-<!ELEMENT FRETURN EMPTY>
-<!ELEMENT FSTORE EMPTY>
-<!ATTLIST FSTORE var CDATA #REQUIRED>
-<!ELEMENT FSUB EMPTY>
-<!ELEMENT GETFIELD EMPTY>
-<!ATTLIST GETFIELD desc CDATA #REQUIRED>
-<!ATTLIST GETFIELD name CDATA #REQUIRED>
-<!ATTLIST GETFIELD owner CDATA #REQUIRED>
-<!ELEMENT GETSTATIC EMPTY>
-<!ATTLIST GETSTATIC desc CDATA #REQUIRED>
-<!ATTLIST GETSTATIC name CDATA #REQUIRED>
-<!ATTLIST GETSTATIC owner CDATA #REQUIRED>
-<!ELEMENT GOTO EMPTY>
-<!ATTLIST GOTO label CDATA #REQUIRED>
-<!ELEMENT I2B EMPTY>
-<!ELEMENT I2C EMPTY>
-<!ELEMENT I2D EMPTY>
-<!ELEMENT I2F EMPTY>
-<!ELEMENT I2L EMPTY>
-<!ELEMENT I2S EMPTY>
-<!ELEMENT IADD EMPTY>
-<!ELEMENT IALOAD EMPTY>
-<!ELEMENT IAND EMPTY>
-<!ELEMENT IASTORE EMPTY>
-<!ELEMENT ICONST_0 EMPTY>
-<!ELEMENT ICONST_1 EMPTY>
-<!ELEMENT ICONST_2 EMPTY>
-<!ELEMENT ICONST_3 EMPTY>
-<!ELEMENT ICONST_4 EMPTY>
-<!ELEMENT ICONST_5 EMPTY>
-<!ELEMENT ICONST_M1 EMPTY>
-<!ELEMENT IDIV EMPTY>
-<!ELEMENT IFEQ EMPTY>
-<!ATTLIST IFEQ label CDATA #REQUIRED>
-<!ELEMENT IFGE EMPTY>
-<!ATTLIST IFGE label CDATA #REQUIRED>
-<!ELEMENT IFGT EMPTY>
-<!ATTLIST IFGT label CDATA #REQUIRED>
-<!ELEMENT IFLE EMPTY>
-<!ATTLIST IFLE label CDATA #REQUIRED>
-<!ELEMENT IFLT EMPTY>
-<!ATTLIST IFLT label CDATA #REQUIRED>
-<!ELEMENT IFNE EMPTY>
-<!ATTLIST IFNE label CDATA #REQUIRED>
-<!ELEMENT IFNONNULL EMPTY>
-<!ATTLIST IFNONNULL label CDATA #REQUIRED>
-<!ELEMENT IFNULL EMPTY>
-<!ATTLIST IFNULL label CDATA #REQUIRED>
-<!ELEMENT IF_ACMPEQ EMPTY>
-<!ATTLIST IF_ACMPEQ label CDATA #REQUIRED>
-<!ELEMENT IF_ACMPNE EMPTY>
-<!ATTLIST IF_ACMPNE label CDATA #REQUIRED>
-<!ELEMENT IF_ICMPEQ EMPTY>
-<!ATTLIST IF_ICMPEQ label CDATA #REQUIRED>
-<!ELEMENT IF_ICMPGE EMPTY>
-<!ATTLIST IF_ICMPGE label CDATA #REQUIRED>
-<!ELEMENT IF_ICMPGT EMPTY>
-<!ATTLIST IF_ICMPGT label CDATA #REQUIRED>
-<!ELEMENT IF_ICMPLE EMPTY>
-<!ATTLIST IF_ICMPLE label CDATA #REQUIRED>
-<!ELEMENT IF_ICMPLT EMPTY>
-<!ATTLIST IF_ICMPLT label CDATA #REQUIRED>
-<!ELEMENT IF_ICMPNE EMPTY>
-<!ATTLIST IF_ICMPNE label CDATA #REQUIRED>
-<!ELEMENT IINC EMPTY>
-<!ATTLIST IINC inc CDATA #REQUIRED>
-<!ATTLIST IINC var CDATA #REQUIRED>
-<!ELEMENT ILOAD EMPTY>
-<!ATTLIST ILOAD var CDATA #REQUIRED>
-<!ELEMENT IMUL EMPTY>
-<!ELEMENT INEG EMPTY>
-<!ELEMENT INSTANCEOF EMPTY>
-<!ATTLIST INSTANCEOF desc CDATA #REQUIRED>
-<!ELEMENT INVOKEINTERFACE EMPTY>
-<!ATTLIST INVOKEINTERFACE desc CDATA #REQUIRED>
-<!ATTLIST INVOKEINTERFACE name CDATA #REQUIRED>
-<!ATTLIST INVOKEINTERFACE owner CDATA #REQUIRED>
-<!ELEMENT INVOKESPECIAL EMPTY>
-<!ATTLIST INVOKESPECIAL desc CDATA #REQUIRED>
-<!ATTLIST INVOKESPECIAL name CDATA #REQUIRED>
-<!ATTLIST INVOKESPECIAL owner CDATA #REQUIRED>
-<!ELEMENT INVOKESTATIC EMPTY>
-<!ATTLIST INVOKESTATIC desc CDATA #REQUIRED>
-<!ATTLIST INVOKESTATIC name CDATA #REQUIRED>
-<!ATTLIST INVOKESTATIC owner CDATA #REQUIRED>
-<!ELEMENT INVOKEVIRTUAL EMPTY>
-<!ATTLIST INVOKEVIRTUAL desc CDATA #REQUIRED>
-<!ATTLIST INVOKEVIRTUAL name CDATA #REQUIRED>
-<!ATTLIST INVOKEVIRTUAL owner CDATA #REQUIRED>
-<!ELEMENT INVOKEDYNAMIC ( bsmArgs+ )>
-<!ATTLIST INVOKEDYNAMIC desc CDATA #REQUIRED>
-<!ATTLIST INVOKEDYNAMIC name CDATA #REQUIRED>
-<!ATTLIST INVOKEDYNAMIC bsm CDATA #REQUIRED>
-<!ELEMENT bsmArgs EMPTY>
-<!ATTLIST bsmArgs cst CDATA #REQUIRED>
-<!ATTLIST bsmArgs desc CDATA #REQUIRED>
-<!ELEMENT IOR EMPTY>
-<!ELEMENT IREM EMPTY>
-<!ELEMENT IRETURN EMPTY>
-<!ELEMENT ISHL EMPTY>
-<!ELEMENT ISHR EMPTY>
-<!ELEMENT ISTORE EMPTY>
-<!ATTLIST ISTORE var CDATA #REQUIRED>
-<!ELEMENT ISUB EMPTY>
-<!ELEMENT IUSHR EMPTY>
-<!ELEMENT IXOR EMPTY>
-<!ELEMENT JSR EMPTY>
-<!ATTLIST JSR label CDATA #REQUIRED>
-<!ELEMENT L2D EMPTY>
-<!ELEMENT L2F EMPTY>
-<!ELEMENT L2I EMPTY>
-<!ELEMENT LADD EMPTY>
-<!ELEMENT LALOAD EMPTY>
-<!ELEMENT LAND EMPTY>
-<!ELEMENT LASTORE EMPTY>
-<!ELEMENT LCMP EMPTY>
-<!ELEMENT LCONST_0 EMPTY>
-<!ELEMENT LCONST_1 EMPTY>
-<!ELEMENT LDC EMPTY>
-<!--
- All characters out of interval 0x20 to 0x7f (inclusive) must
- be encoded (\uXXXX) and character '\' must be replaced by "\\"
--->
-<!ATTLIST LDC cst CDATA #REQUIRED>
-<!ATTLIST LDC desc CDATA #REQUIRED>
-<!ELEMENT LDIV EMPTY>
-<!ELEMENT LLOAD EMPTY>
-<!ATTLIST LLOAD var CDATA #REQUIRED>
-<!ELEMENT LMUL EMPTY>
-<!ELEMENT LNEG EMPTY>
-<!ELEMENT LOR EMPTY>
-<!ELEMENT LREM EMPTY>
-<!ELEMENT LRETURN EMPTY>
-<!ELEMENT LSHL EMPTY>
-<!ELEMENT LSHR EMPTY>
-<!ELEMENT LSTORE EMPTY>
-<!ATTLIST LSTORE var CDATA #REQUIRED>
-<!ELEMENT LSUB EMPTY>
-<!ELEMENT LUSHR EMPTY>
-<!ELEMENT LXOR EMPTY>
-<!ELEMENT MONITORENTER EMPTY>
-<!ELEMENT MONITOREXIT EMPTY>
-<!ELEMENT MULTIANEWARRAY EMPTY>
-<!ATTLIST MULTIANEWARRAY desc CDATA #REQUIRED>
-<!ATTLIST MULTIANEWARRAY dims CDATA #REQUIRED>
-<!ELEMENT NEW EMPTY>
-<!ATTLIST NEW desc CDATA #REQUIRED>
-<!ELEMENT NEWARRAY EMPTY>
-<!ATTLIST NEWARRAY value CDATA #REQUIRED>
-<!ELEMENT NOP EMPTY>
-<!ELEMENT POP EMPTY>
-<!ELEMENT POP2 EMPTY>
-<!ELEMENT PUTFIELD EMPTY>
-<!ATTLIST PUTFIELD desc CDATA #REQUIRED>
-<!ATTLIST PUTFIELD name CDATA #REQUIRED>
-<!ATTLIST PUTFIELD owner CDATA #REQUIRED>
-<!ELEMENT PUTSTATIC EMPTY>
-<!ATTLIST PUTSTATIC desc CDATA #REQUIRED>
-<!ATTLIST PUTSTATIC name CDATA #REQUIRED>
-<!ATTLIST PUTSTATIC owner CDATA #REQUIRED>
-<!ELEMENT RET EMPTY>
-<!ATTLIST RET var CDATA #REQUIRED>
-<!ELEMENT RETURN EMPTY>
-<!ELEMENT SALOAD EMPTY>
-<!ELEMENT SASTORE EMPTY>
-<!ELEMENT SIPUSH EMPTY>
-<!ATTLIST SIPUSH value CDATA #REQUIRED>
-
-<!ELEMENT LOOKUPSWITCH ( label+ )>
-<!ATTLIST LOOKUPSWITCH dflt CDATA #REQUIRED>
-
-<!ELEMENT TABLESWITCH ( label+ )>
-<!ATTLIST TABLESWITCH dflt CDATA #REQUIRED>
-<!ATTLIST TABLESWITCH max CDATA #REQUIRED>
-<!ATTLIST TABLESWITCH min CDATA #REQUIRED>
-
-<!ELEMENT label EMPTY>
-<!ATTLIST label key CDATA #IMPLIED>
-<!ATTLIST label name CDATA #REQUIRED>
-
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
deleted file mode 100644
index d7bbe66..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<html>
-<!--
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
--->
-<body>
-Provides <a href="http://sax.sourceforge.net/">SAX 2.0</a> adapters for ASM
-visitors to convert classes to and from XML.
-These adapters can be chained with other SAX compliant content handlers and
-filters, eg. XSLT or XQuery engines. This package is bundled as
-a separate <tt>asm-xml.jar</tt> library and requires <tt>asm.jar</tt>.
-<p>
-<tt>ASMContentHandler</tt> and <tt>SAXClassAdapter/SAXCodeAdapter</tt>
-are using <a href="asm-xml.dtd">asm-xml.dtd</a>.
-Here is the example of bytecode to bytecode XSLT transformation.
-
-<pre>
- SAXTransformerFactory saxtf = ( SAXTransformerFactory) TransformerFactory.newInstance();
- Templates templates = saxtf.newTemplates( xsltSource);
-
- TransformerHandler handler = saxtf.newTransformerHandler( templates);
- handler.setResult( new SAXResult( new ASMContentHandler( outputStream, computeMax)));
-
- ClassReader cr = new ClassReader( bytecode);
- cr.accept( new SAXClassAdapter( handler, cr.getVersion(), false), false);
-</pre>
-
-See JAXP and SAX documentation for more detils.
-
-<p>
-There are few illustrations of the bytecode transformation with XSLT in
-examples directory. The following XSLT procesors has been tested.
-
-<blockquote>
-<table border="1" cellspacing="0" cellpadding="3">
-<tr>
-<th>Engine</td>
-<th>javax.xml.transform.TransformerFactory property</td>
-</tr>
-
-<tr>
-<td>jd.xslt</td>
-<td>jd.xml.xslt.trax.TransformerFactoryImpl</td>
-</tr>
-
-<tr>
-<td>Saxon</td>
-<td>net.sf.saxon.TransformerFactoryImpl</td>
-</tr>
-
-<tr>
-<td>Caucho</td>
-<td>com.caucho.xsl.Xsl</td>
-</tr>
-
-<tr>
-<td>Xalan interpeter</td>
-<td>org.apache.xalan.processor.TransformerFactory</td>
-</tr>
-
-<tr>
-<td>Xalan xsltc</td>
-<td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
-</tr>
-</table>
-</blockquote>
-
-@since ASM 1.4.3
-
-</body>
-</html>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java
----------------------------------------------------------------------
diff --git a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java
index bbead43..dd44883 100644
--- a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java
+++ b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java
@@ -34,7 +34,7 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
/**
* Maps from condition to opcode to jump to the false code block.
*/
- private static final Map<Condition, Integer> conditionToOpcode = new HashMap<Condition, Integer>();
+ private static final Map<Condition, Integer> conditionToOpcode = new HashMap<>();
static
{
@@ -50,7 +50,7 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
m.put(Condition.GREATER, IF_ICMPLE);
}
- private static final Map<String, Integer> typeToSpecialComparisonOpcode = new HashMap<String, Integer>();
+ private static final Map<String, Integer> typeToSpecialComparisonOpcode = new HashMap<>();
static
{
@@ -61,7 +61,7 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
m.put("double", DCMPL);
}
- private static final Map<Object, Integer> constantOpcodes = new HashMap<Object, Integer>();
+ private static final Map<Object, Integer> constantOpcodes = new HashMap<>();
static
{
@@ -199,7 +199,7 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
{
check();
- doInvoke(INVOKESPECIAL, containingClassName, description);
+ doInvoke(INVOKESPECIAL, containingClassName, description, false);
return this;
}
@@ -223,7 +223,7 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
{
check();
- doInvoke(INVOKEVIRTUAL, className, returnType, methodName, argumentTypes);
+ doInvoke(INVOKEVIRTUAL, className, returnType, methodName, false, argumentTypes);
return this;
}
@@ -234,28 +234,30 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
{
check();
- doInvoke(INVOKEINTERFACE, interfaceName, returnType, methodName, argumentTypes);
+ doInvoke(INVOKEINTERFACE, interfaceName, returnType, methodName, true, argumentTypes);
return this;
}
- private void doInvoke(int opcode, String className, String returnType, String methodName, String... argumentTypes)
+ private void doInvoke(int opcode, String className, String returnType, String methodName, boolean isInterface,
+ String... argumentTypes)
{
v.visitMethodInsn(opcode, cache.toInternalName(className), methodName,
- cache.toMethodDescriptor(returnType, argumentTypes));
+ cache.toMethodDescriptor(returnType, argumentTypes), isInterface);
}
@Override
public InstructionBuilder invokeStatic(Class clazz, Class returnType, String methodName, Class... argumentTypes)
{
- doInvoke(INVOKESTATIC, clazz, returnType, methodName, argumentTypes);
+ doInvoke(INVOKESTATIC, clazz, returnType, methodName, false, argumentTypes);
return this;
}
- private void doInvoke(int opcode, Class clazz, Class returnType, String methodName, Class... argumentTypes)
+ private void doInvoke(int opcode, Class clazz, Class returnType, String methodName, boolean isInterface,
+ Class... argumentTypes)
{
- doInvoke(opcode, clazz.getName(), cache.toTypeName(returnType), methodName,
+ doInvoke(opcode, clazz.getName(), cache.toTypeName(returnType), methodName, isInterface,
PlasticUtils.toTypeNames(argumentTypes));
}
@@ -272,15 +274,16 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
{
check();
- doInvoke(clazz.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, clazz, returnType, methodName, argumentTypes);
+ doInvoke(clazz.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, clazz, returnType, methodName,
+ clazz.isInterface(), argumentTypes);
return this;
}
- private void doInvoke(int opcode, String containingClassName, MethodDescription description)
+ private void doInvoke(int opcode, String containingClassName, MethodDescription description, boolean isInterface)
{
v.visitMethodInsn(opcode, cache.toInternalName(containingClassName), description.methodName,
- cache.toDesc(description));
+ cache.toDesc(description), isInterface);
}
@Override
@@ -306,7 +309,8 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
if (type != null && type != PrimitiveType.VOID)
{
- v.visitMethodInsn(INVOKESTATIC, type.wrapperInternalName, "valueOf", type.valueOfMethodDescriptor);
+ v.visitMethodInsn(INVOKESTATIC, type.wrapperInternalName, "valueOf", type.valueOfMethodDescriptor,
+ false);
}
return this;
@@ -329,7 +333,8 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
private void doUnbox(PrimitiveType type)
{
- v.visitMethodInsn(INVOKEVIRTUAL, type.wrapperInternalName, type.toValueMethodName, type.toValueMethodDescriptor);
+ v.visitMethodInsn(INVOKEVIRTUAL, type.wrapperInternalName, type.toValueMethodName, type.toValueMethodDescriptor,
+ false);
}
@Override
@@ -498,7 +503,7 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
{
check();
- doInvoke(INVOKESPECIAL, className, "void", "<init>", argumentTypes);
+ doInvoke(INVOKESPECIAL, className, "void", "<init>", false, argumentTypes);
return this;
}
@@ -661,14 +666,7 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
final LocalVariable var = state.startVariable(type);
- new InstructionBuilderCallback()
- {
- @Override
- public void doBuild(InstructionBuilder builder)
- {
- callback.doBuild(var, builder);
- }
- }.doBuild(this);
+ callback.doBuild(var, this);
state.stopVariable(var);
@@ -733,27 +731,13 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
v.visitJumpInsn(conditionToOpcode.get(condition), ifFalseLabel);
- new InstructionBuilderCallback()
- {
- @Override
- public void doBuild(InstructionBuilder builder)
- {
- callback.ifTrue(builder);
- }
- }.doBuild(this);
+ callback.ifTrue(this);
v.visitJumpInsn(GOTO, endIfLabel);
v.visitLabel(ifFalseLabel);
- new InstructionBuilderCallback()
- {
- @Override
- public void doBuild(InstructionBuilder builder)
- {
- callback.ifFalse(builder);
- }
- }.doBuild(this);
+ callback.ifFalse(this);
v.visitLabel(endIfLabel);
@@ -772,25 +756,11 @@ public class InstructionBuilderImpl extends Lockable implements Opcodes, Instruc
Label exitLoop = new Label();
- new InstructionBuilderCallback()
- {
- @Override
- public void doBuild(InstructionBuilder builder)
- {
- callback.buildTest(builder);
- }
- }.doBuild(this);
+ callback.buildTest(this);
v.visitJumpInsn(conditionToOpcode.get(condition), exitLoop);
- new InstructionBuilderCallback()
- {
- @Override
- public void doBuild(InstructionBuilder builder)
- {
- callback.buildBody(builder);
- }
- }.doBuild(this);
+ callback.buildBody(this);
v.visitJumpInsn(GOTO, doCheck);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
----------------------------------------------------------------------
diff --git a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
index 9683e1c..223109a 100644
--- a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
+++ b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
@@ -20,13 +20,10 @@ import org.apache.tapestry5.plastic.*;
import java.io.IOException;
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.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
@SuppressWarnings("all")
public class PlasticClassImpl extends Lockable implements PlasticClass, InternalPlasticClassTransformation, Opcodes
@@ -100,9 +97,9 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
private final List<PlasticMethodImpl> methods;
- private final Map<MethodDescription, PlasticMethod> description2method = new HashMap<MethodDescription, PlasticMethod>();
+ private final Map<MethodDescription, PlasticMethod> description2method = new HashMap<>();
- final Set<String> methodNames = new HashSet<String>();
+ final Set<String> methodNames = new HashSet<>();
private final List<ConstructorCallback> constructorCallbacks = PlasticInternalUtils.newList();
@@ -212,7 +209,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
inheritanceData.addInterface(interfaceName);
}
- methods = new ArrayList(classNode.methods.size());
+ methods = new ArrayList<>(classNode.methods.size());
String invalidConstructorMessage = invalidConstructorMessage();
@@ -234,7 +231,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
continue;
}
- /**
+ /*
* Static methods are not visible to the main API methods, but they must still be transformed,
* in case they directly access fields. In addition, track their names to avoid collisions.
*/
@@ -274,7 +271,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
Collections.sort(methods);
- fields = new ArrayList(classNode.fields.size());
+ fields = new ArrayList<>(classNode.fields.size());
for (FieldNode node : classNode.fields)
{
@@ -443,13 +440,13 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
if (list != null)
{
- final Set<String> annotations = new HashSet<String>();
- final List<AnnotationNode> toBeRemoved = new ArrayList<AnnotationNode>();
+ final Set<String> annotations = new HashSet<>();
+ final List<AnnotationNode> toBeRemoved = new ArrayList<>();
final List<AnnotationNode> toBeIterated;
if (reverse)
{
- toBeIterated = new ArrayList<AnnotationNode>(list);
+ toBeIterated = new ArrayList<>(list);
Collections.reverse(toBeIterated);
}
else {
@@ -508,7 +505,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
private static List<Class> getJavaParameterTypes(MethodNode methodNode) {
final ClassLoader classLoader = PlasticInternalUtils.class.getClassLoader();
Type[] parameterTypes = Type.getArgumentTypes(methodNode.desc);
- List<Class> list = new ArrayList<Class>();
+ List<Class> list = new ArrayList<>();
for (Type type : parameterTypes)
{
try
@@ -626,16 +623,16 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
// {
// introduceMethod(m).delegateTo(field);
// }
-
+
Map<MethodSignature, MethodDescription> map = createMethodSignatureMap(interfaceType);
for (MethodSignature methodSignature : map.keySet())
{
introduceMethod(map.get(methodSignature)).delegateTo(field);
}
-
+
return this;
}
-
+
@Override
public PlasticClass proxyInterface(Class interfaceType, PlasticMethod method)
{
@@ -651,7 +648,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
{
introduceMethod(map.get(methodSignature)).delegateTo(method);
}
-
+
return this;
}
@@ -848,7 +845,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
{
check();
- return new ArrayList<PlasticField>(fields);
+ return new ArrayList<>(fields);
}
@Override
@@ -860,7 +857,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
if (unclaimedFields == null)
{
- unclaimedFields = new ArrayList<PlasticField>(fields.size());
+ unclaimedFields = new ArrayList<>(fields.size());
for (PlasticField f : fields)
{
@@ -931,15 +928,8 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
check();
List<PlasticMethod> result = getMethods();
- Iterator<PlasticMethod> iterator = result.iterator();
- while (iterator.hasNext())
- {
- PlasticMethod method = iterator.next();
-
- if (!method.hasAnnotation(annotationType))
- iterator.remove();
- }
+ result.removeIf(method -> !method.hasAnnotation(annotationType));
return result;
}
@@ -949,7 +939,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
{
check();
- return new ArrayList<PlasticMethod>(methods);
+ return new ArrayList<>(methods);
}
@Override
@@ -1266,11 +1256,11 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
{
InsnList insns = methodNode.instructions;
- ListIterator it = insns.iterator();
+ ListIterator<AbstractInsnNode> it = insns.iterator();
while (it.hasNext())
{
- AbstractInsnNode node = (AbstractInsnNode) it.next();
+ AbstractInsnNode node = it.next();
int opcode = node.getOpcode();
@@ -1290,7 +1280,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
// Replace the field access node with the appropriate method invocation.
- insns.insertBefore(fnode, new MethodInsnNode(INVOKEVIRTUAL, fnode.owner, instrumentation.methodName, instrumentation.methodDescription));
+ insns.insertBefore(fnode, new MethodInsnNode(INVOKEVIRTUAL, fnode.owner, instrumentation.methodName, instrumentation.methodDescription, false));
it.remove();
}
@@ -1456,12 +1446,12 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
addClassAnnotations(interfaceClassNode);
- Set<PlasticMethod> introducedMethods = new HashSet<PlasticMethod>();
-
+ Set<PlasticMethod> introducedMethods = new HashSet<>();
+
Map<MethodSignature, MethodDescription> map = createMethodSignatureMap(interfaceType);
-
+
// for (Method m : interfaceType.getMethods())
- for (MethodSignature methodSignature : map.keySet())
+ for (MethodSignature methodSignature : map.keySet())
{
// MethodDescription description = new MethodDescription(m);
final MethodDescription description = map.get(methodSignature);
@@ -1479,80 +1469,72 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
}
private Map<MethodSignature, MethodDescription> createMethodSignatureMap(Class interfaceType) {
- // TAP-2582: preprocessing the method list so we don't add duplicated
+ // TAP-2582: preprocessing the method list so we don't add duplicated
// methods, something that happens when an interface has superinterfaces
// and they define the same method signature.
// In addition, we collect all the thrown checked exceptions, just in case.
- Map<MethodSignature, MethodDescription> map = new HashMap<MethodSignature, MethodDescription>();
+ Map<MethodSignature, MethodDescription> map = new HashMap<>();
for (Method m : interfaceType.getMethods())
{
final MethodSignature methodSignature = new MethodSignature(m);
final MethodDescription newMethodDescription = new MethodDescription(m);
- if (!map.containsKey(methodSignature))
+ if (!map.containsKey(methodSignature))
{
- map.put(methodSignature, newMethodDescription);
+ map.put(methodSignature, newMethodDescription);
}
- else
+ else
{
- if (newMethodDescription.checkedExceptionTypes != null && newMethodDescription.checkedExceptionTypes.length > 0)
- {
- final MethodDescription methodDescription = map.get(methodSignature);
- final Set<String> checkedExceptionTypes = new HashSet<String>();
- checkedExceptionTypes.addAll(Arrays.asList(methodDescription.checkedExceptionTypes));
- checkedExceptionTypes.addAll(Arrays.asList(newMethodDescription.checkedExceptionTypes));
- map.put(methodSignature, new MethodDescription(
- methodDescription,
- checkedExceptionTypes.toArray(new String[checkedExceptionTypes.size()])));
- }
+ if (newMethodDescription.checkedExceptionTypes != null && newMethodDescription.checkedExceptionTypes.length > 0)
+ {
+ final MethodDescription methodDescription = map.get(methodSignature);
+ final Set<String> checkedExceptionTypes = new HashSet<>();
+ checkedExceptionTypes.addAll(Arrays.asList(methodDescription.checkedExceptionTypes));
+ checkedExceptionTypes.addAll(Arrays.asList(newMethodDescription.checkedExceptionTypes));
+ map.put(methodSignature, new MethodDescription(
+ methodDescription,
+ checkedExceptionTypes.toArray(new String[checkedExceptionTypes.size()])));
+ }
}
}
- return map;
- }
-
- final private static class MethodSignature implements Comparable<MethodSignature>{
-
- final private Method method;
- final private String name;
- final private Class<?>[] parameterTypes;
-
- public MethodSignature(Method method) {
- this.method = method;
- this.name = method.getName();
- this.parameterTypes = method.getParameterTypes();
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + Arrays.hashCode(parameterTypes);
- result = prime * result + ((name == null) ? 0 : name.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;
- MethodSignature other = (MethodSignature) obj;
- if (!Arrays.equals(parameterTypes, other.parameterTypes))
- return false;
- if (name == null) {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- return true;
- }
-
- @Override
- public int compareTo(MethodSignature o) {
- return method.getName().compareTo(o.method.getName());
- }
+ return map;
+ }
+
+ final private static class MethodSignature implements Comparable<MethodSignature> {
+ final private Method method;
+ final private String name;
+ final private Class<?>[] parameterTypes;
+
+ public MethodSignature(Method method) {
+ this.method = method;
+ this.name = method.getName();
+ this.parameterTypes = method.getParameterTypes();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(parameterTypes);
+ result = prime * result + ((name == null) ? 0 : name.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;
+
+ MethodSignature other = (MethodSignature) obj;
+ if (!Arrays.equals(parameterTypes, other.parameterTypes)) return false;
+
+ return name == null ? other.name == null : name.equals(other.name);
+ }
+
+ @Override
+ public int compareTo(MethodSignature o) {
+ return method.getName().compareTo(o.method.getName());
+ }
}
@Override
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
----------------------------------------------------------------------
diff --git a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
index dfbb8cf..8ee547f 100644
--- a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
+++ b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
@@ -437,7 +437,7 @@ public class PlasticClassPool implements ClassLoaderDelegate, Opcodes, PlasticCl
// Replace the field access node with the appropriate method invocation.
- insns.insertBefore(fnode, new MethodInsnNode(INVOKEVIRTUAL, ownerInternalName, instrumentation.methodName, instrumentation.methodDescription));
+ insns.insertBefore(fnode, new MethodInsnNode(INVOKEVIRTUAL, ownerInternalName, instrumentation.methodName, instrumentation.methodDescription, false));
it.remove();
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/Main.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/Main.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/Main.java
new file mode 100644
index 0000000..c42fd56
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/Main.java
@@ -0,0 +1,38 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.ioc.internal;
+
+
+import java.util.List;
+
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
+import org.apache.tapestry5.ioc.ObjectLocator;
+import org.apache.tapestry5.ioc.Registry;
+import org.apache.tapestry5.ioc.RegistryBuilder;
+import org.apache.tapestry5.ioc.ServiceBinder;
+import org.apache.tapestry5.ioc.annotations.Advise;
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
+
+public class Main
+{
+
+ public static void main(String[] args) {
+ Registry registry = RegistryBuilder.buildAndStartupRegistry(AdviceModule.class);
+ Session session = registry.getService(Session.class);
+ final List list = session.createSQLQuery("select 1").list();
+ System.out.println(list);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/tapestry-ioc/src/test/resources/hibernate.cfg.xml
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/resources/hibernate.cfg.xml b/tapestry-ioc/src/test/resources/hibernate.cfg.xml
new file mode 100644
index 0000000..d02951b
--- /dev/null
+++ b/tapestry-ioc/src/test/resources/hibernate.cfg.xml
@@ -0,0 +1,42 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ Copyright 2007, 2008 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD//EN"
+ "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+
+ <session-factory>
+ <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
+ <property name="hibernate.connection.url">jdbc:hsqldb:mem:test</property>
+ <property name="hibernate.connection.username">sa</property>
+ <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
+
+ <property name="show_sql">true</property>
+ <property name="format_sql">true</property>
+ <property name="hbm2ddl.auto">update</property>
+
+ <property name="hibernate.c3p0.min_size">5</property>
+ <property name="hibernate.c3p0.max_size">20</property>
+ <property name="hibernate.c3p0.timeout">300</property>
+ <property name="hibernate.c3p0.max_statements">50</property>
+ <property name="hibernate.c3p0.idle_test_period">3000</property>
+ </session-factory>
+
+
+</hibernate-configuration>
[07/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
old mode 100644
new mode 100755
index 2dd644a..1dbdbbd
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
@@ -1,1256 +1,1255 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* An abstract converter from visit events to text.
- *
+ *
* @author Eric Bruneton
*/
public abstract class Printer {
- /**
- * The names of the Java Virtual Machine opcodes.
- */
- public static final String[] OPCODES;
-
- /**
- * The names of the for <code>operand</code> parameter values of the
- * {@link org.objectweb.asm.MethodVisitor#visitIntInsn} method when
- * <code>opcode</code> is <code>NEWARRAY</code>.
- */
- public static final String[] TYPES;
-
- /**
- * The names of the <code>tag</code> field values for
- * {@link org.objectweb.asm.Handle}.
- */
- public static final String[] HANDLE_TAG;
-
- static {
- String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2,"
- + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0,"
- + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,,"
- + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD,"
- + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE,"
- + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE,"
- + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP,"
- + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD,"
- + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV,"
- + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL,"
- + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L,"
- + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP,"
- + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE,"
- + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE,"
- + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH,"
- + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC,"
- + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL,"
- + "INVOKESTATIC,INVOKEINTERFACE,INVOKEDYNAMIC,NEW,NEWARRAY,"
- + "ANEWARRAY,ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,"
- + "MONITORENTER,MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,";
- OPCODES = new String[200];
- int i = 0;
- int j = 0;
- int l;
- while ((l = s.indexOf(',', j)) > 0) {
- OPCODES[i++] = j + 1 == l ? null : s.substring(j, l);
- j = l + 1;
- }
-
- s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,";
- TYPES = new String[12];
- j = 0;
- i = 4;
- while ((l = s.indexOf(',', j)) > 0) {
- TYPES[i++] = s.substring(j, l);
- j = l + 1;
- }
-
- s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC,"
- + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
- + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
- HANDLE_TAG = new String[10];
- j = 0;
- i = 1;
- while ((l = s.indexOf(',', j)) > 0) {
- HANDLE_TAG[i++] = s.substring(j, l);
- j = l + 1;
- }
- }
-
- /**
- * The ASM API version implemented by this class. The value of this field
- * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- protected final int api;
-
- /**
- * A buffer that can be used to create strings.
- */
- protected final StringBuffer buf;
-
- /**
- * The text to be printed. Since the code of methods is not necessarily
- * visited in sequential order, one method after the other, but can be
- * interlaced (some instructions from method one, then some instructions
- * from method two, then some instructions from method one again...), it is
- * not possible to print the visited instructions directly to a sequential
- * stream. A class is therefore printed in a two steps process: a string
- * tree is constructed during the visit, and printed to a sequential stream
- * at the end of the visit. This string tree is stored in this field, as a
- * string list that can contain other string lists, which can themselves
- * contain other string lists, and so on.
- */
- public final List<Object> text;
-
- /**
- * Constructs a new {@link Printer}.
- *
- * @param api
- * the ASM API version implemented by this printer. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- protected Printer(final int api) {
- this.api = api;
- this.buf = new StringBuffer();
- this.text = new ArrayList<Object>();
- }
-
- /**
- * Class header.
- * See {@link org.objectweb.asm.ClassVisitor#visit}.
- *
- * @param version
- * the class version.
- * @param access
- * the class's access flags (see {@link Opcodes}). This parameter
- * also indicates if the class is deprecated.
- * @param name
- * the internal name of the class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- * @param signature
- * the signature of this class. May be <tt>null</tt> if the class
- * is not a generic one, and does not extend or implement generic
- * classes or interfaces.
- * @param superName
- * the internal of name of the super class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- * For interfaces, the super class is {@link Object}. May be
- * <tt>null</tt>, but only for the {@link Object} class.
- * @param interfaces
- * the internal names of the class's interfaces (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- * May be <tt>null</tt>.
- */
- public abstract void visit(final int version, final int access,
- final String name, final String signature, final String superName,
- final String[] interfaces);
-
- /**
- * Class source.
- * See {@link org.objectweb.asm.ClassVisitor#visitSource}.
- *
- * @param source
- * the name of the source file from which the class was compiled.
- * May be <tt>null</tt>.
- * @param debug
- * additional debug information to compute the correspondance
- * between source and compiled elements of the class. May be
- * <tt>null</tt>.
- */
- public abstract void visitSource(final String source, final String debug);
-
-
- /**
- * Module.
- * See {@link org.objectweb.asm.ClassVisitor#visitModule(String, int)}.
- *
- * @param name
- * module name.
- * @param access
- * module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
- * and {@code ACC_MANDATED}.
- * @param version
- * module version or null.
- * @return
- */
- public Printer visitModule(String name, int access, String version) {
- throw new RuntimeException("Must be overriden");
- }
-
- /**
- * Class outer class.
- * See {@link org.objectweb.asm.ClassVisitor#visitOuterClass}.
- *
- * Visits the enclosing class of the class. This method must be called only
- * if the class has an enclosing class.
- *
- * @param owner
- * internal name of the enclosing class of the class.
- * @param name
- * the name of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
- * @param desc
- * the descriptor of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
- */
- public abstract void visitOuterClass(final String owner, final String name,
- final String desc);
-
- /**
- * Class annotation.
- * See {@link org.objectweb.asm.ClassVisitor#visitAnnotation}.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return the printer
- */
- public abstract Printer visitClassAnnotation(final String desc,
- final boolean visible);
-
- /**
- * Class type annotation.
- * See {@link org.objectweb.asm.ClassVisitor#visitTypeAnnotation}.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be
- * {@link org.objectweb.asm.TypeReference#CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
- * {@link org.objectweb.asm.TypeReference#CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND}
- * or {@link org.objectweb.asm.TypeReference#CLASS_EXTENDS CLASS_EXTENDS}.
- * See {@link org.objectweb.asm.TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return the printer
- */
- public Printer visitClassTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
- }
-
- /**
- * Class attribute.
- * See {@link org.objectweb.asm.ClassVisitor#visitAttribute}.
- *
- * @param attr
- * an attribute.
- */
- public abstract void visitClassAttribute(final Attribute attr);
-
- /**
- * Class inner name.
- * See {@link org.objectweb.asm.ClassVisitor#visitInnerClass}.
- *
- * @param name
- * the internal name of an inner class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- * @param outerName
- * the internal name of the class to which the inner class
- * belongs (see {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- * May be <tt>null</tt> for not member classes.
- * @param innerName
- * the (simple) name of the inner class inside its enclosing
- * class. May be <tt>null</tt> for anonymous inner classes.
- * @param access
- * the access flags of the inner class as originally declared in
- * the enclosing class.
- */
- public abstract void visitInnerClass(final String name,
- final String outerName, final String innerName, final int access);
-
- /**
- * Class field.
- * See {@link org.objectweb.asm.ClassVisitor#visitField}.
- *
- * @param access
- * the field's access flags (see {@link Opcodes}). This parameter
- * also indicates if the field is synthetic and/or deprecated.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link org.objectweb.asm.Type Type}).
- * @param signature
- * the field's signature. May be <tt>null</tt> if the field's
- * type does not use generic types.
- * @param value
- * the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value,
- * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String} (for <tt>int</tt>,
- * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
- * respectively). <i>This parameter is only used for static
- * fields</i>. Its value is ignored for non static fields, which
- * must be initialized through bytecode instructions in
- * constructors or methods.
- * @return the printer
- */
- public abstract Printer visitField(final int access, final String name,
- final String desc, final String signature, final Object value);
-
- /**
- * Class method.
- * See {@link org.objectweb.asm.ClassVisitor#visitMethod}.
- *
- * @param access
- * the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link org.objectweb.asm.Type Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt> if the method
- * parameters, return type and exceptions do not use generic
- * types.
- * @param exceptions
- * the internal names of the method's exception classes (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- * @return the printer
- */
- public abstract Printer visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions);
-
- /**
- * Class end. See {@link org.objectweb.asm.ClassVisitor#visitEnd}.
- */
- public abstract void visitClassEnd();
-
- // ------------------------------------------------------------------------
- // Module
- // ------------------------------------------------------------------------
-
- public void visitMainClass(String mainClass) {
- throw new RuntimeException("Must be overriden");
- }
-
- public void visitPackage(String packaze) {
- throw new RuntimeException("Must be overriden");
- }
-
- public void visitRequire(String module, int access, String version) {
- throw new RuntimeException("Must be overriden");
- }
-
- public void visitExport(String packaze, int access, String... modules) {
- throw new RuntimeException("Must be overriden");
- }
-
- public void visitOpen(String packaze, int access, String... modules) {
- throw new RuntimeException("Must be overriden");
+ /** The names of the Java Virtual Machine opcodes. */
+ public static final String[] OPCODES = {
+ "NOP", // 0 (0x0)
+ "ACONST_NULL", // 1 (0x1)
+ "ICONST_M1", // 2 (0x2)
+ "ICONST_0", // 3 (0x3)
+ "ICONST_1", // 4 (0x4)
+ "ICONST_2", // 5 (0x5)
+ "ICONST_3", // 6 (0x6)
+ "ICONST_4", // 7 (0x7)
+ "ICONST_5", // 8 (0x8)
+ "LCONST_0", // 9 (0x9)
+ "LCONST_1", // 10 (0xa)
+ "FCONST_0", // 11 (0xb)
+ "FCONST_1", // 12 (0xc)
+ "FCONST_2", // 13 (0xd)
+ "DCONST_0", // 14 (0xe)
+ "DCONST_1", // 15 (0xf)
+ "BIPUSH", // 16 (0x10)
+ "SIPUSH", // 17 (0x11)
+ "LDC", // 18 (0x12)
+ "LDC_W", // 19 (0x13)
+ "LDC2_W", // 20 (0x14)
+ "ILOAD", // 21 (0x15)
+ "LLOAD", // 22 (0x16)
+ "FLOAD", // 23 (0x17)
+ "DLOAD", // 24 (0x18)
+ "ALOAD", // 25 (0x19)
+ "ILOAD_0", // 26 (0x1a)
+ "ILOAD_1", // 27 (0x1b)
+ "ILOAD_2", // 28 (0x1c)
+ "ILOAD_3", // 29 (0x1d)
+ "LLOAD_0", // 30 (0x1e)
+ "LLOAD_1", // 31 (0x1f)
+ "LLOAD_2", // 32 (0x20)
+ "LLOAD_3", // 33 (0x21)
+ "FLOAD_0", // 34 (0x22)
+ "FLOAD_1", // 35 (0x23)
+ "FLOAD_2", // 36 (0x24)
+ "FLOAD_3", // 37 (0x25)
+ "DLOAD_0", // 38 (0x26)
+ "DLOAD_1", // 39 (0x27)
+ "DLOAD_2", // 40 (0x28)
+ "DLOAD_3", // 41 (0x29)
+ "ALOAD_0", // 42 (0x2a)
+ "ALOAD_1", // 43 (0x2b)
+ "ALOAD_2", // 44 (0x2c)
+ "ALOAD_3", // 45 (0x2d)
+ "IALOAD", // 46 (0x2e)
+ "LALOAD", // 47 (0x2f)
+ "FALOAD", // 48 (0x30)
+ "DALOAD", // 49 (0x31)
+ "AALOAD", // 50 (0x32)
+ "BALOAD", // 51 (0x33)
+ "CALOAD", // 52 (0x34)
+ "SALOAD", // 53 (0x35)
+ "ISTORE", // 54 (0x36)
+ "LSTORE", // 55 (0x37)
+ "FSTORE", // 56 (0x38)
+ "DSTORE", // 57 (0x39)
+ "ASTORE", // 58 (0x3a)
+ "ISTORE_0", // 59 (0x3b)
+ "ISTORE_1", // 60 (0x3c)
+ "ISTORE_2", // 61 (0x3d)
+ "ISTORE_3", // 62 (0x3e)
+ "LSTORE_0", // 63 (0x3f)
+ "LSTORE_1", // 64 (0x40)
+ "LSTORE_2", // 65 (0x41)
+ "LSTORE_3", // 66 (0x42)
+ "FSTORE_0", // 67 (0x43)
+ "FSTORE_1", // 68 (0x44)
+ "FSTORE_2", // 69 (0x45)
+ "FSTORE_3", // 70 (0x46)
+ "DSTORE_0", // 71 (0x47)
+ "DSTORE_1", // 72 (0x48)
+ "DSTORE_2", // 73 (0x49)
+ "DSTORE_3", // 74 (0x4a)
+ "ASTORE_0", // 75 (0x4b)
+ "ASTORE_1", // 76 (0x4c)
+ "ASTORE_2", // 77 (0x4d)
+ "ASTORE_3", // 78 (0x4e)
+ "IASTORE", // 79 (0x4f)
+ "LASTORE", // 80 (0x50)
+ "FASTORE", // 81 (0x51)
+ "DASTORE", // 82 (0x52)
+ "AASTORE", // 83 (0x53)
+ "BASTORE", // 84 (0x54)
+ "CASTORE", // 85 (0x55)
+ "SASTORE", // 86 (0x56)
+ "POP", // 87 (0x57)
+ "POP2", // 88 (0x58)
+ "DUP", // 89 (0x59)
+ "DUP_X1", // 90 (0x5a)
+ "DUP_X2", // 91 (0x5b)
+ "DUP2", // 92 (0x5c)
+ "DUP2_X1", // 93 (0x5d)
+ "DUP2_X2", // 94 (0x5e)
+ "SWAP", // 95 (0x5f)
+ "IADD", // 96 (0x60)
+ "LADD", // 97 (0x61)
+ "FADD", // 98 (0x62)
+ "DADD", // 99 (0x63)
+ "ISUB", // 100 (0x64)
+ "LSUB", // 101 (0x65)
+ "FSUB", // 102 (0x66)
+ "DSUB", // 103 (0x67)
+ "IMUL", // 104 (0x68)
+ "LMUL", // 105 (0x69)
+ "FMUL", // 106 (0x6a)
+ "DMUL", // 107 (0x6b)
+ "IDIV", // 108 (0x6c)
+ "LDIV", // 109 (0x6d)
+ "FDIV", // 110 (0x6e)
+ "DDIV", // 111 (0x6f)
+ "IREM", // 112 (0x70)
+ "LREM", // 113 (0x71)
+ "FREM", // 114 (0x72)
+ "DREM", // 115 (0x73)
+ "INEG", // 116 (0x74)
+ "LNEG", // 117 (0x75)
+ "FNEG", // 118 (0x76)
+ "DNEG", // 119 (0x77)
+ "ISHL", // 120 (0x78)
+ "LSHL", // 121 (0x79)
+ "ISHR", // 122 (0x7a)
+ "LSHR", // 123 (0x7b)
+ "IUSHR", // 124 (0x7c)
+ "LUSHR", // 125 (0x7d)
+ "IAND", // 126 (0x7e)
+ "LAND", // 127 (0x7f)
+ "IOR", // 128 (0x80)
+ "LOR", // 129 (0x81)
+ "IXOR", // 130 (0x82)
+ "LXOR", // 131 (0x83)
+ "IINC", // 132 (0x84)
+ "I2L", // 133 (0x85)
+ "I2F", // 134 (0x86)
+ "I2D", // 135 (0x87)
+ "L2I", // 136 (0x88)
+ "L2F", // 137 (0x89)
+ "L2D", // 138 (0x8a)
+ "F2I", // 139 (0x8b)
+ "F2L", // 140 (0x8c)
+ "F2D", // 141 (0x8d)
+ "D2I", // 142 (0x8e)
+ "D2L", // 143 (0x8f)
+ "D2F", // 144 (0x90)
+ "I2B", // 145 (0x91)
+ "I2C", // 146 (0x92)
+ "I2S", // 147 (0x93)
+ "LCMP", // 148 (0x94)
+ "FCMPL", // 149 (0x95)
+ "FCMPG", // 150 (0x96)
+ "DCMPL", // 151 (0x97)
+ "DCMPG", // 152 (0x98)
+ "IFEQ", // 153 (0x99)
+ "IFNE", // 154 (0x9a)
+ "IFLT", // 155 (0x9b)
+ "IFGE", // 156 (0x9c)
+ "IFGT", // 157 (0x9d)
+ "IFLE", // 158 (0x9e)
+ "IF_ICMPEQ", // 159 (0x9f)
+ "IF_ICMPNE", // 160 (0xa0)
+ "IF_ICMPLT", // 161 (0xa1)
+ "IF_ICMPGE", // 162 (0xa2)
+ "IF_ICMPGT", // 163 (0xa3)
+ "IF_ICMPLE", // 164 (0xa4)
+ "IF_ACMPEQ", // 165 (0xa5)
+ "IF_ACMPNE", // 166 (0xa6)
+ "GOTO", // 167 (0xa7)
+ "JSR", // 168 (0xa8)
+ "RET", // 169 (0xa9)
+ "TABLESWITCH", // 170 (0xaa)
+ "LOOKUPSWITCH", // 171 (0xab)
+ "IRETURN", // 172 (0xac)
+ "LRETURN", // 173 (0xad)
+ "FRETURN", // 174 (0xae)
+ "DRETURN", // 175 (0xaf)
+ "ARETURN", // 176 (0xb0)
+ "RETURN", // 177 (0xb1)
+ "GETSTATIC", // 178 (0xb2)
+ "PUTSTATIC", // 179 (0xb3)
+ "GETFIELD", // 180 (0xb4)
+ "PUTFIELD", // 181 (0xb5)
+ "INVOKEVIRTUAL", // 182 (0xb6)
+ "INVOKESPECIAL", // 183 (0xb7)
+ "INVOKESTATIC", // 184 (0xb8)
+ "INVOKEINTERFACE", // 185 (0xb9)
+ "INVOKEDYNAMIC", // 186 (0xba)
+ "NEW", // 187 (0xbb)
+ "NEWARRAY", // 188 (0xbc)
+ "ANEWARRAY", // 189 (0xbd)
+ "ARRAYLENGTH", // 190 (0xbe)
+ "ATHROW", // 191 (0xbf)
+ "CHECKCAST", // 192 (0xc0)
+ "INSTANCEOF", // 193 (0xc1)
+ "MONITORENTER", // 194 (0xc2)
+ "MONITOREXIT", // 195 (0xc3)
+ "WIDE", // 196 (0xc4)
+ "MULTIANEWARRAY", // 197 (0xc5)
+ "IFNULL", // 198 (0xc6)
+ "IFNONNULL" // 199 (0xc7)
+ };
+
+ /**
+ * The names of the {@code operand} values of the {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn} method when {@code opcode} is {@code NEWARRAY}.
+ */
+ public static final String[] TYPES = {
+ "",
+ "",
+ "",
+ "",
+ "T_BOOLEAN",
+ "T_CHAR",
+ "T_FLOAT",
+ "T_DOUBLE",
+ "T_BYTE",
+ "T_SHORT",
+ "T_INT",
+ "T_LONG"
+ };
+
+ /** The names of the {@code tag} field values for {@link org.apache.tapestry5.internal.plastic.asm.Handle}. */
+ public static final String[] HANDLE_TAG = {
+ "",
+ "H_GETFIELD",
+ "H_GETSTATIC",
+ "H_PUTFIELD",
+ "H_PUTSTATIC",
+ "H_INVOKEVIRTUAL",
+ "H_INVOKESTATIC",
+ "H_INVOKESPECIAL",
+ "H_NEWINVOKESPECIAL",
+ "H_INVOKEINTERFACE"
+ };
+
+ /** Message of the UnsupportedOperationException thrown by methods which must be overridden. */
+ private static final String UNSUPPORTED_OPERATION = "Must be overridden";
+
+ /**
+ * The ASM API version implemented by this class. The value of this field must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected final int api;
+
+ /**
+ * A buffer that can be used to create strings.
+ *
+ * @deprecated use {@link #stringBuilder} instead.
+ */
+ @Deprecated protected final StringBuffer buf;
+
+ /** The builder used to build strings in the various visit methods. */
+ protected final StringBuilder stringBuilder;
+
+ /**
+ * The text to be printed. Since the code of methods is not necessarily visited in sequential
+ * order, one method after the other, but can be interlaced (some instructions from method one,
+ * then some instructions from method two, then some instructions from method one again...), it is
+ * not possible to print the visited instructions directly to a sequential stream. A class is
+ * therefore printed in a two steps process: a string tree is constructed during the visit, and
+ * printed to a sequential stream at the end of the visit. This string tree is stored in this
+ * field, as a string list that can contain other string lists, which can themselves contain other
+ * string lists, and so on.
+ */
+ public final List<Object> text;
+
+ // -----------------------------------------------------------------------------------------------
+ // Constructor
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link Printer}.
+ *
+ * @param api the ASM API version implemented by this printer. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected Printer(final int api) {
+ this.api = api;
+ this.buf = null;
+ this.stringBuilder = new StringBuilder();
+ this.text = new ArrayList<Object>();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Classes
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Class header. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
+ *
+ * @param version the class version. The minor version is stored in the 16 most significant bits,
+ * and the major version in the 16 least significant bits.
+ * @param access the class's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the class is deprecated.
+ * @param name the internal name of the class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ * @param signature the signature of this class. May be {@literal null} if the class is not a
+ * generic one, and does not extend or implement generic classes or interfaces.
+ * @param superName the internal of name of the super class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}). For interfaces, the super class is {@link
+ * Object}. May be {@literal null}, but only for the {@link Object} class.
+ * @param interfaces the internal names of the class's interfaces (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}). May be {@literal null}.
+ */
+ public abstract void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces);
+
+ /**
+ * Class source. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
+ *
+ * @param source the name of the source file from which the class was compiled. May be {@literal
+ * null}.
+ * @param debug additional debug information to compute the correspondence between source and
+ * compiled elements of the class. May be {@literal null}.
+ */
+ public abstract void visitSource(String source, String debug);
+
+ /**
+ * Module. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitModule}.
+ *
+ * @param name the fully qualified name (using dots) of the module.
+ * @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
+ * ACC_MANDATED}.
+ * @param version the module version, or {@literal null}.
+ * @return the printer.
+ */
+ public Printer visitModule(final String name, final int access, final String version) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Visits the nest host class of the class. A nest is a set of classes of the same package that
+ * share access to their private members. One of these classes, called the host, lists the other
+ * members of the nest, which in turn should link to the host of their nest. This method must be
+ * called only once and only if the visited class is a non-host member of a nest. A class is
+ * implicitly its own nest, so it's invalid to call this method with the visited class name as
+ * argument.
+ *
+ * @param nestHost the internal name of the host class of the nest.
+ */
+ public void visitNestHost(final String nestHost) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Class outer class. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
+ *
+ * @param owner internal name of the enclosing class of the class.
+ * @param name the name of the method that contains the class, or {@literal null} if the class is
+ * not enclosed in a method of its enclosing class.
+ * @param descriptor the descriptor of the method that contains the class, or {@literal null} if
+ * the class is not enclosed in a method of its enclosing class.
+ */
+ public abstract void visitOuterClass(String owner, String name, String descriptor);
+
+ /**
+ * Class annotation. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public abstract Printer visitClassAnnotation(String descriptor, boolean visible);
+
+ /**
+ * Class type annotation. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitTypeAnnotation}.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#CLASS_TYPE_PARAMETER}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#CLASS_EXTENDS}. See {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public Printer visitClassTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Class attribute. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
+ *
+ * @param attribute an attribute.
+ */
+ public abstract void visitClassAttribute(Attribute attribute);
+
+ /**
+ * Visits a member of the nest. A nest is a set of classes of the same package that share access
+ * to their private members. One of these classes, called the host, lists the other members of the
+ * nest, which in turn should link to the host of their nest. This method must be called only if
+ * the visited class is the host of a nest. A nest host is implicitly a member of its own nest, so
+ * it's invalid to call this method with the visited class name as argument.
+ *
+ * @param nestMember the internal name of a nest member.
+ */
+ public void visitNestMember(final String nestMember) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Class inner name. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
+ *
+ * @param name the internal name of an inner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ * @param outerName the internal name of the class to which the inner class belongs (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}). May be {@literal null} for not member classes.
+ * @param innerName the (simple) name of the inner class inside its enclosing class. May be
+ * {@literal null} for anonymous inner classes.
+ * @param access the access flags of the inner class as originally declared in the enclosing
+ * class.
+ */
+ public abstract void visitInnerClass(String name, String outerName, String innerName, int access);
+
+ /**
+ * Class field. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
+ *
+ * @param access the field's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the field is synthetic and/or deprecated.
+ * @param name the field's name.
+ * @param descriptor the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param signature the field's signature. May be {@literal null} if the field's type does not use
+ * generic types.
+ * @param value the field's initial value. This parameter, which may be {@literal null} if the
+ * field does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link
+ * Long}, a {@link Double} or a {@link String} (for {@code int}, {@code float}, {@code long}
+ * or {@code String} fields respectively). <i>This parameter is only used for static
+ * fields</i>. Its value is ignored for non static fields, which must be initialized through
+ * bytecode instructions in constructors or methods.
+ * @return the printer.
+ */
+ public abstract Printer visitField(
+ int access, String name, String descriptor, String signature, Object value);
+
+ /**
+ * Class method. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
+ *
+ * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the method is synthetic and/or deprecated.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param signature the method's signature. May be {@literal null} if the method parameters,
+ * return type and exceptions do not use generic types.
+ * @param exceptions the internal names of the method's exception classes (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}). May be {@literal null}.
+ * @return the printer.
+ */
+ public abstract Printer visitMethod(
+ int access, String name, String descriptor, String signature, String[] exceptions);
+
+ /** Class end. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}. */
+ public abstract void visitClassEnd();
+
+ // -----------------------------------------------------------------------------------------------
+ // Modules
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Module main class. See {@link org.apache.tapestry5.internal.plastic.asm.ModuleVisitor#visitMainClass}.
+ *
+ * @param mainClass the internal name of the main class of the current module.
+ */
+ public void visitMainClass(final String mainClass) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Module package. See {@link org.apache.tapestry5.internal.plastic.asm.ModuleVisitor#visitPackage}.
+ *
+ * @param packaze the internal name of a package.
+ */
+ public void visitPackage(final String packaze) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Module require. See {@link org.apache.tapestry5.internal.plastic.asm.ModuleVisitor#visitRequire}.
+ *
+ * @param module the fully qualified name (using dots) of the dependence.
+ * @param access the access flag of the dependence among {@code ACC_TRANSITIVE}, {@code
+ * ACC_STATIC_PHASE}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ * @param version the module version at compile time, or {@literal null}.
+ */
+ public void visitRequire(final String module, final int access, final String version) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Module export. See {@link org.apache.tapestry5.internal.plastic.asm.ModuleVisitor#visitExport}.
+ *
+ * @param packaze the internal name of the exported package.
+ * @param access the access flag of the exported package, valid values are among {@code
+ * ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ * @param modules the fully qualified names (using dots) of the modules that can access the public
+ * classes of the exported package, or {@literal null}.
+ */
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Module open. See {@link org.apache.tapestry5.internal.plastic.asm.ModuleVisitor#visitOpen}.
+ *
+ * @param packaze the internal name of the opened package.
+ * @param access the access flag of the opened package, valid values are among {@code
+ * ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ * @param modules the fully qualified names (using dots) of the modules that can use deep
+ * reflection to the classes of the open package, or {@literal null}.
+ */
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Module use. See {@link org.apache.tapestry5.internal.plastic.asm.ModuleVisitor#visitUse}.
+ *
+ * @param service the internal name of the service.
+ */
+ public void visitUse(final String service) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Module provide. See {@link org.apache.tapestry5.internal.plastic.asm.ModuleVisitor#visitProvide}.
+ *
+ * @param service the internal name of the service.
+ * @param providers the internal names of the implementations of the service (there is at least
+ * one provider).
+ */
+ public void visitProvide(final String service, final String... providers) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /** Module end. See {@link org.apache.tapestry5.internal.plastic.asm.ModuleVisitor#visitEnd}. */
+ public void visitModuleEnd() {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Annotations
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Annotation value. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
+ *
+ * @param name the value name.
+ * @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link
+ * Character}, {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+ * {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.Type} of {@link org.apache.tapestry5.internal.plastic.asm.Type#OBJECT}
+ * or {@link org.apache.tapestry5.internal.plastic.asm.Type#ARRAY} sort. This value can also be an array of byte,
+ * boolean, short, char, int, long, float or double values (this is equivalent to using {@link
+ * #visitArray} and visiting each array element in turn, but is more convenient).
+ */
+ // DontCheck(OverloadMethodsDeclarationOrder): overloads are semantically different.
+ public abstract void visit(String name, Object value);
+
+ /**
+ * Annotation enum value. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
+ *
+ * @param name the value name.
+ * @param descriptor the class descriptor of the enumeration class.
+ * @param value the actual enumeration value.
+ */
+ public abstract void visitEnum(String name, String descriptor, String value);
+
+ /**
+ * Nested annotation value. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
+ *
+ * @param name the value name.
+ * @param descriptor the class descriptor of the nested annotation class.
+ * @return the printer.
+ */
+ public abstract Printer visitAnnotation(String name, String descriptor);
+
+ /**
+ * Annotation array value. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
+ *
+ * @param name the value name.
+ * @return the printer.
+ */
+ public abstract Printer visitArray(String name);
+
+ /** Annotation end. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}. */
+ public abstract void visitAnnotationEnd();
+
+ // -----------------------------------------------------------------------------------------------
+ // Fields
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Field annotation. See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public abstract Printer visitFieldAnnotation(String descriptor, boolean visible);
+
+ /**
+ * Field type annotation. See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitTypeAnnotation}.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#FIELD}. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public Printer visitFieldTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Field attribute. See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
+ *
+ * @param attribute an attribute.
+ */
+ public abstract void visitFieldAttribute(Attribute attribute);
+
+ /** Field end. See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}. */
+ public abstract void visitFieldEnd();
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Method parameter. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameter(String, int)}.
+ *
+ * @param name parameter name or null if none is provided.
+ * @param access the parameter's access flags, only {@code ACC_FINAL}, {@code ACC_SYNTHETIC}
+ * or/and {@code ACC_MANDATED} are allowed (see {@link Opcodes}).
+ */
+ public void visitParameter(final String name, final int access) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Method default annotation. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
+ *
+ * @return the printer.
+ */
+ public abstract Printer visitAnnotationDefault();
+
+ /**
+ * Method annotation. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public abstract Printer visitMethodAnnotation(String descriptor, boolean visible);
+
+ /**
+ * Method type annotation. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeAnnotation}.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#METHOD_TYPE_PARAMETER}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#METHOD_TYPE_PARAMETER_BOUND}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#METHOD_RETURN}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#METHOD_RECEIVER}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#METHOD_FORMAL_PARAMETER} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#THROWS}. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public Printer visitMethodTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Number of method parameters that can have annotations. See {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotableParameterCount}.
+ *
+ * @param parameterCount the number of method parameters than can have annotations. This number
+ * must be less or equal than the number of parameter types in the method descriptor. It can
+ * be strictly less when a method has synthetic parameters and when these parameters are
+ * ignored when computing parameter indices for the purpose of parameter annotations (see
+ * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18).
+ * @param visible {@literal true} to define the number of method parameters that can have
+ * annotations visible at runtime, {@literal false} to define the number of method parameters
+ * that can have annotations invisible at runtime.
+ * @return the printer.
+ */
+ public Printer visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Method parameter annotation. See {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+ *
+ * @param parameter the parameter index. This index must be strictly smaller than the number of
+ * parameters in the method descriptor, and strictly smaller than the parameter count
+ * specified in {@link #visitAnnotableParameterCount}. Important note: <i>a parameter index i
+ * is not required to correspond to the i'th parameter descriptor in the method
+ * descriptor</i>, in particular in case of synthetic parameters (see
+ * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18).
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public abstract Printer visitParameterAnnotation(
+ int parameter, String descriptor, boolean visible);
+
+ /**
+ * Method attribute. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
+ *
+ * @param attribute an attribute.
+ */
+ public abstract void visitMethodAttribute(Attribute attribute);
+
+ /** Method start. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}. */
+ public abstract void visitCode();
+
+ /**
+ * Method stack frame. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+ *
+ * @param type the type of this stack map frame. Must be {@link Opcodes#F_NEW} for expanded
+ * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
+ * Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
+ * @param numLocal the number of local variables in the visited frame.
+ * @param local the local variable types in this frame. This array must not be modified. Primitive
+ * types are represented by {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link
+ * Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a single element).
+ * Reference types are represented by String objects (representing internal names), and
+ * uninitialized types by Label objects (this label designates the NEW instruction that
+ * created this uninitialized value).
+ * @param numStack the number of operand stack elements in the visited frame.
+ * @param stack the operand stack types in this frame. This array must not be modified. Its
+ * content has the same format as the "local" array.
+ */
+ public abstract void visitFrame(
+ int type, int numLocal, Object[] local, int numStack, Object[] stack);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}
+ *
+ * @param opcode the opcode of the instruction to be visited. This opcode is either NOP,
+ * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5,
+ * LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,
+ * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE, DASTORE,
+ * AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2,
+ * SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
+ * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR,
+ * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I,
+ * D2L, D2F, I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+ * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, or MONITOREXIT.
+ */
+ public abstract void visitInsn(int opcode);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
+ *
+ * @param opcode the opcode of the instruction to be visited. This opcode is either BIPUSH, SIPUSH
+ * or NEWARRAY.
+ * @param operand the operand of the instruction to be visited.<br>
+ * When opcode is BIPUSH, operand value should be between Byte.MIN_VALUE and Byte.MAX_VALUE.
+ * <br>
+ * When opcode is SIPUSH, operand value should be between Short.MIN_VALUE and Short.MAX_VALUE.
+ * <br>
+ * When opcode is NEWARRAY, operand value should be one of {@link Opcodes#T_BOOLEAN}, {@link
+ * Opcodes#T_CHAR}, {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, {@link Opcodes#T_BYTE},
+ * {@link Opcodes#T_SHORT}, {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+ */
+ public abstract void visitIntInsn(int opcode, int operand);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
+ *
+ * @param opcode the opcode of the local variable instruction to be visited. This opcode is either
+ * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var the operand of the instruction to be visited. This operand is the index of a local
+ * variable.
+ */
+ public abstract void visitVarInsn(int opcode, int var);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either NEW,
+ * ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param type the operand of the instruction to be visited. This operand must be the internal
+ * name of an object or array class (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ */
+ public abstract void visitTypeInsn(int opcode, String type);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either
+ * GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner the internal name of the field's owner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ * @param name the field's name.
+ * @param descriptor the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ */
+ public abstract void visitFieldInsn(int opcode, String owner, String name, String descriptor);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ boolean isInterface = opcode == Opcodes.INVOKEINTERFACE;
+ visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
}
-
- public void visitUse(String service) {
- throw new RuntimeException("Must be overriden");
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param isInterface if the method's owner class is an interface.
+ */
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ if (isInterface != (opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new IllegalArgumentException("INVOKESPECIAL/STATIC on interfaces require ASM 5");
+ }
+ visitMethodInsn(opcode, owner, name, descriptor);
+ return;
}
-
- public void visitProvide(String service, String... providers) {
- throw new RuntimeException("Must be overriden");
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+ *
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param bootstrapMethodHandle the bootstrap method.
+ * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type} or {@link Handle} value. This method is allowed to modify the
+ * content of the array so a caller should expect that this array may change.
+ */
+ public abstract void visitInvokeDynamicInsn(
+ String name,
+ String descriptor,
+ Handle bootstrapMethodHandle,
+ Object... bootstrapMethodArguments);
+
+ /**
+ * Method jump instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either IFEQ,
+ * IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT,
+ * IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label the operand of the instruction to be visited. This operand is a label that
+ * designates the instruction to which the jump instruction may jump.
+ */
+ public abstract void visitJumpInsn(int opcode, Label label);
+
+ /**
+ * Method label. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
+ *
+ * @param label a {@link Label} object.
+ */
+ public abstract void visitLabel(Label label);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
+ *
+ * @param value the constant to be loaded on the stack. This parameter must be a non null {@link
+ * Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link
+ * Type} of OBJECT or ARRAY sort for {@code .class} constants, for classes whose version is
+ * 49, a {@link Type} of METHOD sort for MethodType, a {@link Handle} for MethodHandle
+ * constants, for classes whose version is 51 or a {@link ConstantDynamic} for a constant
+ * dynamic for classes whose version is 55.
+ */
+ public abstract void visitLdcInsn(Object value);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
+ *
+ * @param var index of the local variable to be incremented.
+ * @param increment amount to increment the local variable by.
+ */
+ public abstract void visitIincInsn(int var, int increment);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+ *
+ * @param min the minimum key value.
+ * @param max the maximum key value.
+ * @param dflt beginning of the default handler block.
+ * @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the
+ * handler block for the {@code min + i} key.
+ */
+ public abstract void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
+ *
+ * @param dflt beginning of the default handler block.
+ * @param keys the values of the keys.
+ * @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the
+ * handler block for the {@code keys[i]} key.
+ */
+ public abstract void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels);
+
+ /**
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
+ *
+ * @param descriptor an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param numDimensions the number of dimensions of the array to allocate.
+ */
+ public abstract void visitMultiANewArrayInsn(String descriptor, int numDimensions);
+
+ /**
+ * Instruction type annotation. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsnAnnotation}.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#INSTANCEOF}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#NEW}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#CONSTRUCTOR_REFERENCE}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#METHOD_REFERENCE}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#CAST}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public Printer visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Method exception handler. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
+ *
+ * @param start the beginning of the exception handler's scope (inclusive).
+ * @param end the end of the exception handler's scope (exclusive).
+ * @param handler the beginning of the exception handler's code.
+ * @param type the internal name of the type of exceptions handled by the handler, or {@literal
+ * null} to catch any exceptions (for "finally" blocks).
+ */
+ public abstract void visitTryCatchBlock(Label start, Label end, Label handler, String type);
+
+ /**
+ * Try catch block type annotation. See {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#EXCEPTION_PARAMETER}. See {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public Printer visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Method debug info. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+ *
+ * @param name the name of a local variable.
+ * @param descriptor the type descriptor of this local variable.
+ * @param signature the type signature of this local variable. May be {@literal null} if the local
+ * variable type does not use generic types.
+ * @param start the first instruction corresponding to the scope of this local variable
+ * (inclusive).
+ * @param end the last instruction corresponding to the scope of this local variable (exclusive).
+ * @param index the local variable's index.
+ */
+ public abstract void visitLocalVariable(
+ String name, String descriptor, String signature, Label start, Label end, int index);
+
+ /**
+ * Local variable type annotation. See {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#LOCAL_VARIABLE} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference#RESOURCE_VARIABLE}. See {@link
+ * org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param start the fist instructions corresponding to the continuous ranges that make the scope
+ * of this local variable (inclusive).
+ * @param end the last instructions corresponding to the continuous ranges that make the scope of
+ * this local variable (exclusive). This array must have the same size as the 'start' array.
+ * @param index the local variable's index in each range. This array must have the same size as
+ * the 'start' array.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return the printer.
+ */
+ public Printer visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ /**
+ * Method debug info. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
+ *
+ * @param line a line number. This number refers to the source file from which the class was
+ * compiled.
+ * @param start the first instruction corresponding to this line number.
+ */
+ public abstract void visitLineNumber(int line, Label start);
+
+ /**
+ * Method max stack and max locals. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
+ *
+ * @param maxStack maximum stack size of the method.
+ * @param maxLocals maximum number of local variables for the method.
+ */
+ public abstract void visitMaxs(int maxStack, int maxLocals);
+
+ /** Method end. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}. */
+ public abstract void visitMethodEnd();
+
+ // -----------------------------------------------------------------------------------------------
+ // Print and utility methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the text constructed by this visitor.
+ *
+ * @return the text constructed by this visitor. See {@link #text}.
+ */
+ public List<Object> getText() {
+ return text;
+ }
+
+ /**
+ * Prints the text constructed by this visitor.
+ *
+ * @param printWriter the print writer to be used.
+ */
+ public void print(final PrintWriter printWriter) {
+ printList(printWriter, text);
+ }
+
+ /**
+ * Prints the given string tree.
+ *
+ * @param printWriter the writer to be used to print the tree.
+ * @param list a string tree, i.e., a string list that can contain other string lists, and so on
+ * recursively.
+ */
+ static void printList(final PrintWriter printWriter, final List<?> list) {
+ for (Object o : list) {
+ if (o instanceof List) {
+ printList(printWriter, (List<?>) o);
+ } else {
+ printWriter.print(o.toString());
+ }
}
-
- /**
- * Module end. See {@link org.objectweb.asm.ModuleVisitor#visitEnd}.
- */
- public void visitModuleEnd() {
- throw new RuntimeException("Must be overriden");
- }
-
- // ------------------------------------------------------------------------
- // Annotations
- // ------------------------------------------------------------------------
-
- /**
- * Annotation value.
- * See {@link org.objectweb.asm.AnnotationVisitor#visit}.
- *
- * @param name
- * the value name.
- * @param value
- * the actual value, whose type must be {@link Byte},
- * {@link Boolean}, {@link Character}, {@link Short},
- * {@link Integer} , {@link Long}, {@link Float}, {@link Double},
- * {@link String} or {@link org.objectweb.asm.Type}
- * or OBJECT or ARRAY sort.
- * This value can also be an array of byte, boolean, short, char, int,
- * long, float or double values (this is equivalent to using
- * {@link #visitArray visitArray} and visiting each array element
- * in turn, but is more convenient).
- */
- public abstract void visit(final String name, final Object value);
-
- /**
- * Annotation enum value.
- * See {@link org.objectweb.asm.AnnotationVisitor#visitEnum}.
- *
- * Visits an enumeration value of the annotation.
- *
- * @param name
- * the value name.
- * @param desc
- * the class descriptor of the enumeration class.
- * @param value
- * the actual enumeration value.
- */
- public abstract void visitEnum(final String name, final String desc,
- final String value);
-
- /**
- * Nested annotation value.
- * See {@link org.objectweb.asm.AnnotationVisitor#visitAnnotation}.
- *
- * @param name
- * the value name.
- * @param desc
- * the class descriptor of the nested annotation class.
- * @return the printer
- */
- public abstract Printer visitAnnotation(final String name, final String desc);
-
- /**
- * Annotation array value.
- * See {@link org.objectweb.asm.AnnotationVisitor#visitArray}.
- *
- * Visits an array value of the annotation. Note that arrays of primitive
- * types (such as byte, boolean, short, char, int, long, float or double)
- * can be passed as value to {@link #visit visit}. This is what
- * {@link org.objectweb.asm.ClassReader} does.
- *
- * @param name
- * the value name.
- * @return the printer
- */
- public abstract Printer visitArray(final String name);
-
- /**
- * Annotation end. See {@link org.objectweb.asm.AnnotationVisitor#visitEnd}.
- */
- public abstract void visitAnnotationEnd();
-
- // ------------------------------------------------------------------------
- // Fields
- // ------------------------------------------------------------------------
-
- /**
- * Field annotation.
- * See {@link org.objectweb.asm.FieldVisitor#visitAnnotation}.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return the printer
- */
- public abstract Printer visitFieldAnnotation(final String desc,
- final boolean visible);
-
- /**
- * Field type annotation.
- * See {@link org.objectweb.asm.FieldVisitor#visitTypeAnnotation}.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be {@link org.objectweb.asm.TypeReference#FIELD FIELD}.
- * See {@link org.objectweb.asm.TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return the printer
- */
- public Printer visitFieldTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
- }
-
- /**
- * Field attribute.
- * See {@link org.objectweb.asm.FieldVisitor#visitAttribute}.
- *
- * @param attr
- * an attribute.
- */
- public abstract void visitFieldAttribute(final Attribute attr);
-
- /**
- * Field end.
- * See {@link org.objectweb.asm.FieldVisitor#visitEnd}.
- */
- public abstract void visitFieldEnd();
-
- // ------------------------------------------------------------------------
- // Methods
- // ------------------------------------------------------------------------
-
- /**
- * Method parameter.
- * See {@link org.objectweb.asm.MethodVisitor#visitParameter(String, int)}.
- *
- * @param name
- * parameter name or null if none is provided.
- * @param access
- * the parameter's access flags, only <tt>ACC_FINAL</tt>,
- * <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
- * allowed (see {@link Opcodes}).
- */
- public void visitParameter(String name, int access) {
- throw new RuntimeException("Must be overriden");
- }
-
- /**
- * Method default annotation.
- * See {@link org.objectweb.asm.MethodVisitor#visitAnnotationDefault}.
- *
- * @return the printer
- */
- public abstract Printer visitAnnotationDefault();
-
- /**
- * Method annotation.
- * See {@link org.objectweb.asm.MethodVisitor#visitAnnotation}.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return the printer
- */
- public abstract Printer visitMethodAnnotation(final String desc,
- final boolean visible);
-
- /**
- * Method type annotation.
- * See {@link org.objectweb.asm.MethodVisitor#visitTypeAnnotation}.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be {@link org.objectweb.asm.TypeReference#FIELD FIELD}.
- * See {@link org.objectweb.asm.TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return the printer
- */
- public Printer visitMethodTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
- }
-
- /**
- * Method parameter annotation.
- * See {@link org.objectweb.asm.MethodVisitor#visitParameterAnnotation}.
- *
- * @param parameter
- * the parameter index.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return the printer
- */
- public abstract Printer visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible);
-
- /**
- * Method attribute.
- * See {@link org.objectweb.asm.MethodVisitor#visitAttribute}.
- *
- * @param attr
- * an attribute.
- */
- public abstract void visitMethodAttribute(final Attribute attr);
-
- /**
- * Method start.
- * See {@link org.objectweb.asm.MethodVisitor#visitCode}.
- */
- public abstract void visitCode();
-
- /**
- * Method stack frame.
- * See {@link org.objectweb.asm.MethodVisitor#visitFrame}.
- *
- * Visits the current state of the local variables and operand stack
- * elements. This method must(*) be called <i>just before</i> any
- * instruction <b>i</b> that follows an unconditional branch instruction
- * such as GOTO or THROW, that is the target of a jump instruction, or that
- * starts an exception handler block. The visited types must describe the
- * values of the local variables and of the operand stack elements <i>just
- * before</i> <b>i</b> is executed.<br>
- * <br>
- * (*) this is mandatory only for classes whose version is greater than or
- * equal to {@link Opcodes#V1_6 V1_6}. <br>
- * <br>
- * The frames of a method must be given either in expanded form, or in
- * compressed form (all frames must use the same format, i.e. you must not
- * mix expanded and compressed frames within a single method):
- * <ul>
- * <li>In expanded form, all frames must have the F_NEW type.</li>
- * <li>In compressed form, frames are basically "deltas" from the state of
- * the previous frame:
- * <ul>
- * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
- * locals as the previous frame and with the empty stack.</li>
- * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same
- * locals as the previous frame and with single value on the stack (
- * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the
- * type of the stack item).</li>
- * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
- * the same as the locals in the previous frame, except that additional
- * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
- * <code>local</code> elements contains values representing added types).</li>
- * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
- * same as the locals in the previous frame, except that the last 1-3 locals
- * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>
- * <li>{@link Opcodes#F_FULL} representing complete frame data.</li>
- * </ul>
- * </li>
- * </ul>
- * <br>
- * In both cases the first frame, corresponding to the method's parameters
- * and access flags, is implicit and must not be visited. Also, it is
- * illegal to visit two or more frames for the same code location (i.e., at
- * least one instruction must be visited between two calls to visitFrame).
- *
- * @param type
- * the type of this stack map frame. Must be
- * {@link Opcodes#F_NEW} for expanded frames, or
- * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
- * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
- * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for
- * compressed frames.
- * @param nLocal
- * the number of local variables in the visited frame.
- * @param local
- * the local variable types in this frame. This array must not be
- * modified. Primitive types are represented by
- * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
- * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
- * represented by a single element). Reference types are
- * represented by String objects (representing internal names),
- * and uninitialized types by Label objects (this label
- * designates the NEW instruction that created this uninitialized
- * value).
- * @param nStack
- * the number of operand stack elements in the visited frame.
- * @param stack
- * the operand stack types in this frame. This array must not be
- * modified. Its content has the same format as the "local"
- * array.
- * @throws IllegalStateException
- * if a frame is visited just after another one, without any
- * instruction between the two (unless this frame is a
- * Opcodes#F_SAME frame, in which case it is silently ignored).
- */
- public abstract void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack);
-
- /**
- * Method instruction.
- * See {@link org.objectweb.asm.MethodVisitor#visitInsn}
- *
- * @param opcode
- * the opcode of the instruction to be visited. This opcode is
- * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
- * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
- * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
- * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
- * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
- * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
- * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
- * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
- * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
- * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
- * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
- * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
- * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
- * or MONITOREXIT.
- */
- public abstract void visitInsn(final int opcode);
-
- /**
- * Method instruction.
- * See {@link org.objectweb.asm.MethodVisitor#visitIntInsn}.
- *
- * @param opcode
- * the opcode of the instruction to be visited. This opcode is
- * either BIPUSH, SIPUSH or NEWARRAY.
- * @param operand
- * the operand of the instruction to be visited.<br>
- * When opcode is BIPUSH, operand value should be between
- * Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
- * When opcode is SIPUSH, operand value should be between
- * Short.MIN_VALUE and Short.MAX_VALUE.<br>
- * When opcode is NEWARRAY, operand value should be one of
- * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
- * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
- * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
- * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
- */
- public abstract void visitIntInsn(final int opcode, final int operand);
-
- /**
- * Method instruction.
- * See {@link org.objectweb.asm.MethodVisitor#visitVarInsn}.
- *
- * @param opcode
- * the opcode of the local variable instruction to be visited.
- * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD,
- * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var
- * the operand of the instruction to be visited. This operand is
- * the index of a local variable.
- */
- public abstract void visitVarInsn(final int opcode, final int var);
-
- /**
- * Method instruction.
- * See {@link org.objectweb.asm.MethodVisitor#visitTypeInsn}.
- *
- /**
- * Visits a type instruction. A type instruction is an instruction that
- * takes the internal name of a class as parameter.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param type
- * the operand of the instruction to be visited. This operand
- * must be the internal name of an object or array class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- */
- public abstract void visitTypeInsn(final int opcode, final String type);
-
- /**
- * Method instruction.
- * See {@link org.objectweb.asm.MethodVisitor#visitFieldInsn}.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner
- * the internal name of the field's owner class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link org.objectweb.asm.Type Type}).
- */
- public abstract void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc);
-
- /**
- * Method instruction.
- * See {@link org.objectweb.asm.MethodVisitor#visitMethodInsn}.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner
- * the internal name of the method's owner class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInt
<TRUNCATED>
[45/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
old mode 100644
new mode 100755
index 24506f9..f36e62d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
@@ -1,339 +1,361 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A dynamically extensible vector of bytes. This class is roughly equivalent to
- * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
- *
+ * A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream
+ * on top of a ByteArrayOutputStream, but is more efficient.
+ *
* @author Eric Bruneton
*/
public class ByteVector {
- /**
- * The content of this vector.
- */
- byte[] data;
+ /** The content of this vector. Only the first {@link #length} bytes contain real data. */
+ byte[] data;
- /**
- * Actual number of bytes in this vector.
- */
- int length;
+ /** The actual number of bytes in this vector. */
+ int length;
- /**
- * Constructs a new {@link ByteVector ByteVector} with a default initial
- * size.
- */
- public ByteVector() {
- data = new byte[64];
- }
+ /** Constructs a new {@link ByteVector} with a default initial capacity. */
+ public ByteVector() {
+ data = new byte[64];
+ }
+
+ /**
+ * Constructs a new {@link ByteVector} with the given initial capacity.
+ *
+ * @param initialCapacity the initial capacity of the byte vector to be constructed.
+ */
+ public ByteVector(final int initialCapacity) {
+ data = new byte[initialCapacity];
+ }
- /**
- * Constructs a new {@link ByteVector ByteVector} with the given initial
- * size.
- *
- * @param initialSize
- * the initial size of the byte vector to be constructed.
- */
- public ByteVector(final int initialSize) {
- data = new byte[initialSize];
+ /**
+ * Constructs a new {@link ByteVector} from the given initial data.
+ *
+ * @param data the initial data of the new byte vector.
+ */
+ ByteVector(final byte[] data) {
+ this.data = data;
+ this.length = data.length;
+ }
+
+ /**
+ * Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary.
+ *
+ * @param byteValue a byte.
+ * @return this byte vector.
+ */
+ public ByteVector putByte(final int byteValue) {
+ int currentLength = length;
+ if (currentLength + 1 > data.length) {
+ enlarge(1);
}
+ data[currentLength++] = (byte) byteValue;
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts a byte into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param b
- * a byte.
- * @return this byte vector.
- */
- public ByteVector putByte(final int b) {
- int length = this.length;
- if (length + 1 > data.length) {
- enlarge(1);
- }
- data[length++] = (byte) b;
- this.length = length;
- return this;
+ /**
+ * Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary.
+ *
+ * @param byteValue1 a byte.
+ * @param byteValue2 another byte.
+ * @return this byte vector.
+ */
+ final ByteVector put11(final int byteValue1, final int byteValue2) {
+ int currentLength = length;
+ if (currentLength + 2 > data.length) {
+ enlarge(2);
}
+ byte[] currentData = data;
+ currentData[currentLength++] = (byte) byteValue1;
+ currentData[currentLength++] = (byte) byteValue2;
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts two bytes into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param b1
- * a byte.
- * @param b2
- * another byte.
- * @return this byte vector.
- */
- ByteVector put11(final int b1, final int b2) {
- int length = this.length;
- if (length + 2 > data.length) {
- enlarge(2);
- }
- byte[] data = this.data;
- data[length++] = (byte) b1;
- data[length++] = (byte) b2;
- this.length = length;
- return this;
+ /**
+ * Puts a short into this byte vector. The byte vector is automatically enlarged if necessary.
+ *
+ * @param shortValue a short.
+ * @return this byte vector.
+ */
+ public ByteVector putShort(final int shortValue) {
+ int currentLength = length;
+ if (currentLength + 2 > data.length) {
+ enlarge(2);
}
+ byte[] currentData = data;
+ currentData[currentLength++] = (byte) (shortValue >>> 8);
+ currentData[currentLength++] = (byte) shortValue;
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts a short into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param s
- * a short.
- * @return this byte vector.
- */
- public ByteVector putShort(final int s) {
- int length = this.length;
- if (length + 2 > data.length) {
- enlarge(2);
- }
- byte[] data = this.data;
- data[length++] = (byte) (s >>> 8);
- data[length++] = (byte) s;
- this.length = length;
- return this;
+ /**
+ * Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if
+ * necessary.
+ *
+ * @param byteValue a byte.
+ * @param shortValue a short.
+ * @return this byte vector.
+ */
+ final ByteVector put12(final int byteValue, final int shortValue) {
+ int currentLength = length;
+ if (currentLength + 3 > data.length) {
+ enlarge(3);
}
+ byte[] currentData = data;
+ currentData[currentLength++] = (byte) byteValue;
+ currentData[currentLength++] = (byte) (shortValue >>> 8);
+ currentData[currentLength++] = (byte) shortValue;
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts a byte and a short into this byte vector. The byte vector is
- * automatically enlarged if necessary.
- *
- * @param b
- * a byte.
- * @param s
- * a short.
- * @return this byte vector.
- */
- ByteVector put12(final int b, final int s) {
- int length = this.length;
- if (length + 3 > data.length) {
- enlarge(3);
- }
- byte[] data = this.data;
- data[length++] = (byte) b;
- data[length++] = (byte) (s >>> 8);
- data[length++] = (byte) s;
- this.length = length;
- return this;
+ /**
+ * Puts two bytes and a short into this byte vector. The byte vector is automatically enlarged if
+ * necessary.
+ *
+ * @param byteValue1 a byte.
+ * @param byteValue2 another byte.
+ * @param shortValue a short.
+ * @return this byte vector.
+ */
+ final ByteVector put112(final int byteValue1, final int byteValue2, final int shortValue) {
+ int currentLength = length;
+ if (currentLength + 4 > data.length) {
+ enlarge(4);
}
+ byte[] currentData = data;
+ currentData[currentLength++] = (byte) byteValue1;
+ currentData[currentLength++] = (byte) byteValue2;
+ currentData[currentLength++] = (byte) (shortValue >>> 8);
+ currentData[currentLength++] = (byte) shortValue;
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts an int into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param i
- * an int.
- * @return this byte vector.
- */
- public ByteVector putInt(final int i) {
- int length = this.length;
- if (length + 4 > data.length) {
- enlarge(4);
- }
- byte[] data = this.data;
- data[length++] = (byte) (i >>> 24);
- data[length++] = (byte) (i >>> 16);
- data[length++] = (byte) (i >>> 8);
- data[length++] = (byte) i;
- this.length = length;
- return this;
+ /**
+ * Puts an int into this byte vector. The byte vector is automatically enlarged if necessary.
+ *
+ * @param intValue an int.
+ * @return this byte vector.
+ */
+ public ByteVector putInt(final int intValue) {
+ int currentLength = length;
+ if (currentLength + 4 > data.length) {
+ enlarge(4);
}
+ byte[] currentData = data;
+ currentData[currentLength++] = (byte) (intValue >>> 24);
+ currentData[currentLength++] = (byte) (intValue >>> 16);
+ currentData[currentLength++] = (byte) (intValue >>> 8);
+ currentData[currentLength++] = (byte) intValue;
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts a long into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param l
- * a long.
- * @return this byte vector.
- */
- public ByteVector putLong(final long l) {
- int length = this.length;
- if (length + 8 > data.length) {
- enlarge(8);
- }
- byte[] data = this.data;
- int i = (int) (l >>> 32);
- data[length++] = (byte) (i >>> 24);
- data[length++] = (byte) (i >>> 16);
- data[length++] = (byte) (i >>> 8);
- data[length++] = (byte) i;
- i = (int) l;
- data[length++] = (byte) (i >>> 24);
- data[length++] = (byte) (i >>> 16);
- data[length++] = (byte) (i >>> 8);
- data[length++] = (byte) i;
- this.length = length;
- return this;
+ /**
+ * Puts one byte and two shorts into this byte vector. The byte vector is automatically enlarged
+ * if necessary.
+ *
+ * @param byteValue a byte.
+ * @param shortValue1 a short.
+ * @param shortValue2 another short.
+ * @return this byte vector.
+ */
+ final ByteVector put122(final int byteValue, final int shortValue1, final int shortValue2) {
+ int currentLength = length;
+ if (currentLength + 5 > data.length) {
+ enlarge(5);
}
+ byte[] currentData = data;
+ currentData[currentLength++] = (byte) byteValue;
+ currentData[currentLength++] = (byte) (shortValue1 >>> 8);
+ currentData[currentLength++] = (byte) shortValue1;
+ currentData[currentLength++] = (byte) (shortValue2 >>> 8);
+ currentData[currentLength++] = (byte) shortValue2;
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts an UTF8 string into this byte vector. The byte vector is
- * automatically enlarged if necessary.
- *
- * @param s
- * a String whose UTF8 encoded length must be less than 65536.
- * @return this byte vector.
- */
- public ByteVector putUTF8(final String s) {
- int charLength = s.length();
- if (charLength > 65535) {
- throw new IllegalArgumentException();
- }
- int len = length;
- if (len + 2 + charLength > data.length) {
- enlarge(2 + charLength);
- }
- byte[] data = this.data;
- // optimistic algorithm: instead of computing the byte length and then
- // serializing the string (which requires two loops), we assume the byte
- // length is equal to char length (which is the most frequent case), and
- // we start serializing the string right away. During the serialization,
- // if we find that this assumption is wrong, we continue with the
- // general method.
- data[len++] = (byte) (charLength >>> 8);
- data[len++] = (byte) charLength;
- for (int i = 0; i < charLength; ++i) {
- char c = s.charAt(i);
- if (c >= '\001' && c <= '\177') {
- data[len++] = (byte) c;
- } else {
- length = len;
- return encodeUTF8(s, i, 65535);
- }
- }
- length = len;
- return this;
+ /**
+ * Puts a long into this byte vector. The byte vector is automatically enlarged if necessary.
+ *
+ * @param longValue a long.
+ * @return this byte vector.
+ */
+ public ByteVector putLong(final long longValue) {
+ int currentLength = length;
+ if (currentLength + 8 > data.length) {
+ enlarge(8);
}
+ byte[] currentData = data;
+ int intValue = (int) (longValue >>> 32);
+ currentData[currentLength++] = (byte) (intValue >>> 24);
+ currentData[currentLength++] = (byte) (intValue >>> 16);
+ currentData[currentLength++] = (byte) (intValue >>> 8);
+ currentData[currentLength++] = (byte) intValue;
+ intValue = (int) longValue;
+ currentData[currentLength++] = (byte) (intValue >>> 24);
+ currentData[currentLength++] = (byte) (intValue >>> 16);
+ currentData[currentLength++] = (byte) (intValue >>> 8);
+ currentData[currentLength++] = (byte) intValue;
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts an UTF8 string into this byte vector. The byte vector is
- * automatically enlarged if necessary. The string length is encoded in two
- * bytes before the encoded characters, if there is space for that (i.e. if
- * this.length - i - 2 >= 0).
- *
- * @param s
- * the String to encode.
- * @param i
- * the index of the first character to encode. The previous
- * characters are supposed to have already been encoded, using
- * only one byte per character.
- * @param maxByteLength
- * the maximum byte length of the encoded string, including the
- * already encoded characters.
- * @return this byte vector.
- */
- ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
- int charLength = s.length();
- int byteLength = i;
- char c;
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- byteLength++;
- } else if (c > '\u07FF') {
- byteLength += 3;
- } else {
- byteLength += 2;
- }
- }
- if (byteLength > maxByteLength) {
- throw new IllegalArgumentException();
- }
- int start = length - i - 2;
- if (start >= 0) {
- data[start] = (byte) (byteLength >>> 8);
- data[start + 1] = (byte) byteLength;
- }
- if (length + byteLength - i > data.length) {
- enlarge(byteLength - i);
- }
- int len = length;
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- data[len++] = (byte) c;
- } else if (c > '\u07FF') {
- data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
- data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- } else {
- data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- }
- }
- length = len;
- return this;
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
+ * necessary.
+ *
+ * @param stringValue a String whose UTF8 encoded length must be less than 65536.
+ * @return this byte vector.
+ */
+ // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
+ public ByteVector putUTF8(final String stringValue) {
+ int charLength = stringValue.length();
+ if (charLength > 65535) {
+ throw new IllegalArgumentException("UTF8 string too large");
+ }
+ int currentLength = length;
+ if (currentLength + 2 + charLength > data.length) {
+ enlarge(2 + charLength);
}
+ byte[] currentData = data;
+ // Optimistic algorithm: instead of computing the byte length and then serializing the string
+ // (which requires two loops), we assume the byte length is equal to char length (which is the
+ // most frequent case), and we start serializing the string right away. During the
+ // serialization, if we find that this assumption is wrong, we continue with the general method.
+ currentData[currentLength++] = (byte) (charLength >>> 8);
+ currentData[currentLength++] = (byte) charLength;
+ for (int i = 0; i < charLength; ++i) {
+ char charValue = stringValue.charAt(i);
+ if (charValue >= '\u0001' && charValue <= '\u007F') {
+ currentData[currentLength++] = (byte) charValue;
+ } else {
+ length = currentLength;
+ return encodeUtf8(stringValue, i, 65535);
+ }
+ }
+ length = currentLength;
+ return this;
+ }
- /**
- * Puts an array of bytes into this byte vector. The byte vector is
- * automatically enlarged if necessary.
- *
- * @param b
- * an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
- * null bytes into this byte vector.
- * @param off
- * index of the fist byte of b that must be copied.
- * @param len
- * number of bytes of b that must be copied.
- * @return this byte vector.
- */
- public ByteVector putByteArray(final byte[] b, final int off, final int len) {
- if (length + len > data.length) {
- enlarge(len);
- }
- if (b != null) {
- System.arraycopy(b, off, data, length, len);
- }
- length += len;
- return this;
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
+ * necessary. The string length is encoded in two bytes before the encoded characters, if there is
+ * space for that (i.e. if this.length - offset - 2 >= 0).
+ *
+ * @param stringValue the String to encode.
+ * @param offset the index of the first character to encode. The previous characters are supposed
+ * to have already been encoded, using only one byte per character.
+ * @param maxByteLength the maximum byte length of the encoded string, including the already
+ * encoded characters.
+ * @return this byte vector.
+ */
+ final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength) {
+ int charLength = stringValue.length();
+ int byteLength = offset;
+ for (int i = offset; i < charLength; ++i) {
+ char charValue = stringValue.charAt(i);
+ if (charValue >= 0x0001 && charValue <= 0x007F) {
+ byteLength++;
+ } else if (charValue <= 0x07FF) {
+ byteLength += 2;
+ } else {
+ byteLength += 3;
+ }
+ }
+ if (byteLength > maxByteLength) {
+ throw new IllegalArgumentException("UTF8 string too large");
+ }
+ // Compute where 'byteLength' must be stored in 'data', and store it at this location.
+ int byteLengthOffset = length - offset - 2;
+ if (byteLengthOffset >= 0) {
+ data[byteLengthOffset] = (byte) (byteLength >>> 8);
+ data[byteLengthOffset + 1] = (byte) byteLength;
+ }
+ if (length + byteLength - offset > data.length) {
+ enlarge(byteLength - offset);
}
+ int currentLength = length;
+ for (int i = offset; i < charLength; ++i) {
+ char charValue = stringValue.charAt(i);
+ if (charValue >= 0x0001 && charValue <= 0x007F) {
+ data[currentLength++] = (byte) charValue;
+ } else if (charValue <= 0x07FF) {
+ data[currentLength++] = (byte) (0xC0 | charValue >> 6 & 0x1F);
+ data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
+ } else {
+ data[currentLength++] = (byte) (0xE0 | charValue >> 12 & 0xF);
+ data[currentLength++] = (byte) (0x80 | charValue >> 6 & 0x3F);
+ data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
+ }
+ }
+ length = currentLength;
+ return this;
+ }
- /**
- * Enlarge this byte vector so that it can receive n more bytes.
- *
- * @param size
- * number of additional bytes that this byte vector should be
- * able to receive.
- */
- private void enlarge(final int size) {
- int length1 = 2 * data.length;
- int length2 = length + size;
- byte[] newData = new byte[length1 > length2 ? length1 : length2];
- System.arraycopy(data, 0, newData, 0, length);
- data = newData;
+ /**
+ * Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if
+ * necessary.
+ *
+ * @param byteArrayValue an array of bytes. May be {@literal null} to put {@code byteLength} null
+ * bytes into this byte vector.
+ * @param byteOffset index of the first byte of byteArrayValue that must be copied.
+ * @param byteLength number of bytes of byteArrayValue that must be copied.
+ * @return this byte vector.
+ */
+ public ByteVector putByteArray(
+ final byte[] byteArrayValue, final int byteOffset, final int byteLength) {
+ if (length + byteLength > data.length) {
+ enlarge(byteLength);
+ }
+ if (byteArrayValue != null) {
+ System.arraycopy(byteArrayValue, byteOffset, data, length, byteLength);
}
+ length += byteLength;
+ return this;
+ }
+
+ /**
+ * Enlarges this byte vector so that it can receive 'size' more bytes.
+ *
+ * @param size number of additional bytes that this byte vector should be able to receive.
+ */
+ private void enlarge(final int size) {
+ int doubleCapacity = 2 * data.length;
+ int minimalCapacity = length + size;
+ byte[] newData = new byte[doubleCapacity > minimalCapacity ? doubleCapacity : minimalCapacity];
+ System.arraycopy(data, 0, newData, 0, length);
+ data = newData;
+ }
}
[24/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
old mode 100644
new mode 100755
index 1f9b7cb..fed9697
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.io.ByteArrayOutputStream;
@@ -34,511 +32,459 @@ import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-
+import java.util.Comparator;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * A {@link ClassVisitor} that adds a serial version unique identifier to a
- * class if missing. Here is typical usage of this class:
- *
- * <pre>
- * ClassWriter cw = new ClassWriter(...);
- * ClassVisitor sv = new SerialVersionUIDAdder(cw);
- * ClassVisitor ca = new MyClassAdapter(sv);
- * new ClassReader(orginalClass).accept(ca, false);
- * </pre>
- *
- * The SVUID algorithm can be found <a href=
- * "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
- * >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
- *
+ * A {@link ClassVisitor} that adds a serial version unique identifier to a class if missing. A
+ * typical usage of this class is:
+ *
* <pre>
- * The serialVersionUID is computed using the signature of a stream of bytes
- * that reflect the class definition. The National Institute of Standards and
- * Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
- * signature for the stream. The first two 32-bit quantities are used to form a
- * 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
- * types to a sequence of bytes. The values input to the stream are defined by
- * the Java Virtual Machine (VM) specification for classes.
- *
- * The sequence of items in the stream is as follows:
- *
- * 1. The class name written using UTF encoding.
- * 2. The class modifiers written as a 32-bit integer.
- * 3. The name of each interface sorted by name written using UTF encoding.
- * 4. For each field of the class sorted by field name (except private static
- * and private transient fields):
- * 1. The name of the field in UTF encoding.
- * 2. The modifiers of the field written as a 32-bit integer.
- * 3. The descriptor of the field in UTF encoding
- * 5. If a class initializer exists, write out the following:
- * 1. The name of the method, <clinit>, in UTF encoding.
- * 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
- * written as a 32-bit integer.
- * 3. The descriptor of the method, ()V, in UTF encoding.
- * 6. For each non-private constructor sorted by method name and signature:
- * 1. The name of the method, <init>, in UTF encoding.
- * 2. The modifiers of the method written as a 32-bit integer.
- * 3. The descriptor of the method in UTF encoding.
- * 7. For each non-private method sorted by method name and signature:
- * 1. The name of the method in UTF encoding.
- * 2. The modifiers of the method written as a 32-bit integer.
- * 3. The descriptor of the method in UTF encoding.
- * 8. The SHA-1 algorithm is executed on the stream of bytes produced by
- * DataOutputStream and produces five 32-bit values sha[0..4].
- *
- * 9. The hash value is assembled from the first and second 32-bit values of
- * the SHA-1 message digest. If the result of the message digest, the five
- * 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named
- * sha, the hash value would be computed as follows:
- *
- * long hash = ((sha[0] >>> 24) & 0xFF) |
- * ((sha[0] >>> 16) & 0xFF) << 8 |
- * ((sha[0] >>> 8) & 0xFF) << 16 |
- * ((sha[0] >>> 0) & 0xFF) << 24 |
- * ((sha[1] >>> 24) & 0xFF) << 32 |
- * ((sha[1] >>> 16) & 0xFF) << 40 |
- * ((sha[1] >>> 8) & 0xFF) << 48 |
- * ((sha[1] >>> 0) & 0xFF) << 56;
+ * ClassWriter classWriter = new ClassWriter(...);
+ * ClassVisitor svuidAdder = new SerialVersionUIDAdder(classWriter);
+ * ClassVisitor classVisitor = new MyClassAdapter(svuidAdder);
+ * new ClassReader(orginalClass).accept(classVisitor, 0);
* </pre>
- *
+ *
+ * <p>The SVUID algorithm can be found at <a href=
+ * "https://docs.oracle.com/javase/10/docs/specs/serialization/class.html#stream-unique-identifiers"
+ * >https://docs.oracle.com/javase/10/docs/specs/serialization/class.html#stream-unique-identifiers</a>:
+ *
+ * <p>The serialVersionUID is computed using the signature of a stream of bytes that reflect the
+ * class definition. The National Institute of Standards and Technology (NIST) Secure Hash Algorithm
+ * (SHA-1) is used to compute a signature for the stream. The first two 32-bit quantities are used
+ * to form a 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data types to a
+ * sequence of bytes. The values input to the stream are defined by the Java Virtual Machine (VM)
+ * specification for classes.
+ *
+ * <p>The sequence of items in the stream is as follows:
+ *
+ * <ol>
+ * <li>The class name written using UTF encoding.
+ * <li>The class modifiers written as a 32-bit integer.
+ * <li>The name of each interface sorted by name written using UTF encoding.
+ * <li>For each field of the class sorted by field name (except private static and private
+ * transient fields):
+ * <ol>
+ * <li>The name of the field in UTF encoding.
+ * <li>The modifiers of the field written as a 32-bit integer.
+ * <li>The descriptor of the field in UTF encoding
+ * </ol>
+ * <li>If a class initializer exists, write out the following:
+ * <ol>
+ * <li>The name of the method, <clinit>, in UTF encoding.
+ * <li>The modifier of the method, STATIC, written as a 32-bit integer.
+ * <li>The descriptor of the method, ()V, in UTF encoding.
+ * </ol>
+ * <li>For each non-private constructor sorted by method name and signature:
+ * <ol>
+ * <li>The name of the method, <init>, in UTF encoding.
+ * <li>The modifiers of the method written as a 32-bit integer.
+ * <li>The descriptor of the method in UTF encoding.
+ * </ol>
+ * <li>For each non-private method sorted by method name and signature:
+ * <ol>
+ * <li>The name of the method in UTF encoding.
+ * <li>The modifiers of the method written as a 32-bit integer.
+ * <li>The descriptor of the method in UTF encoding.
+ * </ol>
+ * <li>The SHA-1 algorithm is executed on the stream of bytes produced by DataOutputStream and
+ * produces five 32-bit values sha[0..4].
+ * <li>The hash value is assembled from the first and second 32-bit values of the SHA-1 message
+ * digest. If the result of the message digest, the five 32-bit words H0 H1 H2 H3 H4, is in an
+ * array of five int values named sha, the hash value would be computed as follows: long hash
+ * = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF) << 8
+ * | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF)
+ * << 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16)
+ * & 0xFF) << 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1]
+ * >>> 0) & 0xFF) << 56;
+ * </ol>
+ *
* @author Rajendra Inamdar, Vishal Vishnoi
*/
+// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public class SerialVersionUIDAdder extends ClassVisitor {
- /**
- * Flag that indicates if we need to compute SVUID.
- */
- private boolean computeSVUID;
-
- /**
- * Set to true if the class already has SVUID.
- */
- private boolean hasSVUID;
-
- /**
- * Classes access flags.
- */
- private int access;
-
- /**
- * Internal name of the class
- */
- private String name;
-
- /**
- * Interfaces implemented by the class.
- */
- private String[] interfaces;
-
- /**
- * Collection of fields. (except private static and private transient
- * fields)
- */
- private Collection<Item> svuidFields;
-
- /**
- * Set to true if the class has static initializer.
- */
- private boolean hasStaticInitializer;
-
- /**
- * Collection of non-private constructors.
- */
- private Collection<Item> svuidConstructors;
-
- /**
- * Collection of non-private methods.
- */
- private Collection<Item> svuidMethods;
-
- /**
- * Creates a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use
- * this constructor</i>. Instead, they must use the
- * {@link #SerialVersionUIDAdder(int, ClassVisitor)} version.
- *
- * @param cv
- * a {@link ClassVisitor} to which this visitor will delegate
- * calls.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public SerialVersionUIDAdder(final ClassVisitor cv) {
- this(Opcodes.ASM6, cv);
- if (getClass() != SerialVersionUIDAdder.class) {
- throw new IllegalStateException();
- }
- }
+ /** The JVM name of static initializer methods. */
+ private static final String CLINIT = "<clinit>";
- /**
- * Creates a new {@link SerialVersionUIDAdder}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param cv
- * a {@link ClassVisitor} to which this visitor will delegate
- * calls.
- */
- protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) {
- super(api, cv);
- svuidFields = new ArrayList<Item>();
- svuidConstructors = new ArrayList<Item>();
- svuidMethods = new ArrayList<Item>();
- }
+ /** A flag that indicates if we need to compute SVUID. */
+ private boolean computeSvuid;
- // ------------------------------------------------------------------------
- // Overridden methods
- // ------------------------------------------------------------------------
-
- /*
- * Visit class header and get class name, access , and interfaces
- * information (step 1,2, and 3) for SVUID computation.
- */
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- computeSVUID = (access & Opcodes.ACC_ENUM) == 0;
-
- if (computeSVUID) {
- this.name = name;
- this.access = access;
- this.interfaces = new String[interfaces.length];
- System.arraycopy(interfaces, 0, this.interfaces, 0,
- interfaces.length);
- }
+ /** Whether the class already has a SVUID. */
+ private boolean hasSvuid;
- super.visit(version, access, name, signature, superName, interfaces);
- }
+ /** The class access flags. */
+ private int access;
- /*
- * Visit the methods and get constructor and method information (step 5 and
- * 7). Also determine if there is a class initializer (step 6).
- */
- @Override
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- if (computeSVUID) {
- if ("<clinit>".equals(name)) {
- hasStaticInitializer = true;
- }
- /*
- * Remembers non private constructors and methods for SVUID
- * computation For constructor and method modifiers, only the
- * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
- * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
- * are used.
- */
- int mods = access
- & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
- | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
- | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
- | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
-
- // all non private methods
- if ((access & Opcodes.ACC_PRIVATE) == 0) {
- if ("<init>".equals(name)) {
- svuidConstructors.add(new Item(name, mods, desc));
- } else if (!"<clinit>".equals(name)) {
- svuidMethods.add(new Item(name, mods, desc));
- }
- }
- }
+ /** The internal name of the class. */
+ private String name;
- return super.visitMethod(access, name, desc, signature, exceptions);
- }
+ /** The interfaces implemented by the class. */
+ private String[] interfaces;
- /*
- * Gets class field information for step 4 of the algorithm. Also determines
- * if the class already has a SVUID.
- */
- @Override
- public FieldVisitor visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- if (computeSVUID) {
- if ("serialVersionUID".equals(name)) {
- // since the class already has SVUID, we won't be computing it.
- computeSVUID = false;
- hasSVUID = true;
- }
- /*
- * Remember field for SVUID computation For field modifiers, only
- * the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC,
- * ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when
- * computing serialVersionUID values.
- */
- if ((access & Opcodes.ACC_PRIVATE) == 0
- || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
- int mods = access
- & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
- | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
- | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT);
- svuidFields.add(new Item(name, mods, desc));
- }
- }
+ /** The fields of the class that are needed to compute the SVUID. */
+ private Collection<Item> svuidFields;
- return super.visitField(access, name, desc, signature, value);
- }
+ /** Whether the class has a static initializer. */
+ private boolean hasStaticInitializer;
- /**
- * Handle a bizarre special case. Nested classes (static classes declared
- * inside another class) that are protected have their access bit set to
- * public in their class files to deal with some odd reflection situation.
- * Our SVUID computation must do as the JVM does and ignore access bits in
- * the class file in favor of the access bits InnerClass attribute.
- */
- @Override
- public void visitInnerClass(final String aname, final String outerName,
- final String innerName, final int attr_access) {
- if ((name != null) && name.equals(aname)) {
- this.access = attr_access;
- }
- super.visitInnerClass(aname, outerName, innerName, attr_access);
- }
+ /** The constructors of the class that are needed to compute the SVUID. */
+ private Collection<Item> svuidConstructors;
- /*
- * Add the SVUID if class doesn't have one
- */
- @Override
- public void visitEnd() {
- // compute SVUID and add it to the class
- if (computeSVUID && !hasSVUID) {
- try {
- addSVUID(computeSVUID());
- } catch (Throwable e) {
- throw new RuntimeException("Error while computing SVUID for "
- + name, e);
- }
- }
+ /** The methods of the class that are needed to compute the SVUID. */
+ private Collection<Item> svuidMethods;
- super.visitEnd();
+ /**
+ * Constructs a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the {@link #SerialVersionUIDAdder(int, ClassVisitor)}
+ * version.
+ *
+ * @param classVisitor a {@link ClassVisitor} to which this visitor will delegate calls.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public SerialVersionUIDAdder(final ClassVisitor classVisitor) {
+ this(Opcodes.ASM7, classVisitor);
+ if (getClass() != SerialVersionUIDAdder.class) {
+ throw new IllegalStateException();
}
-
- // ------------------------------------------------------------------------
- // Utility methods
- // ------------------------------------------------------------------------
-
- /**
- * Returns true if the class already has a SVUID field. The result of this
- * method is only valid when visitEnd is or has been called.
- *
- * @return true if the class already has a SVUID field.
- */
- public boolean hasSVUID() {
- return hasSVUID;
+ }
+
+ /**
+ * Constructs a new {@link SerialVersionUIDAdder}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param classVisitor a {@link ClassVisitor} to which this visitor will delegate calls.
+ */
+ protected SerialVersionUIDAdder(final int api, final ClassVisitor classVisitor) {
+ super(api, classVisitor);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Overridden methods
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ // Get the class name, access flags, and interfaces information (step 1, 2 and 3) for SVUID
+ // computation.
+ computeSvuid = (access & Opcodes.ACC_ENUM) == 0;
+
+ if (computeSvuid) {
+ this.name = name;
+ this.access = access;
+ this.interfaces = new String[interfaces.length];
+ this.svuidFields = new ArrayList<Item>();
+ this.svuidConstructors = new ArrayList<Item>();
+ this.svuidMethods = new ArrayList<Item>();
+ System.arraycopy(interfaces, 0, this.interfaces, 0, interfaces.length);
}
- protected void addSVUID(long svuid) {
- FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL
- + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, svuid);
- if (fv != null) {
- fv.visitEnd();
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ // Get constructor and method information (step 5 and 7). Also determine if there is a class
+ // initializer (step 6).
+ if (computeSvuid) {
+ if (CLINIT.equals(name)) {
+ hasStaticInitializer = true;
+ }
+ // Collect the non private constructors and methods. Only the ACC_PUBLIC, ACC_PRIVATE,
+ // ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and
+ // ACC_STRICT flags are used.
+ int mods =
+ access
+ & (Opcodes.ACC_PUBLIC
+ | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED
+ | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL
+ | Opcodes.ACC_SYNCHRONIZED
+ | Opcodes.ACC_NATIVE
+ | Opcodes.ACC_ABSTRACT
+ | Opcodes.ACC_STRICT);
+
+ if ((access & Opcodes.ACC_PRIVATE) == 0) {
+ if ("<init>".equals(name)) {
+ svuidConstructors.add(new Item(name, mods, descriptor));
+ } else if (!CLINIT.equals(name)) {
+ svuidMethods.add(new Item(name, mods, descriptor));
}
+ }
}
- /**
- * Computes and returns the value of SVUID.
- *
- * @return Returns the serial version UID
- * @throws IOException
- * if an I/O error occurs
- */
- protected long computeSVUID() throws IOException {
- ByteArrayOutputStream bos;
- DataOutputStream dos = null;
- long svuid = 0;
-
- try {
- bos = new ByteArrayOutputStream();
- dos = new DataOutputStream(bos);
-
- /*
- * 1. The class name written using UTF encoding.
- */
- dos.writeUTF(name.replace('/', '.'));
-
- /*
- * 2. The class modifiers written as a 32-bit integer.
- */
- int access = this.access;
- if ((access & Opcodes.ACC_INTERFACE) != 0) {
- access = (svuidMethods.size() > 0) ? (access | Opcodes.ACC_ABSTRACT)
- : (access & ~Opcodes.ACC_ABSTRACT);
- }
- dos.writeInt(access
- & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
- | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT));
-
- /*
- * 3. The name of each interface sorted by name written using UTF
- * encoding.
- */
- Arrays.sort(interfaces);
- for (int i = 0; i < interfaces.length; i++) {
- dos.writeUTF(interfaces[i].replace('/', '.'));
- }
-
- /*
- * 4. For each field of the class sorted by field name (except
- * private static and private transient fields):
- *
- * 1. The name of the field in UTF encoding. 2. The modifiers of the
- * field written as a 32-bit integer. 3. The descriptor of the field
- * in UTF encoding
- *
- * Note that field signatures are not dot separated. Method and
- * constructor signatures are dot separated. Go figure...
- */
- writeItems(svuidFields, dos, false);
-
- /*
- * 5. If a class initializer exists, write out the following: 1. The
- * name of the method, <clinit>, in UTF encoding. 2. The modifier of
- * the method, java.lang.reflect.Modifier.STATIC, written as a
- * 32-bit integer. 3. The descriptor of the method, ()V, in UTF
- * encoding.
- */
- if (hasStaticInitializer) {
- dos.writeUTF("<clinit>");
- dos.writeInt(Opcodes.ACC_STATIC);
- dos.writeUTF("()V");
- } // if..
-
- /*
- * 6. For each non-private constructor sorted by method name and
- * signature: 1. The name of the method, <init>, in UTF encoding. 2.
- * The modifiers of the method written as a 32-bit integer. 3. The
- * descriptor of the method in UTF encoding.
- */
- writeItems(svuidConstructors, dos, true);
-
- /*
- * 7. For each non-private method sorted by method name and
- * signature: 1. The name of the method in UTF encoding. 2. The
- * modifiers of the method written as a 32-bit integer. 3. The
- * descriptor of the method in UTF encoding.
- */
- writeItems(svuidMethods, dos, true);
-
- dos.flush();
-
- /*
- * 8. The SHA-1 algorithm is executed on the stream of bytes
- * produced by DataOutputStream and produces five 32-bit values
- * sha[0..4].
- */
- byte[] hashBytes = computeSHAdigest(bos.toByteArray());
-
- /*
- * 9. The hash value is assembled from the first and second 32-bit
- * values of the SHA-1 message digest. If the result of the message
- * digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of
- * five int values named sha, the hash value would be computed as
- * follows:
- *
- * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF)
- * << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) <<
- * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) <<
- * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) <<
- * 56;
- */
- for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
- svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
- }
- } finally {
- // close the stream (if open)
- if (dos != null) {
- dos.close();
- }
- }
-
- return svuid;
+ return super.visitMethod(access, name, descriptor, signature, exceptions);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value) {
+ // Get the class field information for step 4 of the algorithm. Also determine if the class
+ // already has a SVUID.
+ if (computeSvuid) {
+ if ("serialVersionUID".equals(name)) {
+ // Since the class already has SVUID, we won't be computing it.
+ computeSvuid = false;
+ hasSvuid = true;
+ }
+ // Collect the non private fields. Only the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED,
+ // ACC_STATIC, ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when computing
+ // serialVersionUID values.
+ if ((access & Opcodes.ACC_PRIVATE) == 0
+ || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
+ int mods =
+ access
+ & (Opcodes.ACC_PUBLIC
+ | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED
+ | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL
+ | Opcodes.ACC_VOLATILE
+ | Opcodes.ACC_TRANSIENT);
+ svuidFields.add(new Item(name, mods, desc));
+ }
}
- /**
- * Returns the SHA-1 message digest of the given value.
- *
- * @param value
- * the value whose SHA message digest must be computed.
- * @return the SHA-1 message digest of the given value.
- */
- protected byte[] computeSHAdigest(final byte[] value) {
- try {
- return MessageDigest.getInstance("SHA").digest(value);
- } catch (Exception e) {
- throw new UnsupportedOperationException(e.toString());
- }
+ return super.visitField(access, name, desc, signature, value);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String innerClassName,
+ final String outerName,
+ final String innerName,
+ final int innerClassAccess) {
+ // Handles a bizarre special case. Nested classes (static classes declared inside another class)
+ // that are protected have their access bit set to public in their class files to deal with some
+ // odd reflection situation. Our SVUID computation must do as the JVM does and ignore access
+ // bits in the class file in favor of the access bits of the InnerClass attribute.
+ if ((name != null) && name.equals(innerClassName)) {
+ this.access = innerClassAccess;
}
-
- /**
- * Sorts the items in the collection and writes it to the data output stream
- *
- * @param itemCollection
- * collection of items
- * @param dos
- * a <code>DataOutputStream</code> value
- * @param dotted
- * a <code>boolean</code> value
- * @exception IOException
- * if an error occurs
- */
- private static void writeItems(final Collection<Item> itemCollection,
- final DataOutput dos, final boolean dotted) throws IOException {
- int size = itemCollection.size();
- Item[] items = itemCollection.toArray(new Item[size]);
- Arrays.sort(items);
- for (int i = 0; i < size; i++) {
- dos.writeUTF(items[i].name);
- dos.writeInt(items[i].access);
- dos.writeUTF(dotted ? items[i].desc.replace('/', '.')
- : items[i].desc);
- }
+ super.visitInnerClass(innerClassName, outerName, innerName, innerClassAccess);
+ }
+
+ @Override
+ public void visitEnd() {
+ // Add the SVUID field to the class if it doesn't have one.
+ if (computeSvuid && !hasSvuid) {
+ try {
+ addSVUID(computeSVUID());
+ } catch (IOException e) {
+ throw new IllegalStateException("Error while computing SVUID for " + name, e);
+ }
}
- // ------------------------------------------------------------------------
- // Inner classes
- // ------------------------------------------------------------------------
-
- private static class Item implements Comparable<Item> {
+ super.visitEnd();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns true if the class already has a SVUID field. The result of this method is only valid
+ * when visitEnd has been called.
+ *
+ * @return true if the class already has a SVUID field.
+ */
+ // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
+ public boolean hasSVUID() {
+ return hasSvuid;
+ }
+
+ /**
+ * Adds a final static serialVersionUID field to the class, with the given value.
+ *
+ * @param svuid the serialVersionUID field value.
+ */
+ // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
+ protected void addSVUID(final long svuid) {
+ FieldVisitor fieldVisitor =
+ super.visitField(
+ Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, svuid);
+ if (fieldVisitor != null) {
+ fieldVisitor.visitEnd();
+ }
+ }
+
+ /**
+ * Computes and returns the value of SVUID.
+ *
+ * @return the serial version UID.
+ * @throws IOException if an I/O error occurs.
+ */
+ // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
+ protected long computeSVUID() throws IOException {
+ ByteArrayOutputStream byteArrayOutputStream = null;
+ DataOutputStream dataOutputStream = null;
+ long svuid = 0;
+
+ try {
+ byteArrayOutputStream = new ByteArrayOutputStream();
+ dataOutputStream = new DataOutputStream(byteArrayOutputStream);
+
+ // 1. The class name written using UTF encoding.
+ dataOutputStream.writeUTF(name.replace('/', '.'));
+
+ // 2. The class modifiers written as a 32-bit integer.
+ int mods = access;
+ if ((mods & Opcodes.ACC_INTERFACE) != 0) {
+ mods =
+ svuidMethods.isEmpty() ? (mods & ~Opcodes.ACC_ABSTRACT) : (mods | Opcodes.ACC_ABSTRACT);
+ }
+ dataOutputStream.writeInt(
+ mods
+ & (Opcodes.ACC_PUBLIC
+ | Opcodes.ACC_FINAL
+ | Opcodes.ACC_INTERFACE
+ | Opcodes.ACC_ABSTRACT));
+
+ // 3. The name of each interface sorted by name written using UTF encoding.
+ Arrays.sort(interfaces);
+ for (String interfaceName : interfaces) {
+ dataOutputStream.writeUTF(interfaceName.replace('/', '.'));
+ }
+
+ // 4. For each field of the class sorted by field name (except private static and private
+ // transient fields):
+ // 1. The name of the field in UTF encoding.
+ // 2. The modifiers of the field written as a 32-bit integer.
+ // 3. The descriptor of the field in UTF encoding.
+ // Note that field signatures are not dot separated. Method and constructor signatures are dot
+ // separated. Go figure...
+ writeItems(svuidFields, dataOutputStream, false);
+
+ // 5. If a class initializer exists, write out the following:
+ // 1. The name of the method, <clinit>, in UTF encoding.
+ // 2. The modifier of the method, ACC_STATIC, written as a 32-bit integer.
+ // 3. The descriptor of the method, ()V, in UTF encoding.
+ if (hasStaticInitializer) {
+ dataOutputStream.writeUTF(CLINIT);
+ dataOutputStream.writeInt(Opcodes.ACC_STATIC);
+ dataOutputStream.writeUTF("()V");
+ }
+
+ // 6. For each non-private constructor sorted by method name and signature:
+ // 1. The name of the method, <init>, in UTF encoding.
+ // 2. The modifiers of the method written as a 32-bit integer.
+ // 3. The descriptor of the method in UTF encoding.
+ writeItems(svuidConstructors, dataOutputStream, true);
+
+ // 7. For each non-private method sorted by method name and signature:
+ // 1. The name of the method in UTF encoding.
+ // 2. The modifiers of the method written as a 32-bit integer.
+ // 3. The descriptor of the method in UTF encoding.
+ writeItems(svuidMethods, dataOutputStream, true);
+
+ dataOutputStream.flush();
+
+ // 8. The SHA-1 algorithm is executed on the stream of bytes produced by DataOutputStream and
+ // produces five 32-bit values sha[0..4].
+ byte[] hashBytes = computeSHAdigest(byteArrayOutputStream.toByteArray());
+
+ // 9. The hash value is assembled from the first and second 32-bit values of the SHA-1 message
+ // digest. If the result of the message digest, the five 32-bit words H0 H1 H2 H3 H4, is in an
+ // array of five int values named sha, the hash value would be computed as follows:
+ for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+ svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
+ }
+ } finally {
+ if (dataOutputStream != null) {
+ dataOutputStream.close();
+ }
+ }
- final String name;
+ return svuid;
+ }
+
+ /**
+ * Returns the SHA-1 message digest of the given value.
+ *
+ * @param value the value whose SHA message digest must be computed.
+ * @return the SHA-1 message digest of the given value.
+ */
+ // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
+ protected byte[] computeSHAdigest(final byte[] value) {
+ try {
+ return MessageDigest.getInstance("SHA").digest(value);
+ } catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException(e);
+ }
+ }
+
+ /**
+ * Sorts the items in the collection and writes it to the given output stream.
+ *
+ * @param itemCollection a collection of items.
+ * @param dataOutputStream where the items must be written.
+ * @param dotted whether package names must use dots, instead of slashes.
+ * @exception IOException if an error occurs.
+ */
+ private static void writeItems(
+ final Collection<Item> itemCollection,
+ final DataOutput dataOutputStream,
+ final boolean dotted)
+ throws IOException {
+ Item[] items = itemCollection.toArray(new Item[0]);
+ Arrays.sort(
+ items,
+ new Comparator<Item>() {
+ @Override
+ public int compare(final Item item1, final Item item2) {
+ int result = item1.name.compareTo(item2.name);
+ if (result == 0) {
+ result = item1.descriptor.compareTo(item2.descriptor);
+ }
+ return result;
+ }
+ });
+ for (Item item : items) {
+ dataOutputStream.writeUTF(item.name);
+ dataOutputStream.writeInt(item.access);
+ dataOutputStream.writeUTF(dotted ? item.descriptor.replace('/', '.') : item.descriptor);
+ }
+ }
- final int access;
+ // -----------------------------------------------------------------------------------------------
+ // Inner classes
+ // -----------------------------------------------------------------------------------------------
- final String desc;
+ private static final class Item {
- Item(final String name, final int access, final String desc) {
- this.name = name;
- this.access = access;
- this.desc = desc;
- }
+ final String name;
+ final int access;
+ final String descriptor;
- public int compareTo(final Item other) {
- int retVal = name.compareTo(other.name);
- if (retVal == 0) {
- retVal = desc.compareTo(other.desc);
- }
- return retVal;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (o instanceof Item) {
- return compareTo((Item) o) == 0;
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return (name + desc).hashCode();
- }
+ Item(final String name, final int access, final String descriptor) {
+ this.name = name;
+ this.access = access;
+ this.descriptor = descriptor;
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SignatureRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SignatureRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SignatureRemapper.java
old mode 100644
new mode 100755
index b16e028..d5d29ff
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SignatureRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SignatureRemapper.java
@@ -1,159 +1,174 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
-import java.util.Stack;
-
+import java.util.ArrayList;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
/**
- * A {@link SignatureVisitor} adapter for type mapping.
- *
+ * A {@link SignatureVisitor} that remaps types with a {@link Remapper}.
+ *
* @author Eugene Kuleshov
*/
public class SignatureRemapper extends SignatureVisitor {
- private final SignatureVisitor v;
-
- private final Remapper remapper;
-
- private Stack<String> classNames = new Stack<String>();
-
- public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) {
- this(Opcodes.ASM6, v, remapper);
- }
-
- protected SignatureRemapper(final int api, final SignatureVisitor v,
- final Remapper remapper) {
- super(api);
- this.v = v;
- this.remapper = remapper;
- }
-
- @Override
- public void visitClassType(String name) {
- classNames.push(name);
- v.visitClassType(remapper.mapType(name));
- }
-
- @Override
- public void visitInnerClassType(String name) {
- String outerClassName = classNames.pop();
- String className = outerClassName + '$' + name;
- classNames.push(className);
- String remappedOuter = remapper.mapType(outerClassName) + '$';
- String remappedName = remapper.mapType(className);
- int index = remappedName.startsWith(remappedOuter) ? remappedOuter
- .length() : remappedName.lastIndexOf('$') + 1;
- v.visitInnerClassType(remappedName.substring(index));
- }
-
- @Override
- public void visitFormalTypeParameter(String name) {
- v.visitFormalTypeParameter(name);
- }
-
- @Override
- public void visitTypeVariable(String name) {
- v.visitTypeVariable(name);
- }
-
- @Override
- public SignatureVisitor visitArrayType() {
- v.visitArrayType();
- return this;
- }
-
- @Override
- public void visitBaseType(char descriptor) {
- v.visitBaseType(descriptor);
- }
-
- @Override
- public SignatureVisitor visitClassBound() {
- v.visitClassBound();
- return this;
- }
-
- @Override
- public SignatureVisitor visitExceptionType() {
- v.visitExceptionType();
- return this;
- }
-
- @Override
- public SignatureVisitor visitInterface() {
- v.visitInterface();
- return this;
- }
-
- @Override
- public SignatureVisitor visitInterfaceBound() {
- v.visitInterfaceBound();
- return this;
- }
-
- @Override
- public SignatureVisitor visitParameterType() {
- v.visitParameterType();
- return this;
- }
-
- @Override
- public SignatureVisitor visitReturnType() {
- v.visitReturnType();
- return this;
- }
-
- @Override
- public SignatureVisitor visitSuperclass() {
- v.visitSuperclass();
- return this;
- }
-
- @Override
- public void visitTypeArgument() {
- v.visitTypeArgument();
- }
-
- @Override
- public SignatureVisitor visitTypeArgument(char wildcard) {
- v.visitTypeArgument(wildcard);
- return this;
- }
-
- @Override
- public void visitEnd() {
- v.visitEnd();
- classNames.pop();
- }
+ private final SignatureVisitor signatureVisitor;
+
+ private final Remapper remapper;
+
+ private ArrayList<String> classNames = new ArrayList<String>();
+
+ /**
+ * Constructs a new {@link SignatureRemapper}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #SignatureRemapper(int,SignatureVisitor,Remapper)} version.
+ *
+ * @param signatureVisitor the signature visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited signature.
+ */
+ public SignatureRemapper(final SignatureVisitor signatureVisitor, final Remapper remapper) {
+ this(Opcodes.ASM7, signatureVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new {@link SignatureRemapper}.
+ *
+ * @param api the ASM API version supported by this remapper. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6}.
+ * @param signatureVisitor the signature visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited signature.
+ */
+ protected SignatureRemapper(
+ final int api, final SignatureVisitor signatureVisitor, final Remapper remapper) {
+ super(api);
+ this.signatureVisitor = signatureVisitor;
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ classNames.add(name);
+ signatureVisitor.visitClassType(remapper.mapType(name));
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ String outerClassName = classNames.remove(classNames.size() - 1);
+ String className = outerClassName + '$' + name;
+ classNames.add(className);
+ String remappedOuter = remapper.mapType(outerClassName) + '$';
+ String remappedName = remapper.mapType(className);
+ int index =
+ remappedName.startsWith(remappedOuter)
+ ? remappedOuter.length()
+ : remappedName.lastIndexOf('$') + 1;
+ signatureVisitor.visitInnerClassType(remappedName.substring(index));
+ }
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ signatureVisitor.visitFormalTypeParameter(name);
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ signatureVisitor.visitTypeVariable(name);
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ signatureVisitor.visitArrayType();
+ return this;
+ }
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ signatureVisitor.visitBaseType(descriptor);
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ signatureVisitor.visitClassBound();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ signatureVisitor.visitExceptionType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ signatureVisitor.visitInterface();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ signatureVisitor.visitInterfaceBound();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ signatureVisitor.visitParameterType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ signatureVisitor.visitReturnType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ signatureVisitor.visitSuperclass();
+ return this;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ signatureVisitor.visitTypeArgument();
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ signatureVisitor.visitTypeArgument(wildcard);
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ signatureVisitor.visitEnd();
+ classNames.remove(classNames.size() - 1);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
old mode 100644
new mode 100755
index 68c7825..bd76a09
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -40,36 +38,59 @@ import java.util.Map;
*/
public class SimpleRemapper extends Remapper {
- private final Map<String, String> mapping;
+ private final Map<String, String> mapping;
- public SimpleRemapper(Map<String, String> mapping) {
- this.mapping = mapping;
- }
+ /**
+ * Constructs a new {@link SimpleRemapper} with the given mapping.
+ *
+ * @param mapping a map specifying a remapping as follows:
+ * <ul>
+ * <li>for method names, the key is the owner, name and descriptor of the method (in the
+ * form <owner>.<name><descriptor>), and the value is the new method
+ * name.
+ * <li>for invokedynamic method names, the key is the name and descriptor of the method (in
+ * the form .<name><descriptor>), and the value is the new method name.
+ * <li>for field names, the key is the owner and name of the field (in the form
+ * <owner>.<name>), and the value is the new field name.
+ * <li>for internal names, the key is the old internal name, and the value is the new
+ * internal name.
+ * </ul>
+ */
+ public SimpleRemapper(final Map<String, String> mapping) {
+ this.mapping = mapping;
+ }
- public SimpleRemapper(String oldName, String newName) {
- this.mapping = Collections.singletonMap(oldName, newName);
- }
+ /**
+ * Constructs a new {@link SimpleRemapper} with the given mapping.
+ *
+ * @param oldName the key corresponding to a method, field or internal name (see {@link
+ * #SimpleRemapper(Map)} for the format of these keys).
+ * @param newName the new method, field or internal name.
+ */
+ public SimpleRemapper(final String oldName, final String newName) {
+ this.mapping = Collections.singletonMap(oldName, newName);
+ }
- @Override
- public String mapMethodName(String owner, String name, String desc) {
- String s = map(owner + '.' + name + desc);
- return s == null ? name : s;
- }
+ @Override
+ public String mapMethodName(final String owner, final String name, final String descriptor) {
+ String remappedName = map(owner + '.' + name + descriptor);
+ return remappedName == null ? name : remappedName;
+ }
- @Override
- public String mapInvokeDynamicMethodName(String name, String desc) {
- String s = map('.' + name + desc);
- return s == null ? name : s;
- }
+ @Override
+ public String mapInvokeDynamicMethodName(final String name, final String descriptor) {
+ String remappedName = map('.' + name + descriptor);
+ return remappedName == null ? name : remappedName;
+ }
- @Override
- public String mapFieldName(String owner, String name, String desc) {
- String s = map(owner + '.' + name);
- return s == null ? name : s;
- }
+ @Override
+ public String mapFieldName(final String owner, final String name, final String descriptor) {
+ String remappedName = map(owner + '.' + name);
+ return remappedName == null ? name : remappedName;
+ }
- @Override
- public String map(String key) {
- return mapping.get(key);
- }
+ @Override
+ public String map(final String key) {
+ return mapping.get(key);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
old mode 100644
new mode 100755
index 2bb33e5..ee0228d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
@@ -34,64 +32,93 @@ import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * A {@link ClassVisitor} that merges clinit methods into a single one.
- *
+ * A {@link ClassVisitor} that merges <clinit> methods into a single one. All the existing
+ * <clinit> methods are renamed, and a new one is created, which calls all the renamed
+ * methods.
+ *
* @author Eric Bruneton
*/
public class StaticInitMerger extends ClassVisitor {
- private String name;
+ /** The internal name of the visited class. */
+ private String owner;
- private MethodVisitor clinit;
+ /** The prefix to use to rename the existing <clinit> methods. */
+ private final String renamedClinitMethodPrefix;
- private final String prefix;
+ /** The number of <clinit> methods visited so far. */
+ private int numClinitMethods;
- private int counter;
+ /** The MethodVisitor for the merged <clinit> method. */
+ private MethodVisitor mergedClinitVisitor;
- public StaticInitMerger(final String prefix, final ClassVisitor cv) {
- this(Opcodes.ASM6, prefix, cv);
- }
+ /**
+ * Constructs a new {@link StaticInitMerger}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #StaticInitMerger(int, String, ClassVisitor)} version.
+ *
+ * @param prefix the prefix to use to rename the existing <clinit> methods.
+ * @param classVisitor the class visitor to which this visitor must delegate method calls. May be
+ * null.
+ */
+ public StaticInitMerger(final String prefix, final ClassVisitor classVisitor) {
+ this(Opcodes.ASM7, prefix, classVisitor);
+ }
- protected StaticInitMerger(final int api, final String prefix,
- final ClassVisitor cv) {
- super(api, cv);
- this.prefix = prefix;
- }
+ /**
+ * Constructs a new {@link StaticInitMerger}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
+ * @param prefix the prefix to use to rename the existing <clinit> methods.
+ * @param classVisitor the class visitor to which this visitor must delegate method calls. May be
+ * null.
+ */
+ protected StaticInitMerger(final int api, final String prefix, final ClassVisitor classVisitor) {
+ super(api, classVisitor);
+ this.renamedClinitMethodPrefix = prefix;
+ }
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- cv.visit(version, access, name, signature, superName, interfaces);
- this.name = name;
- }
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ super.visit(version, access, name, signature, superName, interfaces);
+ this.owner = name;
+ }
- @Override
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- MethodVisitor mv;
- if ("<clinit>".equals(name)) {
- int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
- String n = prefix + counter++;
- mv = cv.visitMethod(a, n, desc, signature, exceptions);
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ MethodVisitor methodVisitor;
+ if ("<clinit>".equals(name)) {
+ int newAccess = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
+ String newName = renamedClinitMethodPrefix + numClinitMethods++;
+ methodVisitor = super.visitMethod(newAccess, newName, descriptor, signature, exceptions);
- if (clinit == null) {
- clinit = cv.visitMethod(a, name, desc, null, null);
- }
- clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc,
- false);
- } else {
- mv = cv.visitMethod(access, name, desc, signature, exceptions);
- }
- return mv;
+ if (mergedClinitVisitor == null) {
+ mergedClinitVisitor = super.visitMethod(newAccess, name, descriptor, null, null);
+ }
+ mergedClinitVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, owner, newName, descriptor, false);
+ } else {
+ methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
}
+ return methodVisitor;
+ }
- @Override
- public void visitEnd() {
- if (clinit != null) {
- clinit.visitInsn(Opcodes.RETURN);
- clinit.visitMaxs(0, 0);
- }
- cv.visitEnd();
+ @Override
+ public void visitEnd() {
+ if (mergedClinitVisitor != null) {
+ mergedClinitVisitor.visitInsn(Opcodes.RETURN);
+ mergedClinitVisitor.visitMaxs(0, 0);
}
+ super.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
old mode 100644
new mode 100755
index 322d7bb..d83cb36
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
@@ -1,57 +1,51 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import org.apache.tapestry5.internal.plastic.asm.Label;
/**
* A code generator for switch statements.
- *
+ *
* @author Juozas Baliuka
* @author Chris Nokleberg
* @author Eric Bruneton
*/
public interface TableSwitchGenerator {
- /**
- * Generates the code for a switch case.
- *
- * @param key
- * the switch case key.
- * @param end
- * a label that corresponds to the end of the switch statement.
- */
- void generateCase(int key, Label end);
+ /**
+ * Generates the code for a switch case.
+ *
+ * @param key the switch case key.
+ * @param end a label that corresponds to the end of the switch statement.
+ */
+ void generateCase(int key, Label end);
- /**
- * Generates the code for the default switch case.
- */
- void generateDefault();
+ /** Generates the code for the default switch case. */
+ void generateDefault();
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
old mode 100644
new mode 100755
index 7b20b30..e579d76
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
@@ -1,96 +1,119 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.Collections;
import java.util.Comparator;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
/**
- * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers
- * are sorted in a method innermost-to-outermost. This allows the programmer to
- * add handlers without worrying about ordering them correctly with respect to
- * existing, in-code handlers.
- *
- * Behavior is only defined for properly-nested handlers. If any "try" blocks
- * overlap (something that isn't possible in Java code) then this may not do
- * what you want. In fact, this adapter just sorts by the length of the "try"
- * block, taking advantage of the fact that a given try block must be larger
- * than any block it contains).
- *
+ * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers are sorted in a
+ * method innermost-to-outermost. This allows the programmer to add handlers without worrying about
+ * ordering them correctly with respect to existing, in-code handlers.
+ *
+ * <p>Behavior is only defined for properly-nested handlers. If any "try" blocks overlap (something
+ * that isn't possible in Java code) then this may not do what you want. In fact, this adapter just
+ * sorts by the length of the "try" block, taking advantage of the fact that a given try block must
+ * be larger than any block it contains).
+ *
* @author Adrian Sampson
*/
public class TryCatchBlockSorter extends MethodNode {
- public TryCatchBlockSorter(final MethodVisitor mv, final int access,
- final String name, final String desc, final String signature,
- final String[] exceptions) {
- this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
+ /**
+ * Constructs a new {@link TryCatchBlockSorter}.
+ *
+ * @param methodVisitor the method visitor to which this visitor must delegate method calls. May
+ * be {@literal null}.
+ * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the method is synthetic and/or deprecated.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param signature the method's signature. May be {@literal null} if the method parameters,
+ * return type and exceptions do not use generic types.
+ * @param exceptions the internal names of the method's exception classes (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}). May be {@literal null}.
+ */
+ public TryCatchBlockSorter(
+ final MethodVisitor methodVisitor,
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ this(Opcodes.ASM7, methodVisitor, access, name, descriptor, signature, exceptions);
+ if (getClass() != TryCatchBlockSorter.class) {
+ throw new IllegalStateException();
}
+ }
- protected TryCatchBlockSorter(final int api, final MethodVisitor mv,
- final int access, final String name, final String desc,
- final String signature, final String[] exceptions) {
- super(api, access, name, desc, signature, exceptions);
- this.mv = mv;
- }
+ protected TryCatchBlockSorter(
+ final int api,
+ final MethodVisitor methodVisitor,
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ super(api, access, name, descriptor, signature, exceptions);
+ this.mv = methodVisitor;
+ }
- @Override
- public void visitEnd() {
- // Compares TryCatchBlockNodes by the length of their "try" block.
- Comparator<TryCatchBlockNode> comp = new Comparator<TryCatchBlockNode>() {
+ @Override
+ public void visitEnd() {
+ // Sort the TryCatchBlockNode elements by the length of their "try" block.
+ Collections.sort(
+ tryCatchBlocks,
+ new Comparator<TryCatchBlockNode>() {
- public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) {
- int len1 = blockLength(t1);
- int len2 = blockLength(t2);
- return len1 - len2;
- }
+ @Override
+ public int compare(
+ final TryCatchBlockNode tryCatchBlockNode1,
+ final TryCatchBlockNode tryCatchBlockNode2) {
+ return blockLength(tryCatchBlockNode1) - blockLength(tryCatchBlockNode2);
+ }
- private int blockLength(TryCatchBlockNode block) {
- int startidx = instructions.indexOf(block.start);
- int endidx = instructions.indexOf(block.end);
- return endidx - startidx;
- }
- };
- Collections.sort(tryCatchBlocks, comp);
- // Updates the 'target' of each try catch block annotation.
- for (int i = 0; i < tryCatchBlocks.size(); ++i) {
- tryCatchBlocks.get(i).updateIndex(i);
- }
- if (mv != null) {
- accept(mv);
- }
+ private int blockLength(final TryCatchBlockNode tryCatchBlockNode) {
+ int startIndex = instructions.indexOf(tryCatchBlockNode.start);
+ int endIndex = instructions.indexOf(tryCatchBlockNode.end);
+ return endIndex - startIndex;
+ }
+ });
+ // Update the 'target' of each try catch block annotation.
+ for (int i = 0; i < tryCatchBlocks.size(); ++i) {
+ tryCatchBlocks.get(i).updateIndex(i);
+ }
+ if (mv != null) {
+ accept(mv);
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
old mode 100644
new mode 100755
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/package.html
old mode 100644
new mode 100755
index 2d4a765..85de04d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/package.html
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/package.html
@@ -32,7 +32,7 @@
Provides a small and fast bytecode manipulation framework.
<p>
-The <a href="http://www.objectweb.org/asm">ASM</a> framework is organized
+The <a href="http://asm.ow2.org/">ASM</a> framework is organized
around the {@link org.objectweb.asm.ClassVisitor ClassVisitor},
{@link org.objectweb.asm.FieldVisitor FieldVisitor},
{@link org.objectweb.asm.MethodVisitor MethodVisitor} and
@@ -52,8 +52,7 @@ In order to generate a class from scratch, only the {@link
org.objectweb.asm.ClassWriter ClassWriter} class is necessary. Indeed,
in order to generate a class, one must just call its visit<i>Xxx</i>
methods with the appropriate arguments to generate the desired fields
-and methods. See the "helloworld" example in the ASM distribution for
-more details about class generation.
+and methods.
<p>
In order to modify existing classes, one must use a {@link
@@ -68,19 +67,7 @@ modification process. In order to make it easier to implement such
class modifiers, the {@link org.objectweb.asm.ClassVisitor
ClassVisitor} and {@link org.objectweb.asm.MethodVisitor MethodVisitor}
classes delegate by default all the method calls they receive to an
-optional visitor. See the "adapt" example in the ASM
-distribution for more details about class modification.
-
-<p>
-The size of the core ASM library, <tt>asm.jar</tt>, is only 45KB, which is much
-smaller than the size of the
-<a href="http://jakarta.apache.org/bcel">BCEL</a> library (504KB), and than the
-size of the
-<a href="http://serp.sourceforge.net">SERP</a> library (150KB). ASM is also
-much faster than these tools. Indeed the overhead of a load time class
-transformation process is of the order of 60% with ASM, 700% or more with BCEL,
-and 1100% or more with SERP (see the <tt>test/perf</tt> directory in the ASM
-distribution)!
+optional visitor.
@since ASM 1.3
</body>
[08/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java
old mode 100644
new mode 100755
index cdc2531..0d6d28d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java
@@ -1,151 +1,212 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import java.util.HashSet;
-
import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
+ * A {@link ModuleVisitor} that checks that its methods are properly used.
+ *
* @author Remi Forax
*/
-public final class CheckModuleAdapter extends ModuleVisitor {
- private boolean end;
- private final boolean isOpen;
-
- private final HashSet<String> requireNames = new HashSet<String>();
- private final HashSet<String> exportNames = new HashSet<String>();
- private final HashSet<String> openNames = new HashSet<String>();
- private final HashSet<String> useNames = new HashSet<String>();
- private final HashSet<String> provideNames = new HashSet<String>();
-
- public CheckModuleAdapter(final ModuleVisitor mv, final boolean isOpen) {
- super(Opcodes.ASM6, mv);
- this.isOpen = isOpen;
+public class CheckModuleAdapter extends ModuleVisitor {
+ /** Whether the visited module is open. */
+ private final boolean isOpen;
+
+ /** The fully qualified names of the dependencies of the visited module. */
+ private final NameSet requiredModules = new NameSet("Modules requires");
+
+ /** The internal names of the packages exported by the visited module. */
+ private final NameSet exportedPackages = new NameSet("Module exports");
+
+ /** The internal names of the packages opened by the visited module. */
+ private final NameSet openedPackages = new NameSet("Module opens");
+
+ /** The internal names of the services used by the visited module. */
+ private final NameSet usedServices = new NameSet("Module uses");
+
+ /** The internal names of the services provided by the visited module. */
+ private final NameSet providedServices = new NameSet("Module provides");
+
+ /** The class version number. */
+ int classVersion;
+
+ /** Whether the {@link #visitEnd} method has been called. */
+ private boolean visitEndCalled;
+
+ /**
+ * Constructs a new {@link CheckModuleAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #CheckModuleAdapter(int, ModuleVisitor, boolean)} version.
+ *
+ * @param moduleVisitor the module visitor to which this adapter must delegate calls.
+ * @param isOpen whether the visited module is open. Open modules have their {@link
+ * Opcodes#ACC_OPEN} access flag set in {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitModule}.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public CheckModuleAdapter(final ModuleVisitor moduleVisitor, final boolean isOpen) {
+ this(Opcodes.ASM7, moduleVisitor, isOpen);
+ if (getClass() != CheckModuleAdapter.class) {
+ throw new IllegalStateException();
}
-
- @Override
- public void visitRequire(String module, int access, String version) {
- checkEnd();
- if (module == null) {
- throw new IllegalArgumentException("require cannot be null");
- }
- checkDeclared("requires", requireNames, module);
- CheckClassAdapter.checkAccess(access, Opcodes.ACC_STATIC_PHASE
- + Opcodes.ACC_TRANSITIVE + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_MANDATED);
- super.visitRequire(module, access, version);
+ }
+
+ /**
+ * Constructs a new {@link CheckModuleAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param moduleVisitor the module visitor to which this adapter must delegate calls.
+ * @param isOpen whether the visited module is open. Open modules have their {@link
+ * Opcodes#ACC_OPEN} access flag set in {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitModule}.
+ */
+ protected CheckModuleAdapter(
+ final int api, final ModuleVisitor moduleVisitor, final boolean isOpen) {
+ super(api, moduleVisitor);
+ this.isOpen = isOpen;
+ }
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ // Modules can only appear in V9 or more classes.
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, mainClass, "module main class");
+ super.visitMainClass(mainClass);
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "module package");
+ super.visitPackage(packaze);
+ }
+
+ @Override
+ public void visitRequire(final String module, final int access, final String version) {
+ checkVisitEndNotCalled();
+ CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "required module");
+ requiredModules.checkNameNotAlreadyDeclared(module);
+ CheckClassAdapter.checkAccess(
+ access,
+ Opcodes.ACC_STATIC_PHASE
+ | Opcodes.ACC_TRANSITIVE
+ | Opcodes.ACC_SYNTHETIC
+ | Opcodes.ACC_MANDATED);
+ if (classVersion >= Opcodes.V10
+ && module.equals("java.base")
+ && (access & (Opcodes.ACC_STATIC_PHASE | Opcodes.ACC_TRANSITIVE)) != 0) {
+ throw new IllegalArgumentException(
+ "Invalid access flags: "
+ + access
+ + " java.base can not be declared ACC_TRANSITIVE or ACC_STATIC_PHASE");
}
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- checkEnd();
- if (packaze == null) {
- throw new IllegalArgumentException("packaze cannot be null");
- }
- CheckMethodAdapter.checkInternalName(packaze, "package name");
- checkDeclared("exports", exportNames, packaze);
- CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC
- + Opcodes.ACC_MANDATED);
- if (modules != null) {
- for (int i = 0; i < modules.length; i++) {
- if (modules[i] == null) {
- throw new IllegalArgumentException("module at index " + i + " cannot be null");
- }
- }
- }
- super.visitExport(packaze, access, modules);
+ super.visitRequire(module, access, version);
+ }
+
+ @Override
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ checkVisitEndNotCalled();
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "package name");
+ exportedPackages.checkNameNotAlreadyDeclared(packaze);
+ CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED);
+ if (modules != null) {
+ for (String module : modules) {
+ CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "module export to");
+ }
}
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- checkEnd();
- if (isOpen) {
- throw new IllegalArgumentException("an open module can not use open directive");
- }
- if (packaze == null) {
- throw new IllegalArgumentException("packaze cannot be null");
- }
- CheckMethodAdapter.checkInternalName(packaze, "package name");
- checkDeclared("opens", openNames, packaze);
- CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC
- + Opcodes.ACC_MANDATED);
- if (modules != null) {
- for (int i = 0; i < modules.length; i++) {
- if (modules[i] == null) {
- throw new IllegalArgumentException("module at index " + i + " cannot be null");
- }
- }
- }
- super.visitOpen(packaze, access, modules);
+ super.visitExport(packaze, access, modules);
+ }
+
+ @Override
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ checkVisitEndNotCalled();
+ if (isOpen) {
+ throw new UnsupportedOperationException("An open module can not use open directive");
}
-
- @Override
- public void visitUse(String service) {
- checkEnd();
- CheckMethodAdapter.checkInternalName(service, "service");
- checkDeclared("uses", useNames, service);
- super.visitUse(service);
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "package name");
+ openedPackages.checkNameNotAlreadyDeclared(packaze);
+ CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED);
+ if (modules != null) {
+ for (String module : modules) {
+ CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "module open to");
+ }
}
-
- @Override
- public void visitProvide(String service, String... providers) {
- checkEnd();
- CheckMethodAdapter.checkInternalName(service, "service");
- checkDeclared("provides", provideNames, service);
- if (providers == null || providers.length == 0) {
- throw new IllegalArgumentException("providers cannot be null or empty");
- }
- for (int i = 0; i < providers.length; i++) {
- CheckMethodAdapter.checkInternalName(providers[i], "provider");
- }
- super.visitProvide(service, providers);
+ super.visitOpen(packaze, access, modules);
+ }
+
+ @Override
+ public void visitUse(final String service) {
+ checkVisitEndNotCalled();
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, service, "service");
+ usedServices.checkNameNotAlreadyDeclared(service);
+ super.visitUse(service);
+ }
+
+ @Override
+ public void visitProvide(final String service, final String... providers) {
+ checkVisitEndNotCalled();
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, service, "service");
+ providedServices.checkNameNotAlreadyDeclared(service);
+ if (providers == null || providers.length == 0) {
+ throw new IllegalArgumentException("Providers cannot be null or empty");
}
-
- @Override
- public void visitEnd() {
- checkEnd();
- end = true;
- super.visitEnd();
+ for (String provider : providers) {
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, provider, "provider");
}
+ super.visitProvide(service, providers);
+ }
- private void checkEnd() {
- if (end) {
- throw new IllegalStateException(
- "Cannot call a visit method after visitEnd has been called");
- }
+ @Override
+ public void visitEnd() {
+ checkVisitEndNotCalled();
+ visitEndCalled = true;
+ super.visitEnd();
+ }
+
+ private void checkVisitEndNotCalled() {
+ if (visitEndCalled) {
+ throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");
+ }
+ }
+
+ private static class NameSet {
+
+ private final String type;
+ private final HashSet<String> names;
+
+ NameSet(final String type) {
+ this.type = type;
+ this.names = new HashSet<String>();
}
-
- private static void checkDeclared(String directive, HashSet<String> names, String name) {
- if (!names.add(name)) {
- throw new IllegalArgumentException(directive + " " + name + " already declared");
- }
+
+ void checkNameNotAlreadyDeclared(final String name) {
+ if (!names.add(name)) {
+ throw new IllegalArgumentException(type + " " + name + " already declared");
+ }
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
old mode 100644
new mode 100755
index bca5dd7..8103a10
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
@@ -1,356 +1,359 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
+import java.util.EnumSet;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
/**
* A {@link SignatureVisitor} that checks that its methods are properly used.
- *
+ *
* @author Eric Bruneton
*/
public class CheckSignatureAdapter extends SignatureVisitor {
- /**
- * Type to be used to check class signatures. See
- * {@link #CheckSignatureAdapter(int, SignatureVisitor)
- * CheckSignatureAdapter}.
- */
- public static final int CLASS_SIGNATURE = 0;
-
- /**
- * Type to be used to check method signatures. See
- * {@link #CheckSignatureAdapter(int, SignatureVisitor)
- * CheckSignatureAdapter}.
- */
- public static final int METHOD_SIGNATURE = 1;
-
- /**
- * Type to be used to check type signatures.See
- * {@link #CheckSignatureAdapter(int, SignatureVisitor)
- * CheckSignatureAdapter}.
- */
- public static final int TYPE_SIGNATURE = 2;
-
- private static final int EMPTY = 1;
-
- private static final int FORMAL = 2;
-
- private static final int BOUND = 4;
-
- private static final int SUPER = 8;
-
- private static final int PARAM = 16;
-
- private static final int RETURN = 32;
-
- private static final int SIMPLE_TYPE = 64;
-
- private static final int CLASS_TYPE = 128;
-
- private static final int END = 256;
-
- /**
- * Type of the signature to be checked.
- */
- private final int type;
-
- /**
- * State of the automaton used to check the order of method calls.
- */
- private int state;
-
- /**
- * <tt>true</tt> if the checked type signature can be 'V'.
- */
- private boolean canBeVoid;
-
- /**
- * The visitor to which this adapter must delegate calls. May be
- * <tt>null</tt>.
- */
- private final SignatureVisitor sv;
-
- /**
- * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must
- * not use this constructor</i>. Instead, they must use the
- * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version.
- *
- * @param type
- * the type of signature to be checked. See
- * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
- * {@link #TYPE_SIGNATURE}.
- * @param sv
- * the visitor to which this adapter must delegate calls. May be
- * <tt>null</tt>.
- */
- public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
- this(Opcodes.ASM6, type, sv);
+ /**
+ * Type to be used to check class signatures. See {@link #CheckSignatureAdapter(int,
+ * SignatureVisitor)}.
+ */
+ public static final int CLASS_SIGNATURE = 0;
+
+ /**
+ * Type to be used to check method signatures. See {@link #CheckSignatureAdapter(int,
+ * SignatureVisitor)}.
+ */
+ public static final int METHOD_SIGNATURE = 1;
+
+ /**
+ * Type to be used to check type signatures.See {@link #CheckSignatureAdapter(int,
+ * SignatureVisitor)}.
+ */
+ public static final int TYPE_SIGNATURE = 2;
+
+ /** The valid automaton states for a {@link #visitFormalTypeParameter} method call. */
+ private static final EnumSet<State> VISIT_FORMAL_TYPE_PARAMETER_STATES =
+ EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND);
+
+ /** The valid automaton states for a {@link #visitClassBound} method call. */
+ private static final EnumSet<State> VISIT_CLASS_BOUND_STATES = EnumSet.of(State.FORMAL);
+
+ /** The valid automaton states for a {@link #visitInterfaceBound} method call. */
+ private static final EnumSet<State> VISIT_INTERFACE_BOUND_STATES =
+ EnumSet.of(State.FORMAL, State.BOUND);
+
+ /** The valid automaton states for a {@link #visitSuperclass} method call. */
+ private static final EnumSet<State> VISIT_SUPER_CLASS_STATES =
+ EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND);
+
+ /** The valid automaton states for a {@link #visitInterface} method call. */
+ private static final EnumSet<State> VISIT_INTERFACE_STATES = EnumSet.of(State.SUPER);
+
+ /** The valid automaton states for a {@link #visitParameterType} method call. */
+ private static final EnumSet<State> VISIT_PARAMETER_TYPE_STATES =
+ EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND, State.PARAM);
+
+ /** The valid automaton states for a {@link #visitReturnType} method call. */
+ private static final EnumSet<State> VISIT_RETURN_TYPE_STATES =
+ EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND, State.PARAM);
+
+ /** The valid automaton states for a {@link #visitExceptionType} method call. */
+ private static final EnumSet<State> VISIT_EXCEPTION_TYPE_STATES = EnumSet.of(State.RETURN);
+
+ /** The possible states of the automaton used to check the order of method calls. */
+ private enum State {
+ EMPTY,
+ FORMAL,
+ BOUND,
+ SUPER,
+ PARAM,
+ RETURN,
+ SIMPLE_TYPE,
+ CLASS_TYPE,
+ END;
+ }
+
+ private static final String INVALID = "Invalid ";
+
+ /** The type of the visited signature. */
+ private final int type;
+
+ /** The current state of the automaton used to check the order of method calls. */
+ private State state;
+
+ /** Whether the visited signature can be 'V'. */
+ private boolean canBeVoid;
+
+ /** The visitor to which this adapter must delegate calls. May be {@literal null}. */
+ private final SignatureVisitor signatureVisitor;
+
+ /**
+ * Constructs a new {@link CheckSignatureAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the {@link #CheckSignatureAdapter(int, int,
+ * SignatureVisitor)} version.
+ *
+ * @param type the type of signature to be checked. See {@link #CLASS_SIGNATURE}, {@link
+ * #METHOD_SIGNATURE} and {@link #TYPE_SIGNATURE}.
+ * @param signatureVisitor the visitor to which this adapter must delegate calls. May be {@literal
+ * null}.
+ */
+ public CheckSignatureAdapter(final int type, final SignatureVisitor signatureVisitor) {
+ this(Opcodes.ASM7, type, signatureVisitor);
+ }
+
+ /**
+ * Constructs a new {@link CheckSignatureAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param type the type of signature to be checked. See {@link #CLASS_SIGNATURE}, {@link
+ * #METHOD_SIGNATURE} and {@link #TYPE_SIGNATURE}.
+ * @param signatureVisitor the visitor to which this adapter must delegate calls. May be {@literal
+ * null}.
+ */
+ protected CheckSignatureAdapter(
+ final int api, final int type, final SignatureVisitor signatureVisitor) {
+ super(api);
+ this.type = type;
+ this.state = State.EMPTY;
+ this.signatureVisitor = signatureVisitor;
+ }
+
+ // class and method signatures
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ if (type == TYPE_SIGNATURE || !VISIT_FORMAL_TYPE_PARAMETER_STATES.contains(state)) {
+ throw new IllegalStateException();
}
-
- /**
- * Creates a new {@link CheckSignatureAdapter} object.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param type
- * the type of signature to be checked. See
- * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
- * {@link #TYPE_SIGNATURE}.
- * @param sv
- * the visitor to which this adapter must delegate calls. May be
- * <tt>null</tt>.
- */
- protected CheckSignatureAdapter(final int api, final int type,
- final SignatureVisitor sv) {
- super(api);
- this.type = type;
- this.state = EMPTY;
- this.sv = sv;
+ checkIdentifier(name, "formal type parameter");
+ state = State.FORMAL;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitFormalTypeParameter(name);
}
+ }
- // class and method signatures
-
- @Override
- public void visitFormalTypeParameter(final String name) {
- if (type == TYPE_SIGNATURE
- || (state != EMPTY && state != FORMAL && state != BOUND)) {
- throw new IllegalStateException();
- }
- checkIdentifier(name, "formal type parameter");
- state = FORMAL;
- if (sv != null) {
- sv.visitFormalTypeParameter(name);
- }
+ @Override
+ public SignatureVisitor visitClassBound() {
+ if (type == TYPE_SIGNATURE || !VISIT_CLASS_BOUND_STATES.contains(state)) {
+ throw new IllegalStateException();
}
-
- @Override
- public SignatureVisitor visitClassBound() {
- if (state != FORMAL) {
- throw new IllegalStateException();
- }
- state = BOUND;
- SignatureVisitor v = sv == null ? null : sv.visitClassBound();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ state = State.BOUND;
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitClassBound());
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ if (type == TYPE_SIGNATURE || !VISIT_INTERFACE_BOUND_STATES.contains(state)) {
+ throw new IllegalArgumentException();
}
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitInterfaceBound());
+ }
- @Override
- public SignatureVisitor visitInterfaceBound() {
- if (state != FORMAL && state != BOUND) {
- throw new IllegalArgumentException();
- }
- SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ // class signatures
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ if (type != CLASS_SIGNATURE || !VISIT_SUPER_CLASS_STATES.contains(state)) {
+ throw new IllegalArgumentException();
+ }
+ state = State.SUPER;
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitSuperclass());
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ if (type != CLASS_SIGNATURE || !VISIT_INTERFACE_STATES.contains(state)) {
+ throw new IllegalStateException();
}
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitInterface());
+ }
- // class signatures
+ // method signatures
- @Override
- public SignatureVisitor visitSuperclass() {
- if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) {
- throw new IllegalArgumentException();
- }
- state = SUPER;
- SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ @Override
+ public SignatureVisitor visitParameterType() {
+ if (type != METHOD_SIGNATURE || !VISIT_PARAMETER_TYPE_STATES.contains(state)) {
+ throw new IllegalArgumentException();
}
-
- @Override
- public SignatureVisitor visitInterface() {
- if (state != SUPER) {
- throw new IllegalStateException();
- }
- SignatureVisitor v = sv == null ? null : sv.visitInterface();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ state = State.PARAM;
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitParameterType());
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ if (type != METHOD_SIGNATURE || !VISIT_RETURN_TYPE_STATES.contains(state)) {
+ throw new IllegalArgumentException();
}
-
- // method signatures
-
- @Override
- public SignatureVisitor visitParameterType() {
- if (type != METHOD_SIGNATURE
- || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
- throw new IllegalArgumentException();
- }
- state = PARAM;
- SignatureVisitor v = sv == null ? null : sv.visitParameterType();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ state = State.RETURN;
+ CheckSignatureAdapter checkSignatureAdapter =
+ new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitReturnType());
+ checkSignatureAdapter.canBeVoid = true;
+ return checkSignatureAdapter;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (type != METHOD_SIGNATURE || !VISIT_EXCEPTION_TYPE_STATES.contains(state)) {
+ throw new IllegalStateException();
}
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitExceptionType());
+ }
- @Override
- public SignatureVisitor visitReturnType() {
- if (type != METHOD_SIGNATURE
- || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
- throw new IllegalArgumentException();
- }
- state = RETURN;
- SignatureVisitor v = sv == null ? null : sv.visitReturnType();
- CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
- cv.canBeVoid = true;
- return cv;
- }
+ // type signatures
- @Override
- public SignatureVisitor visitExceptionType() {
- if (state != RETURN) {
- throw new IllegalStateException();
- }
- SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ @Override
+ public void visitBaseType(final char descriptor) {
+ if (type != TYPE_SIGNATURE || state != State.EMPTY) {
+ throw new IllegalStateException();
}
-
- // type signatures
-
- @Override
- public void visitBaseType(final char descriptor) {
- if (type != TYPE_SIGNATURE || state != EMPTY) {
- throw new IllegalStateException();
- }
- if (descriptor == 'V') {
- if (!canBeVoid) {
- throw new IllegalArgumentException();
- }
- } else {
- if ("ZCBSIFJD".indexOf(descriptor) == -1) {
- throw new IllegalArgumentException();
- }
- }
- state = SIMPLE_TYPE;
- if (sv != null) {
- sv.visitBaseType(descriptor);
- }
+ if (descriptor == 'V') {
+ if (!canBeVoid) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+ throw new IllegalArgumentException();
+ }
}
-
- @Override
- public void visitTypeVariable(final String name) {
- if (type != TYPE_SIGNATURE || state != EMPTY) {
- throw new IllegalStateException();
- }
- checkIdentifier(name, "type variable");
- state = SIMPLE_TYPE;
- if (sv != null) {
- sv.visitTypeVariable(name);
- }
+ state = State.SIMPLE_TYPE;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitBaseType(descriptor);
}
+ }
- @Override
- public SignatureVisitor visitArrayType() {
- if (type != TYPE_SIGNATURE || state != EMPTY) {
- throw new IllegalStateException();
- }
- state = SIMPLE_TYPE;
- SignatureVisitor v = sv == null ? null : sv.visitArrayType();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ @Override
+ public void visitTypeVariable(final String name) {
+ if (type != TYPE_SIGNATURE || state != State.EMPTY) {
+ throw new IllegalStateException();
}
-
- @Override
- public void visitClassType(final String name) {
- if (type != TYPE_SIGNATURE || state != EMPTY) {
- throw new IllegalStateException();
- }
- checkClassName(name, "class name");
- state = CLASS_TYPE;
- if (sv != null) {
- sv.visitClassType(name);
- }
+ checkIdentifier(name, "type variable");
+ state = State.SIMPLE_TYPE;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitTypeVariable(name);
}
+ }
- @Override
- public void visitInnerClassType(final String name) {
- if (state != CLASS_TYPE) {
- throw new IllegalStateException();
- }
- checkIdentifier(name, "inner class name");
- if (sv != null) {
- sv.visitInnerClassType(name);
- }
+ @Override
+ public SignatureVisitor visitArrayType() {
+ if (type != TYPE_SIGNATURE || state != State.EMPTY) {
+ throw new IllegalStateException();
+ }
+ state = State.SIMPLE_TYPE;
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitArrayType());
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if (type != TYPE_SIGNATURE || state != State.EMPTY) {
+ throw new IllegalStateException();
}
+ checkClassName(name, "class name");
+ state = State.CLASS_TYPE;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitClassType(name);
+ }
+ }
- @Override
- public void visitTypeArgument() {
- if (state != CLASS_TYPE) {
- throw new IllegalStateException();
- }
- if (sv != null) {
- sv.visitTypeArgument();
- }
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (state != State.CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ checkIdentifier(name, "inner class name");
+ if (signatureVisitor != null) {
+ signatureVisitor.visitInnerClassType(name);
}
+ }
- @Override
- public SignatureVisitor visitTypeArgument(final char wildcard) {
- if (state != CLASS_TYPE) {
- throw new IllegalStateException();
- }
- if ("+-=".indexOf(wildcard) == -1) {
- throw new IllegalArgumentException();
- }
- SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ @Override
+ public void visitTypeArgument() {
+ if (state != State.CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if (signatureVisitor != null) {
+ signatureVisitor.visitTypeArgument();
}
+ }
- @Override
- public void visitEnd() {
- if (state != CLASS_TYPE) {
- throw new IllegalStateException();
- }
- state = END;
- if (sv != null) {
- sv.visitEnd();
- }
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (state != State.CLASS_TYPE) {
+ throw new IllegalStateException();
}
+ if ("+-=".indexOf(wildcard) == -1) {
+ throw new IllegalArgumentException();
+ }
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE,
+ signatureVisitor == null ? null : signatureVisitor.visitTypeArgument(wildcard));
+ }
+
+ @Override
+ public void visitEnd() {
+ if (state != State.CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ state = State.END;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitEnd();
+ }
+ }
- private void checkClassName(final String name, final String msg) {
- if (name == null || name.length() == 0) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not be null or empty)");
- }
- for (int i = 0; i < name.length(); ++i) {
- if (".;[<>:".indexOf(name.charAt(i)) != -1) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not contain . ; [ < > or :): " + name);
- }
- }
+ private void checkClassName(final String name, final String message) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException(INVALID + message + " (must not be null or empty)");
}
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[<>:".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException(
+ INVALID + message + " (must not contain . ; [ < > or :): " + name);
+ }
+ }
+ }
- private void checkIdentifier(final String name, final String msg) {
- if (name == null || name.length() == 0) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not be null or empty)");
- }
- for (int i = 0; i < name.length(); ++i) {
- if (".;[/<>:".indexOf(name.charAt(i)) != -1) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not contain . ; [ / < > or :): " + name);
- }
- }
+ private void checkIdentifier(final String name, final String message) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException(INVALID + message + " (must not be null or empty)");
+ }
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/<>:".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException(
+ INVALID + message + " (must not contain . ; [ / < > or :): " + name);
+ }
}
+ }
}
[37/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
old mode 100644
new mode 100755
index ed5d751..cc47afd
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
@@ -1,881 +1,781 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java method. The methods of this class must be called in
- * the following order: ( <tt>visitParameter</tt> )* [
- * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |
- * <tt>visitParameterAnnotation</tt> <tt>visitTypeAnnotation</tt> |
- * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
- * <tt>visit<i>X</i>Insn</tt> | <tt>visitLabel</tt> |
- * <tt>visitInsnAnnotation</tt> | <tt>visitTryCatchBlock</tt> |
- * <tt>visitTryCatchAnnotation</tt> | <tt>visitLocalVariable</tt> |
- * <tt>visitLocalVariableAnnotation</tt> | <tt>visitLineNumber</tt> )*
- * <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In addition, the
- * <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must be called in
- * the sequential order of the bytecode instructions of the visited code,
- * <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
- * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
- * labels passed as arguments have been visited,
- * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the
- * corresponding try catch block has been visited, and the
- * <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and
- * <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels
- * passed as arguments have been visited.
- *
+ * A visitor to visit a Java method. The methods of this class must be called in the following
+ * order: ( {@code visitParameter} )* [ {@code visitAnnotationDefault} ] ( {@code visitAnnotation} |
+ * {@code visitAnnotableParameterCount} | {@code visitParameterAnnotation} {@code
+ * visitTypeAnnotation} | {@code visitAttribute} )* [ {@code visitCode} ( {@code visitFrame} |
+ * {@code visit<i>X</i>Insn} | {@code visitLabel} | {@code visitInsnAnnotation} | {@code
+ * visitTryCatchBlock} | {@code visitTryCatchAnnotation} | {@code visitLocalVariable} | {@code
+ * visitLocalVariableAnnotation} | {@code visitLineNumber} )* {@code visitMaxs} ] {@code visitEnd}.
+ * In addition, the {@code visit<i>X</i>Insn} and {@code visitLabel} methods must be called in the
+ * sequential order of the bytecode instructions of the visited code, {@code visitInsnAnnotation}
+ * must be called <i>after</i> the annotated instruction, {@code visitTryCatchBlock} must be called
+ * <i>before</i> the labels passed as arguments have been visited, {@code
+ * visitTryCatchBlockAnnotation} must be called <i>after</i> the corresponding try catch block has
+ * been visited, and the {@code visitLocalVariable}, {@code visitLocalVariableAnnotation} and {@code
+ * visitLineNumber} methods must be called <i>after</i> the labels passed as arguments have been
+ * visited.
+ *
* @author Eric Bruneton
*/
public abstract class MethodVisitor {
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- protected final int api;
-
- /**
- * The method visitor to which this visitor must delegate method calls. May
- * be null.
- */
- protected MethodVisitor mv;
-
- /**
- * Constructs a new {@link MethodVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public MethodVisitor(final int api) {
- this(api, null);
- }
-
- /**
- * Constructs a new {@link MethodVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param mv
- * the method visitor to which this visitor must delegate method
- * calls. May be null.
- */
- public MethodVisitor(final int api, final MethodVisitor mv) {
- if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.mv = mv;
- }
-
- // -------------------------------------------------------------------------
- // Parameters, annotations and non standard attributes
- // -------------------------------------------------------------------------
-
- /**
- * Visits a parameter of this method.
- *
- * @param name
- * parameter name or null if none is provided.
- * @param access
- * the parameter's access flags, only <tt>ACC_FINAL</tt>,
- * <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
- * allowed (see {@link Opcodes}).
- */
- public void visitParameter(String name, int access) {
- if (api < Opcodes.ASM5) {
- throw new RuntimeException();
- }
- if (mv != null) {
- mv.visitParameter(name, access);
- }
- }
-
- /**
- * Visits the default value of this annotation interface method.
- *
- * @return a visitor to the visit the actual default value of this
- * annotation interface method, or <tt>null</tt> if this visitor is
- * not interested in visiting this default value. The 'name'
- * parameters passed to the methods of this annotation visitor are
- * ignored. Moreover, exacly one visit method must be called on this
- * annotation visitor, followed by visitEnd.
- */
- public AnnotationVisitor visitAnnotationDefault() {
- if (mv != null) {
- return mv.visitAnnotationDefault();
- }
- return null;
- }
-
- /**
- * Visits an annotation of this method.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (mv != null) {
- return mv.visitAnnotation(desc, visible);
- }
- return null;
- }
-
- /**
- * Visits an annotation on a type in the method signature.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER
- * METHOD_TYPE_PARAMETER},
- * {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND
- * METHOD_TYPE_PARAMETER_BOUND},
- * {@link TypeReference#METHOD_RETURN METHOD_RETURN},
- * {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER},
- * {@link TypeReference#METHOD_FORMAL_PARAMETER
- * METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS
- * THROWS}. See {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- if (api < Opcodes.ASM5) {
- throw new RuntimeException();
- }
- if (mv != null) {
- return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
- return null;
- }
-
- /**
- * Visits an annotation of a parameter this method.
- *
- * @param parameter
- * the parameter index.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitParameterAnnotation(int parameter,
- String desc, boolean visible) {
- if (mv != null) {
- return mv.visitParameterAnnotation(parameter, desc, visible);
- }
- return null;
- }
-
- /**
- * Visits a non standard attribute of this method.
- *
- * @param attr
- * an attribute.
- */
- public void visitAttribute(Attribute attr) {
- if (mv != null) {
- mv.visitAttribute(attr);
- }
- }
-
- /**
- * Starts the visit of the method's code, if any (i.e. non abstract method).
- */
- public void visitCode() {
- if (mv != null) {
- mv.visitCode();
- }
- }
-
- /**
- * Visits the current state of the local variables and operand stack
- * elements. This method must(*) be called <i>just before</i> any
- * instruction <b>i</b> that follows an unconditional branch instruction
- * such as GOTO or THROW, that is the target of a jump instruction, or that
- * starts an exception handler block. The visited types must describe the
- * values of the local variables and of the operand stack elements <i>just
- * before</i> <b>i</b> is executed.<br>
- * <br>
- * (*) this is mandatory only for classes whose version is greater than or
- * equal to {@link Opcodes#V1_6 V1_6}. <br>
- * <br>
- * The frames of a method must be given either in expanded form, or in
- * compressed form (all frames must use the same format, i.e. you must not
- * mix expanded and compressed frames within a single method):
- * <ul>
- * <li>In expanded form, all frames must have the F_NEW type.</li>
- * <li>In compressed form, frames are basically "deltas" from the state of
- * the previous frame:
- * <ul>
- * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
- * locals as the previous frame and with the empty stack.</li>
- * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same
- * locals as the previous frame and with single value on the stack (
- * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the
- * type of the stack item).</li>
- * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
- * the same as the locals in the previous frame, except that additional
- * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
- * <code>local</code> elements contains values representing added types).</li>
- * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
- * same as the locals in the previous frame, except that the last 1-3 locals
- * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>
- * <li>{@link Opcodes#F_FULL} representing complete frame data.</li>
- * </ul>
- * </li>
- * </ul>
- * <br>
- * In both cases the first frame, corresponding to the method's parameters
- * and access flags, is implicit and must not be visited. Also, it is
- * illegal to visit two or more frames for the same code location (i.e., at
- * least one instruction must be visited between two calls to visitFrame).
- *
- * @param type
- * the type of this stack map frame. Must be
- * {@link Opcodes#F_NEW} for expanded frames, or
- * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
- * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
- * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for
- * compressed frames.
- * @param nLocal
- * the number of local variables in the visited frame.
- * @param local
- * the local variable types in this frame. This array must not be
- * modified. Primitive types are represented by
- * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
- * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
- * represented by a single element). Reference types are
- * represented by String objects (representing internal names),
- * and uninitialized types by Label objects (this label
- * designates the NEW instruction that created this uninitialized
- * value).
- * @param nStack
- * the number of operand stack elements in the visited frame.
- * @param stack
- * the operand stack types in this frame. This array must not be
- * modified. Its content has the same format as the "local"
- * array.
- * @throws IllegalStateException
- * if a frame is visited just after another one, without any
- * instruction between the two (unless this frame is a
- * Opcodes#F_SAME frame, in which case it is silently ignored).
- */
- public void visitFrame(int type, int nLocal, Object[] local, int nStack,
- Object[] stack) {
- if (mv != null) {
- mv.visitFrame(type, nLocal, local, nStack, stack);
- }
- }
-
- // -------------------------------------------------------------------------
- // Normal instructions
- // -------------------------------------------------------------------------
-
- /**
- * Visits a zero operand instruction.
- *
- * @param opcode
- * the opcode of the instruction to be visited. This opcode is
- * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
- * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
- * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
- * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
- * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
- * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
- * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
- * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
- * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
- * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
- * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
- * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
- * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
- * or MONITOREXIT.
- */
- public void visitInsn(int opcode) {
- if (mv != null) {
- mv.visitInsn(opcode);
- }
- }
-
- /**
- * Visits an instruction with a single int operand.
- *
- * @param opcode
- * the opcode of the instruction to be visited. This opcode is
- * either BIPUSH, SIPUSH or NEWARRAY.
- * @param operand
- * the operand of the instruction to be visited.<br>
- * When opcode is BIPUSH, operand value should be between
- * Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
- * When opcode is SIPUSH, operand value should be between
- * Short.MIN_VALUE and Short.MAX_VALUE.<br>
- * When opcode is NEWARRAY, operand value should be one of
- * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
- * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
- * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
- * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
- */
- public void visitIntInsn(int opcode, int operand) {
- if (mv != null) {
- mv.visitIntInsn(opcode, operand);
- }
- }
-
- /**
- * Visits a local variable instruction. A local variable instruction is an
- * instruction that loads or stores the value of a local variable.
- *
- * @param opcode
- * the opcode of the local variable instruction to be visited.
- * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD,
- * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var
- * the operand of the instruction to be visited. This operand is
- * the index of a local variable.
- */
- public void visitVarInsn(int opcode, int var) {
- if (mv != null) {
- mv.visitVarInsn(opcode, var);
- }
- }
-
- /**
- * Visits a type instruction. A type instruction is an instruction that
- * takes the internal name of a class as parameter.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param type
- * the operand of the instruction to be visited. This operand
- * must be the internal name of an object or array class (see
- * {@link Type#getInternalName() getInternalName}).
- */
- public void visitTypeInsn(int opcode, String type) {
- if (mv != null) {
- mv.visitTypeInsn(opcode, type);
- }
- }
-
- /**
- * Visits a field instruction. A field instruction is an instruction that
- * loads or stores the value of a field of an object.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner
- * the internal name of the field's owner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link Type Type}).
- */
- public void visitFieldInsn(int opcode, String owner, String name,
- String desc) {
- if (mv != null) {
- mv.visitFieldInsn(opcode, owner, name, desc);
- }
- }
-
- /**
- * Visits a method instruction. A method instruction is an instruction that
- * invokes a method.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner
- * the internal name of the method's owner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- */
- @Deprecated
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc) {
- if (api >= Opcodes.ASM5) {
- boolean itf = opcode == Opcodes.INVOKEINTERFACE;
- visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc);
- }
- }
-
- /**
- * Visits a method instruction. A method instruction is an instruction that
- * invokes a method.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner
- * the internal name of the method's owner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param itf
- * if the method's owner class is an interface.
- */
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc, boolean itf) {
- if (api < Opcodes.ASM5) {
- if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
- throw new IllegalArgumentException(
- "INVOKESPECIAL/STATIC on interfaces require ASM 5");
- }
- visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- }
-
- /**
- * Visits an invokedynamic instruction.
- *
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the bootstrap method constant arguments. Each argument must be
- * an {@link Integer}, {@link Float}, {@link Long},
- * {@link Double}, {@link String}, {@link Type} or {@link Handle}
- * value. This method is allowed to modify the content of the
- * array so a caller should expect that this array may change.
- */
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- if (mv != null) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
- }
-
- /**
- * Visits a jump instruction. A jump instruction is an instruction that may
- * jump to another instruction.
- *
- * @param opcode
- * the opcode of the type instruction to be visited. This opcode
- * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
- * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
- * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
- * @param label
- * the operand of the instruction to be visited. This operand is
- * a label that designates the instruction to which the jump
- * instruction may jump.
- */
- public void visitJumpInsn(int opcode, Label label) {
- if (mv != null) {
- mv.visitJumpInsn(opcode, label);
- }
- }
-
- /**
- * Visits a label. A label designates the instruction that will be visited
- * just after it.
- *
- * @param label
- * a {@link Label Label} object.
- */
- public void visitLabel(Label label) {
- if (mv != null) {
- mv.visitLabel(label);
- }
- }
-
- // -------------------------------------------------------------------------
- // Special instructions
- // -------------------------------------------------------------------------
-
- /**
- * Visits a LDC instruction. Note that new constant types may be added in
- * future versions of the Java Virtual Machine. To easily detect new
- * constant types, implementations of this method should check for
- * unexpected constant types, like this:
- *
- * <pre>
- * if (cst instanceof Integer) {
- * // ...
- * } else if (cst instanceof Float) {
- * // ...
- * } else if (cst instanceof Long) {
- * // ...
- * } else if (cst instanceof Double) {
- * // ...
- * } else if (cst instanceof String) {
- * // ...
- * } else if (cst instanceof Type) {
- * int sort = ((Type) cst).getSort();
- * if (sort == Type.OBJECT) {
- * // ...
- * } else if (sort == Type.ARRAY) {
- * // ...
- * } else if (sort == Type.METHOD) {
- * // ...
- * } else {
- * // throw an exception
- * }
- * } else if (cst instanceof Handle) {
- * // ...
- * } else {
- * // throw an exception
- * }
- * </pre>
- *
- * @param cst
- * the constant to be loaded on the stack. This parameter must be
- * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double}, a {@link String}, a {@link Type} of OBJECT or
- * ARRAY sort for <tt>.class</tt> constants, for classes whose
- * version is 49.0, a {@link Type} of METHOD sort or a
- * {@link Handle} for MethodType and MethodHandle constants, for
- * classes whose version is 51.0.
- */
- public void visitLdcInsn(Object cst) {
- if (mv != null) {
- mv.visitLdcInsn(cst);
- }
- }
-
- /**
- * Visits an IINC instruction.
- *
- * @param var
- * index of the local variable to be incremented.
- * @param increment
- * amount to increment the local variable by.
- */
- public void visitIincInsn(int var, int increment) {
- if (mv != null) {
- mv.visitIincInsn(var, increment);
- }
- }
-
- /**
- * Visits a TABLESWITCH instruction.
- *
- * @param min
- * the minimum key value.
- * @param max
- * the maximum key value.
- * @param dflt
- * beginning of the default handler block.
- * @param labels
- * beginnings of the handler blocks. <tt>labels[i]</tt> is the
- * beginning of the handler block for the <tt>min + i</tt> key.
- */
- public void visitTableSwitchInsn(int min, int max, Label dflt,
- Label... labels) {
- if (mv != null) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
- }
-
- /**
- * Visits a LOOKUPSWITCH instruction.
- *
- * @param dflt
- * beginning of the default handler block.
- * @param keys
- * the values of the keys.
- * @param labels
- * beginnings of the handler blocks. <tt>labels[i]</tt> is the
- * beginning of the handler block for the <tt>keys[i]</tt> key.
- */
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- if (mv != null) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
- }
-
- /**
- * Visits a MULTIANEWARRAY instruction.
- *
- * @param desc
- * an array type descriptor (see {@link Type Type}).
- * @param dims
- * number of dimensions of the array to allocate.
- */
- public void visitMultiANewArrayInsn(String desc, int dims) {
- if (mv != null) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
- }
-
- /**
- * Visits an annotation on an instruction. This method must be called just
- * <i>after</i> the annotated instruction. It can be called several times
- * for the same instruction.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF},
- * {@link TypeReference#NEW NEW},
- * {@link TypeReference#CONSTRUCTOR_REFERENCE
- * CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE
- * METHOD_REFERENCE}, {@link TypeReference#CAST CAST},
- * {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
- * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
- * {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT
- * METHOD_INVOCATION_TYPE_ARGUMENT},
- * {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
- * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
- * {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT
- * METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitInsnAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- if (api < Opcodes.ASM5) {
- throw new RuntimeException();
- }
- if (mv != null) {
- return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
- }
- return null;
- }
-
- // -------------------------------------------------------------------------
- // Exceptions table entries, debug information, max stack and max locals
- // -------------------------------------------------------------------------
-
- /**
- * Visits a try catch block.
- *
- * @param start
- * beginning of the exception handler's scope (inclusive).
- * @param end
- * end of the exception handler's scope (exclusive).
- * @param handler
- * beginning of the exception handler's code.
- * @param type
- * internal name of the type of exceptions handled by the
- * handler, or <tt>null</tt> to catch any exceptions (for
- * "finally" blocks).
- * @throws IllegalArgumentException
- * if one of the labels has already been visited by this visitor
- * (by the {@link #visitLabel visitLabel} method).
- */
- public void visitTryCatchBlock(Label start, Label end, Label handler,
- String type) {
- if (mv != null) {
- mv.visitTryCatchBlock(start, end, handler, type);
- }
- }
-
- /**
- * Visits an annotation on an exception handler type. This method must be
- * called <i>after</i> the {@link #visitTryCatchBlock} for the annotated
- * exception handler. It can be called several times for the same exception
- * handler.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be {@link TypeReference#EXCEPTION_PARAMETER
- * EXCEPTION_PARAMETER}. See {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- if (api < Opcodes.ASM5) {
- throw new RuntimeException();
- }
- if (mv != null) {
- return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
- }
- return null;
- }
-
- /**
- * Visits a local variable declaration.
- *
- * @param name
- * the name of a local variable.
- * @param desc
- * the type descriptor of this local variable.
- * @param signature
- * the type signature of this local variable. May be
- * <tt>null</tt> if the local variable type does not use generic
- * types.
- * @param start
- * the first instruction corresponding to the scope of this local
- * variable (inclusive).
- * @param end
- * the last instruction corresponding to the scope of this local
- * variable (exclusive).
- * @param index
- * the local variable's index.
- * @throws IllegalArgumentException
- * if one of the labels has not already been visited by this
- * visitor (by the {@link #visitLabel visitLabel} method).
- */
- public void visitLocalVariable(String name, String desc, String signature,
- Label start, Label end, int index) {
- if (mv != null) {
- mv.visitLocalVariable(name, desc, signature, start, end, index);
- }
- }
-
- /**
- * Visits an annotation on a local variable type.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be {@link TypeReference#LOCAL_VARIABLE
- * LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE
- * RESOURCE_VARIABLE}. See {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param start
- * the fist instructions corresponding to the continuous ranges
- * that make the scope of this local variable (inclusive).
- * @param end
- * the last instructions corresponding to the continuous ranges
- * that make the scope of this local variable (exclusive). This
- * array must have the same size as the 'start' array.
- * @param index
- * the local variable's index in each range. This array must have
- * the same size as the 'start' array.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
- TypePath typePath, Label[] start, Label[] end, int[] index,
- String desc, boolean visible) {
- if (api < Opcodes.ASM5) {
- throw new RuntimeException();
- }
- if (mv != null) {
- return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
- end, index, desc, visible);
- }
- return null;
- }
-
- /**
- * Visits a line number declaration.
- *
- * @param line
- * a line number. This number refers to the source file from
- * which the class was compiled.
- * @param start
- * the first instruction corresponding to this line number.
- * @throws IllegalArgumentException
- * if <tt>start</tt> has not already been visited by this
- * visitor (by the {@link #visitLabel visitLabel} method).
- */
- public void visitLineNumber(int line, Label start) {
- if (mv != null) {
- mv.visitLineNumber(line, start);
- }
- }
-
- /**
- * Visits the maximum stack size and the maximum number of local variables
- * of the method.
- *
- * @param maxStack
- * maximum stack size of the method.
- * @param maxLocals
- * maximum number of local variables for the method.
- */
- public void visitMaxs(int maxStack, int maxLocals) {
- if (mv != null) {
- mv.visitMaxs(maxStack, maxLocals);
- }
- }
-
- /**
- * Visits the end of the method. This method, which is the last one to be
- * called, is used to inform the visitor that all the annotations and
- * attributes of the method have been visited.
- */
- public void visitEnd() {
- if (mv != null) {
- mv.visitEnd();
- }
- }
+ private static final String REQUIRES_ASM5 = "This feature requires ASM5";
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected final int api;
+
+ /** The method visitor to which this visitor must delegate method calls. May be null. */
+ protected MethodVisitor mv;
+
+ /**
+ * Constructs a new {@link MethodVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public MethodVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link MethodVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param methodVisitor the method visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ public MethodVisitor(final int api, final MethodVisitor methodVisitor) {
+ if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
+ throw new IllegalArgumentException();
+ }
+ this.api = api;
+ this.mv = methodVisitor;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Parameters, annotations and non standard attributes
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Visits a parameter of this method.
+ *
+ * @param name parameter name or null if none is provided.
+ * @param access the parameter's access flags, only {@code ACC_FINAL}, {@code ACC_SYNTHETIC}
+ * or/and {@code ACC_MANDATED} are allowed (see {@link Opcodes}).
+ */
+ public void visitParameter(final String name, final int access) {
+ if (api < Opcodes.ASM5) {
+ throw new UnsupportedOperationException(REQUIRES_ASM5);
+ }
+ if (mv != null) {
+ mv.visitParameter(name, access);
+ }
+ }
+
+ /**
+ * Visits the default value of this annotation interface method.
+ *
+ * @return a visitor to the visit the actual default value of this annotation interface method, or
+ * {@literal null} if this visitor is not interested in visiting this default value. The
+ * 'name' parameters passed to the methods of this annotation visitor are ignored. Moreover,
+ * exacly one visit method must be called on this annotation visitor, followed by visitEnd.
+ */
+ public AnnotationVisitor visitAnnotationDefault() {
+ if (mv != null) {
+ return mv.visitAnnotationDefault();
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation of this method.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ if (mv != null) {
+ return mv.visitAnnotation(descriptor, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation on a type in the method signature.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link TypeReference#METHOD_TYPE_PARAMETER}, {@link
+ * TypeReference#METHOD_TYPE_PARAMETER_BOUND}, {@link TypeReference#METHOD_RETURN}, {@link
+ * TypeReference#METHOD_RECEIVER}, {@link TypeReference#METHOD_FORMAL_PARAMETER} or {@link
+ * TypeReference#THROWS}. See {@link TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new UnsupportedOperationException(REQUIRES_ASM5);
+ }
+ if (mv != null) {
+ return mv.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits the number of method parameters that can have annotations. By default (i.e. when this
+ * method is not called), all the method parameters defined by the method descriptor can have
+ * annotations.
+ *
+ * @param parameterCount the number of method parameters than can have annotations. This number
+ * must be less or equal than the number of parameter types in the method descriptor. It can
+ * be strictly less when a method has synthetic parameters and when these parameters are
+ * ignored when computing parameter indices for the purpose of parameter annotations (see
+ * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18).
+ * @param visible {@literal true} to define the number of method parameters that can have
+ * annotations visible at runtime, {@literal false} to define the number of method parameters
+ * that can have annotations invisible at runtime.
+ */
+ public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ if (mv != null) {
+ mv.visitAnnotableParameterCount(parameterCount, visible);
+ }
+ }
+
+ /**
+ * Visits an annotation of a parameter this method.
+ *
+ * @param parameter the parameter index. This index must be strictly smaller than the number of
+ * parameters in the method descriptor, and strictly smaller than the parameter count
+ * specified in {@link #visitAnnotableParameterCount}. Important note: <i>a parameter index i
+ * is not required to correspond to the i'th parameter descriptor in the method
+ * descriptor</i>, in particular in case of synthetic parameters (see
+ * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18).
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ if (mv != null) {
+ return mv.visitParameterAnnotation(parameter, descriptor, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a non standard attribute of this method.
+ *
+ * @param attribute an attribute.
+ */
+ public void visitAttribute(final Attribute attribute) {
+ if (mv != null) {
+ mv.visitAttribute(attribute);
+ }
+ }
+
+ /** Starts the visit of the method's code, if any (i.e. non abstract method). */
+ public void visitCode() {
+ if (mv != null) {
+ mv.visitCode();
+ }
+ }
+
+ /**
+ * Visits the current state of the local variables and operand stack elements. This method must(*)
+ * be called <i>just before</i> any instruction <b>i</b> that follows an unconditional branch
+ * instruction such as GOTO or THROW, that is the target of a jump instruction, or that starts an
+ * exception handler block. The visited types must describe the values of the local variables and
+ * of the operand stack elements <i>just before</i> <b>i</b> is executed.<br>
+ * <br>
+ * (*) this is mandatory only for classes whose version is greater than or equal to {@link
+ * Opcodes#V1_6}. <br>
+ * <br>
+ * The frames of a method must be given either in expanded form, or in compressed form (all frames
+ * must use the same format, i.e. you must not mix expanded and compressed frames within a single
+ * method):
+ *
+ * <ul>
+ * <li>In expanded form, all frames must have the F_NEW type.
+ * <li>In compressed form, frames are basically "deltas" from the state of the previous frame:
+ * <ul>
+ * <li>{@link Opcodes#F_SAME} representing frame with exactly the same locals as the
+ * previous frame and with the empty stack.
+ * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same locals as the
+ * previous frame and with single value on the stack ( <code>numStack</code> is 1 and
+ * <code>stack[0]</code> contains value for the type of the stack item).
+ * <li>{@link Opcodes#F_APPEND} representing frame with current locals are the same as the
+ * locals in the previous frame, except that additional locals are defined (<code>
+ * numLocal</code> is 1, 2 or 3 and <code>local</code> elements contains values
+ * representing added types).
+ * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the same as the
+ * locals in the previous frame, except that the last 1-3 locals are absent and with
+ * the empty stack (<code>numLocal</code> is 1, 2 or 3).
+ * <li>{@link Opcodes#F_FULL} representing complete frame data.
+ * </ul>
+ * </ul>
+ *
+ * <br>
+ * In both cases the first frame, corresponding to the method's parameters and access flags, is
+ * implicit and must not be visited. Also, it is illegal to visit two or more frames for the same
+ * code location (i.e., at least one instruction must be visited between two calls to visitFrame).
+ *
+ * @param type the type of this stack map frame. Must be {@link Opcodes#F_NEW} for expanded
+ * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
+ * Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
+ * @param numLocal the number of local variables in the visited frame.
+ * @param local the local variable types in this frame. This array must not be modified. Primitive
+ * types are represented by {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link
+ * Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a single element).
+ * Reference types are represented by String objects (representing internal names), and
+ * uninitialized types by Label objects (this label designates the NEW instruction that
+ * created this uninitialized value).
+ * @param numStack the number of operand stack elements in the visited frame.
+ * @param stack the operand stack types in this frame. This array must not be modified. Its
+ * content has the same format as the "local" array.
+ * @throws IllegalStateException if a frame is visited just after another one, without any
+ * instruction between the two (unless this frame is a Opcodes#F_SAME frame, in which case it
+ * is silently ignored).
+ */
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ if (mv != null) {
+ mv.visitFrame(type, numLocal, local, numStack, stack);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Normal instructions
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Visits a zero operand instruction.
+ *
+ * @param opcode the opcode of the instruction to be visited. This opcode is either NOP,
+ * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5,
+ * LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,
+ * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE, DASTORE,
+ * AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2,
+ * SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
+ * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR,
+ * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I,
+ * D2L, D2F, I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+ * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, or MONITOREXIT.
+ */
+ public void visitInsn(final int opcode) {
+ if (mv != null) {
+ mv.visitInsn(opcode);
+ }
+ }
+
+ /**
+ * Visits an instruction with a single int operand.
+ *
+ * @param opcode the opcode of the instruction to be visited. This opcode is either BIPUSH, SIPUSH
+ * or NEWARRAY.
+ * @param operand the operand of the instruction to be visited.<br>
+ * When opcode is BIPUSH, operand value should be between Byte.MIN_VALUE and Byte.MAX_VALUE.
+ * <br>
+ * When opcode is SIPUSH, operand value should be between Short.MIN_VALUE and Short.MAX_VALUE.
+ * <br>
+ * When opcode is NEWARRAY, operand value should be one of {@link Opcodes#T_BOOLEAN}, {@link
+ * Opcodes#T_CHAR}, {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, {@link Opcodes#T_BYTE},
+ * {@link Opcodes#T_SHORT}, {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+ */
+ public void visitIntInsn(final int opcode, final int operand) {
+ if (mv != null) {
+ mv.visitIntInsn(opcode, operand);
+ }
+ }
+
+ /**
+ * Visits a local variable instruction. A local variable instruction is an instruction that loads
+ * or stores the value of a local variable.
+ *
+ * @param opcode the opcode of the local variable instruction to be visited. This opcode is either
+ * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var the operand of the instruction to be visited. This operand is the index of a local
+ * variable.
+ */
+ public void visitVarInsn(final int opcode, final int var) {
+ if (mv != null) {
+ mv.visitVarInsn(opcode, var);
+ }
+ }
+
+ /**
+ * Visits a type instruction. A type instruction is an instruction that takes the internal name of
+ * a class as parameter.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either NEW,
+ * ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param type the operand of the instruction to be visited. This operand must be the internal
+ * name of an object or array class (see {@link Type#getInternalName()}).
+ */
+ public void visitTypeInsn(final int opcode, final String type) {
+ if (mv != null) {
+ mv.visitTypeInsn(opcode, type);
+ }
+ }
+
+ /**
+ * Visits a field instruction. A field instruction is an instruction that loads or stores the
+ * value of a field of an object.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either
+ * GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner the internal name of the field's owner class (see {@link Type#getInternalName()}).
+ * @param name the field's name.
+ * @param descriptor the field's descriptor (see {@link Type}).
+ */
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (mv != null) {
+ mv.visitFieldInsn(opcode, owner, name, descriptor);
+ }
+ }
+
+ /**
+ * Visits a method instruction. A method instruction is an instruction that invokes a method.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see {@link
+ * Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ boolean isInterface = opcode == Opcodes.INVOKEINTERFACE;
+ visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, descriptor);
+ }
+ }
+
+ /**
+ * Visits a method instruction. A method instruction is an instruction that invokes a method.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see {@link
+ * Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param isInterface if the method's owner class is an interface.
+ */
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ if (isInterface != (opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new IllegalArgumentException("INVOKESPECIAL/STATIC on interfaces requires ASM5");
+ }
+ visitMethodInsn(opcode, owner, name, descriptor);
+ return;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+ }
+
+ /**
+ * Visits an invokedynamic instruction.
+ *
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param bootstrapMethodHandle the bootstrap method.
+ * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link
+ * Type}, {@link Handle} or {@link ConstantDynamic} value. This method is allowed to modify
+ * the content of the array so a caller should expect that this array may change.
+ */
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ if (api < Opcodes.ASM5) {
+ throw new UnsupportedOperationException(REQUIRES_ASM5);
+ }
+ if (mv != null) {
+ mv.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ }
+ }
+
+ /**
+ * Visits a jump instruction. A jump instruction is an instruction that may jump to another
+ * instruction.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This opcode is either IFEQ,
+ * IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT,
+ * IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label the operand of the instruction to be visited. This operand is a label that
+ * designates the instruction to which the jump instruction may jump.
+ */
+ public void visitJumpInsn(final int opcode, final Label label) {
+ if (mv != null) {
+ mv.visitJumpInsn(opcode, label);
+ }
+ }
+
+ /**
+ * Visits a label. A label designates the instruction that will be visited just after it.
+ *
+ * @param label a {@link Label} object.
+ */
+ public void visitLabel(final Label label) {
+ if (mv != null) {
+ mv.visitLabel(label);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Special instructions
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Visits a LDC instruction. Note that new constant types may be added in future versions of the
+ * Java Virtual Machine. To easily detect new constant types, implementations of this method
+ * should check for unexpected constant types, like this:
+ *
+ * <pre>
+ * if (cst instanceof Integer) {
+ * // ...
+ * } else if (cst instanceof Float) {
+ * // ...
+ * } else if (cst instanceof Long) {
+ * // ...
+ * } else if (cst instanceof Double) {
+ * // ...
+ * } else if (cst instanceof String) {
+ * // ...
+ * } else if (cst instanceof Type) {
+ * int sort = ((Type) cst).getSort();
+ * if (sort == Type.OBJECT) {
+ * // ...
+ * } else if (sort == Type.ARRAY) {
+ * // ...
+ * } else if (sort == Type.METHOD) {
+ * // ...
+ * } else {
+ * // throw an exception
+ * }
+ * } else if (cst instanceof Handle) {
+ * // ...
+ * } else if (cst instanceof ConstantDynamic) {
+ * // ...
+ * } else {
+ * // throw an exception
+ * }
+ * </pre>
+ *
+ * @param value the constant to be loaded on the stack. This parameter must be a non null {@link
+ * Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link
+ * Type} of OBJECT or ARRAY sort for {@code .class} constants, for classes whose version is
+ * 49, a {@link Type} of METHOD sort for MethodType, a {@link Handle} for MethodHandle
+ * constants, for classes whose version is 51 or a {@link ConstantDynamic} for a constant
+ * dynamic for classes whose version is 55.
+ */
+ public void visitLdcInsn(final Object value) {
+ if (api < Opcodes.ASM5
+ && (value instanceof Handle
+ || (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) {
+ throw new UnsupportedOperationException(REQUIRES_ASM5);
+ }
+ if (api != Opcodes.ASM7 && value instanceof ConstantDynamic) {
+ throw new UnsupportedOperationException("This feature requires ASM7");
+ }
+ if (mv != null) {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Visits an IINC instruction.
+ *
+ * @param var index of the local variable to be incremented.
+ * @param increment amount to increment the local variable by.
+ */
+ public void visitIincInsn(final int var, final int increment) {
+ if (mv != null) {
+ mv.visitIincInsn(var, increment);
+ }
+ }
+
+ /**
+ * Visits a TABLESWITCH instruction.
+ *
+ * @param min the minimum key value.
+ * @param max the maximum key value.
+ * @param dflt beginning of the default handler block.
+ * @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the
+ * handler block for the {@code min + i} key.
+ */
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ if (mv != null) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ /**
+ * Visits a LOOKUPSWITCH instruction.
+ *
+ * @param dflt beginning of the default handler block.
+ * @param keys the values of the keys.
+ * @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the
+ * handler block for the {@code keys[i]} key.
+ */
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ if (mv != null) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ /**
+ * Visits a MULTIANEWARRAY instruction.
+ *
+ * @param descriptor an array type descriptor (see {@link Type}).
+ * @param numDimensions the number of dimensions of the array to allocate.
+ */
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ if (mv != null) {
+ mv.visitMultiANewArrayInsn(descriptor, numDimensions);
+ }
+ }
+
+ /**
+ * Visits an annotation on an instruction. This method must be called just <i>after</i> the
+ * annotated instruction. It can be called several times for the same instruction.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link TypeReference#INSTANCEOF}, {@link TypeReference#NEW}, {@link
+ * TypeReference#CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE}, {@link
+ * TypeReference#CAST}, {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link
+ * TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
+ * TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link
+ * TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new UnsupportedOperationException(REQUIRES_ASM5);
+ }
+ if (mv != null) {
+ return mv.visitInsnAnnotation(typeRef, typePath, descriptor, visible);
+ }
+ return null;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Exceptions table entries, debug information, max stack and max locals
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Visits a try catch block.
+ *
+ * @param start the beginning of the exception handler's scope (inclusive).
+ * @param end the end of the exception handler's scope (exclusive).
+ * @param handler the beginning of the exception handler's code.
+ * @param type the internal name of the type of exceptions handled by the handler, or {@literal
+ * null} to catch any exceptions (for "finally" blocks).
+ * @throws IllegalArgumentException if one of the labels has already been visited by this visitor
+ * (by the {@link #visitLabel} method).
+ */
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ if (mv != null) {
+ mv.visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+
+ /**
+ * Visits an annotation on an exception handler type. This method must be called <i>after</i> the
+ * {@link #visitTryCatchBlock} for the annotated exception handler. It can be called several times
+ * for the same exception handler.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link TypeReference#EXCEPTION_PARAMETER}. See {@link TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new UnsupportedOperationException(REQUIRES_ASM5);
+ }
+ if (mv != null) {
+ return mv.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a local variable declaration.
+ *
+ * @param name the name of a local variable.
+ * @param descriptor the type descriptor of this local variable.
+ * @param signature the type signature of this local variable. May be {@literal null} if the local
+ * variable type does not use generic types.
+ * @param start the first instruction corresponding to the scope of this local variable
+ * (inclusive).
+ * @param end the last instruction corresponding to the scope of this local variable (exclusive).
+ * @param index the local variable's index.
+ * @throws IllegalArgumentException if one of the labels has not already been visited by this
+ * visitor (by the {@link #visitLabel} method).
+ */
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ if (mv != null) {
+ mv.visitLocalVariable(name, descriptor, signature, start, end, index);
+ }
+ }
+
+ /**
+ * Visits an annotation on a local variable type.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link TypeReference#LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE}. See {@link
+ * TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param start the fist instructions corresponding to the continuous ranges that make the scope
+ * of this local variable (inclusive).
+ * @param end the last instructions corresponding to the continuous ranges that make the scope of
+ * this local variable (exclusive). This array must have the same size as the 'start' array.
+ * @param index the local variable's index in each range. This array must have the same size as
+ * the 'start' array.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new UnsupportedOperationException(REQUIRES_ASM5);
+ }
+ if (mv != null) {
+ return mv.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, index, descriptor, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a line number declaration.
+ *
+ * @param line a line number. This number refers to the source file from which the class was
+ * compiled.
+ * @param start the first instruction corresponding to this line number.
+ * @throws IllegalArgumentException if {@code start} has not already been visited by this visitor
+ * (by the {@link #visitLabel} method).
+ */
+ public void visitLineNumber(final int line, final Label start) {
+ if (mv != null) {
+ mv.visitLineNumber(line, start);
+ }
+ }
+
+ /**
+ * Visits the maximum stack size and the maximum number of local variables of the method.
+ *
+ * @param maxStack maximum stack size of the method.
+ * @param maxLocals maximum number of local variables for the method.
+ */
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (mv != null) {
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+ }
+
+ /**
+ * Visits the end of the method. This method, which is the last one to be called, is used to
+ * inform the visitor that all the annotations and attributes of the method have been visited.
+ */
+ public void visitEnd() {
+ if (mv != null) {
+ mv.visitEnd();
+ }
+ }
}
[10/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
old mode 100644
new mode 100755
index af4fb52..2624841
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
@@ -38,85 +36,81 @@ import org.apache.tapestry5.internal.plastic.asm.TypeReference;
/**
* A {@link FieldVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
*/
public class CheckFieldAdapter extends FieldVisitor {
- private boolean end;
+ /** Whether the {@link #visitEnd} method has been called. */
+ private boolean visitEndCalled;
- /**
- * Constructs a new {@link CheckFieldAdapter}. <i>Subclasses must not use
- * this constructor</i>. Instead, they must use the
- * {@link #CheckFieldAdapter(int, FieldVisitor)} version.
- *
- * @param fv
- * the field visitor to which this adapter must delegate calls.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public CheckFieldAdapter(final FieldVisitor fv) {
- this(Opcodes.ASM6, fv);
- if (getClass() != CheckFieldAdapter.class) {
- throw new IllegalStateException();
- }
+ /**
+ * Constructs a new {@link CheckFieldAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #CheckFieldAdapter(int, FieldVisitor)} version.
+ *
+ * @param fieldVisitor the field visitor to which this adapter must delegate calls.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public CheckFieldAdapter(final FieldVisitor fieldVisitor) {
+ this(Opcodes.ASM7, fieldVisitor);
+ if (getClass() != CheckFieldAdapter.class) {
+ throw new IllegalStateException();
}
+ }
- /**
- * Constructs a new {@link CheckFieldAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param fv
- * the field visitor to which this adapter must delegate calls.
- */
- protected CheckFieldAdapter(final int api, final FieldVisitor fv) {
- super(api, fv);
- }
+ /**
+ * Constructs a new {@link CheckFieldAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param fieldVisitor the field visitor to which this adapter must delegate calls.
+ */
+ protected CheckFieldAdapter(final int api, final FieldVisitor fieldVisitor) {
+ super(api, fieldVisitor);
+ }
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- checkEnd();
- CheckMethodAdapter.checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ checkVisitEndNotCalled();
+ // Annotations can only appear in V1_5 or more classes.
+ CheckMethodAdapter.checkDescriptor(Opcodes.V1_5, descriptor, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(descriptor, visible));
+ }
- @Override
- public AnnotationVisitor visitTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- checkEnd();
- int sort = typeRef >>> 24;
- if (sort != TypeReference.FIELD) {
- throw new IllegalArgumentException("Invalid type reference sort 0x"
- + Integer.toHexString(sort));
- }
- CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
- CheckMethodAdapter.checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
- typePath, desc, visible));
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ checkVisitEndNotCalled();
+ int sort = new TypeReference(typeRef).getSort();
+ if (sort != TypeReference.FIELD) {
+ throw new IllegalArgumentException(
+ "Invalid type reference sort 0x" + Integer.toHexString(sort));
}
+ CheckClassAdapter.checkTypeRef(typeRef);
+ CheckMethodAdapter.checkDescriptor(Opcodes.V1_5, descriptor, false);
+ return new CheckAnnotationAdapter(
+ super.visitTypeAnnotation(typeRef, typePath, descriptor, visible));
+ }
- @Override
- public void visitAttribute(final Attribute attr) {
- checkEnd();
- if (attr == null) {
- throw new IllegalArgumentException(
- "Invalid attribute (must not be null)");
- }
- super.visitAttribute(attr);
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ checkVisitEndNotCalled();
+ if (attribute == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
}
+ super.visitAttribute(attribute);
+ }
- @Override
- public void visitEnd() {
- checkEnd();
- end = true;
- super.visitEnd();
- }
+ @Override
+ public void visitEnd() {
+ checkVisitEndNotCalled();
+ visitEndCalled = true;
+ super.visitEnd();
+ }
- private void checkEnd() {
- if (end) {
- throw new IllegalStateException(
- "Cannot call a visit method after visitEnd has been called");
- }
+ private void checkVisitEndNotCalled() {
+ if (visitEndCalled) {
+ throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");
}
+ }
}
[06/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
old mode 100644
new mode 100755
index fa5e1da..69b57ff
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
@@ -1,56 +1,41 @@
/**
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
+ * ASM: a very small and fast Java bytecode manipulation framework Copyright (c) 2000-2011 INRIA,
+ * France Telecom 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * <p>Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met: 1. Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions
+ * in binary form must reproduce the above copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
+ * <p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.apache.tapestry5.internal.plastic.asm.util;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Label;
/**
- * An {@link org.objectweb.asm.Attribute Attribute} that can print a readable
- * representation of itself.
- *
- * Implementations should construct readable output from an attribute data
- * structure. Such representation could be used in unit test assertions.
- *
+ * An {@link org.apache.tapestry5.internal.plastic.asm.Attribute} that can print a readable representation of itself.
+ *
* @author Eugene Kuleshov
*/
public interface Textifiable {
- /**
- * Build a human readable representation of this attribute.
- *
- * @param buf
- * a buffer used for printing Java code.
- * @param labelNames
- * map of label instances to their names.
- */
- void textify(StringBuffer buf, Map<Label, String> labelNames);
+ /**
+ * Generates a human readable representation of this attribute.
+ *
+ * @param outputBuffer where the human representation of this attribute must be appended.
+ * @param labelNames the human readable names of the labels.
+ */
+ void textify(StringBuffer outputBuffer, Map<Label, String> labelNames);
}
[39/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
old mode 100644
new mode 100755
index c7f377c..3927ca8
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
@@ -1,222 +1,189 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
* A reference to a field or a method.
- *
+ *
* @author Remi Forax
* @author Eric Bruneton
*/
public final class Handle {
- /**
- * The kind of field or method designated by this Handle. Should be
- * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- */
- final int tag;
-
- /**
- * The internal name of the class that owns the field or method designated
- * by this handle.
- */
- final String owner;
-
- /**
- * The name of the field or method designated by this handle.
- */
- final String name;
-
- /**
- * The descriptor of the field or method designated by this handle.
- */
- final String desc;
-
-
- /**
- * Indicate if the owner is an interface or not.
- */
- final boolean itf;
-
- /**
- * Constructs a new field or method handle.
- *
- * @param tag
- * the kind of field or method designated by this Handle. Must be
- * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner
- * the internal name of the class that owns the field or method
- * designated by this handle.
- * @param name
- * the name of the field or method designated by this handle.
- * @param desc
- * the descriptor of the field or method designated by this
- * handle.
- *
- * @deprecated this constructor has been superseded
- * by {@link #Handle(int, String, String, String, boolean)}.
- */
- @Deprecated
- public Handle(int tag, String owner, String name, String desc) {
- this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
- }
+ /**
+ * The kind of field or method designated by this Handle. Should be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
+ * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
+ */
+ private final int tag;
- /**
- * Constructs a new field or method handle.
- *
- * @param tag
- * the kind of field or method designated by this Handle. Must be
- * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner
- * the internal name of the class that owns the field or method
- * designated by this handle.
- * @param name
- * the name of the field or method designated by this handle.
- * @param desc
- * the descriptor of the field or method designated by this
- * handle.
- * @param itf
- * true if the owner is an interface.
- */
- public Handle(int tag, String owner, String name, String desc, boolean itf) {
- this.tag = tag;
- this.owner = owner;
- this.name = name;
- this.desc = desc;
- this.itf = itf;
- }
-
- /**
- * Returns the kind of field or method designated by this handle.
- *
- * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- */
- public int getTag() {
- return tag;
- }
+ /** The internal name of the class that owns the field or method designated by this handle. */
+ private final String owner;
- /**
- * Returns the internal name of the class that owns the field or method
- * designated by this handle.
- *
- * @return the internal name of the class that owns the field or method
- * designated by this handle.
- */
- public String getOwner() {
- return owner;
- }
+ /** The name of the field or method designated by this handle. */
+ private final String name;
- /**
- * Returns the name of the field or method designated by this handle.
- *
- * @return the name of the field or method designated by this handle.
- */
- public String getName() {
- return name;
- }
+ /** The descriptor of the field or method designated by this handle. */
+ private final String descriptor;
- /**
- * Returns the descriptor of the field or method designated by this handle.
- *
- * @return the descriptor of the field or method designated by this handle.
- */
- public String getDesc() {
- return desc;
- }
-
- /**
- * Returns true if the owner of the field or method designated
- * by this handle is an interface.
- *
- * @return true if the owner of the field or method designated
- * by this handle is an interface.
- */
- public boolean isInterface() {
- return itf;
- }
+ /** Whether the owner is an interface or not. */
+ private final boolean isInterface;
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
- if (!(obj instanceof Handle)) {
- return false;
- }
- Handle h = (Handle) obj;
- return tag == h.tag && itf == h.itf && owner.equals(h.owner)
- && name.equals(h.name) && desc.equals(h.desc);
- }
+ /**
+ * Constructs a new field or method handle.
+ *
+ * @param tag the kind of field or method designated by this Handle. Must be {@link
+ * Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link
+ * Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
+ * Opcodes#H_INVOKEINTERFACE}.
+ * @param owner the internal name of the class that owns the field or method designated by this
+ * handle.
+ * @param name the name of the field or method designated by this handle.
+ * @param descriptor the descriptor of the field or method designated by this handle.
+ * @deprecated this constructor has been superseded by {@link #Handle(int, String, String, String,
+ * boolean)}.
+ */
+ @Deprecated
+ public Handle(final int tag, final String owner, final String name, final String descriptor) {
+ this(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE);
+ }
- @Override
- public int hashCode() {
- return tag + (itf? 64: 0) + owner.hashCode() * name.hashCode() * desc.hashCode();
- }
+ /**
+ * Constructs a new field or method handle.
+ *
+ * @param tag the kind of field or method designated by this Handle. Must be {@link
+ * Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link
+ * Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
+ * Opcodes#H_INVOKEINTERFACE}.
+ * @param owner the internal name of the class that owns the field or method designated by this
+ * handle.
+ * @param name the name of the field or method designated by this handle.
+ * @param descriptor the descriptor of the field or method designated by this handle.
+ * @param isInterface whether the owner is an interface or not.
+ */
+ public Handle(
+ final int tag,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ this.tag = tag;
+ this.owner = owner;
+ this.name = name;
+ this.descriptor = descriptor;
+ this.isInterface = isInterface;
+ }
+
+ /**
+ * Returns the kind of field or method designated by this handle.
+ *
+ * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link
+ * Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, {@link
+ * Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
+ */
+ public int getTag() {
+ return tag;
+ }
+
+ /**
+ * Returns the internal name of the class that owns the field or method designated by this handle.
+ *
+ * @return the internal name of the class that owns the field or method designated by this handle.
+ */
+ public String getOwner() {
+ return owner;
+ }
+
+ /**
+ * Returns the name of the field or method designated by this handle.
+ *
+ * @return the name of the field or method designated by this handle.
+ */
+ public String getName() {
+ return name;
+ }
- /**
- * Returns the textual representation of this handle. The textual
- * representation is:
- *
- * <pre>
- * for a reference to a class:
- * owner '.' name desc ' ' '(' tag ')'
- * for a reference to an interface:
- * owner '.' name desc ' ' '(' tag ' ' itf ')'
- * </pre>
- *
- * . As this format is unambiguous, it can be parsed if necessary.
- */
- @Override
- public String toString() {
- return owner + '.' + name + desc + " (" + tag + (itf? " itf": "") + ')';
+ /**
+ * Returns the descriptor of the field or method designated by this handle.
+ *
+ * @return the descriptor of the field or method designated by this handle.
+ */
+ public String getDesc() {
+ return descriptor;
+ }
+
+ /**
+ * Returns true if the owner of the field or method designated by this handle is an interface.
+ *
+ * @return true if the owner of the field or method designated by this handle is an interface.
+ */
+ public boolean isInterface() {
+ return isInterface;
+ }
+
+ @Override
+ public boolean equals(final Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (!(object instanceof Handle)) {
+ return false;
}
+ Handle handle = (Handle) object;
+ return tag == handle.tag
+ && isInterface == handle.isInterface
+ && owner.equals(handle.owner)
+ && name.equals(handle.name)
+ && descriptor.equals(handle.descriptor);
+ }
+
+ @Override
+ public int hashCode() {
+ return tag
+ + (isInterface ? 64 : 0)
+ + owner.hashCode() * name.hashCode() * descriptor.hashCode();
+ }
+
+ /**
+ * Returns the textual representation of this handle. The textual representation is:
+ *
+ * <ul>
+ * <li>for a reference to a class: owner "." name descriptor " (" tag ")",
+ * <li>for a reference to an interface: owner "." name descriptor " (" tag " itf)".
+ * </ul>
+ */
+ @Override
+ public String toString() {
+ return owner + '.' + name + descriptor + " (" + tag + (isInterface ? " itf" : "") + ')';
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
old mode 100644
new mode 100755
index a387654..3ce40f9
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
@@ -1,121 +1,198 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * Information about an exception handler block.
- *
+ * Information about an exception handler. Corresponds to an element of the exception_table array of
+ * a Code attribute, as defined in the Java Virtual Machine Specification (JVMS). Handler instances
+ * can be chained together, with their {@link #nextHandler} field, to describe a full JVMS
+ * exception_table array.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS
+ * 4.7.3</a>
* @author Eric Bruneton
*/
-class Handler {
+final class Handler {
+
+ /**
+ * The start_pc field of this JVMS exception_table entry. Corresponds to the beginning of the
+ * exception handler's scope (inclusive).
+ */
+ final Label startPc;
+
+ /**
+ * The end_pc field of this JVMS exception_table entry. Corresponds to the end of the exception
+ * handler's scope (exclusive).
+ */
+ final Label endPc;
+
+ /**
+ * The handler_pc field of this JVMS exception_table entry. Corresponding to the beginning of the
+ * exception handler's code.
+ */
+ final Label handlerPc;
- /**
- * Beginning of the exception handler's scope (inclusive).
- */
- Label start;
+ /**
+ * The catch_type field of this JVMS exception_table entry. This is the constant pool index of the
+ * internal name of the type of exceptions handled by this handler, or 0 to catch any exceptions.
+ */
+ final int catchType;
- /**
- * End of the exception handler's scope (exclusive).
- */
- Label end;
+ /**
+ * The internal name of the type of exceptions handled by this handler, or {@literal null} to
+ * catch any exceptions.
+ */
+ final String catchTypeDescriptor;
- /**
- * Beginning of the exception handler's code.
- */
- Label handler;
+ /** The next exception handler. */
+ Handler nextHandler;
- /**
- * Internal name of the type of exceptions handled by this handler, or
- * <tt>null</tt> to catch any exceptions.
- */
- String desc;
+ /**
+ * Constructs a new Handler.
+ *
+ * @param startPc the start_pc field of this JVMS exception_table entry.
+ * @param endPc the end_pc field of this JVMS exception_table entry.
+ * @param handlerPc the handler_pc field of this JVMS exception_table entry.
+ * @param catchType The catch_type field of this JVMS exception_table entry.
+ * @param catchTypeDescriptor The internal name of the type of exceptions handled by this handler,
+ * or {@literal null} to catch any exceptions.
+ */
+ Handler(
+ final Label startPc,
+ final Label endPc,
+ final Label handlerPc,
+ final int catchType,
+ final String catchTypeDescriptor) {
+ this.startPc = startPc;
+ this.endPc = endPc;
+ this.handlerPc = handlerPc;
+ this.catchType = catchType;
+ this.catchTypeDescriptor = catchTypeDescriptor;
+ }
- /**
- * Constant pool index of the internal name of the type of exceptions
- * handled by this handler, or 0 to catch any exceptions.
- */
- int type;
+ /**
+ * Constructs a new Handler from the given one, with a different scope.
+ *
+ * @param handler an existing Handler.
+ * @param startPc the start_pc field of this JVMS exception_table entry.
+ * @param endPc the end_pc field of this JVMS exception_table entry.
+ */
+ Handler(final Handler handler, final Label startPc, final Label endPc) {
+ this(startPc, endPc, handler.handlerPc, handler.catchType, handler.catchTypeDescriptor);
+ this.nextHandler = handler.nextHandler;
+ }
+
+ /**
+ * Removes the range between start and end from the Handler list that begins with the given
+ * element.
+ *
+ * @param firstHandler the beginning of a Handler list. May be {@literal null}.
+ * @param start the start of the range to be removed.
+ * @param end the end of the range to be removed. Maybe {@literal null}.
+ * @return the exception handler list with the start-end range removed.
+ */
+ static Handler removeRange(final Handler firstHandler, final Label start, final Label end) {
+ if (firstHandler == null) {
+ return null;
+ } else {
+ firstHandler.nextHandler = removeRange(firstHandler.nextHandler, start, end);
+ }
+ int handlerStart = firstHandler.startPc.bytecodeOffset;
+ int handlerEnd = firstHandler.endPc.bytecodeOffset;
+ int rangeStart = start.bytecodeOffset;
+ int rangeEnd = end == null ? Integer.MAX_VALUE : end.bytecodeOffset;
+ // Return early if [handlerStart,handlerEnd[ and [rangeStart,rangeEnd[ don't intersect.
+ if (rangeStart >= handlerEnd || rangeEnd <= handlerStart) {
+ return firstHandler;
+ }
+ if (rangeStart <= handlerStart) {
+ if (rangeEnd >= handlerEnd) {
+ // If [handlerStart,handlerEnd[ is included in [rangeStart,rangeEnd[, remove firstHandler.
+ return firstHandler.nextHandler;
+ } else {
+ // [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ = [rangeEnd,handlerEnd[
+ return new Handler(firstHandler, end, firstHandler.endPc);
+ }
+ } else if (rangeEnd >= handlerEnd) {
+ // [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ = [handlerStart,rangeStart[
+ return new Handler(firstHandler, firstHandler.startPc, start);
+ } else {
+ // [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ =
+ // [handlerStart,rangeStart[ + [rangeEnd,handerEnd[
+ firstHandler.nextHandler = new Handler(firstHandler, end, firstHandler.endPc);
+ return new Handler(firstHandler, firstHandler.startPc, start);
+ }
+ }
+
+ /**
+ * Returns the number of elements of the Handler list that begins with the given element.
+ *
+ * @param firstHandler the beginning of a Handler list. May be {@literal null}.
+ * @return the number of elements of the Handler list that begins with 'handler'.
+ */
+ static int getExceptionTableLength(final Handler firstHandler) {
+ int length = 0;
+ Handler handler = firstHandler;
+ while (handler != null) {
+ length++;
+ handler = handler.nextHandler;
+ }
+ return length;
+ }
- /**
- * Next exception handler block info.
- */
- Handler next;
+ /**
+ * Returns the size in bytes of the JVMS exception_table corresponding to the Handler list that
+ * begins with the given element. <i>This includes the exception_table_length field.</i>
+ *
+ * @param firstHandler the beginning of a Handler list. May be {@literal null}.
+ * @return the size in bytes of the exception_table_length and exception_table structures.
+ */
+ static int getExceptionTableSize(final Handler firstHandler) {
+ return 2 + 8 * getExceptionTableLength(firstHandler);
+ }
- /**
- * Removes the range between start and end from the given exception
- * handlers.
- *
- * @param h
- * an exception handler list.
- * @param start
- * the start of the range to be removed.
- * @param end
- * the end of the range to be removed. Maybe null.
- * @return the exception handler list with the start-end range removed.
- */
- static Handler remove(Handler h, Label start, Label end) {
- if (h == null) {
- return null;
- } else {
- h.next = remove(h.next, start, end);
- }
- int hstart = h.start.position;
- int hend = h.end.position;
- int s = start.position;
- int e = end == null ? Integer.MAX_VALUE : end.position;
- // if [hstart,hend[ and [s,e[ intervals intersect...
- if (s < hend && e > hstart) {
- if (s <= hstart) {
- if (e >= hend) {
- // [hstart,hend[ fully included in [s,e[, h removed
- h = h.next;
- } else {
- // [hstart,hend[ minus [s,e[ = [e,hend[
- h.start = end;
- }
- } else if (e >= hend) {
- // [hstart,hend[ minus [s,e[ = [hstart,s[
- h.end = start;
- } else {
- // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
- Handler g = new Handler();
- g.start = end;
- g.end = h.end;
- g.handler = h.handler;
- g.desc = h.desc;
- g.type = h.type;
- g.next = h.next;
- h.end = start;
- h.next = g;
- }
- }
- return h;
+ /**
+ * Puts the JVMS exception_table corresponding to the Handler list that begins with the given
+ * element. <i>This includes the exception_table_length field.</i>
+ *
+ * @param firstHandler the beginning of a Handler list. May be {@literal null}.
+ * @param output where the exception_table_length and exception_table structures must be put.
+ */
+ static void putExceptionTable(final Handler firstHandler, final ByteVector output) {
+ output.putShort(getExceptionTableLength(firstHandler));
+ Handler handler = firstHandler;
+ while (handler != null) {
+ output
+ .putShort(handler.startPc.bytecodeOffset)
+ .putShort(handler.endPc.bytecodeOffset)
+ .putShort(handler.handlerPc.bytecodeOffset)
+ .putShort(handler.catchType);
+ handler = handler.nextHandler;
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
deleted file mode 100644
index d47a7c0..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm;
-
-/**
- * A constant pool item. Constant pool items can be created with the 'newXXX'
- * methods in the {@link ClassWriter} class.
- *
- * @author Eric Bruneton
- */
-final class Item {
-
- /**
- * Index of this item in the constant pool.
- */
- int index;
-
- /**
- * Type of this constant pool item. A single class is used to represent all
- * constant pool item types, in order to minimize the bytecode size of this
- * package. The value of this field is one of {@link ClassWriter#INT},
- * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
- * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
- * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
- * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
- * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
- * {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
- * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
- *
- * MethodHandle constant 9 variations are stored using a range of 9 values
- * from {@link ClassWriter#HANDLE_BASE} + 1 to
- * {@link ClassWriter#HANDLE_BASE} + 9.
- *
- * Special Item types are used for Items that are stored in the ClassWriter
- * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
- * avoid clashes with normal constant pool items in the ClassWriter constant
- * pool's hash table. These special item types are
- * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
- * {@link ClassWriter#TYPE_MERGED}.
- */
- int type;
-
- /**
- * Value of this item, for an integer item.
- */
- int intVal;
-
- /**
- * Value of this item, for a long item.
- */
- long longVal;
-
- /**
- * First part of the value of this item, for items that do not hold a
- * primitive value.
- */
- String strVal1;
-
- /**
- * Second part of the value of this item, for items that do not hold a
- * primitive value.
- */
- String strVal2;
-
- /**
- * Third part of the value of this item, for items that do not hold a
- * primitive value.
- */
- String strVal3;
-
- /**
- * The hash code value of this constant pool item.
- */
- int hashCode;
-
- /**
- * Link to another constant pool item, used for collision lists in the
- * constant pool's hash table.
- */
- Item next;
-
- /**
- * Constructs an uninitialized {@link Item}.
- */
- Item() {
- }
-
- /**
- * Constructs an uninitialized {@link Item} for constant pool element at
- * given position.
- *
- * @param index
- * index of the item to be constructed.
- */
- Item(final int index) {
- this.index = index;
- }
-
- /**
- * Constructs a copy of the given item.
- *
- * @param index
- * index of the item to be constructed.
- * @param i
- * the item that must be copied into the item to be constructed.
- */
- Item(final int index, final Item i) {
- this.index = index;
- type = i.type;
- intVal = i.intVal;
- longVal = i.longVal;
- strVal1 = i.strVal1;
- strVal2 = i.strVal2;
- strVal3 = i.strVal3;
- hashCode = i.hashCode;
- }
-
- /**
- * Sets this item to an integer item.
- *
- * @param intVal
- * the value of this item.
- */
- void set(final int intVal) {
- this.type = ClassWriter.INT;
- this.intVal = intVal;
- this.hashCode = 0x7FFFFFFF & (type + intVal);
- }
-
- /**
- * Sets this item to a long item.
- *
- * @param longVal
- * the value of this item.
- */
- void set(final long longVal) {
- this.type = ClassWriter.LONG;
- this.longVal = longVal;
- this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
- }
-
- /**
- * Sets this item to a float item.
- *
- * @param floatVal
- * the value of this item.
- */
- void set(final float floatVal) {
- this.type = ClassWriter.FLOAT;
- this.intVal = Float.floatToRawIntBits(floatVal);
- this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
- }
-
- /**
- * Sets this item to a double item.
- *
- * @param doubleVal
- * the value of this item.
- */
- void set(final double doubleVal) {
- this.type = ClassWriter.DOUBLE;
- this.longVal = Double.doubleToRawLongBits(doubleVal);
- this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
- }
-
- /**
- * Sets this item to an item that do not hold a primitive value.
- *
- * @param type
- * the type of this item.
- * @param strVal1
- * first part of the value of this item.
- * @param strVal2
- * second part of the value of this item.
- * @param strVal3
- * third part of the value of this item.
- */
- @SuppressWarnings("fallthrough")
- void set(final int type, final String strVal1, final String strVal2,
- final String strVal3) {
- this.type = type;
- this.strVal1 = strVal1;
- this.strVal2 = strVal2;
- this.strVal3 = strVal3;
- switch (type) {
- case ClassWriter.CLASS:
- this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.MTYPE:
- case ClassWriter.MODULE:
- case ClassWriter.PACKAGE:
- case ClassWriter.TYPE_NORMAL:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
- return;
- case ClassWriter.NAME_TYPE: {
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
- * strVal2.hashCode());
- return;
- }
- // ClassWriter.FIELD:
- // ClassWriter.METH:
- // ClassWriter.IMETH:
- // ClassWriter.HANDLE_BASE + 1..9
- default:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
- * strVal2.hashCode() * strVal3.hashCode());
- }
- }
-
- /**
- * Sets the item to an InvokeDynamic item.
- *
- * @param name
- * invokedynamic's name.
- * @param desc
- * invokedynamic's desc.
- * @param bsmIndex
- * zero based index into the class attribute BootrapMethods.
- */
- void set(String name, String desc, int bsmIndex) {
- this.type = ClassWriter.INDY;
- this.longVal = bsmIndex;
- this.strVal1 = name;
- this.strVal2 = desc;
- this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex
- * strVal1.hashCode() * strVal2.hashCode());
- }
-
- /**
- * Sets the item to a BootstrapMethod item.
- *
- * @param position
- * position in byte in the class attribute BootrapMethods.
- * @param hashCode
- * hashcode of the item. This hashcode is processed from the
- * hashcode of the bootstrap method and the hashcode of all
- * bootstrap arguments.
- */
- void set(int position, int hashCode) {
- this.type = ClassWriter.BSM;
- this.intVal = position;
- this.hashCode = hashCode;
- }
-
- /**
- * Indicates if the given item is equal to this one. <i>This method assumes
- * that the two items have the same {@link #type}</i>.
- *
- * @param i
- * the item to be compared to this one. Both items must have the
- * same {@link #type}.
- * @return <tt>true</tt> if the given item if equal to this one,
- * <tt>false</tt> otherwise.
- */
- boolean isEqualTo(final Item i) {
- switch (type) {
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- case ClassWriter.MODULE:
- case ClassWriter.PACKAGE:
- case ClassWriter.MTYPE:
- case ClassWriter.TYPE_NORMAL:
- return i.strVal1.equals(strVal1);
- case ClassWriter.TYPE_MERGED:
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- return i.longVal == longVal;
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- return i.intVal == intVal;
- case ClassWriter.TYPE_UNINIT:
- return i.intVal == intVal && i.strVal1.equals(strVal1);
- case ClassWriter.NAME_TYPE:
- return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
- case ClassWriter.INDY: {
- return i.longVal == longVal && i.strVal1.equals(strVal1)
- && i.strVal2.equals(strVal2);
- }
- // case ClassWriter.FIELD:
- // case ClassWriter.METH:
- // case ClassWriter.IMETH:
- // case ClassWriter.HANDLE_BASE + 1..9
- default:
- return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
- && i.strVal3.equals(strVal3);
- }
- }
-
-}
[42/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
old mode 100644
new mode 100755
index fa40875..2416289
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
@@ -1,1851 +1,985 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A {@link ClassVisitor} that generates classes in bytecode form. More
- * precisely this visitor generates a byte array conforming to the Java class
- * file format. It can be used alone, to generate a Java class "from scratch",
- * or with one or more {@link ClassReader ClassReader} and adapter class visitor
- * to generate a modified class from one or more existing Java classes.
- *
+ * A {@link ClassVisitor} that generates a corresponding ClassFile structure, as defined in the Java
+ * Virtual Machine Specification (JVMS). It can be used alone, to generate a Java class "from
+ * scratch", or with one or more {@link ClassReader} and adapter {@link ClassVisitor} to generate a
+ * modified class from one or more existing Java classes.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a>
* @author Eric Bruneton
*/
public class ClassWriter extends ClassVisitor {
- /**
- * Flag to automatically compute the maximum stack size and the maximum
- * number of local variables of methods. If this flag is set, then the
- * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
- * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
- * method will be ignored, and computed automatically from the signature and
- * the bytecode of each method.
- *
- * @see #ClassWriter(int)
- */
- public static final int COMPUTE_MAXS = 1;
-
- /**
- * Flag to automatically compute the stack map frames of methods from
- * scratch. If this flag is set, then the calls to the
- * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
- * frames are recomputed from the methods bytecode. The arguments of the
- * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
- * recomputed from the bytecode. In other words, COMPUTE_FRAMES implies
- * COMPUTE_MAXS.
- *
- * @see #ClassWriter(int)
- */
- public static final int COMPUTE_FRAMES = 2;
-
- /**
- * Pseudo access flag to distinguish between the synthetic attribute and the
- * synthetic access flag.
- */
- static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
-
- /**
- * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC.
- */
- static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE
- / Opcodes.ACC_SYNTHETIC;
-
- /**
- * The type of instructions without any argument.
- */
- static final int NOARG_INSN = 0;
-
- /**
- * The type of instructions with an signed byte argument.
- */
- static final int SBYTE_INSN = 1;
-
- /**
- * The type of instructions with an signed short argument.
- */
- static final int SHORT_INSN = 2;
-
- /**
- * The type of instructions with a local variable index argument.
- */
- static final int VAR_INSN = 3;
-
- /**
- * The type of instructions with an implicit local variable index argument.
- */
- static final int IMPLVAR_INSN = 4;
-
- /**
- * The type of instructions with a type descriptor argument.
- */
- static final int TYPE_INSN = 5;
-
- /**
- * The type of field and method invocations instructions.
- */
- static final int FIELDORMETH_INSN = 6;
-
- /**
- * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction.
- */
- static final int ITFMETH_INSN = 7;
-
- /**
- * The type of the INVOKEDYNAMIC instruction.
- */
- static final int INDYMETH_INSN = 8;
-
- /**
- * The type of instructions with a 2 bytes bytecode offset label.
- */
- static final int LABEL_INSN = 9;
-
- /**
- * The type of instructions with a 4 bytes bytecode offset label.
- */
- static final int LABELW_INSN = 10;
-
- /**
- * The type of the LDC instruction.
- */
- static final int LDC_INSN = 11;
-
- /**
- * The type of the LDC_W and LDC2_W instructions.
- */
- static final int LDCW_INSN = 12;
-
- /**
- * The type of the IINC instruction.
- */
- static final int IINC_INSN = 13;
-
- /**
- * The type of the TABLESWITCH instruction.
- */
- static final int TABL_INSN = 14;
-
- /**
- * The type of the LOOKUPSWITCH instruction.
- */
- static final int LOOK_INSN = 15;
-
- /**
- * The type of the MULTIANEWARRAY instruction.
- */
- static final int MANA_INSN = 16;
-
- /**
- * The type of the WIDE instruction.
- */
- static final int WIDE_INSN = 17;
-
- /**
- * The type of the ASM pseudo instructions with an unsigned 2 bytes offset
- * label (see Label#resolve).
- */
- static final int ASM_LABEL_INSN = 18;
-
- /**
- * The type of the ASM pseudo instructions with a 4 bytes offset label.
- */
- static final int ASM_LABELW_INSN = 19;
-
- /**
- * Represents a frame inserted between already existing frames. This kind of
- * frame can only be used if the frame content can be computed from the
- * previous existing frame and from the instructions between this existing
- * frame and the inserted one, without any knowledge of the type hierarchy.
- * This kind of frame is only used when an unconditional jump is inserted in
- * a method while expanding an ASM pseudo instruction (see ClassReader).
- */
- static final int F_INSERT = 256;
-
- /**
- * The instruction types of all JVM opcodes.
- */
- static final byte[] TYPE;
-
- /**
- * The type of CONSTANT_Class constant pool items.
- */
- static final int CLASS = 7;
-
- /**
- * The type of CONSTANT_Fieldref constant pool items.
- */
- static final int FIELD = 9;
-
- /**
- * The type of CONSTANT_Methodref constant pool items.
- */
- static final int METH = 10;
-
- /**
- * The type of CONSTANT_InterfaceMethodref constant pool items.
- */
- static final int IMETH = 11;
-
- /**
- * The type of CONSTANT_String constant pool items.
- */
- static final int STR = 8;
-
- /**
- * The type of CONSTANT_Integer constant pool items.
- */
- static final int INT = 3;
-
- /**
- * The type of CONSTANT_Float constant pool items.
- */
- static final int FLOAT = 4;
-
- /**
- * The type of CONSTANT_Long constant pool items.
- */
- static final int LONG = 5;
-
- /**
- * The type of CONSTANT_Double constant pool items.
- */
- static final int DOUBLE = 6;
-
- /**
- * The type of CONSTANT_NameAndType constant pool items.
- */
- static final int NAME_TYPE = 12;
-
- /**
- * The type of CONSTANT_Utf8 constant pool items.
- */
- static final int UTF8 = 1;
-
- /**
- * The type of CONSTANT_MethodType constant pool items.
- */
- static final int MTYPE = 16;
-
- /**
- * The type of CONSTANT_MethodHandle constant pool items.
- */
- static final int HANDLE = 15;
-
- /**
- * The type of CONSTANT_InvokeDynamic constant pool items.
- */
- static final int INDY = 18;
-
- /**
- * The type of CONSTANT_Module constant pool items.
- */
- static final int MODULE = 19;
-
- /**
- * The type of CONSTANT_Package constant pool items.
- */
- static final int PACKAGE = 20;
-
- /**
- * The base value for all CONSTANT_MethodHandle constant pool items.
- * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
- * different items (from 21 to 29).
- */
- static final int HANDLE_BASE = 20;
-
- /**
- * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
- * instead of the constant pool, in order to avoid clashes with normal
- * constant pool items in the ClassWriter constant pool's hash table.
- */
- static final int TYPE_NORMAL = 30;
-
- /**
- * Uninitialized type Item stored in the ClassWriter
- * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
- * avoid clashes with normal constant pool items in the ClassWriter constant
- * pool's hash table.
- */
- static final int TYPE_UNINIT = 31;
-
- /**
- * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
- * instead of the constant pool, in order to avoid clashes with normal
- * constant pool items in the ClassWriter constant pool's hash table.
- */
- static final int TYPE_MERGED = 32;
-
- /**
- * The type of BootstrapMethods items. These items are stored in a special
- * class attribute named BootstrapMethods and not in the constant pool.
- */
- static final int BSM = 33;
-
- /**
- * The class reader from which this class writer was constructed, if any.
- */
- ClassReader cr;
-
- /**
- * Minor and major version numbers of the class to be generated.
- */
- int version;
-
- /**
- * Index of the next item to be added in the constant pool.
- */
- int index;
-
- /**
- * The constant pool of this class.
- */
- final ByteVector pool;
-
- /**
- * The constant pool's hash table data.
- */
- Item[] items;
-
- /**
- * The threshold of the constant pool's hash table.
- */
- int threshold;
-
- /**
- * A reusable key used to look for items in the {@link #items} hash table.
- */
- final Item key;
-
- /**
- * A reusable key used to look for items in the {@link #items} hash table.
- */
- final Item key2;
-
- /**
- * A reusable key used to look for items in the {@link #items} hash table.
- */
- final Item key3;
-
- /**
- * A reusable key used to look for items in the {@link #items} hash table.
- */
- final Item key4;
-
- /**
- * A type table used to temporarily store internal names that will not
- * necessarily be stored in the constant pool. This type table is used by
- * the control flow and data flow analysis algorithm used to compute stack
- * map frames from scratch. This array associates to each index <tt>i</tt>
- * the Item whose index is <tt>i</tt>. All Item objects stored in this array
- * are also stored in the {@link #items} hash table. These two arrays allow
- * to retrieve an Item from its index or, conversely, to get the index of an
- * Item from its value. Each Item stores an internal name in its
- * {@link Item#strVal1} field.
- */
- Item[] typeTable;
-
- /**
- * Number of elements in the {@link #typeTable} array.
- */
- private short typeCount;
-
- /**
- * The access flags of this class.
- */
- private int access;
-
- /**
- * The constant pool item that contains the internal name of this class.
- */
- private int name;
-
- /**
- * The internal name of this class.
- */
- String thisName;
-
- /**
- * The constant pool item that contains the signature of this class.
- */
- private int signature;
-
- /**
- * The constant pool item that contains the internal name of the super class
- * of this class.
- */
- private int superName;
-
- /**
- * Number of interfaces implemented or extended by this class or interface.
- */
- private int interfaceCount;
-
- /**
- * The interfaces implemented or extended by this class or interface. More
- * precisely, this array contains the indexes of the constant pool items
- * that contain the internal names of these interfaces.
- */
- private int[] interfaces;
-
- /**
- * The index of the constant pool item that contains the name of the source
- * file from which this class was compiled.
- */
- private int sourceFile;
-
- /**
- * The SourceDebug attribute of this class.
- */
- private ByteVector sourceDebug;
-
- /**
- * The module attribute of this class.
- */
- private ModuleWriter moduleWriter;
-
- /**
- * The constant pool item that contains the name of the enclosing class of
- * this class.
- */
- private int enclosingMethodOwner;
-
- /**
- * The constant pool item that contains the name and descriptor of the
- * enclosing method of this class.
- */
- private int enclosingMethod;
-
- /**
- * The runtime visible annotations of this class.
- */
- private AnnotationWriter anns;
-
- /**
- * The runtime invisible annotations of this class.
- */
- private AnnotationWriter ianns;
-
- /**
- * The runtime visible type annotations of this class.
- */
- private AnnotationWriter tanns;
-
- /**
- * The runtime invisible type annotations of this class.
- */
- private AnnotationWriter itanns;
-
- /**
- * The non standard attributes of this class.
- */
- private Attribute attrs;
-
- /**
- * The number of entries in the InnerClasses attribute.
- */
- private int innerClassesCount;
-
- /**
- * The InnerClasses attribute.
- */
- private ByteVector innerClasses;
-
- /**
- * The number of entries in the BootstrapMethods attribute.
- */
- int bootstrapMethodsCount;
-
- /**
- * The BootstrapMethods attribute.
- */
- ByteVector bootstrapMethods;
-
- /**
- * The fields of this class. These fields are stored in a linked list of
- * {@link FieldWriter} objects, linked to each other by their
- * {@link FieldWriter#fv} field. This field stores the first element of this
- * list.
- */
- FieldWriter firstField;
-
- /**
- * The fields of this class. These fields are stored in a linked list of
- * {@link FieldWriter} objects, linked to each other by their
- * {@link FieldWriter#fv} field. This field stores the last element of this
- * list.
- */
- FieldWriter lastField;
-
- /**
- * The methods of this class. These methods are stored in a linked list of
- * {@link MethodWriter} objects, linked to each other by their
- * {@link MethodWriter#mv} field. This field stores the first element of
- * this list.
- */
- MethodWriter firstMethod;
-
- /**
- * The methods of this class. These methods are stored in a linked list of
- * {@link MethodWriter} objects, linked to each other by their
- * {@link MethodWriter#mv} field. This field stores the last element of this
- * list.
- */
- MethodWriter lastMethod;
-
- /**
- * Indicates what must be automatically computed.
- *
- * @see MethodWriter#compute
- */
- private int compute;
-
- /**
- * <tt>true</tt> if some methods have wide forward jumps using ASM pseudo
- * instructions, which need to be expanded into sequences of standard
- * bytecode instructions. In this case the class is re-read and re-written
- * with a ClassReader -> ClassWriter chain to perform this transformation.
- */
- boolean hasAsmInsns;
-
- // ------------------------------------------------------------------------
- // Static initializer
- // ------------------------------------------------------------------------
-
- /**
- * Computes the instruction types of JVM opcodes.
- */
- static {
- int i;
- byte[] b = new byte[221];
- String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
- + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
- + "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST";
- for (i = 0; i < b.length; ++i) {
- b[i] = (byte) (s.charAt(i) - 'A');
- }
- TYPE = b;
-
- // code to generate the above string
- //
- // // SBYTE_INSN instructions
- // b[Constants.NEWARRAY] = SBYTE_INSN;
- // b[Constants.BIPUSH] = SBYTE_INSN;
- //
- // // SHORT_INSN instructions
- // b[Constants.SIPUSH] = SHORT_INSN;
- //
- // // (IMPL)VAR_INSN instructions
- // b[Constants.RET] = VAR_INSN;
- // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
- // b[i] = VAR_INSN;
- // }
- // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
- // b[i] = VAR_INSN;
- // }
- // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
- // b[i] = IMPLVAR_INSN;
- // }
- // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
- // b[i] = IMPLVAR_INSN;
- // }
- //
- // // TYPE_INSN instructions
- // b[Constants.NEW] = TYPE_INSN;
- // b[Constants.ANEWARRAY] = TYPE_INSN;
- // b[Constants.CHECKCAST] = TYPE_INSN;
- // b[Constants.INSTANCEOF] = TYPE_INSN;
- //
- // // (Set)FIELDORMETH_INSN instructions
- // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
- // b[i] = FIELDORMETH_INSN;
- // }
- // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
- // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN;
- //
- // // LABEL(W)_INSN instructions
- // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
- // b[i] = LABEL_INSN;
- // }
- // b[Constants.IFNULL] = LABEL_INSN;
- // b[Constants.IFNONNULL] = LABEL_INSN;
- // b[200] = LABELW_INSN; // GOTO_W
- // b[201] = LABELW_INSN; // JSR_W
- // // temporary opcodes used internally by ASM - see Label and
- // MethodWriter
- // for (i = 202; i < 220; ++i) {
- // b[i] = ASM_LABEL_INSN;
- // }
- // b[220] = ASM_LABELW_INSN;
- //
- // // LDC(_W) instructions
- // b[Constants.LDC] = LDC_INSN;
- // b[19] = LDCW_INSN; // LDC_W
- // b[20] = LDCW_INSN; // LDC2_W
- //
- // // special instructions
- // b[Constants.IINC] = IINC_INSN;
- // b[Constants.TABLESWITCH] = TABL_INSN;
- // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
- // b[Constants.MULTIANEWARRAY] = MANA_INSN;
- // b[196] = WIDE_INSN; // WIDE
- //
- // for (i = 0; i < b.length; ++i) {
- // System.err.print((char)('A' + b[i]));
- // }
- // System.err.println();
- }
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link ClassWriter} object.
- *
- * @param flags
- * option flags that can be used to modify the default behavior
- * of this class. See {@link #COMPUTE_MAXS},
- * {@link #COMPUTE_FRAMES}.
- */
- public ClassWriter(final int flags) {
- super(Opcodes.ASM6);
- index = 1;
- pool = new ByteVector();
- items = new Item[256];
- threshold = (int) (0.75d * items.length);
- key = new Item();
- key2 = new Item();
- key3 = new Item();
- key4 = new Item();
- this.compute = (flags & COMPUTE_FRAMES) != 0 ? MethodWriter.FRAMES
- : ((flags & COMPUTE_MAXS) != 0 ? MethodWriter.MAXS
- : MethodWriter.NOTHING);
- }
-
- /**
- * Constructs a new {@link ClassWriter} object and enables optimizations for
- * "mostly add" bytecode transformations. These optimizations are the
- * following:
- *
- * <ul>
- * <li>The constant pool from the original class is copied as is in the new
- * class, which saves time. New constant pool entries will be added at the
- * end if necessary, but unused constant pool entries <i>won't be
- * removed</i>.</li>
- * <li>Methods that are not transformed are copied as is in the new class,
- * directly from the original class bytecode (i.e. without emitting visit
- * events for all the method instructions), which saves a <i>lot</i> of
- * time. Untransformed methods are detected by the fact that the
- * {@link ClassReader} receives {@link MethodVisitor} objects that come from
- * a {@link ClassWriter} (and not from any other {@link ClassVisitor}
- * instance).</li>
- * </ul>
- *
- * @param classReader
- * the {@link ClassReader} used to read the original class. It
- * will be used to copy the entire constant pool from the
- * original class and also to copy other fragments of original
- * bytecode where applicable.
- * @param flags
- * option flags that can be used to modify the default behavior
- * of this class. <i>These option flags do not affect methods
- * that are copied as is in the new class. This means that
- * neither the maximum stack size nor the stack frames will be
- * computed for these methods</i>. See {@link #COMPUTE_MAXS},
- * {@link #COMPUTE_FRAMES}.
- */
- public ClassWriter(final ClassReader classReader, final int flags) {
- this(flags);
- classReader.copyPool(this);
- this.cr = classReader;
- }
-
- // ------------------------------------------------------------------------
- // Implementation of the ClassVisitor abstract class
- // ------------------------------------------------------------------------
-
- @Override
- public final void visit(final int version, final int access,
- final String name, final String signature, final String superName,
- final String[] interfaces) {
- this.version = version;
- this.access = access;
- this.name = newClass(name);
- thisName = name;
- if (signature != null) {
- this.signature = newUTF8(signature);
- }
- this.superName = superName == null ? 0 : newClass(superName);
- if (interfaces != null && interfaces.length > 0) {
- interfaceCount = interfaces.length;
- this.interfaces = new int[interfaceCount];
- for (int i = 0; i < interfaceCount; ++i) {
- this.interfaces[i] = newClass(interfaces[i]);
- }
- }
- }
-
- @Override
- public final void visitSource(final String file, final String debug) {
- if (file != null) {
- sourceFile = newUTF8(file);
- }
- if (debug != null) {
- sourceDebug = new ByteVector().encodeUTF8(debug, 0,
- Integer.MAX_VALUE);
- }
- }
-
- @Override
- public final ModuleVisitor visitModule(final String name,
- final int access, final String version) {
- return moduleWriter = new ModuleWriter(this,
- newModule(name), access,
- version == null ? 0 : newUTF8(version));
- }
-
- @Override
- public final void visitOuterClass(final String owner, final String name,
- final String desc) {
- enclosingMethodOwner = newClass(owner);
- if (name != null && desc != null) {
- enclosingMethod = newNameType(name, desc);
- }
- }
-
- @Override
- public final AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- ByteVector bv = new ByteVector();
- // write type, and reserve space for values count
- bv.putShort(newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
- if (visible) {
- aw.next = anns;
- anns = aw;
- } else {
- aw.next = ianns;
- ianns = aw;
- }
- return aw;
- }
-
- @Override
- public final AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, final String desc, final boolean visible) {
- ByteVector bv = new ByteVector();
- // write target_type and target_info
- AnnotationWriter.putTarget(typeRef, typePath, bv);
- // write type, and reserve space for values count
- bv.putShort(newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv,
- bv.length - 2);
- if (visible) {
- aw.next = tanns;
- tanns = aw;
- } else {
- aw.next = itanns;
- itanns = aw;
- }
- return aw;
- }
-
- @Override
- public final void visitAttribute(final Attribute attr) {
- attr.next = attrs;
- attrs = attr;
- }
-
- @Override
- public final void visitInnerClass(final String name,
- final String outerName, final String innerName, final int access) {
- if (innerClasses == null) {
- innerClasses = new ByteVector();
- }
- // Sec. 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
- // constant_pool table which represents a class or interface C that is
- // not a package member must have exactly one corresponding entry in the
- // classes array". To avoid duplicates we keep track in the intVal field
- // of the Item of each CONSTANT_Class_info entry C whether an inner
- // class entry has already been added for C (this field is unused for
- // class entries, and changing its value does not change the hashcode
- // and equality tests). If so we store the index of this inner class
- // entry (plus one) in intVal. This hack allows duplicate detection in
- // O(1) time.
- Item nameItem = newStringishItem(CLASS, name);
- if (nameItem.intVal == 0) {
- ++innerClassesCount;
- innerClasses.putShort(nameItem.index);
- innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
- innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
- innerClasses.putShort(access);
- nameItem.intVal = innerClassesCount;
- } else {
- // Compare the inner classes entry nameItem.intVal - 1 with the
- // arguments of this method and throw an exception if there is a
- // difference?
- }
- }
-
- @Override
- public final FieldVisitor visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- return new FieldWriter(this, access, name, desc, signature, value);
- }
-
- @Override
- public final MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- return new MethodWriter(this, access, name, desc, signature,
- exceptions, compute);
- }
-
- @Override
- public final void visitEnd() {
- }
-
- // ------------------------------------------------------------------------
- // Other public methods
- // ------------------------------------------------------------------------
-
- /**
- * Returns the bytecode of the class that was build with this class writer.
- *
- * @return the bytecode of the class that was build with this class writer.
- */
- public byte[] toByteArray() {
- if (index > 0xFFFF) {
- throw new RuntimeException("Class file too large!");
- }
- // computes the real size of the bytecode of this class
- int size = 24 + 2 * interfaceCount;
- int nbFields = 0;
- FieldWriter fb = firstField;
- while (fb != null) {
- ++nbFields;
- size += fb.getSize();
- fb = (FieldWriter) fb.fv;
- }
- int nbMethods = 0;
- MethodWriter mb = firstMethod;
- while (mb != null) {
- ++nbMethods;
- size += mb.getSize();
- mb = (MethodWriter) mb.mv;
- }
- int attributeCount = 0;
- if (bootstrapMethods != null) {
- // we put it as first attribute in order to improve a bit
- // ClassReader.copyBootstrapMethods
- ++attributeCount;
- size += 8 + bootstrapMethods.length;
- newUTF8("BootstrapMethods");
- }
- if (signature != 0) {
- ++attributeCount;
- size += 8;
- newUTF8("Signature");
- }
- if (sourceFile != 0) {
- ++attributeCount;
- size += 8;
- newUTF8("SourceFile");
- }
- if (sourceDebug != null) {
- ++attributeCount;
- size += sourceDebug.length + 6;
- newUTF8("SourceDebugExtension");
- }
- if (enclosingMethodOwner != 0) {
- ++attributeCount;
- size += 10;
- newUTF8("EnclosingMethod");
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- ++attributeCount;
- size += 6;
- newUTF8("Deprecated");
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((version & 0xFFFF) < Opcodes.V1_5
- || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- ++attributeCount;
- size += 6;
- newUTF8("Synthetic");
- }
- }
- if (innerClasses != null) {
- ++attributeCount;
- size += 8 + innerClasses.length;
- newUTF8("InnerClasses");
- }
- if (anns != null) {
- ++attributeCount;
- size += 8 + anns.getSize();
- newUTF8("RuntimeVisibleAnnotations");
- }
- if (ianns != null) {
- ++attributeCount;
- size += 8 + ianns.getSize();
- newUTF8("RuntimeInvisibleAnnotations");
- }
- if (tanns != null) {
- ++attributeCount;
- size += 8 + tanns.getSize();
- newUTF8("RuntimeVisibleTypeAnnotations");
- }
- if (itanns != null) {
- ++attributeCount;
- size += 8 + itanns.getSize();
- newUTF8("RuntimeInvisibleTypeAnnotations");
- }
- if (moduleWriter != null) {
- attributeCount += 1 + moduleWriter.attributeCount;
- size += 6 + moduleWriter.size + moduleWriter.attributesSize;
- newUTF8("Module");
- }
- if (attrs != null) {
- attributeCount += attrs.getCount();
- size += attrs.getSize(this, null, 0, -1, -1);
- }
- size += pool.length;
- // allocates a byte vector of this size, in order to avoid unnecessary
- // arraycopy operations in the ByteVector.enlarge() method
- ByteVector out = new ByteVector(size);
- out.putInt(0xCAFEBABE).putInt(version);
- out.putShort(index).putByteArray(pool.data, 0, pool.length);
- int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC);
- out.putShort(access & ~mask).putShort(name).putShort(superName);
- out.putShort(interfaceCount);
- for (int i = 0; i < interfaceCount; ++i) {
- out.putShort(interfaces[i]);
- }
- out.putShort(nbFields);
- fb = firstField;
- while (fb != null) {
- fb.put(out);
- fb = (FieldWriter) fb.fv;
- }
- out.putShort(nbMethods);
- mb = firstMethod;
- while (mb != null) {
- mb.put(out);
- mb = (MethodWriter) mb.mv;
- }
- out.putShort(attributeCount);
- if (bootstrapMethods != null) {
- out.putShort(newUTF8("BootstrapMethods"));
- out.putInt(bootstrapMethods.length + 2).putShort(
- bootstrapMethodsCount);
- out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
- }
- if (signature != 0) {
- out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
- }
- if (sourceFile != 0) {
- out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
- }
- if (sourceDebug != null) {
- int len = sourceDebug.length;
- out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
- out.putByteArray(sourceDebug.data, 0, len);
- }
- if (moduleWriter != null) {
- out.putShort(newUTF8("Module"));
- moduleWriter.put(out);
- moduleWriter.putAttributes(out);
- }
- if (enclosingMethodOwner != 0) {
- out.putShort(newUTF8("EnclosingMethod")).putInt(4);
- out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- out.putShort(newUTF8("Deprecated")).putInt(0);
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((version & 0xFFFF) < Opcodes.V1_5
- || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- out.putShort(newUTF8("Synthetic")).putInt(0);
- }
- }
- if (innerClasses != null) {
- out.putShort(newUTF8("InnerClasses"));
- out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
- out.putByteArray(innerClasses.data, 0, innerClasses.length);
- }
- if (anns != null) {
- out.putShort(newUTF8("RuntimeVisibleAnnotations"));
- anns.put(out);
- }
- if (ianns != null) {
- out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
- ianns.put(out);
- }
- if (tanns != null) {
- out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
- tanns.put(out);
- }
- if (itanns != null) {
- out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
- itanns.put(out);
- }
- if (attrs != null) {
- attrs.put(this, null, 0, -1, -1, out);
- }
- if (hasAsmInsns) {
- boolean hasFrames = false;
- mb = firstMethod;
- while (mb != null) {
- hasFrames |= mb.frameCount > 0;
- mb = (MethodWriter) mb.mv;
- }
- anns = null;
- ianns = null;
- attrs = null;
- moduleWriter = null;
- firstField = null;
- lastField = null;
- firstMethod = null;
- lastMethod = null;
- compute =
- hasFrames ? MethodWriter.INSERTED_FRAMES : MethodWriter.NOTHING;
- hasAsmInsns = false;
- new ClassReader(out.data).accept(this,
- (hasFrames ? ClassReader.EXPAND_FRAMES : 0)
- | ClassReader.EXPAND_ASM_INSNS);
- return toByteArray();
- }
- return out.data;
- }
-
- // ------------------------------------------------------------------------
- // Utility methods: constant pool management
- // ------------------------------------------------------------------------
-
- /**
- * Adds a number or string constant to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- *
- * @param cst
- * the value of the constant to be added to the constant pool.
- * This parameter must be an {@link Integer}, a {@link Float}, a
- * {@link Long}, a {@link Double}, a {@link String} or a
- * {@link Type}.
- * @return a new or already existing constant item with the given value.
- */
- Item newConstItem(final Object cst) {
- if (cst instanceof Integer) {
- int val = ((Integer) cst).intValue();
- return newInteger(val);
- } else if (cst instanceof Byte) {
- int val = ((Byte) cst).intValue();
- return newInteger(val);
- } else if (cst instanceof Character) {
- int val = ((Character) cst).charValue();
- return newInteger(val);
- } else if (cst instanceof Short) {
- int val = ((Short) cst).intValue();
- return newInteger(val);
- } else if (cst instanceof Boolean) {
- int val = ((Boolean) cst).booleanValue() ? 1 : 0;
- return newInteger(val);
- } else if (cst instanceof Float) {
- float val = ((Float) cst).floatValue();
- return newFloat(val);
- } else if (cst instanceof Long) {
- long val = ((Long) cst).longValue();
- return newLong(val);
- } else if (cst instanceof Double) {
- double val = ((Double) cst).doubleValue();
- return newDouble(val);
- } else if (cst instanceof String) {
- return newStringishItem(STR, (String) cst);
- } else if (cst instanceof Type) {
- Type t = (Type) cst;
- int s = t.getSort();
- if (s == Type.OBJECT) {
- return newStringishItem(CLASS, t.getInternalName());
- } else if (s == Type.METHOD) {
- return newStringishItem(MTYPE, t.getDescriptor());
- } else { // s == primitive type or array
- return newStringishItem(CLASS, t.getDescriptor());
- }
- } else if (cst instanceof Handle) {
- Handle h = (Handle) cst;
- return newHandleItem(h.tag, h.owner, h.name, h.desc, h.itf);
- } else {
- throw new IllegalArgumentException("value " + cst);
- }
- }
-
- /**
- * Adds a number or string constant to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param cst
- * the value of the constant to be added to the constant pool.
- * This parameter must be an {@link Integer}, a {@link Float}, a
- * {@link Long}, a {@link Double} or a {@link String}.
- * @return the index of a new or already existing constant item with the
- * given value.
- */
- public int newConst(final Object cst) {
- return newConstItem(cst).index;
- }
-
- /**
- * Adds an UTF8 string to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param value
- * the String value.
- * @return the index of a new or already existing UTF8 item.
- */
- public int newUTF8(final String value) {
- key.set(UTF8, value, null, null);
- Item result = get(key);
- if (result == null) {
- pool.putByte(UTF8).putUTF8(value);
- result = new Item(index++, key);
- put(result);
- }
- return result.index;
- }
-
- /**
- * Adds a string reference, a class reference, a method type, a module
- * or a package to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- *
- * @param type
- * a type among STR, CLASS, MTYPE, MODULE or PACKAGE
- * @param value
- * string value of the reference.
- * @return a new or already existing reference item.
- */
- Item newStringishItem(final int type, final String value) {
- key2.set(type, value, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(type, newUTF8(value));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a class reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param value
- * the internal name of the class.
- * @return the index of a new or already existing class reference item.
- */
- public int newClass(final String value) {
- return newStringishItem(CLASS, value).index;
- }
-
- /**
- * Adds a method type reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param methodDesc
- * method descriptor of the method type.
- * @return the index of a new or already existing method type reference
- * item.
- */
- public int newMethodType(final String methodDesc) {
- return newStringishItem(MTYPE, methodDesc).index;
- }
-
- /**
- * Adds a module reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param moduleName
- * name of the module.
- * @return the index of a new or already existing module reference
- * item.
- */
- public int newModule(final String moduleName) {
- return newStringishItem(MODULE, moduleName).index;
- }
-
- /**
- * Adds a package reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param packageName
- * name of the package in its internal form.
- * @return the index of a new or already existing module reference
- * item.
- */
- public int newPackage(final String packageName) {
- return newStringishItem(PACKAGE, packageName).index;
- }
-
- /**
- * Adds a handle to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param tag
- * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner
- * the internal name of the field or method owner class.
- * @param name
- * the name of the field or method.
- * @param desc
- * the descriptor of the field or method.
- * @param itf
- * true if the owner is an interface.
- * @return a new or an already existing method type reference item.
- */
- Item newHandleItem(final int tag, final String owner, final String name,
- final String desc, final boolean itf) {
- key4.set(HANDLE_BASE + tag, owner, name, desc);
- Item result = get(key4);
- if (result == null) {
- if (tag <= Opcodes.H_PUTSTATIC) {
- put112(HANDLE, tag, newField(owner, name, desc));
- } else {
- put112(HANDLE,
- tag,
- newMethod(owner, name, desc, itf));
- }
- result = new Item(index++, key4);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a handle to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param tag
- * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner
- * the internal name of the field or method owner class.
- * @param name
- * the name of the field or method.
- * @param desc
- * the descriptor of the field or method.
- * @return the index of a new or already existing method type reference
- * item.
- *
- * @deprecated this method is superseded by
- * {@link #newHandle(int, String, String, String, boolean)}.
- */
- @Deprecated
- public int newHandle(final int tag, final String owner, final String name,
- final String desc) {
- return newHandle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
- }
-
- /**
- * Adds a handle to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param tag
- * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner
- * the internal name of the field or method owner class.
- * @param name
- * the name of the field or method.
- * @param desc
- * the descriptor of the field or method.
- * @param itf
- * true if the owner is an interface.
- * @return the index of a new or already existing method type reference
- * item.
- */
- public int newHandle(final int tag, final String owner, final String name,
- final String desc, final boolean itf) {
- return newHandleItem(tag, owner, name, desc, itf).index;
- }
-
- /**
- * Adds an invokedynamic reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param name
- * name of the invoked method.
- * @param desc
- * descriptor of the invoke method.
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the bootstrap method constant arguments.
- *
- * @return a new or an already existing invokedynamic type reference item.
- */
- Item newInvokeDynamicItem(final String name, final String desc,
- final Handle bsm, final Object... bsmArgs) {
- // cache for performance
- ByteVector bootstrapMethods = this.bootstrapMethods;
- if (bootstrapMethods == null) {
- bootstrapMethods = this.bootstrapMethods = new ByteVector();
- }
-
- int position = bootstrapMethods.length; // record current position
-
- int hashCode = bsm.hashCode();
- bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,
- bsm.desc, bsm.isInterface()));
-
- int argsLength = bsmArgs.length;
- bootstrapMethods.putShort(argsLength);
-
- for (int i = 0; i < argsLength; i++) {
- Object bsmArg = bsmArgs[i];
- hashCode ^= bsmArg.hashCode();
- bootstrapMethods.putShort(newConst(bsmArg));
- }
-
- byte[] data = bootstrapMethods.data;
- int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments)
- hashCode &= 0x7FFFFFFF;
- Item result = items[hashCode % items.length];
- loop: while (result != null) {
- if (result.type != BSM || result.hashCode != hashCode) {
- result = result.next;
- continue;
- }
-
- // because the data encode the size of the argument
- // we don't need to test if these size are equals
- int resultPosition = result.intVal;
- for (int p = 0; p < length; p++) {
- if (data[position + p] != data[resultPosition + p]) {
- result = result.next;
- continue loop;
- }
- }
- break;
- }
-
- int bootstrapMethodIndex;
- if (result != null) {
- bootstrapMethodIndex = result.index;
- bootstrapMethods.length = position; // revert to old position
- } else {
- bootstrapMethodIndex = bootstrapMethodsCount++;
- result = new Item(bootstrapMethodIndex);
- result.set(position, hashCode);
- put(result);
- }
-
- // now, create the InvokeDynamic constant
- key3.set(name, desc, bootstrapMethodIndex);
- result = get(key3);
- if (result == null) {
- put122(INDY, bootstrapMethodIndex, newNameType(name, desc));
- result = new Item(index++, key3);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds an invokedynamic reference to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param name
- * name of the invoked method.
- * @param desc
- * descriptor of the invoke method.
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the bootstrap method constant arguments.
- *
- * @return the index of a new or already existing invokedynamic reference
- * item.
- */
- public int newInvokeDynamic(final String name, final String desc,
- final Handle bsm, final Object... bsmArgs) {
- return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
- }
-
- /**
- * Adds a field reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- *
- * @param owner
- * the internal name of the field's owner class.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor.
- * @return a new or already existing field reference item.
- */
- Item newFieldItem(final String owner, final String name, final String desc) {
- key3.set(FIELD, owner, name, desc);
- Item result = get(key3);
- if (result == null) {
- put122(FIELD, newClass(owner), newNameType(name, desc));
- result = new Item(index++, key3);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a field reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param owner
- * the internal name of the field's owner class.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor.
- * @return the index of a new or already existing field reference item.
- */
- public int newField(final String owner, final String name, final String desc) {
- return newFieldItem(owner, name, desc).index;
- }
-
- /**
- * Adds a method reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- *
- * @param owner
- * the internal name of the method's owner class.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor.
- * @param itf
- * <tt>true</tt> if <tt>owner</tt> is an interface.
- * @return a new or already existing method reference item.
- */
- Item newMethodItem(final String owner, final String name,
- final String desc, final boolean itf) {
- int type = itf ? IMETH : METH;
- key3.set(type, owner, name, desc);
- Item result = get(key3);
- if (result == null) {
- put122(type, newClass(owner), newNameType(name, desc));
- result = new Item(index++, key3);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a method reference to the constant pool of the class being build.
- * Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param owner
- * the internal name of the method's owner class.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor.
- * @param itf
- * <tt>true</tt> if <tt>owner</tt> is an interface.
- * @return the index of a new or already existing method reference item.
- */
- public int newMethod(final String owner, final String name,
- final String desc, final boolean itf) {
- return newMethodItem(owner, name, desc, itf).index;
- }
-
- /**
- * Adds an integer to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item.
- *
- * @param value
- * the int value.
- * @return a new or already existing int item.
- */
- Item newInteger(final int value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(INT).putInt(value);
- result = new Item(index++, key);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a float to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value
- * the float value.
- * @return a new or already existing float item.
- */
- Item newFloat(final float value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(FLOAT).putInt(key.intVal);
- result = new Item(index++, key);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a long to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value
- * the long value.
- * @return a new or already existing long item.
- */
- Item newLong(final long value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(LONG).putLong(value);
- result = new Item(index, key);
- index += 2;
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a double to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value
- * the double value.
- * @return a new or already existing double item.
- */
- Item newDouble(final double value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(DOUBLE).putLong(key.longVal);
- result = new Item(index, key);
- index += 2;
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a name and type to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param name
- * a name.
- * @param desc
- * a type descriptor.
- * @return the index of a new or already existing name and type item.
- */
- public int newNameType(final String name, final String desc) {
- return newNameTypeItem(name, desc).index;
- }
-
- /**
- * Adds a name and type to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item.
- *
- * @param name
- * a name.
- * @param desc
- * a type descriptor.
- * @return a new or already existing name and type item.
- */
- Item newNameTypeItem(final String name, final String desc) {
- key2.set(NAME_TYPE, name, desc, null);
- Item result = get(key2);
- if (result == null) {
- put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds the given internal name to {@link #typeTable} and returns its index.
- * Does nothing if the type table already contains this internal name.
- *
- * @param type
- * the internal name to be added to the type table.
- * @return the index of this internal name in the type table.
- */
- int addType(final String type) {
- key.set(TYPE_NORMAL, type, null, null);
- Item result = get(key);
- if (result == null) {
- result = addType(key);
- }
- return result.index;
- }
-
- /**
- * Adds the given "uninitialized" type to {@link #typeTable} and returns its
- * index. This method is used for UNINITIALIZED types, made of an internal
- * name and a bytecode offset.
- *
- * @param type
- * the internal name to be added to the type table.
- * @param offset
- * the bytecode offset of the NEW instruction that created this
- * UNINITIALIZED type value.
- * @return the index of this internal name in the type table.
- */
- int addUninitializedType(final String type, final int offset) {
- key.type = TYPE_UNINIT;
- key.intVal = offset;
- key.strVal1 = type;
- key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
- Item result = get(key);
- if (result == null) {
- result = addType(key);
- }
- return result.index;
- }
-
- /**
- * Adds the given Item to {@link #typeTable}.
- *
- * @param item
- * the value to be added to the type table.
- * @return the added Item, which a new Item instance with the same value as
- * the given Item.
- */
- private Item addType(final Item item) {
- ++typeCount;
- Item result = new Item(typeCount, key);
- put(result);
- if (typeTable == null) {
- typeTable = new Item[16];
- }
- if (typeCount == typeTable.length) {
- Item[] newTable = new Item[2 * typeTable.length];
- System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
- typeTable = newTable;
- }
- typeTable[typeCount] = result;
- return result;
- }
-
- /**
- * Returns the index of the common super type of the two given types. This
- * method calls {@link #getCommonSuperClass} and caches the result in the
- * {@link #items} hash table to speedup future calls with the same
- * parameters.
- *
- * @param type1
- * index of an internal name in {@link #typeTable}.
- * @param type2
- * index of an internal name in {@link #typeTable}.
- * @return the index of the common super type of the two given types.
- */
- int getMergedType(final int type1, final int type2) {
- key2.type = TYPE_MERGED;
- key2.longVal = type1 | (((long) type2) << 32);
- key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
- Item result = get(key2);
- if (result == null) {
- String t = typeTable[type1].strVal1;
- String u = typeTable[type2].strVal1;
- key2.intVal = addType(getCommonSuperClass(t, u));
- result = new Item((short) 0, key2);
- put(result);
- }
- return result.intVal;
- }
-
- /**
- * Returns the common super type of the two given types. The default
- * implementation of this method <i>loads</i> the two given classes and uses
- * the java.lang.Class methods to find the common super class. It can be
- * overridden to compute this common super type in other ways, in particular
- * without actually loading any class, or to take into account the class
- * that is currently being generated by this ClassWriter, which can of
- * course not be loaded since it is under construction.
- *
- * @param type1
- * the internal name of a class.
- * @param type2
- * the internal name of another class.
- * @return the internal name of the common super class of the two given
- * classes.
- */
- protected String getCommonSuperClass(final String type1, final String type2) {
- Class<?> c, d;
- ClassLoader classLoader = getClass().getClassLoader();
- try {
- c = Class.forName(type1.replace('/', '.'), false, classLoader);
- d = Class.forName(type2.replace('/', '.'), false, classLoader);
- } catch (Exception e) {
- throw new RuntimeException(e.toString());
- }
- if (c.isAssignableFrom(d)) {
- return type1;
- }
- if (d.isAssignableFrom(c)) {
- return type2;
- }
- if (c.isInterface() || d.isInterface()) {
- return "java/lang/Object";
- } else {
- do {
- c = c.getSuperclass();
- } while (!c.isAssignableFrom(d));
- return c.getName().replace('.', '/');
- }
- }
-
- /**
- * Returns the constant pool's hash table item which is equal to the given
- * item.
- *
- * @param key
- * a constant pool item.
- * @return the constant pool's hash table item which is equal to the given
- * item, or <tt>null</tt> if there is no such item.
- */
- private Item get(final Item key) {
- Item i = items[key.hashCode % items.length];
- while (i != null && (i.type != key.type || !key.isEqualTo(i))) {
- i = i.next;
- }
- return i;
- }
-
- /**
- * Puts the given item in the constant pool's hash table. The hash table
- * <i>must</i> not already contains this item.
- *
- * @param i
- * the item to be added to the constant pool's hash table.
- */
- private void put(final Item i) {
- if (index + typeCount > threshold) {
- int ll = items.length;
- int nl = ll * 2 + 1;
- Item[] newItems = new Item[nl];
- for (int l = ll - 1; l >= 0; --l) {
- Item j = items[l];
- while (j != null) {
- int index = j.hashCode % newItems.length;
- Item k = j.next;
- j.next = newItems[index];
- newItems[index] = j;
- j = k;
- }
- }
- items = newItems;
- threshold = (int) (nl * 0.75);
- }
- int index = i.hashCode % items.length;
- i.next = items[index];
- items[index] = i;
- }
-
- /**
- * Puts one byte and two shorts into the constant pool.
- *
- * @param b
- * a byte.
- * @param s1
- * a short.
- * @param s2
- * another short.
- */
- private void put122(final int b, final int s1, final int s2) {
- pool.put12(b, s1).putShort(s2);
- }
-
- /**
- * Puts two bytes and one short into the constant pool.
- *
- * @param b1
- * a byte.
- * @param b2
- * another byte.
- * @param s
- * a short.
- */
- private void put112(final int b1, final int b2, final int s) {
- pool.put11(b1, b2).putShort(s);
- }
+ /**
+ * A flag to automatically compute the maximum stack size and the maximum number of local
+ * variables of methods. If this flag is set, then the arguments of the {@link
+ * MethodVisitor#visitMaxs} method of the {@link MethodVisitor} returned by the {@link
+ * #visitMethod} method will be ignored, and computed automatically from the signature and the
+ * bytecode of each method.
+ *
+ * <p><b>Note:</b> for classes whose version is {@link Opcodes#V1_7} of more, this option requires
+ * valid stack map frames. The maximum stack size is then computed from these frames, and from the
+ * bytecode instructions in between. If stack map frames are not present or must be recomputed,
+ * used {@link #COMPUTE_FRAMES} instead.
+ *
+ * @see #ClassWriter(int)
+ */
+ public static final int COMPUTE_MAXS = 1;
+
+ /**
+ * A flag to automatically compute the stack map frames of methods from scratch. If this flag is
+ * set, then the calls to the {@link MethodVisitor#visitFrame} method are ignored, and the stack
+ * map frames are recomputed from the methods bytecode. The arguments of the {@link
+ * MethodVisitor#visitMaxs} method are also ignored and recomputed from the bytecode. In other
+ * words, {@link #COMPUTE_FRAMES} implies {@link #COMPUTE_MAXS}.
+ *
+ * @see #ClassWriter(int)
+ */
+ public static final int COMPUTE_FRAMES = 2;
+
+ // Note: fields are ordered as in the ClassFile structure, and those related to attributes are
+ // ordered as in Section 4.7 of the JVMS.
+
+ /**
+ * The minor_version and major_version fields of the JVMS ClassFile structure. minor_version is
+ * stored in the 16 most significant bits, and major_version in the 16 least significant bits.
+ */
+ private int version;
+
+ /** The symbol table for this class (contains the constant_pool and the BootstrapMethods). */
+ private final SymbolTable symbolTable;
+
+ /**
+ * The access_flags field of the JVMS ClassFile structure. This field can contain ASM specific
+ * access flags, such as {@link Opcodes#ACC_DEPRECATED}, which are removed when generating the
+ * ClassFile structure.
+ */
+ private int accessFlags;
+
+ /** The this_class field of the JVMS ClassFile structure. */
+ private int thisClass;
+
+ /** The super_class field of the JVMS ClassFile structure. */
+ private int superClass;
+
+ /** The interface_count field of the JVMS ClassFile structure. */
+ private int interfaceCount;
+
+ /** The 'interfaces' array of the JVMS ClassFile structure. */
+ private int[] interfaces;
+
+ /**
+ * The fields of this class, stored in a linked list of {@link FieldWriter} linked via their
+ * {@link FieldWriter#fv} field. This field stores the first element of this list.
+ */
+ private FieldWriter firstField;
+
+ /**
+ * The fields of this class, stored in a linked list of {@link FieldWriter} linked via their
+ * {@link FieldWriter#fv} field. This field stores the last element of this list.
+ */
+ private FieldWriter lastField;
+
+ /**
+ * The methods of this class, stored in a linked list of {@link MethodWriter} linked via their
+ * {@link MethodWriter#mv} field. This field stores the first element of this list.
+ */
+ private MethodWriter firstMethod;
+
+ /**
+ * The methods of this class, stored in a linked list of {@link MethodWriter} linked via their
+ * {@link MethodWriter#mv} field. This field stores the last element of this list.
+ */
+ private MethodWriter lastMethod;
+
+ /** The number_of_classes field of the InnerClasses attribute, or 0. */
+ private int numberOfInnerClasses;
+
+ /** The 'classes' array of the InnerClasses attribute, or {@literal null}. */
+ private ByteVector innerClasses;
+
+ /** The class_index field of the EnclosingMethod attribute, or 0. */
+ private int enclosingClassIndex;
+
+ /** The method_index field of the EnclosingMethod attribute. */
+ private int enclosingMethodIndex;
+
+ /** The signature_index field of the Signature attribute, or 0. */
+ private int signatureIndex;
+
+ /** The source_file_index field of the SourceFile attribute, or 0. */
+ private int sourceFileIndex;
+
+ /** The debug_extension field of the SourceDebugExtension attribute, or {@literal null}. */
+ private ByteVector debugExtension;
+
+ /**
+ * The last runtime visible annotation of this class. The previous ones can be accessed with the
+ * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeVisibleAnnotation;
+
+ /**
+ * The last runtime invisible annotation of this class. The previous ones can be accessed with the
+ * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeInvisibleAnnotation;
+
+ /**
+ * The last runtime visible type annotation of this class. The previous ones can be accessed with
+ * the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
+
+ /**
+ * The last runtime invisible type annotation of this class. The previous ones can be accessed
+ * with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeInvisibleTypeAnnotation;
+
+ /** The Module attribute of this class, or {@literal null}. */
+ private ModuleWriter moduleWriter;
+
+ /** The host_class_index field of the NestHost attribute, or 0. */
+ private int nestHostClassIndex;
+
+ /** The number_of_classes field of the NestMembers attribute, or 0. */
+ private int numberOfNestMemberClasses;
+
+ /** The 'classes' array of the NestMembers attribute, or {@literal null}. */
+ private ByteVector nestMemberClasses;
+
+ /**
+ * The first non standard attribute of this class. The next ones can be accessed with the {@link
+ * Attribute#nextAttribute} field. May be {@literal null}.
+ *
+ * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
+ * firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
+ * #toByteArray} method writes the attributes in the order defined by this list, i.e. in the
+ * reverse order specified by the user.
+ */
+ private Attribute firstAttribute;
+
+ /**
+ * Indicates what must be automatically computed in {@link MethodWriter}. Must be one of {@link
+ * MethodWriter#COMPUTE_NOTHING}, {@link MethodWriter#COMPUTE_MAX_STACK_AND_LOCAL}, {@link
+ * MethodWriter#COMPUTE_INSERTED_FRAMES}, or {@link MethodWriter#COMPUTE_ALL_FRAMES}.
+ */
+ private int compute;
+
+ // -----------------------------------------------------------------------------------------------
+ // Constructor
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ClassWriter} object.
+ *
+ * @param flags option flags that can be used to modify the default behavior of this class. Must
+ * be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}.
+ */
+ public ClassWriter(final int flags) {
+ this(null, flags);
+ }
+
+ /**
+ * Constructs a new {@link ClassWriter} object and enables optimizations for "mostly add" bytecode
+ * transformations. These optimizations are the following:
+ *
+ * <ul>
+ * <li>The constant pool and bootstrap methods from the original class are copied as is in the
+ * new class, which saves time. New constant pool entries and new bootstrap methods will be
+ * added at the end if necessary, but unused constant pool entries or bootstrap methods
+ * <i>won't be removed</i>.
+ * <li>Methods that are not transformed are copied as is in the new class, directly from the
+ * original class bytecode (i.e. without emitting visit events for all the method
+ * instructions), which saves a <i>lot</i> of time. Untransformed methods are detected by
+ * the fact that the {@link ClassReader} receives {@link MethodVisitor} objects that come
+ * from a {@link ClassWriter} (and not from any other {@link ClassVisitor} instance).
+ * </ul>
+ *
+ * @param classReader the {@link ClassReader} used to read the original class. It will be used to
+ * copy the entire constant pool and bootstrap methods from the original class and also to
+ * copy other fragments of original bytecode where applicable.
+ * @param flags option flags that can be used to modify the default behavior of this class.Must be
+ * zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. <i>These option flags do
+ * not affect methods that are copied as is in the new class. This means that neither the
+ * maximum stack size nor the stack frames will be computed for these methods</i>.
+ */
+ public ClassWriter(final ClassReader classReader, final int flags) {
+ super(Opcodes.ASM7);
+ symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader);
+ if ((flags & COMPUTE_FRAMES) != 0) {
+ this.compute = MethodWriter.COMPUTE_ALL_FRAMES;
+ } else if ((flags & COMPUTE_MAXS) != 0) {
+ this.compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL;
+ } else {
+ this.compute = MethodWriter.COMPUTE_NOTHING;
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the ClassVisitor abstract class
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public final void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ this.version = version;
+ this.accessFlags = access;
+ this.thisClass = symbolTable.setMajorVersionAndClassName(version & 0xFFFF, name);
+ if (signature != null) {
+ this.signatureIndex = symbolTable.addConstantUtf8(signature);
+ }
+ this.superClass = superName == null ? 0 : symbolTable.addConstantClass(superName).index;
+ if (interfaces != null && interfaces.length > 0) {
+ interfaceCount = interfaces.length;
+ this.interfaces = new int[interfaceCount];
+ for (int i = 0; i < interfaceCount; ++i) {
+ this.interfaces[i] = symbolTable.addConstantClass(interfaces[i]).index;
+ }
+ }
+ if (compute == MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL && (version & 0xFFFF) >= Opcodes.V1_7) {
+ compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES;
+ }
+ }
+
+ @Override
+ public final void visitSource(final String file, final String debug) {
+ if (file != null) {
+ sourceFileIndex = symbolTable.addConstantUtf8(file);
+ }
+ if (debug != null) {
+ debugExtension = new ByteVector().encodeUtf8(debug, 0, Integer.MAX_VALUE);
+ }
+ }
+
+ @Override
+ public final ModuleVisitor visitModule(
+ final String name, final int access, final String version) {
+ return moduleWriter =
+ new ModuleWriter(
+ symbolTable,
+ symbolTable.addConstantModule(name).index,
+ access,
+ version == null ? 0 : symbolTable.addConstantUtf8(version));
+ }
+
+ @Override
+ public void visitNestHost(final String nestHost) {
+ nestHostClassIndex = symbolTable.addConstantClass(nestHost).index;
+ }
+
+ @Override
+ public final void visitOuterClass(
+ final String owner, final String name, final String descriptor) {
+ enclosingClassIndex = symbolTable.addConstantClass(owner).index;
+ if (name != null && descriptor != null) {
+ enclosingMethodIndex = symbolTable.addConstantNameAndType(name, descriptor);
+ }
+ }
+
+ @Override
+ public final AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ // Create a ByteVector to hold an 'annotation' JVMS structure.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
+ ByteVector annotation = new ByteVector();
+ // Write type_index and reserve space for num_element_value_pairs.
+ annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
+ if (visible) {
+ return lastRuntimeVisibleAnnotation =
+ new AnnotationWriter(symbolTable, annotation, lastRuntimeVisibleAnnotation);
+ } else {
+ return lastRuntimeInvisibleAnnotation =
+ new AnnotationWriter(symbolTable, annotation, lastRuntimeInvisibleAnnotation);
+ }
+ }
+
+ @Override
+ public final AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ // Create a ByteVector to hold a 'type_annotation' JVMS structure.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.
+ ByteVector typeAnnotation = new ByteVector();
+ // Write target_type, target_info, and target_path.
+ TypeReference.putTarget(typeRef, typeAnnotation);
+ TypePath.put(typePath, typeAnnotation);
+ // Write type_index and reserve space for num_element_value_pairs.
+ typeAnnotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
+ if (visible) {
+ return lastRuntimeVisibleTypeAnnotation =
+ new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeVisibleTypeAnnotation);
+ } else {
+ return lastRuntimeInvisibleTypeAnnotation =
+ new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeInvisibleTypeAnnotation);
+ }
+ }
+
+ @Override
+ public final void visitAttribute(final Attribute attribute) {
+ // Store the attributes in the <i>reverse</i> order of their visit by this method.
+ attribute.nextAttribute = firstAttribute;
+ firstAttribute = attribute;
+ }
+
+ @Override
+ public void visitNestMember(final String nestMember) {
+ if (nestMemberClasses == null) {
+ nestMemberClasses = new ByteVector();
+ }
+ ++numberOfNestMemberClasses;
+ nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index);
+ }
+
+ @Override
+ public final void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ if (innerClasses == null) {
+ innerClasses = new ByteVector();
+ }
+ // Section 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the constant_pool table
+ // which represents a class or interface C that is not a package member must have exactly one
+ // corresponding entry in the classes array". To avoid duplicates we keep track in the info
+ // field of the Symbol of each CONSTANT_Class_info entry C whether an inner class entry has
+ // already been added for C. If so, we store the index of this inner class entry (plus one) in
+ // the info field. This trick allows duplicate detection in O(1) time.
+ Symbol nameSymbol = symbolTable.addConstantClass(name);
+ if (nameSymbol.info == 0) {
+ ++numberOfInnerClasses;
+ innerClasses.putShort(nameSymbol.index);
+ innerClasses.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index);
+ innerClasses.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName));
+ innerClasses.putShort(access);
+ nameSymbol.info = numberOfInnerClasses;
+ }
+ // Else, compare the inner classes entry nameSymbol.info - 1 with the arguments of this method
+ // and throw an exception if there is a difference?
+ }
+
+ @Override
+ public final FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ FieldWriter fieldWriter =
+ new FieldWriter(symbolTable, access, name, descriptor, signature, value);
+ if (firstField == null) {
+ firstField = fieldWriter;
+ } else {
+ lastField.fv = fieldWriter;
+ }
+ return lastField = fieldWriter;
+ }
+
+ @Override
+ public final MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ MethodWriter methodWriter =
+ new MethodWriter(symbolTable, access, name, descriptor, signature, exceptions, compute);
+ if (firstMethod == null) {
+ firstMethod = methodWriter;
+ } else {
+ lastMethod.mv = methodWriter;
+ }
+ return lastMethod = methodWriter;
+ }
+
+ @Override
+ public final void visitEnd() {
+ // Nothing to do.
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Other public methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the content of the class file that was built by this ClassWriter.
+ *
+ * @return the binary content of the JVMS ClassFile structure that was built by this ClassWriter.
+ * @throws ClassTooLargeException if the constant pool of the class is too large.
+ * @throws MethodTooLargeException if the Code attribute of a method is too large.
+ */
+ public byte[] toByteArray() throws ClassTooLargeException, MethodTooLargeException {
+ // First step: compute the size in bytes of the ClassFile structure.
+ // The magic field uses 4 bytes, 10 mandatory fields (minor_version, major_version,
+ // constant_pool_count, access_flags, this_class, super_class, interfaces_count, fields_count,
+ // methods_count and attributes_count) use 2 bytes each, and each interface uses 2 bytes too.
+ int size = 24 + 2 * interfaceCount;
+ int fieldsCount = 0;
+ FieldWriter fieldWriter = firstField;
+ while (fieldWriter != null) {
+ ++fieldsCount;
+ size += fieldWriter.computeFieldInfoSize();
+ fieldWriter = (FieldWriter) fieldWriter.fv;
+ }
+ int methodsCount = 0;
+ MethodWriter methodWriter = firstMethod;
+ while (methodWriter != null) {
+ ++methodsCount;
+ size += methodWriter.computeMethodInfoSize();
+ methodWriter = (MethodWriter) methodWriter.mv;
+ }
+ // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
+ int attributesCount = 0;
+ if (innerClasses != null) {
+ ++attributesCount;
+ size += 8 + innerClasses.length;
+ symbolTable.addConstantUtf8(Constants.INNER_CLASSES);
+ }
+ if (enclosingClassIndex != 0) {
+ ++attributesCount;
+ size += 10;
+ symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD);
+ }
+ if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) {
+ ++attributesCount;
+ size += 6;
+ symbolTable.addConstantUtf8(Constants.SYNTHETIC);
+ }
+ if (signatureIndex != 0) {
+ ++attributesCount;
+ size += 8;
+ symbolTable.addConstantUtf8(Constants.SIGNATURE);
+ }
+ if (sourceFileIndex != 0) {
+ ++attributesCount;
+ size += 8;
+ symbolTable.addConstantUtf8(Constants.SOURCE_FILE);
+ }
+ if (debugExtension != null) {
+ ++attributesCount;
+ size += 6 + debugExtension.length;
+ symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION);
+ }
+ if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributesCount;
+ size += 6;
+ symbolTable.addConstantUtf8(Constants.DEPRECATED);
+ }
+ if (lastRuntimeVisibleAnnotation != null) {
+ ++attributesCount;
+ size +=
+ lastRuntimeVisibleAnnotation.computeAnnotationsSize(
+ Constants.RUNTIME_VISIBLE_ANNOTAT
<TRUNCATED>
[15/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
old mode 100644
new mode 100755
index b7c94c8..afe4d78
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
@@ -1,226 +1,268 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
/**
- * A semantic bytecode interpreter. More precisely, this interpreter only
- * manages the computation of values from other values: it does not manage the
- * transfer of values to or from the stack, and to or from the local variables.
- * This separation allows a generic bytecode {@link Analyzer} to work with
- * various semantic interpreters, without needing to duplicate the code to
- * simulate the transfer of values.
- *
- * @param <V>
- * type of the Value used for the analysis.
- *
+ * A semantic bytecode interpreter. More precisely, this interpreter only manages the computation of
+ * values from other values: it does not manage the transfer of values to or from the stack, and to
+ * or from the local variables. This separation allows a generic bytecode {@link Analyzer} to work
+ * with various semantic interpreters, without needing to duplicate the code to simulate the
+ * transfer of values.
+ *
+ * @param <V> type of the Value used for the analysis.
* @author Eric Bruneton
*/
public abstract class Interpreter<V extends Value> {
- protected final int api;
-
- protected Interpreter(final int api) {
- this.api = api;
- }
-
- /**
- * Creates a new value that represents the given type.
- *
- * Called for method parameters (including <code>this</code>), exception
- * handler variable and with <code>null</code> type for variables reserved
- * by long and double types.
- *
- * @param type
- * a primitive or reference type, or <tt>null</tt> to represent
- * an uninitialized value.
- * @return a value that represents the given type. The size of the returned
- * value must be equal to the size of the given type.
- */
- public abstract V newValue(Type type);
-
- /**
- * Interprets a bytecode instruction without arguments. This method is
- * called for the following opcodes:
- *
- * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4,
- * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0,
- * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW
- *
- * @param insn
- * the bytecode instruction to be interpreted.
- * @return the result of the interpretation of the given instruction.
- * @throws AnalyzerException
- * if an error occured during the interpretation.
- */
- public abstract V newOperation(AbstractInsnNode insn)
- throws AnalyzerException;
-
- /**
- * Interprets a bytecode instruction that moves a value on the stack or to
- * or from local variables. This method is called for the following opcodes:
- *
- * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
- * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
- *
- * @param insn
- * the bytecode instruction to be interpreted.
- * @param value
- * the value that must be moved by the instruction.
- * @return the result of the interpretation of the given instruction. The
- * returned value must be <tt>equal</tt> to the given value.
- * @throws AnalyzerException
- * if an error occured during the interpretation.
- */
- public abstract V copyOperation(AbstractInsnNode insn, V value)
- throws AnalyzerException;
-
- /**
- * Interprets a bytecode instruction with a single argument. This method is
- * called for the following opcodes:
- *
- * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
- * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
- * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
- * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
- * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
- *
- * @param insn
- * the bytecode instruction to be interpreted.
- * @param value
- * the argument of the instruction to be interpreted.
- * @return the result of the interpretation of the given instruction.
- * @throws AnalyzerException
- * if an error occured during the interpretation.
- */
- public abstract V unaryOperation(AbstractInsnNode insn, V value)
- throws AnalyzerException;
-
- /**
- * Interprets a bytecode instruction with two arguments. This method is
- * called for the following opcodes:
- *
- * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
- * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
- * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
- * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
- * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
- * IF_ACMPEQ, IF_ACMPNE, PUTFIELD
- *
- * @param insn
- * the bytecode instruction to be interpreted.
- * @param value1
- * the first argument of the instruction to be interpreted.
- * @param value2
- * the second argument of the instruction to be interpreted.
- * @return the result of the interpretation of the given instruction.
- * @throws AnalyzerException
- * if an error occured during the interpretation.
- */
- public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
- throws AnalyzerException;
-
- /**
- * Interprets a bytecode instruction with three arguments. This method is
- * called for the following opcodes:
- *
- * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
- *
- * @param insn
- * the bytecode instruction to be interpreted.
- * @param value1
- * the first argument of the instruction to be interpreted.
- * @param value2
- * the second argument of the instruction to be interpreted.
- * @param value3
- * the third argument of the instruction to be interpreted.
- * @return the result of the interpretation of the given instruction.
- * @throws AnalyzerException
- * if an error occured during the interpretation.
- */
- public abstract V ternaryOperation(AbstractInsnNode insn, V value1,
- V value2, V value3) throws AnalyzerException;
-
- /**
- * Interprets a bytecode instruction with a variable number of arguments.
- * This method is called for the following opcodes:
- *
- * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
- * MULTIANEWARRAY and INVOKEDYNAMIC
- *
- * @param insn
- * the bytecode instruction to be interpreted.
- * @param values
- * the arguments of the instruction to be interpreted.
- * @return the result of the interpretation of the given instruction.
- * @throws AnalyzerException
- * if an error occured during the interpretation.
- */
- public abstract V naryOperation(AbstractInsnNode insn,
- List<? extends V> values) throws AnalyzerException;
-
- /**
- * Interprets a bytecode return instruction. This method is called for the
- * following opcodes:
- *
- * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
- *
- * @param insn
- * the bytecode instruction to be interpreted.
- * @param value
- * the argument of the instruction to be interpreted.
- * @param expected
- * the expected return type of the analyzed method.
- * @throws AnalyzerException
- * if an error occured during the interpretation.
- */
- public abstract void returnOperation(AbstractInsnNode insn, V value,
- V expected) throws AnalyzerException;
-
- /**
- * Merges two values. The merge operation must return a value that
- * represents both values (for instance, if the two values are two types,
- * the merged value must be a common super type of the two types. If the two
- * values are integer intervals, the merged value must be an interval that
- * contains the previous ones. Likewise for other types of values).
- *
- * @param v
- * a value.
- * @param w
- * another value.
- * @return the merged value. If the merged value is equal to <tt>v</tt>,
- * this method <i>must</i> return <tt>v</tt>.
- */
- public abstract V merge(V v, V w);
+ /**
+ * The ASM API version supported by this interpreter. The value of this field must be one of
+ * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+ */
+ protected final int api;
+
+ /**
+ * Constructs a new {@link Interpreter}.
+ *
+ * @param api the ASM API version supported by this interpreter. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+ */
+ protected Interpreter(final int api) {
+ this.api = api;
+ }
+
+ /**
+ * Creates a new value that represents the given type.
+ *
+ * <p>Called for method parameters (including <code>this</code>), exception handler variable and
+ * with <code>null</code> type for variables reserved by long and double types.
+ *
+ * <p>An interpreter may choose to implement one or more of {@link
+ * Interpreter#newReturnTypeValue(Type)}, {@link Interpreter#newParameterValue(boolean, int,
+ * Type)}, {@link Interpreter#newEmptyValue(int)}, {@link
+ * Interpreter#newExceptionValue(TryCatchBlockNode, Frame, Type)} to distinguish different types
+ * of new value.
+ *
+ * @param type a primitive or reference type, or {@literal null} to represent an uninitialized
+ * value.
+ * @return a value that represents the given type. The size of the returned value must be equal to
+ * the size of the given type.
+ */
+ public abstract V newValue(Type type);
+
+ /**
+ * Creates a new value that represents the given parameter type. This method is called to
+ * initialize the value of a local corresponding to a method parameter in a frame.
+ *
+ * <p>By default, calls <code>newValue(type)</code>.
+ *
+ * @param isInstanceMethod {@literal true} if the method is non-static.
+ * @param local the local variable index.
+ * @param type a primitive or reference type.
+ * @return a value that represents the given type. The size of the returned value must be equal to
+ * the size of the given type.
+ */
+ public V newParameterValue(final boolean isInstanceMethod, final int local, final Type type) {
+ return newValue(type);
+ }
+
+ /**
+ * Creates a new value that represents the given return type. This method is called to initialize
+ * the return type value of a frame.
+ *
+ * <p>By default, calls <code>newValue(type)</code>.
+ *
+ * @param type a primitive or reference type.
+ * @return a value that represents the given type. The size of the returned value must be equal to
+ * the size of the given type.
+ */
+ public V newReturnTypeValue(final Type type) {
+ return newValue(type);
+ }
+
+ /**
+ * Creates a new uninitialized value for a local variable. This method is called to initialize the
+ * value of a local that does not correspond to a method parameter, and to reset one half of a
+ * size-2 value when the other half is assigned a size-1 value.
+ *
+ * <p>By default, calls <code>newValue(null)</code>.
+ *
+ * @param local the local variable index.
+ * @return a value representing an uninitialized value. The size of the returned value must be
+ * equal to 1.
+ */
+ public V newEmptyValue(final int local) {
+ return newValue(null);
+ }
+
+ /**
+ * Creates a new value that represents the given exception type. This method is called to
+ * initialize the exception value on the call stack at the entry of an exception handler.
+ *
+ * <p>By default, calls <code>newValue(exceptionType)</code>.
+ *
+ * @param tryCatchBlockNode the exception handler.
+ * @param handlerFrame the exception handler frame.
+ * @param exceptionType the exception type handled by this handler.
+ * @return a value that represents the given {@code exceptionType}. The size of the returned value
+ * must be equal to 1.
+ */
+ public V newExceptionValue(
+ final TryCatchBlockNode tryCatchBlockNode,
+ final Frame<V> handlerFrame,
+ final Type exceptionType) {
+ return newValue(exceptionType);
+ }
+
+ /**
+ * Interprets a bytecode instruction without arguments. This method is called for the following
+ * opcodes:
+ *
+ * <p>ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5,
+ * LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, BIPUSH, SIPUSH, LDC, JSR,
+ * GETSTATIC, NEW
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occurred during the interpretation.
+ */
+ public abstract V newOperation(AbstractInsnNode insn) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction that moves a value on the stack or to or from local
+ * variables. This method is called for the following opcodes:
+ *
+ * <p>ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE, DUP, DUP_X1,
+ * DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value the value that must be moved by the instruction.
+ * @return the result of the interpretation of the given instruction. The returned value must be
+ * {@code equal} to the given value.
+ * @throws AnalyzerException if an error occurred during the interpretation.
+ */
+ public abstract V copyOperation(AbstractInsnNode insn, V value) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a single argument. This method is called for the
+ * following opcodes:
+ *
+ * <p>INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,
+ * I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN,
+ * FRETURN, DRETURN, ARETURN, PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW,
+ * CHECKCAST, INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value the argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occurred during the interpretation.
+ */
+ public abstract V unaryOperation(AbstractInsnNode insn, V value) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with two arguments. This method is called for the following
+ * opcodes:
+ *
+ * <p>IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD, LADD, FADD, DADD,
+ * ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM,
+ * ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG,
+ * DCMPL, DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
+ * IF_ACMPNE, PUTFIELD
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value1 the first argument of the instruction to be interpreted.
+ * @param value2 the second argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occurred during the interpretation.
+ */
+ public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with three arguments. This method is called for the following
+ * opcodes:
+ *
+ * <p>IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value1 the first argument of the instruction to be interpreted.
+ * @param value2 the second argument of the instruction to be interpreted.
+ * @param value3 the third argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occurred during the interpretation.
+ */
+ public abstract V ternaryOperation(AbstractInsnNode insn, V value1, V value2, V value3)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a variable number of arguments. This method is called
+ * for the following opcodes:
+ *
+ * <p>INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE, MULTIANEWARRAY and
+ * INVOKEDYNAMIC
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param values the arguments of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occurred during the interpretation.
+ */
+ public abstract V naryOperation(AbstractInsnNode insn, List<? extends V> values)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode return instruction. This method is called for the following opcodes:
+ *
+ * <p>IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value the argument of the instruction to be interpreted.
+ * @param expected the expected return type of the analyzed method.
+ * @throws AnalyzerException if an error occurred during the interpretation.
+ */
+ public abstract void returnOperation(AbstractInsnNode insn, V value, V expected)
+ throws AnalyzerException;
+
+ /**
+ * Merges two values. The merge operation must return a value that represents both values (for
+ * instance, if the two values are two types, the merged value must be a common super type of the
+ * two types. If the two values are integer intervals, the merged value must be an interval that
+ * contains the previous ones. Likewise for other types of values).
+ *
+ * @param value1 a value.
+ * @param value2 another value.
+ * @return the merged value. If the merged value is equal to {@code value1}, this method
+ * <i>must</i> return {@code value1}.
+ */
+ public abstract V merge(V value1, V value2);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
old mode 100644
new mode 100755
index 0cc2f28..90487a4
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
@@ -1,320 +1,376 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.Type;
/**
- * An extended {@link BasicVerifier} that performs more precise verifications.
- * This verifier computes exact class types, instead of using a single "object
- * reference" type (as done in the {@link BasicVerifier}).
- *
+ * An extended {@link BasicVerifier} that performs more precise verifications. This verifier
+ * computes exact class types, instead of using a single "object reference" type (as done in {@link
+ * BasicVerifier}).
+ *
* @author Eric Bruneton
* @author Bing Ran
*/
public class SimpleVerifier extends BasicVerifier {
- /**
- * The class that is verified.
- */
- private final Type currentClass;
+ /** The type of the class that is verified. */
+ private final Type currentClass;
- /**
- * The super class of the class that is verified.
- */
- private final Type currentSuperClass;
+ /** The type of the super class of the class that is verified. */
+ private final Type currentSuperClass;
- /**
- * The interfaces implemented by the class that is verified.
- */
- private final List<Type> currentClassInterfaces;
+ /** The types of the interfaces directly implemented by the class that is verified. */
+ private final List<Type> currentClassInterfaces;
- /**
- * If the class that is verified is an interface.
- */
- private final boolean isInterface;
+ /** Whether the class that is verified is an interface. */
+ private final boolean isInterface;
- /**
- * The loader to use for referenced classes.
- */
- private ClassLoader loader = getClass().getClassLoader();
+ /** The loader to use to load the referenced classes. */
+ private ClassLoader loader = getClass().getClassLoader();
- /**
- * Constructs a new {@link SimpleVerifier}.
- */
- public SimpleVerifier() {
- this(null, null, false);
- }
+ /**
+ * Constructs a new {@link SimpleVerifier}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version.
+ */
+ public SimpleVerifier() {
+ this(null, null, false);
+ }
- /**
- * Constructs a new {@link SimpleVerifier} to verify a specific class. This
- * class will not be loaded into the JVM since it may be incorrect.
- *
- * @param currentClass
- * the class that is verified.
- * @param currentSuperClass
- * the super class of the class that is verified.
- * @param isInterface
- * if the class that is verified is an interface.
- */
- public SimpleVerifier(final Type currentClass,
- final Type currentSuperClass, final boolean isInterface) {
- this(currentClass, currentSuperClass, null, isInterface);
- }
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This class will not be
+ * loaded into the JVM since it may be incorrect. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version.
+ *
+ * @param currentClass the type of the class to be verified.
+ * @param currentSuperClass the type of the super class of the class to be verified.
+ * @param isInterface whether the class to be verifier is an interface.
+ */
+ public SimpleVerifier(
+ final Type currentClass, final Type currentSuperClass, final boolean isInterface) {
+ this(currentClass, currentSuperClass, null, isInterface);
+ }
- /**
- * Constructs a new {@link SimpleVerifier} to verify a specific class. This
- * class will not be loaded into the JVM since it may be incorrect.
- *
- * @param currentClass
- * the class that is verified.
- * @param currentSuperClass
- * the super class of the class that is verified.
- * @param currentClassInterfaces
- * the interfaces implemented by the class that is verified.
- * @param isInterface
- * if the class that is verified is an interface.
- */
- public SimpleVerifier(final Type currentClass,
- final Type currentSuperClass,
- final List<Type> currentClassInterfaces, final boolean isInterface) {
- this(ASM6, currentClass, currentSuperClass, currentClassInterfaces,
- isInterface);
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This class will not be
+ * loaded into the JVM since it may be incorrect. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version.
+ *
+ * @param currentClass the type of the class to be verified.
+ * @param currentSuperClass the type of the super class of the class to be verified.
+ * @param currentClassInterfaces the types of the interfaces directly implemented by the class to
+ * be verified.
+ * @param isInterface whether the class to be verifier is an interface.
+ */
+ public SimpleVerifier(
+ final Type currentClass,
+ final Type currentSuperClass,
+ final List<Type> currentClassInterfaces,
+ final boolean isInterface) {
+ this(ASM7, currentClass, currentSuperClass, currentClassInterfaces, isInterface);
+ if (getClass() != SimpleVerifier.class) {
+ throw new IllegalStateException();
}
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This class will not be
+ * loaded into the JVM since it may be incorrect.
+ *
+ * @param api the ASM API version supported by this verifier. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+ * @param currentClass the type of the class to be verified.
+ * @param currentSuperClass the type of the super class of the class to be verified.
+ * @param currentClassInterfaces the types of the interfaces directly implemented by the class to
+ * be verified.
+ * @param isInterface whether the class to be verifier is an interface.
+ */
+ protected SimpleVerifier(
+ final int api,
+ final Type currentClass,
+ final Type currentSuperClass,
+ final List<Type> currentClassInterfaces,
+ final boolean isInterface) {
+ super(api);
+ this.currentClass = currentClass;
+ this.currentSuperClass = currentSuperClass;
+ this.currentClassInterfaces = currentClassInterfaces;
+ this.isInterface = isInterface;
+ }
- protected SimpleVerifier(final int api, final Type currentClass,
- final Type currentSuperClass,
- final List<Type> currentClassInterfaces, final boolean isInterface) {
- super(api);
- this.currentClass = currentClass;
- this.currentSuperClass = currentSuperClass;
- this.currentClassInterfaces = currentClassInterfaces;
- this.isInterface = isInterface;
+ /**
+ * Sets the <code>ClassLoader</code> to be used in {@link #getClass}.
+ *
+ * @param loader the <code>ClassLoader</code> to use.
+ */
+ public void setClassLoader(final ClassLoader loader) {
+ this.loader = loader;
+ }
+
+ @Override
+ public BasicValue newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
}
- /**
- * Set the <code>ClassLoader</code> which will be used to load referenced
- * classes. This is useful if you are verifying multiple interdependent
- * classes.
- *
- * @param loader
- * a <code>ClassLoader</code> to use
- */
- public void setClassLoader(final ClassLoader loader) {
- this.loader = loader;
+ boolean isArray = type.getSort() == Type.ARRAY;
+ if (isArray) {
+ switch (type.getElementType().getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ return new BasicValue(type);
+ default:
+ break;
+ }
}
- @Override
- public BasicValue newValue(final Type type) {
- if (type == null) {
- return BasicValue.UNINITIALIZED_VALUE;
+ BasicValue value = super.newValue(type);
+ if (BasicValue.REFERENCE_VALUE.equals(value)) {
+ if (isArray) {
+ value = newValue(type.getElementType());
+ StringBuilder descriptor = new StringBuilder();
+ for (int i = 0; i < type.getDimensions(); ++i) {
+ descriptor.append('[');
}
+ descriptor.append(value.getType().getDescriptor());
+ value = new BasicValue(Type.getType(descriptor.toString()));
+ } else {
+ value = new BasicValue(type);
+ }
+ }
+ return value;
+ }
- boolean isArray = type.getSort() == Type.ARRAY;
- if (isArray) {
- switch (type.getElementType().getSort()) {
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- return new BasicValue(type);
- }
- }
+ @Override
+ protected boolean isArrayValue(final BasicValue value) {
+ Type type = value.getType();
+ return type != null && (type.getSort() == Type.ARRAY || type.equals(NULL_TYPE));
+ }
- BasicValue v = super.newValue(type);
- if (BasicValue.REFERENCE_VALUE.equals(v)) {
- if (isArray) {
- v = newValue(type.getElementType());
- String desc = v.getType().getDescriptor();
- for (int i = 0; i < type.getDimensions(); ++i) {
- desc = '[' + desc;
- }
- v = new BasicValue(Type.getType(desc));
- } else {
- v = new BasicValue(type);
- }
- }
- return v;
+ @Override
+ protected BasicValue getElementValue(final BasicValue objectArrayValue) throws AnalyzerException {
+ Type arrayType = objectArrayValue.getType();
+ if (arrayType != null) {
+ if (arrayType.getSort() == Type.ARRAY) {
+ return newValue(Type.getType(arrayType.getDescriptor().substring(1)));
+ } else if (arrayType.equals(NULL_TYPE)) {
+ return objectArrayValue;
+ }
}
+ throw new AssertionError();
+ }
- @Override
- protected boolean isArrayValue(final BasicValue value) {
- Type t = value.getType();
- return t != null
- && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+ @Override
+ protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
+ Type expectedType = expected.getType();
+ Type type = value.getType();
+ switch (expectedType.getSort()) {
+ case Type.INT:
+ case Type.FLOAT:
+ case Type.LONG:
+ case Type.DOUBLE:
+ return type.equals(expectedType);
+ case Type.ARRAY:
+ case Type.OBJECT:
+ if (type.equals(NULL_TYPE)) {
+ return true;
+ } else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+ if (isAssignableFrom(expectedType, type)) {
+ return true;
+ } else if (getClass(expectedType).isInterface()) {
+ // The merge of class or interface types can only yield class types (because it is not
+ // possible in general to find an unambiguous common super interface, due to multiple
+ // inheritance). Because of this limitation, we need to relax the subtyping check here
+ // if 'value' is an interface.
+ return Object.class.isAssignableFrom(getClass(type));
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ default:
+ throw new AssertionError();
}
+ }
- @Override
- protected BasicValue getElementValue(final BasicValue objectArrayValue)
- throws AnalyzerException {
- Type arrayType = objectArrayValue.getType();
- if (arrayType != null) {
- if (arrayType.getSort() == Type.ARRAY) {
- return newValue(Type.getType(arrayType.getDescriptor()
- .substring(1)));
- } else if ("Lnull;".equals(arrayType.getDescriptor())) {
- return objectArrayValue;
- }
+ @Override
+ public BasicValue merge(final BasicValue value1, final BasicValue value2) {
+ if (!value1.equals(value2)) {
+ Type type1 = value1.getType();
+ Type type2 = value2.getType();
+ if (type1 != null
+ && (type1.getSort() == Type.OBJECT || type1.getSort() == Type.ARRAY)
+ && type2 != null
+ && (type2.getSort() == Type.OBJECT || type2.getSort() == Type.ARRAY)) {
+ if (type1.equals(NULL_TYPE)) {
+ return value2;
}
- throw new Error("Internal error");
+ if (type2.equals(NULL_TYPE)) {
+ return value1;
+ }
+ if (isAssignableFrom(type1, type2)) {
+ return value1;
+ }
+ if (isAssignableFrom(type2, type1)) {
+ return value2;
+ }
+ int numDimensions = 0;
+ if (type1.getSort() == Type.ARRAY
+ && type2.getSort() == Type.ARRAY
+ && type1.getDimensions() == type2.getDimensions()
+ && type1.getElementType().getSort() == Type.OBJECT
+ && type2.getElementType().getSort() == Type.OBJECT) {
+ numDimensions = type1.getDimensions();
+ type1 = type1.getElementType();
+ type2 = type2.getElementType();
+ }
+ do {
+ if (type1 == null || isInterface(type1)) {
+ return newArrayValue(Type.getObjectType("java/lang/Object"), numDimensions);
+ }
+ type1 = getSuperClass(type1);
+ if (isAssignableFrom(type1, type2)) {
+ return newArrayValue(type1, numDimensions);
+ }
+ } while (true);
+ }
+ return BasicValue.UNINITIALIZED_VALUE;
}
+ return value1;
+ }
- @Override
- protected boolean isSubTypeOf(final BasicValue value,
- final BasicValue expected) {
- Type expectedType = expected.getType();
- Type type = value.getType();
- switch (expectedType.getSort()) {
- case Type.INT:
- case Type.FLOAT:
- case Type.LONG:
- case Type.DOUBLE:
- return type.equals(expectedType);
- case Type.ARRAY:
- case Type.OBJECT:
- if ("Lnull;".equals(type.getDescriptor())) {
- return true;
- } else if (type.getSort() == Type.OBJECT
- || type.getSort() == Type.ARRAY) {
- return isAssignableFrom(expectedType, type);
- } else {
- return false;
- }
- default:
- throw new Error("Internal error");
- }
+ private BasicValue newArrayValue(final Type type, final int dimensions) {
+ if (dimensions == 0) {
+ return newValue(type);
+ } else {
+ StringBuilder descriptor = new StringBuilder();
+ for (int i = 0; i < dimensions; ++i) {
+ descriptor.append('[');
+ }
+ descriptor.append(type.getDescriptor());
+ return newValue(Type.getType(descriptor.toString()));
}
+ }
- @Override
- public BasicValue merge(final BasicValue v, final BasicValue w) {
- if (!v.equals(w)) {
- Type t = v.getType();
- Type u = w.getType();
- if (t != null
- && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) {
- if (u != null
- && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) {
- if ("Lnull;".equals(t.getDescriptor())) {
- return w;
- }
- if ("Lnull;".equals(u.getDescriptor())) {
- return v;
- }
- if (isAssignableFrom(t, u)) {
- return v;
- }
- if (isAssignableFrom(u, t)) {
- return w;
- }
- // TODO case of array classes of the same dimension
- // TODO should we look also for a common super interface?
- // problem: there may be several possible common super
- // interfaces
- do {
- if (t == null || isInterface(t)) {
- return BasicValue.REFERENCE_VALUE;
- }
- t = getSuperClass(t);
- if (isAssignableFrom(t, u)) {
- return newValue(t);
- }
- } while (true);
- }
- }
- return BasicValue.UNINITIALIZED_VALUE;
- }
- return v;
+ /**
+ * Returns whether the given type corresponds to the type of an interface. The default
+ * implementation of this method loads the class and uses the reflection API to return its result
+ * (unless the given type corresponds to the class being verified).
+ *
+ * @param type a type.
+ * @return whether 'type' corresponds to an interface.
+ */
+ protected boolean isInterface(final Type type) {
+ if (currentClass != null && currentClass.equals(type)) {
+ return isInterface;
}
+ return getClass(type).isInterface();
+ }
- protected boolean isInterface(final Type t) {
- if (currentClass != null && t.equals(currentClass)) {
- return isInterface;
- }
- return getClass(t).isInterface();
+ /**
+ * Returns the type corresponding to the super class of the given type. The default implementation
+ * of this method loads the class and uses the reflection API to return its result (unless the
+ * given type corresponds to the class being verified).
+ *
+ * @param type a type.
+ * @return the type corresponding to the super class of 'type'.
+ */
+ protected Type getSuperClass(final Type type) {
+ if (currentClass != null && currentClass.equals(type)) {
+ return currentSuperClass;
}
+ Class<?> superClass = getClass(type).getSuperclass();
+ return superClass == null ? null : Type.getType(superClass);
+ }
- protected Type getSuperClass(final Type t) {
- if (currentClass != null && t.equals(currentClass)) {
- return currentSuperClass;
+ /**
+ * Returns whether the class corresponding to the first argument is either the same as, or is a
+ * superclass or superinterface of the class corresponding to the second argument. The default
+ * implementation of this method loads the classes and uses the reflection API to return its
+ * result (unless the result can be computed from the class being verified, and the types of its
+ * super classes and implemented interfaces).
+ *
+ * @param type1 a type.
+ * @param type2 another type.
+ * @return whether the class corresponding to 'type1' is either the same as, or is a superclass or
+ * superinterface of the class corresponding to 'type2'.
+ */
+ protected boolean isAssignableFrom(final Type type1, final Type type2) {
+ if (type1.equals(type2)) {
+ return true;
+ }
+ if (currentClass != null && currentClass.equals(type1)) {
+ if (getSuperClass(type2) == null) {
+ return false;
+ } else {
+ if (isInterface) {
+ return type2.getSort() == Type.OBJECT || type2.getSort() == Type.ARRAY;
}
- Class<?> c = getClass(t).getSuperclass();
- return c == null ? null : Type.getType(c);
+ return isAssignableFrom(type1, getSuperClass(type2));
+ }
}
-
- protected boolean isAssignableFrom(final Type t, final Type u) {
- if (t.equals(u)) {
+ if (currentClass != null && currentClass.equals(type2)) {
+ if (isAssignableFrom(type1, currentSuperClass)) {
+ return true;
+ }
+ if (currentClassInterfaces != null) {
+ for (Type currentClassInterface : currentClassInterfaces) {
+ if (isAssignableFrom(type1, currentClassInterface)) {
return true;
+ }
}
- if (currentClass != null && t.equals(currentClass)) {
- if (getSuperClass(u) == null) {
- return false;
- } else {
- if (isInterface) {
- return u.getSort() == Type.OBJECT
- || u.getSort() == Type.ARRAY;
- }
- return isAssignableFrom(t, getSuperClass(u));
- }
- }
- if (currentClass != null && u.equals(currentClass)) {
- if (isAssignableFrom(t, currentSuperClass)) {
- return true;
- }
- if (currentClassInterfaces != null) {
- for (int i = 0; i < currentClassInterfaces.size(); ++i) {
- Type v = currentClassInterfaces.get(i);
- if (isAssignableFrom(t, v)) {
- return true;
- }
- }
- }
- return false;
- }
- Class<?> tc = getClass(t);
- if (tc.isInterface()) {
- tc = Object.class;
- }
- return tc.isAssignableFrom(getClass(u));
+ }
+ return false;
}
+ return getClass(type1).isAssignableFrom(getClass(type2));
+ }
- protected Class<?> getClass(final Type t) {
- try {
- if (t.getSort() == Type.ARRAY) {
- return Class.forName(t.getDescriptor().replace('/', '.'),
- false, loader);
- }
- return Class.forName(t.getClassName(), false, loader);
- } catch (ClassNotFoundException e) {
- throw new RuntimeException(e.toString());
- }
+ /**
+ * Loads the class corresponding to the given type. The class is loaded with the class loader
+ * specified with {@link #setClassLoader}, or with the class loader of this class if no class
+ * loader was specified.
+ *
+ * @param type a type.
+ * @return the class corresponding to 'type'.
+ */
+ protected Class<?> getClass(final Type type) {
+ try {
+ if (type.getSort() == Type.ARRAY) {
+ return Class.forName(type.getDescriptor().replace('/', '.'), false, loader);
+ }
+ return Class.forName(type.getClassName(), false, loader);
+ } catch (ClassNotFoundException e) {
+ throw new TypeNotPresentException(e.toString(), e);
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
old mode 100644
new mode 100755
index 2aacb42..45df958
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.AbstractSet;
@@ -36,99 +34,159 @@ import java.util.NoSuchElementException;
import java.util.Set;
/**
- * A set of at most two elements.
- *
+ * An immutable set of at most two elements, optimized for speed compared to a generic set
+ * implementation.
+ *
* @author Eric Bruneton
*/
-class SmallSet<E> extends AbstractSet<E> implements Iterator<E> {
+final class SmallSet<T> extends AbstractSet<T> {
- // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+ /** The first element of this set, maybe {@literal null}. */
+ private final T element1;
- E e1, e2;
+ /**
+ * The second element of this set, maybe {@literal null}. If {@link #element1} is {@literal null}
+ * then this field must be {@literal null}, otherwise it must be different from {@link #element1}.
+ */
+ private final T element2;
- static final <T> Set<T> emptySet() {
- return new SmallSet<T>(null, null);
- }
+ // -----------------------------------------------------------------------------------------------
+ // Constructors
+ // -----------------------------------------------------------------------------------------------
- SmallSet(final E e1, final E e2) {
- this.e1 = e1;
- this.e2 = e2;
- }
+ /** Constructs an empty set. */
+ SmallSet() {
+ this.element1 = null;
+ this.element2 = null;
+ }
- // -------------------------------------------------------------------------
- // Implementation of inherited abstract methods
- // -------------------------------------------------------------------------
+ /**
+ * Constructs a set with exactly one element.
+ *
+ * @param element the unique set element.
+ */
+ SmallSet(final T element) {
+ this.element1 = element;
+ this.element2 = null;
+ }
- @Override
- public Iterator<E> iterator() {
- return new SmallSet<E>(e1, e2);
+ /**
+ * Constructs a new {@link SmallSet}.
+ *
+ * @param element1 see {@link #element1}.
+ * @param element2 see {@link #element2}.
+ */
+ private SmallSet(final T element1, final T element2) {
+ this.element1 = element1;
+ this.element2 = element2;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the inherited abstract methods
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public Iterator<T> iterator() {
+ return new IteratorImpl<T>(element1, element2);
+ }
+
+ @Override
+ public int size() {
+ return element1 == null ? 0 : (element2 == null ? 1 : 2);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the union of this set and of the given set.
+ *
+ * @param otherSet another small set.
+ * @return the union of this set and of otherSet.
+ */
+ Set<T> union(final SmallSet<T> otherSet) {
+ // If the two sets are equal, return this set.
+ if ((otherSet.element1 == element1 && otherSet.element2 == element2)
+ || (otherSet.element1 == element2 && otherSet.element2 == element1)) {
+ return this;
+ }
+ // If one set is empty, return the other.
+ if (otherSet.element1 == null) {
+ return this;
+ }
+ if (element1 == null) {
+ return otherSet;
}
- @Override
- public int size() {
- return e1 == null ? 0 : (e2 == null ? 1 : 2);
+ // At this point we know that the two sets are non empty and are different.
+ // If otherSet contains exactly one element:
+ if (otherSet.element2 == null) {
+ // If this set also contains exactly one element, we have two distinct elements.
+ if (element2 == null) {
+ return new SmallSet<T>(element1, otherSet.element1);
+ }
+ // If otherSet is included in this set, return this set.
+ if (otherSet.element1 == element1 || otherSet.element1 == element2) {
+ return this;
+ }
+ }
+ // If this set contains exactly one element, then otherSet contains two elements (because of the
+ // above tests). Thus, if otherSet contains this set, return otherSet:
+ if (element2 == null && (element1 == otherSet.element1 || element1 == otherSet.element2)) {
+ return otherSet;
}
- // -------------------------------------------------------------------------
- // Implementation of the Iterator interface
- // -------------------------------------------------------------------------
+ // At this point we know that there are at least 3 distinct elements, so we need a generic set
+ // to store the result.
+ HashSet<T> result = new HashSet<T>(4);
+ result.add(element1);
+ if (element2 != null) {
+ result.add(element2);
+ }
+ result.add(otherSet.element1);
+ if (otherSet.element2 != null) {
+ result.add(otherSet.element2);
+ }
+ return result;
+ }
- public boolean hasNext() {
- return e1 != null;
+ static class IteratorImpl<T> implements Iterator<T> {
+
+ /** The next element to return in {@link #next}. Maybe {@literal null}. */
+ private T firstElement;
+
+ /**
+ * The element to return in {@link #next}, after {@link #firstElement} is returned. If {@link
+ * #firstElement} is {@literal null} then this field must be {@literal null}, otherwise it must
+ * be different from {@link #firstElement}.
+ */
+ private T secondElement;
+
+ IteratorImpl(final T firstElement, final T secondElement) {
+ this.firstElement = firstElement;
+ this.secondElement = secondElement;
}
- public E next() {
- if (e1 == null) {
- throw new NoSuchElementException();
- }
- E e = e1;
- e1 = e2;
- e2 = null;
- return e;
+ @Override
+ public boolean hasNext() {
+ return firstElement != null;
}
- public void remove() {
+ @Override
+ public T next() {
+ if (firstElement == null) {
+ throw new NoSuchElementException();
+ }
+ T element = firstElement;
+ firstElement = secondElement;
+ secondElement = null;
+ return element;
}
- // -------------------------------------------------------------------------
- // Utility methods
- // -------------------------------------------------------------------------
-
- Set<E> union(final SmallSet<E> s) {
- if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) {
- return this; // if the two sets are equal, return this
- }
- if (s.e1 == null) {
- return this; // if s is empty, return this
- }
- if (e1 == null) {
- return s; // if this is empty, return s
- }
- if (s.e2 == null) { // s contains exactly one element
- if (e2 == null) {
- return new SmallSet<E>(e1, s.e1); // necessarily e1 != s.e1
- } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this
- return this;
- }
- }
- if (e2 == null) { // this contains exactly one element
- // if (s.e2 == null) { // cannot happen
- // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1
- // } else
- if (e1 == s.e1 || e1 == s.e2) { // this in included in s
- return s;
- }
- }
- // here we know that there are at least 3 distinct elements
- HashSet<E> r = new HashSet<E>(4);
- r.add(e1);
- if (e2 != null) {
- r.add(e2);
- }
- r.add(s.e1);
- if (s.e2 != null) {
- r.add(s.e2);
- }
- return r;
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
old mode 100644
new mode 100755
index 7a257e7..a84b44a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
@@ -1,38 +1,35 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
@@ -43,156 +40,182 @@ import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
/**
* An {@link Interpreter} for {@link SourceValue} values.
- *
+ *
* @author Eric Bruneton
*/
-public class SourceInterpreter extends Interpreter<SourceValue> implements
- Opcodes {
+public class SourceInterpreter extends Interpreter<SourceValue> implements Opcodes {
- public SourceInterpreter() {
- super(ASM6);
+ /**
+ * Constructs a new {@link SourceInterpreter} for the latest ASM API version. <i>Subclasses must
+ * not use this constructor</i>. Instead, they must use the {@link #SourceInterpreter(int)}
+ * version.
+ */
+ public SourceInterpreter() {
+ super(ASM7);
+ if (getClass() != SourceInterpreter.class) {
+ throw new IllegalStateException();
}
+ }
- protected SourceInterpreter(final int api) {
- super(api);
- }
+ /**
+ * Constructs a new {@link SourceInterpreter}.
+ *
+ * @param api the ASM API version supported by this interpreter. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+ */
+ protected SourceInterpreter(final int api) {
+ super(api);
+ }
- @Override
- public SourceValue newValue(final Type type) {
- if (type == Type.VOID_TYPE) {
- return null;
- }
- return new SourceValue(type == null ? 1 : type.getSize());
+ @Override
+ public SourceValue newValue(final Type type) {
+ if (type == Type.VOID_TYPE) {
+ return null;
}
+ return new SourceValue(type == null ? 1 : type.getSize());
+ }
- @Override
- public SourceValue newOperation(final AbstractInsnNode insn) {
- int size;
- switch (insn.getOpcode()) {
- case LCONST_0:
- case LCONST_1:
- case DCONST_0:
- case DCONST_1:
- size = 2;
- break;
- case LDC:
- Object cst = ((LdcInsnNode) insn).cst;
- size = cst instanceof Long || cst instanceof Double ? 2 : 1;
- break;
- case GETSTATIC:
- size = Type.getType(((FieldInsnNode) insn).desc).getSize();
- break;
- default:
- size = 1;
- }
- return new SourceValue(size, insn);
+ @Override
+ public SourceValue newOperation(final AbstractInsnNode insn) {
+ int size;
+ switch (insn.getOpcode()) {
+ case LCONST_0:
+ case LCONST_1:
+ case DCONST_0:
+ case DCONST_1:
+ size = 2;
+ break;
+ case LDC:
+ Object value = ((LdcInsnNode) insn).cst;
+ size = value instanceof Long || value instanceof Double ? 2 : 1;
+ break;
+ case GETSTATIC:
+ size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+ break;
+ default:
+ size = 1;
+ break;
}
+ return new SourceValue(size, insn);
+ }
- @Override
- public SourceValue copyOperation(final AbstractInsnNode insn,
- final SourceValue value) {
- return new SourceValue(value.getSize(), insn);
- }
+ @Override
+ public SourceValue copyOperation(final AbstractInsnNode insn, final SourceValue value) {
+ return new SourceValue(value.getSize(), insn);
+ }
- @Override
- public SourceValue unaryOperation(final AbstractInsnNode insn,
- final SourceValue value) {
- int size;
- switch (insn.getOpcode()) {
- case LNEG:
- case DNEG:
- case I2L:
- case I2D:
- case L2D:
- case F2L:
- case F2D:
- case D2L:
- size = 2;
- break;
- case GETFIELD:
- size = Type.getType(((FieldInsnNode) insn).desc).getSize();
- break;
- default:
- size = 1;
- }
- return new SourceValue(size, insn);
+ @Override
+ public SourceValue unaryOperation(final AbstractInsnNode insn, final SourceValue value) {
+ int size;
+ switch (insn.getOpcode()) {
+ case LNEG:
+ case DNEG:
+ case I2L:
+ case I2D:
+ case L2D:
+ case F2L:
+ case F2D:
+ case D2L:
+ size = 2;
+ break;
+ case GETFIELD:
+ size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+ break;
+ default:
+ size = 1;
+ break;
}
+ return new SourceValue(size, insn);
+ }
- @Override
- public SourceValue binaryOperation(final AbstractInsnNode insn,
- final SourceValue value1, final SourceValue value2) {
- int size;
- switch (insn.getOpcode()) {
- case LALOAD:
- case DALOAD:
- case LADD:
- case DADD:
- case LSUB:
- case DSUB:
- case LMUL:
- case DMUL:
- case LDIV:
- case DDIV:
- case LREM:
- case DREM:
- case LSHL:
- case LSHR:
- case LUSHR:
- case LAND:
- case LOR:
- case LXOR:
- size = 2;
- break;
- default:
- size = 1;
- }
- return new SourceValue(size, insn);
+ @Override
+ public SourceValue binaryOperation(
+ final AbstractInsnNode insn, final SourceValue value1, final SourceValue value2) {
+ int size;
+ switch (insn.getOpcode()) {
+ case LALOAD:
+ case DALOAD:
+ case LADD:
+ case DADD:
+ case LSUB:
+ case DSUB:
+ case LMUL:
+ case DMUL:
+ case LDIV:
+ case DDIV:
+ case LREM:
+ case DREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ size = 2;
+ break;
+ default:
+ size = 1;
+ break;
}
+ return new SourceValue(size, insn);
+ }
- @Override
- public SourceValue ternaryOperation(final AbstractInsnNode insn,
- final SourceValue value1, final SourceValue value2,
- final SourceValue value3) {
- return new SourceValue(1, insn);
- }
+ @Override
+ public SourceValue ternaryOperation(
+ final AbstractInsnNode insn,
+ final SourceValue value1,
+ final SourceValue value2,
+ final SourceValue value3) {
+ return new SourceValue(1, insn);
+ }
- @Override
- public SourceValue naryOperation(final AbstractInsnNode insn,
- final List<? extends SourceValue> values) {
- int size;
- int opcode = insn.getOpcode();
- if (opcode == MULTIANEWARRAY) {
- size = 1;
- } else {
- String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
- : ((MethodInsnNode) insn).desc;
- size = Type.getReturnType(desc).getSize();
- }
- return new SourceValue(size, insn);
+ @Override
+ public SourceValue naryOperation(
+ final AbstractInsnNode insn, final List<? extends SourceValue> values) {
+ int size;
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ size = 1;
+ } else if (opcode == INVOKEDYNAMIC) {
+ size = Type.getReturnType(((InvokeDynamicInsnNode) insn).desc).getSize();
+ } else {
+ size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
}
+ return new SourceValue(size, insn);
+ }
- @Override
- public void returnOperation(final AbstractInsnNode insn,
- final SourceValue value, final SourceValue expected) {
+ @Override
+ public void returnOperation(
+ final AbstractInsnNode insn, final SourceValue value, final SourceValue expected) {
+ // Nothing to do.
+ }
+
+ @Override
+ public SourceValue merge(final SourceValue value1, final SourceValue value2) {
+ if (value1.insns instanceof SmallSet && value2.insns instanceof SmallSet) {
+ Set<AbstractInsnNode> setUnion =
+ ((SmallSet<AbstractInsnNode>) value1.insns)
+ .union((SmallSet<AbstractInsnNode>) value2.insns);
+ if (setUnion == value1.insns && value1.size == value2.size) {
+ return value1;
+ } else {
+ return new SourceValue(Math.min(value1.size, value2.size), setUnion);
+ }
+ }
+ if (value1.size != value2.size || !containsAll(value1.insns, value2.insns)) {
+ HashSet<AbstractInsnNode> setUnion = new HashSet<AbstractInsnNode>();
+ setUnion.addAll(value1.insns);
+ setUnion.addAll(value2.insns);
+ return new SourceValue(Math.min(value1.size, value2.size), setUnion);
}
+ return value1;
+ }
- @Override
- public SourceValue merge(final SourceValue d, final SourceValue w) {
- if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) {
- Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns)
- .union((SmallSet<AbstractInsnNode>) w.insns);
- if (s == d.insns && d.size == w.size) {
- return d;
- } else {
- return new SourceValue(Math.min(d.size, w.size), s);
- }
- }
- if (d.size != w.size || !d.insns.containsAll(w.insns)) {
- HashSet<AbstractInsnNode> s = new HashSet<AbstractInsnNode>();
- s.addAll(d.insns);
- s.addAll(w.insns);
- return new SourceValue(Math.min(d.size, w.size), s);
- }
- return d;
+ private static <E> boolean containsAll(final Set<E> self, final Set<E> other) {
+ if (self.size() < other.size()) {
+ return false;
}
+ return self.containsAll(other);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
old mode 100644
new mode 100755
index 0cb2f50..3b68854
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
@@ -1,97 +1,119 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.Set;
-
import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
/**
- * A {@link Value} that is represented by its type in a two types type system.
- * This type system distinguishes the ONEWORD and TWOWORDS types.
- *
+ * A {@link Value} which keeps track of the bytecode instructions that can produce it.
+ *
* @author Eric Bruneton
*/
public class SourceValue implements Value {
- /**
- * The size of this value.
- */
- public final int size;
+ /**
+ * The size of this value, in 32 bits words. This size is 1 for byte, boolean, char, short, int,
+ * float, object and array types, and 2 for long and double.
+ */
+ public final int size;
- /**
- * The instructions that can produce this value. For example, for the Java
- * code below, the instructions that can produce the value of <tt>i</tt> at
- * line 5 are the txo ISTORE instructions at line 1 and 3:
- *
- * <pre>
- * 1: i = 0;
- * 2: if (...) {
- * 3: i = 1;
- * 4: }
- * 5: return i;
- * </pre>
- *
- * This field is a set of {@link AbstractInsnNode} objects.
- */
- public final Set<AbstractInsnNode> insns;
+ /**
+ * The instructions that can produce this value. For example, for the Java code below, the
+ * instructions that can produce the value of {@code i} at line 5 are the two ISTORE instructions
+ * at line 1 and 3:
+ *
+ * <pre>
+ * 1: i = 0;
+ * 2: if (...) {
+ * 3: i = 1;
+ * 4: }
+ * 5: return i;
+ * </pre>
+ */
+ public final Set<AbstractInsnNode> insns;
- public SourceValue(final int size) {
- this(size, SmallSet.<AbstractInsnNode> emptySet());
- }
+ /**
+ * Constructs a new {@link SourceValue}.
+ *
+ * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char,
+ * short, int, float, object and array types, and 2 for long and double.
+ */
+ public SourceValue(final int size) {
+ this(size, new SmallSet<AbstractInsnNode>());
+ }
- public SourceValue(final int size, final AbstractInsnNode insn) {
- this.size = size;
- this.insns = new SmallSet<AbstractInsnNode>(insn, null);
- }
+ /**
+ * Constructs a new {@link SourceValue}.
+ *
+ * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char,
+ * short, int, float, object and array types, and 2 for long and double.
+ * @param insnNode an instruction that can produce this value.
+ */
+ public SourceValue(final int size, final AbstractInsnNode insnNode) {
+ this.size = size;
+ this.insns = new SmallSet<AbstractInsnNode>(insnNode);
+ }
- public SourceValue(final int size, final Set<AbstractInsnNode> insns) {
- this.size = size;
- this.insns = insns;
- }
+ /**
+ * Constructs a new {@link SourceValue}.
+ *
+ * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char,
+ * short, int, float, object and array types, and 2 for long and double.
+ * @param insnSet the instructions that can produce this value.
+ */
+ public SourceValue(final int size, final Set<AbstractInsnNode> insnSet) {
+ this.size = size;
+ this.insns = insnSet;
+ }
- public int getSize() {
- return size;
- }
+ /**
+ * Returns the size of this value.
+ *
+ * @return the size of this value, in 32 bits words. This size is 1 for byte, boolean, char,
+ * short, int, float, object and array types, and 2 for long and double.
+ */
+ @Override
+ public int getSize() {
+ return size;
+ }
- @Override
- public boolean equals(final Object value) {
- if (!(value instanceof SourceValue)) {
- return false;
- }
- SourceValue v = (SourceValue) value;
- return size == v.size && insns.equals(v.insns);
+ @Override
+ public boolean equals(final Object value) {
+ if (!(value instanceof SourceValue)) {
+ return false;
}
+ SourceValue sourceValue = (SourceValue) value;
+ return size == sourceValue.size && insns.equals(sourceValue.insns);
+ }
- @Override
- public int hashCode() {
- return insns.hashCode();
- }
+ @Override
+ public int hashCode() {
+ return insns.hashCode();
+ }
}
[09/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
old mode 100644
new mode 100755
index 931a73d..e355c78
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
@@ -1,46 +1,43 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
@@ -50,1503 +47,1420 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
import org.apache.tapestry5.internal.plastic.asm.TypeReference;
import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.AnalyzerException;
import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier;
/**
- * A {@link MethodVisitor} that checks that its methods are properly used. More
- * precisely this method adapter checks each instruction individually, i.e.,
- * each visit method checks some preconditions based <i>only</i> on its
- * arguments - such as the fact that the given opcode is correct for a given
- * visit method. This adapter can also perform some basic data flow checks (more
- * precisely those that can be performed without the full class hierarchy - see
- * {@link org.objectweb.asm.tree.analysis.BasicVerifier}). For instance in a
- * method whose signature is <tt>void m ()</tt>, the invalid instruction
- * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow
- * checks are enabled. These checks are enabled by using the
- * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor.
- * They are not performed if any other constructor is used.
- *
+ * A {@link MethodVisitor} that checks that its methods are properly used. More precisely this
+ * method adapter checks each instruction individually, i.e., each visit method checks some
+ * preconditions based <i>only</i> on its arguments - such as the fact that the given opcode is
+ * correct for a given visit method. This adapter can also perform some basic data flow checks (more
+ * precisely those that can be performed without the full class hierarchy - see {@link
+ * org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier}). For instance in a method whose signature is
+ * {@code void m ()}, the invalid instruction IRETURN, or the invalid sequence IADD L2I will be
+ * detected if the data flow checks are enabled. These checks are enabled by using the {@link
+ * #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor. They are not performed if
+ * any other constructor is used.
+ *
* @author Eric Bruneton
*/
public class CheckMethodAdapter extends MethodVisitor {
- /**
- * The class version number.
- */
- public int version;
-
- /**
- * The access flags of the method.
- */
- private int access;
-
- /**
- * <tt>true</tt> if the visitCode method has been called.
- */
- private boolean startCode;
-
- /**
- * <tt>true</tt> if the visitMaxs method has been called.
- */
- private boolean endCode;
-
- /**
- * <tt>true</tt> if the visitEnd method has been called.
- */
- private boolean endMethod;
-
- /**
- * Number of visited instructions.
- */
- private int insnCount;
-
- /**
- * The already visited labels. This map associate Integer values to pseudo
- * code offsets.
- */
- private final Map<Label, Integer> labels;
-
- /**
- * The labels used in this method. Every used label must be visited with
- * visitLabel before the end of the method (i.e. should be in #labels).
- */
- private Set<Label> usedLabels;
-
- /**
- * Number of visited frames in expanded form.
- */
- private int expandedFrames;
-
- /**
- * Number of visited frames in compressed form.
- */
- private int compressedFrames;
-
- /**
- * Number of instructions before the last visited frame.
- */
- private int lastFrame = -1;
-
- /**
- * The exception handler ranges. Each pair of list element contains the
- * start and end labels of an exception handler block.
- */
- private List<Label> handlers;
-
- /**
- * Code of the visit method to be used for each opcode.
- */
- private static final int[] TYPE;
-
- /**
- * The Label.status field.
- */
- private static Field labelStatusField;
-
- static {
- String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
- + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
- + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
- TYPE = new int[s.length()];
- for (int i = 0; i < TYPE.length; ++i) {
- TYPE[i] = s.charAt(i) - 'A' - 1;
- }
+ /** The 'generic' instruction visit methods (i.e. those that take an opcode argument). */
+ private enum Method {
+ VISIT_INSN,
+ VISIT_INT_INSN,
+ VISIT_VAR_INSN,
+ VISIT_TYPE_INSN,
+ VISIT_FIELD_INSN,
+ VISIT_METHOD_INSN,
+ VISIT_JUMP_INSN
+ }
+
+ /** The method to use to visit each instruction. Only generic methods are represented here. */
+ private static final Method[] OPCODE_METHODS = {
+ Method.VISIT_INSN, // NOP
+ Method.VISIT_INSN, // ACONST_NULL
+ Method.VISIT_INSN, // ICONST_M1
+ Method.VISIT_INSN, // ICONST_0
+ Method.VISIT_INSN, // ICONST_1
+ Method.VISIT_INSN, // ICONST_2
+ Method.VISIT_INSN, // ICONST_3
+ Method.VISIT_INSN, // ICONST_4
+ Method.VISIT_INSN, // ICONST_5
+ Method.VISIT_INSN, // LCONST_0
+ Method.VISIT_INSN, // LCONST_1
+ Method.VISIT_INSN, // FCONST_0
+ Method.VISIT_INSN, // FCONST_1
+ Method.VISIT_INSN, // FCONST_2
+ Method.VISIT_INSN, // DCONST_0
+ Method.VISIT_INSN, // DCONST_1
+ Method.VISIT_INT_INSN, // BIPUSH
+ Method.VISIT_INT_INSN, // SIPUSH
+ null, // LDC
+ null, // LDC_W
+ null, // LDC2_W
+ Method.VISIT_VAR_INSN, // ILOAD
+ Method.VISIT_VAR_INSN, // LLOAD
+ Method.VISIT_VAR_INSN, // FLOAD
+ Method.VISIT_VAR_INSN, // DLOAD
+ Method.VISIT_VAR_INSN, // ALOAD
+ null, // ILOAD_0
+ null, // ILOAD_1
+ null, // ILOAD_2
+ null, // ILOAD_3
+ null, // LLOAD_0
+ null, // LLOAD_1
+ null, // LLOAD_2
+ null, // LLOAD_3
+ null, // FLOAD_0
+ null, // FLOAD_1
+ null, // FLOAD_2
+ null, // FLOAD_3
+ null, // DLOAD_0
+ null, // DLOAD_1
+ null, // DLOAD_2
+ null, // DLOAD_3
+ null, // ALOAD_0
+ null, // ALOAD_1
+ null, // ALOAD_2
+ null, // ALOAD_3
+ Method.VISIT_INSN, // IALOAD
+ Method.VISIT_INSN, // LALOAD
+ Method.VISIT_INSN, // FALOAD
+ Method.VISIT_INSN, // DALOAD
+ Method.VISIT_INSN, // AALOAD
+ Method.VISIT_INSN, // BALOAD
+ Method.VISIT_INSN, // CALOAD
+ Method.VISIT_INSN, // SALOAD
+ Method.VISIT_VAR_INSN, // ISTORE
+ Method.VISIT_VAR_INSN, // LSTORE
+ Method.VISIT_VAR_INSN, // FSTORE
+ Method.VISIT_VAR_INSN, // DSTORE
+ Method.VISIT_VAR_INSN, // ASTORE
+ null, // ISTORE_0
+ null, // ISTORE_1
+ null, // ISTORE_2
+ null, // ISTORE_3
+ null, // LSTORE_0
+ null, // LSTORE_1
+ null, // LSTORE_2
+ null, // LSTORE_3
+ null, // FSTORE_0
+ null, // FSTORE_1
+ null, // FSTORE_2
+ null, // FSTORE_3
+ null, // DSTORE_0
+ null, // DSTORE_1
+ null, // DSTORE_2
+ null, // DSTORE_3
+ null, // ASTORE_0
+ null, // ASTORE_1
+ null, // ASTORE_2
+ null, // ASTORE_3
+ Method.VISIT_INSN, // IASTORE
+ Method.VISIT_INSN, // LASTORE
+ Method.VISIT_INSN, // FASTORE
+ Method.VISIT_INSN, // DASTORE
+ Method.VISIT_INSN, // AASTORE
+ Method.VISIT_INSN, // BASTORE
+ Method.VISIT_INSN, // CASTORE
+ Method.VISIT_INSN, // SASTORE
+ Method.VISIT_INSN, // POP
+ Method.VISIT_INSN, // POP2
+ Method.VISIT_INSN, // DUP
+ Method.VISIT_INSN, // DUP_X1
+ Method.VISIT_INSN, // DUP_X2
+ Method.VISIT_INSN, // DUP2
+ Method.VISIT_INSN, // DUP2_X1
+ Method.VISIT_INSN, // DUP2_X2
+ Method.VISIT_INSN, // SWAP
+ Method.VISIT_INSN, // IADD
+ Method.VISIT_INSN, // LADD
+ Method.VISIT_INSN, // FADD
+ Method.VISIT_INSN, // DADD
+ Method.VISIT_INSN, // ISUB
+ Method.VISIT_INSN, // LSUB
+ Method.VISIT_INSN, // FSUB
+ Method.VISIT_INSN, // DSUB
+ Method.VISIT_INSN, // IMUL
+ Method.VISIT_INSN, // LMUL
+ Method.VISIT_INSN, // FMUL
+ Method.VISIT_INSN, // DMUL
+ Method.VISIT_INSN, // IDIV
+ Method.VISIT_INSN, // LDIV
+ Method.VISIT_INSN, // FDIV
+ Method.VISIT_INSN, // DDIV
+ Method.VISIT_INSN, // IREM
+ Method.VISIT_INSN, // LREM
+ Method.VISIT_INSN, // FREM
+ Method.VISIT_INSN, // DREM
+ Method.VISIT_INSN, // INEG
+ Method.VISIT_INSN, // LNEG
+ Method.VISIT_INSN, // FNEG
+ Method.VISIT_INSN, // DNEG
+ Method.VISIT_INSN, // ISHL
+ Method.VISIT_INSN, // LSHL
+ Method.VISIT_INSN, // ISHR
+ Method.VISIT_INSN, // LSHR
+ Method.VISIT_INSN, // IUSHR
+ Method.VISIT_INSN, // LUSHR
+ Method.VISIT_INSN, // IAND
+ Method.VISIT_INSN, // LAND
+ Method.VISIT_INSN, // IOR
+ Method.VISIT_INSN, // LOR
+ Method.VISIT_INSN, // IXOR
+ Method.VISIT_INSN, // LXOR
+ null, // IINC
+ Method.VISIT_INSN, // I2L
+ Method.VISIT_INSN, // I2F
+ Method.VISIT_INSN, // I2D
+ Method.VISIT_INSN, // L2I
+ Method.VISIT_INSN, // L2F
+ Method.VISIT_INSN, // L2D
+ Method.VISIT_INSN, // F2I
+ Method.VISIT_INSN, // F2L
+ Method.VISIT_INSN, // F2D
+ Method.VISIT_INSN, // D2I
+ Method.VISIT_INSN, // D2L
+ Method.VISIT_INSN, // D2F
+ Method.VISIT_INSN, // I2B
+ Method.VISIT_INSN, // I2C
+ Method.VISIT_INSN, // I2S
+ Method.VISIT_INSN, // LCMP
+ Method.VISIT_INSN, // FCMPL
+ Method.VISIT_INSN, // FCMPG
+ Method.VISIT_INSN, // DCMPL
+ Method.VISIT_INSN, // DCMPG
+ Method.VISIT_JUMP_INSN, // IFEQ
+ Method.VISIT_JUMP_INSN, // IFNE
+ Method.VISIT_JUMP_INSN, // IFLT
+ Method.VISIT_JUMP_INSN, // IFGE
+ Method.VISIT_JUMP_INSN, // IFGT
+ Method.VISIT_JUMP_INSN, // IFLE
+ Method.VISIT_JUMP_INSN, // IF_ICMPEQ
+ Method.VISIT_JUMP_INSN, // IF_ICMPNE
+ Method.VISIT_JUMP_INSN, // IF_ICMPLT
+ Method.VISIT_JUMP_INSN, // IF_ICMPGE
+ Method.VISIT_JUMP_INSN, // IF_ICMPGT
+ Method.VISIT_JUMP_INSN, // IF_ICMPLE
+ Method.VISIT_JUMP_INSN, // IF_ACMPEQ
+ Method.VISIT_JUMP_INSN, // IF_ACMPNE
+ Method.VISIT_JUMP_INSN, // GOTO
+ Method.VISIT_JUMP_INSN, // JSR
+ Method.VISIT_VAR_INSN, // RET
+ null, // TABLESWITCH
+ null, // LOOKUPSWITCH
+ Method.VISIT_INSN, // IRETURN
+ Method.VISIT_INSN, // LRETURN
+ Method.VISIT_INSN, // FRETURN
+ Method.VISIT_INSN, // DRETURN
+ Method.VISIT_INSN, // ARETURN
+ Method.VISIT_INSN, // RETURN
+ Method.VISIT_FIELD_INSN, // GETSTATIC
+ Method.VISIT_FIELD_INSN, // PUTSTATIC
+ Method.VISIT_FIELD_INSN, // GETFIELD
+ Method.VISIT_FIELD_INSN, // PUTFIELD
+ Method.VISIT_METHOD_INSN, // INVOKEVIRTUAL
+ Method.VISIT_METHOD_INSN, // INVOKESPECIAL
+ Method.VISIT_METHOD_INSN, // INVOKESTATIC
+ Method.VISIT_METHOD_INSN, // INVOKEINTERFACE
+ null, // INVOKEDYNAMIC
+ Method.VISIT_TYPE_INSN, // NEW
+ Method.VISIT_INT_INSN, // NEWARRAY
+ Method.VISIT_TYPE_INSN, // ANEWARRAY
+ Method.VISIT_INSN, // ARRAYLENGTH
+ Method.VISIT_INSN, // ATHROW
+ Method.VISIT_TYPE_INSN, // CHECKCAST
+ Method.VISIT_TYPE_INSN, // INSTANCEOF
+ Method.VISIT_INSN, // MONITORENTER
+ Method.VISIT_INSN, // MONITOREXIT
+ null, // WIDE
+ null, // MULTIANEWARRAY
+ Method.VISIT_JUMP_INSN, // IFNULL
+ Method.VISIT_JUMP_INSN // IFNONNULL
+ };
+
+ private static final String INVALID = "Invalid ";
+ private static final String INVALID_DESCRIPTOR = "Invalid descriptor: ";
+ private static final String INVALID_TYPE_REFERENCE = "Invalid type reference sort 0x";
+ private static final String INVALID_LOCAL_VARIABLE_INDEX = "Invalid local variable index";
+ private static final String MUST_NOT_BE_NULL_OR_EMPTY = " (must not be null or empty)";
+ private static final String START_LABEL = "start label";
+ private static final String END_LABEL = "end label";
+
+ /** The class version number. */
+ public int version;
+
+ /** The access flags of the visited method. */
+ private int access;
+
+ /**
+ * The number of method parameters that can have runtime visible annotations. 0 means that all the
+ * parameters from the method descriptor can have annotations.
+ */
+ private int visibleAnnotableParameterCount;
+
+ /**
+ * The number of method parameters that can have runtime invisible annotations. 0 means that all
+ * the parameters from the method descriptor can have annotations.
+ */
+ private int invisibleAnnotableParameterCount;
+
+ /** Whether the {@link #visitCode} method has been called. */
+ private boolean visitCodeCalled;
+
+ /** Whether the {@link #visitMaxs} method has been called. */
+ private boolean visitMaxCalled;
+
+ /** Whether the {@link #visitEnd} method has been called. */
+ private boolean visitEndCalled;
+
+ /** The number of visited instructions so far. */
+ private int insnCount;
+
+ /** The index of the instruction designated by each visited label. */
+ private final Map<Label, Integer> labelInsnIndices;
+
+ /** The labels referenced by the visited method. */
+ private Set<Label> referencedLabels;
+
+ /** The index of the instruction corresponding to the last visited stack map frame. */
+ private int lastFrameInsnIndex = -1;
+
+ /** The number of visited frames in expanded form. */
+ private int numExpandedFrames;
+
+ /** The number of visited frames in compressed form. */
+ private int numCompressedFrames;
+
+ /**
+ * The exception handler ranges. Each pair of list element contains the start and end labels of an
+ * exception handler block.
+ */
+ private List<Label> handlers;
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter will not perform any
+ * data flow check (see {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ * <i>Subclasses must not use this constructor</i>. Instead, they must use the {@link
+ * #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+ *
+ * @param methodvisitor the method visitor to which this adapter must delegate calls.
+ */
+ public CheckMethodAdapter(final MethodVisitor methodvisitor) {
+ this(methodvisitor, new HashMap<Label, Integer>());
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter will not perform any
+ * data flow check (see {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ * <i>Subclasses must not use this constructor</i>. Instead, they must use the {@link
+ * #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+ *
+ * @param methodVisitor the method visitor to which this adapter must delegate calls.
+ * @param labelInsnIndices the index of the instruction designated by each visited label so far
+ * (in other methods). This map is updated with the labels from the visited method.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public CheckMethodAdapter(
+ final MethodVisitor methodVisitor, final Map<Label, Integer> labelInsnIndices) {
+ this(Opcodes.ASM7, methodVisitor, labelInsnIndices);
+ if (getClass() != CheckMethodAdapter.class) {
+ throw new IllegalStateException();
}
-
- // code to generate the above string
- // public static void main (String[] args) {
- // int[] TYPE = new int[] {
- // 0, //NOP
- // 0, //ACONST_NULL
- // 0, //ICONST_M1
- // 0, //ICONST_0
- // 0, //ICONST_1
- // 0, //ICONST_2
- // 0, //ICONST_3
- // 0, //ICONST_4
- // 0, //ICONST_5
- // 0, //LCONST_0
- // 0, //LCONST_1
- // 0, //FCONST_0
- // 0, //FCONST_1
- // 0, //FCONST_2
- // 0, //DCONST_0
- // 0, //DCONST_1
- // 1, //BIPUSH
- // 1, //SIPUSH
- // 7, //LDC
- // -1, //LDC_W
- // -1, //LDC2_W
- // 2, //ILOAD
- // 2, //LLOAD
- // 2, //FLOAD
- // 2, //DLOAD
- // 2, //ALOAD
- // -1, //ILOAD_0
- // -1, //ILOAD_1
- // -1, //ILOAD_2
- // -1, //ILOAD_3
- // -1, //LLOAD_0
- // -1, //LLOAD_1
- // -1, //LLOAD_2
- // -1, //LLOAD_3
- // -1, //FLOAD_0
- // -1, //FLOAD_1
- // -1, //FLOAD_2
- // -1, //FLOAD_3
- // -1, //DLOAD_0
- // -1, //DLOAD_1
- // -1, //DLOAD_2
- // -1, //DLOAD_3
- // -1, //ALOAD_0
- // -1, //ALOAD_1
- // -1, //ALOAD_2
- // -1, //ALOAD_3
- // 0, //IALOAD
- // 0, //LALOAD
- // 0, //FALOAD
- // 0, //DALOAD
- // 0, //AALOAD
- // 0, //BALOAD
- // 0, //CALOAD
- // 0, //SALOAD
- // 2, //ISTORE
- // 2, //LSTORE
- // 2, //FSTORE
- // 2, //DSTORE
- // 2, //ASTORE
- // -1, //ISTORE_0
- // -1, //ISTORE_1
- // -1, //ISTORE_2
- // -1, //ISTORE_3
- // -1, //LSTORE_0
- // -1, //LSTORE_1
- // -1, //LSTORE_2
- // -1, //LSTORE_3
- // -1, //FSTORE_0
- // -1, //FSTORE_1
- // -1, //FSTORE_2
- // -1, //FSTORE_3
- // -1, //DSTORE_0
- // -1, //DSTORE_1
- // -1, //DSTORE_2
- // -1, //DSTORE_3
- // -1, //ASTORE_0
- // -1, //ASTORE_1
- // -1, //ASTORE_2
- // -1, //ASTORE_3
- // 0, //IASTORE
- // 0, //LASTORE
- // 0, //FASTORE
- // 0, //DASTORE
- // 0, //AASTORE
- // 0, //BASTORE
- // 0, //CASTORE
- // 0, //SASTORE
- // 0, //POP
- // 0, //POP2
- // 0, //DUP
- // 0, //DUP_X1
- // 0, //DUP_X2
- // 0, //DUP2
- // 0, //DUP2_X1
- // 0, //DUP2_X2
- // 0, //SWAP
- // 0, //IADD
- // 0, //LADD
- // 0, //FADD
- // 0, //DADD
- // 0, //ISUB
- // 0, //LSUB
- // 0, //FSUB
- // 0, //DSUB
- // 0, //IMUL
- // 0, //LMUL
- // 0, //FMUL
- // 0, //DMUL
- // 0, //IDIV
- // 0, //LDIV
- // 0, //FDIV
- // 0, //DDIV
- // 0, //IREM
- // 0, //LREM
- // 0, //FREM
- // 0, //DREM
- // 0, //INEG
- // 0, //LNEG
- // 0, //FNEG
- // 0, //DNEG
- // 0, //ISHL
- // 0, //LSHL
- // 0, //ISHR
- // 0, //LSHR
- // 0, //IUSHR
- // 0, //LUSHR
- // 0, //IAND
- // 0, //LAND
- // 0, //IOR
- // 0, //LOR
- // 0, //IXOR
- // 0, //LXOR
- // 8, //IINC
- // 0, //I2L
- // 0, //I2F
- // 0, //I2D
- // 0, //L2I
- // 0, //L2F
- // 0, //L2D
- // 0, //F2I
- // 0, //F2L
- // 0, //F2D
- // 0, //D2I
- // 0, //D2L
- // 0, //D2F
- // 0, //I2B
- // 0, //I2C
- // 0, //I2S
- // 0, //LCMP
- // 0, //FCMPL
- // 0, //FCMPG
- // 0, //DCMPL
- // 0, //DCMPG
- // 6, //IFEQ
- // 6, //IFNE
- // 6, //IFLT
- // 6, //IFGE
- // 6, //IFGT
- // 6, //IFLE
- // 6, //IF_ICMPEQ
- // 6, //IF_ICMPNE
- // 6, //IF_ICMPLT
- // 6, //IF_ICMPGE
- // 6, //IF_ICMPGT
- // 6, //IF_ICMPLE
- // 6, //IF_ACMPEQ
- // 6, //IF_ACMPNE
- // 6, //GOTO
- // 6, //JSR
- // 2, //RET
- // 9, //TABLESWITCH
- // 10, //LOOKUPSWITCH
- // 0, //IRETURN
- // 0, //LRETURN
- // 0, //FRETURN
- // 0, //DRETURN
- // 0, //ARETURN
- // 0, //RETURN
- // 4, //GETSTATIC
- // 4, //PUTSTATIC
- // 4, //GETFIELD
- // 4, //PUTFIELD
- // 5, //INVOKEVIRTUAL
- // 5, //INVOKESPECIAL
- // 5, //INVOKESTATIC
- // 5, //INVOKEINTERFACE
- // -1, //INVOKEDYNAMIC
- // 3, //NEW
- // 1, //NEWARRAY
- // 3, //ANEWARRAY
- // 0, //ARRAYLENGTH
- // 0, //ATHROW
- // 3, //CHECKCAST
- // 3, //INSTANCEOF
- // 0, //MONITORENTER
- // 0, //MONITOREXIT
- // -1, //WIDE
- // 11, //MULTIANEWARRAY
- // 6, //IFNULL
- // 6, //IFNONNULL
- // -1, //GOTO_W
- // -1 //JSR_W
- // };
- // for (int i = 0; i < TYPE.length; ++i) {
- // System.out.print((char)(TYPE[i] + 1 + 'A'));
- // }
- // System.out.println();
- // }
-
- /**
- * Constructs a new {@link CheckMethodAdapter} object. This method adapter
- * will not perform any data flow check (see
- * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
- * <i>Subclasses must not use this constructor</i>. Instead, they must use
- * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
- *
- * @param mv
- * the method visitor to which this adapter must delegate calls.
- */
- public CheckMethodAdapter(final MethodVisitor mv) {
- this(mv, new HashMap<Label, Integer>());
- }
-
- /**
- * Constructs a new {@link CheckMethodAdapter} object. This method adapter
- * will not perform any data flow check (see
- * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
- * <i>Subclasses must not use this constructor</i>. Instead, they must use
- * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
- *
- * @param mv
- * the method visitor to which this adapter must delegate calls.
- * @param labels
- * a map of already visited labels (in other methods).
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public CheckMethodAdapter(final MethodVisitor mv,
- final Map<Label, Integer> labels) {
- this(Opcodes.ASM6, mv, labels);
- if (getClass() != CheckMethodAdapter.class) {
- throw new IllegalStateException();
- }
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter will not perform any
+ * data flow check (see {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ *
+ * @param api the ASM API version implemented by this CheckMethodAdapter. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param methodVisitor the method visitor to which this adapter must delegate calls.
+ * @param labelInsnIndices the index of the instruction designated by each visited label so far
+ * (in other methods). This map is updated with the labels from the visited method.
+ */
+ protected CheckMethodAdapter(
+ final int api,
+ final MethodVisitor methodVisitor,
+ final Map<Label, Integer> labelInsnIndices) {
+ super(api, methodVisitor);
+ this.labelInsnIndices = labelInsnIndices;
+ this.referencedLabels = new HashSet<Label>();
+ this.handlers = new ArrayList<Label>();
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter will perform basic data
+ * flow checks. For instance in a method whose signature is {@code void m ()}, the invalid
+ * instruction IRETURN, or the invalid sequence IADD L2I will be detected. <i>Subclasses must not
+ * use this constructor</i>. Instead, they must use the {@link
+ * #CheckMethodAdapter(int,int,String,String,MethodVisitor,Map)} version.
+ *
+ * @param access the method's access flags.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param methodVisitor the method visitor to which this adapter must delegate calls.
+ * @param labelInsnIndices the index of the instruction designated by each visited label so far
+ * (in other methods). This map is updated with the labels from the visited method.
+ */
+ public CheckMethodAdapter(
+ final int access,
+ final String name,
+ final String descriptor,
+ final MethodVisitor methodVisitor,
+ final Map<Label, Integer> labelInsnIndices) {
+ this(Opcodes.ASM7, access, name, descriptor, methodVisitor, labelInsnIndices);
+ if (getClass() != CheckMethodAdapter.class) {
+ throw new IllegalStateException();
}
-
- /**
- * Constructs a new {@link CheckMethodAdapter} object. This method adapter
- * will not perform any data flow check (see
- * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
- *
- * @param api
- * the ASM API version implemented by this CheckMethodAdapter.
- * Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5}
- * or {@link Opcodes#ASM6}.
- * @param mv
- * the method visitor to which this adapter must delegate calls.
- * @param labels
- * a map of already visited labels (in other methods).
- */
- protected CheckMethodAdapter(final int api, final MethodVisitor mv,
- final Map<Label, Integer> labels) {
- super(api, mv);
- this.labels = labels;
- this.usedLabels = new HashSet<Label>();
- this.handlers = new ArrayList<Label>();
- }
-
- /**
- * Constructs a new {@link CheckMethodAdapter} object. This method adapter
- * will perform basic data flow checks. For instance in a method whose
- * signature is <tt>void m ()</tt>, the invalid instruction IRETURN, or the
- * invalid sequence IADD L2I will be detected.
- *
- * @param access
- * the method's access flags.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param cmv
- * the method visitor to which this adapter must delegate calls.
- * @param labels
- * a map of already visited labels (in other methods).
- */
- public CheckMethodAdapter(final int access, final String name,
- final String desc, final MethodVisitor cmv,
- final Map<Label, Integer> labels) {
- this(new MethodNode(Opcodes.ASM5, access, name, desc, null, null) {
- @Override
- public void visitEnd() {
- Analyzer<BasicValue> a = new Analyzer<BasicValue>(
- new BasicVerifier());
- try {
- a.analyze("dummy", this);
- } catch (Exception e) {
- if (e instanceof IndexOutOfBoundsException
- && maxLocals == 0 && maxStack == 0) {
- throw new RuntimeException(
- "Data flow checking option requires valid, non zero maxLocals and maxStack values.");
- }
- e.printStackTrace();
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw, true);
- CheckClassAdapter.printAnalyzerResult(this, a, pw);
- pw.close();
- throw new RuntimeException(e.getMessage() + ' '
- + sw.toString());
- }
- accept(cmv);
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter will perform basic data
+ * flow checks. For instance in a method whose signature is {@code void m ()}, the invalid
+ * instruction IRETURN, or the invalid sequence IADD L2I will be detected.
+ *
+ * @param api the ASM API version implemented by this CheckMethodAdapter. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param access the method's access flags.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param methodVisitor the method visitor to which this adapter must delegate calls.
+ * @param labelInsnIndices the index of the instruction designated by each visited label so far
+ * (in other methods). This map is updated with the labels from the visited method.
+ */
+ protected CheckMethodAdapter(
+ final int api,
+ final int access,
+ final String name,
+ final String descriptor,
+ final MethodVisitor methodVisitor,
+ final Map<Label, Integer> labelInsnIndices) {
+ this(
+ api,
+ new MethodNode(api, access, name, descriptor, null, null) {
+ @Override
+ public void visitEnd() {
+ Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(new BasicVerifier());
+ try {
+ analyzer.analyze("dummy", this);
+ } catch (IndexOutOfBoundsException e) {
+ if (maxLocals == 0 && maxStack == 0) {
+ throw new IllegalArgumentException(
+ "Data flow checking option requires valid, non zero maxLocals and maxStack.",
+ e);
+ }
+ throwError(analyzer, e);
+ } catch (AnalyzerException e) {
+ throwError(analyzer, e);
}
- }, labels);
- this.access = access;
+ accept(methodVisitor);
+ }
+
+ private void throwError(final Analyzer<BasicValue> analyzer, final Exception e) {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(stringWriter, true);
+ CheckClassAdapter.printAnalyzerResult(this, analyzer, printWriter);
+ printWriter.close();
+ throw new IllegalArgumentException(e.getMessage() + ' ' + stringWriter.toString(), e);
+ }
+ },
+ labelInsnIndices);
+ this.access = access;
+ }
+
+ @Override
+ public void visitParameter(final String name, final int access) {
+ if (name != null) {
+ checkUnqualifiedName(version, name, "name");
}
-
- @Override
- public void visitParameter(String name, int access) {
- if (name != null) {
- checkUnqualifiedName(version, name, "name");
- }
- CheckClassAdapter.checkAccess(access, Opcodes.ACC_FINAL
- + Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC);
- super.visitParameter(name, access);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- checkEndMethod();
- checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- checkEndMethod();
- int sort = typeRef >>> 24;
- if (sort != TypeReference.METHOD_TYPE_PARAMETER
- && sort != TypeReference.METHOD_TYPE_PARAMETER_BOUND
- && sort != TypeReference.METHOD_RETURN
- && sort != TypeReference.METHOD_RECEIVER
- && sort != TypeReference.METHOD_FORMAL_PARAMETER
- && sort != TypeReference.THROWS) {
- throw new IllegalArgumentException("Invalid type reference sort 0x"
- + Integer.toHexString(sort));
- }
- CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
- CheckMethodAdapter.checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
- typePath, desc, visible));
+ CheckClassAdapter.checkAccess(
+ access, Opcodes.ACC_FINAL + Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC);
+ super.visitParameter(name, access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ checkVisitEndNotCalled();
+ checkDescriptor(version, descriptor, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(descriptor, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ checkVisitEndNotCalled();
+ int sort = new TypeReference(typeRef).getSort();
+ if (sort != TypeReference.METHOD_TYPE_PARAMETER
+ && sort != TypeReference.METHOD_TYPE_PARAMETER_BOUND
+ && sort != TypeReference.METHOD_RETURN
+ && sort != TypeReference.METHOD_RECEIVER
+ && sort != TypeReference.METHOD_FORMAL_PARAMETER
+ && sort != TypeReference.THROWS) {
+ throw new IllegalArgumentException(INVALID_TYPE_REFERENCE + Integer.toHexString(sort));
}
-
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- checkEndMethod();
- return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false);
+ CheckClassAdapter.checkTypeRef(typeRef);
+ CheckMethodAdapter.checkDescriptor(version, descriptor, false);
+ return new CheckAnnotationAdapter(
+ super.visitTypeAnnotation(typeRef, typePath, descriptor, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ checkVisitEndNotCalled();
+ return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false);
+ }
+
+ @Override
+ public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ checkVisitEndNotCalled();
+ if (visible) {
+ visibleAnnotableParameterCount = parameterCount;
+ } else {
+ invisibleAnnotableParameterCount = parameterCount;
}
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- checkEndMethod();
- checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitParameterAnnotation(
- parameter, desc, visible));
+ super.visitAnnotableParameterCount(parameterCount, visible);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ checkVisitEndNotCalled();
+ if ((visible
+ && visibleAnnotableParameterCount > 0
+ && parameter >= visibleAnnotableParameterCount)
+ || (!visible
+ && invisibleAnnotableParameterCount > 0
+ && parameter >= invisibleAnnotableParameterCount)) {
+ throw new IllegalArgumentException("Invalid parameter index");
}
-
- @Override
- public void visitAttribute(final Attribute attr) {
- checkEndMethod();
- if (attr == null) {
- throw new IllegalArgumentException(
- "Invalid attribute (must not be null)");
- }
- super.visitAttribute(attr);
+ checkDescriptor(version, descriptor, false);
+ return new CheckAnnotationAdapter(
+ super.visitParameterAnnotation(parameter, descriptor, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ checkVisitEndNotCalled();
+ if (attribute == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
}
+ super.visitAttribute(attribute);
+ }
- @Override
- public void visitCode() {
- if ((access & Opcodes.ACC_ABSTRACT) != 0) {
- throw new RuntimeException("Abstract methods cannot have code");
- }
- startCode = true;
- super.visitCode();
+ @Override
+ public void visitCode() {
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ throw new UnsupportedOperationException("Abstract methods cannot have code");
}
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- if (insnCount == lastFrame) {
- throw new IllegalStateException(
- "At most one frame can be visited at a given code location.");
- }
- lastFrame = insnCount;
- int mLocal;
- int mStack;
- switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- mLocal = Integer.MAX_VALUE;
- mStack = Integer.MAX_VALUE;
- break;
-
- case Opcodes.F_SAME:
- mLocal = 0;
- mStack = 0;
- break;
-
- case Opcodes.F_SAME1:
- mLocal = 0;
- mStack = 1;
- break;
-
- case Opcodes.F_APPEND:
- case Opcodes.F_CHOP:
- mLocal = 3;
- mStack = 0;
- break;
-
- default:
- throw new IllegalArgumentException("Invalid frame type " + type);
- }
-
- if (nLocal > mLocal) {
- throw new IllegalArgumentException("Invalid nLocal=" + nLocal
- + " for frame type " + type);
- }
- if (nStack > mStack) {
- throw new IllegalArgumentException("Invalid nStack=" + nStack
- + " for frame type " + type);
- }
-
- if (type != Opcodes.F_CHOP) {
- if (nLocal > 0 && (local == null || local.length < nLocal)) {
- throw new IllegalArgumentException(
- "Array local[] is shorter than nLocal");
- }
- for (int i = 0; i < nLocal; ++i) {
- checkFrameValue(local[i]);
- }
- }
- if (nStack > 0 && (stack == null || stack.length < nStack)) {
- throw new IllegalArgumentException(
- "Array stack[] is shorter than nStack");
- }
- for (int i = 0; i < nStack; ++i) {
- checkFrameValue(stack[i]);
- }
- if (type == Opcodes.F_NEW) {
- ++expandedFrames;
- } else {
- ++compressedFrames;
- }
- if (expandedFrames > 0 && compressedFrames > 0) {
- throw new RuntimeException(
- "Expanded and compressed frames must not be mixed.");
- }
- super.visitFrame(type, nLocal, local, nStack, stack);
- }
-
- @Override
- public void visitInsn(final int opcode) {
- checkStartCode();
- checkEndCode();
- checkOpcode(opcode, 0);
- super.visitInsn(opcode);
- ++insnCount;
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- checkStartCode();
- checkEndCode();
- checkOpcode(opcode, 1);
- switch (opcode) {
- case Opcodes.BIPUSH:
- checkSignedByte(operand, "Invalid operand");
- break;
- case Opcodes.SIPUSH:
- checkSignedShort(operand, "Invalid operand");
- break;
- // case Constants.NEWARRAY:
- default:
- if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
- throw new IllegalArgumentException(
- "Invalid operand (must be an array type code T_...): "
- + operand);
- }
- }
- super.visitIntInsn(opcode, operand);
- ++insnCount;
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- checkStartCode();
- checkEndCode();
- checkOpcode(opcode, 2);
- checkUnsignedShort(var, "Invalid variable index");
- super.visitVarInsn(opcode, var);
- ++insnCount;
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- checkStartCode();
- checkEndCode();
- checkOpcode(opcode, 3);
- checkInternalName(type, "type");
- if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
- throw new IllegalArgumentException(
- "NEW cannot be used to create arrays: " + type);
- }
- super.visitTypeInsn(opcode, type);
- ++insnCount;
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- checkStartCode();
- checkEndCode();
- checkOpcode(opcode, 4);
- checkInternalName(owner, "owner");
- checkUnqualifiedName(version, name, "name");
- checkDesc(desc, false);
- super.visitFieldInsn(opcode, owner, name, desc);
- ++insnCount;
- }
-
- @Deprecated
- @Override
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
+ visitCodeCalled = true;
+ super.visitCode();
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ if (insnCount == lastFrameInsnIndex) {
+ throw new IllegalStateException("At most one frame can be visited at a given code location.");
}
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc, boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
+ lastFrameInsnIndex = insnCount;
+ int maxNumLocal;
+ int maxNumStack;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ maxNumLocal = Integer.MAX_VALUE;
+ maxNumStack = Integer.MAX_VALUE;
+ break;
+
+ case Opcodes.F_SAME:
+ maxNumLocal = 0;
+ maxNumStack = 0;
+ break;
+
+ case Opcodes.F_SAME1:
+ maxNumLocal = 0;
+ maxNumStack = 1;
+ break;
+
+ case Opcodes.F_APPEND:
+ case Opcodes.F_CHOP:
+ maxNumLocal = 3;
+ maxNumStack = 0;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Invalid frame type " + type);
}
- private void doVisitMethodInsn(int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- checkStartCode();
- checkEndCode();
- checkOpcode(opcode, 5);
- if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
- checkMethodIdentifier(version, name, "name");
- }
- checkInternalName(owner, "owner");
- checkMethodDesc(desc);
- if (opcode == Opcodes.INVOKEVIRTUAL && itf) {
- throw new IllegalArgumentException(
- "INVOKEVIRTUAL can't be used with interfaces");
- }
- if (opcode == Opcodes.INVOKEINTERFACE && !itf) {
- throw new IllegalArgumentException(
- "INVOKEINTERFACE can't be used with classes");
- }
- if (opcode == Opcodes.INVOKESPECIAL && itf
- && (version & 0xFFFF) < Opcodes.V1_8) {
- throw new IllegalArgumentException(
- "INVOKESPECIAL can't be used with interfaces prior to Java 8");
- }
-
- // Calling super.visitMethodInsn requires to call the correct version
- // depending on this.api (otherwise infinite loops can occur). To
- // simplify and to make it easier to automatically remove the backward
- // compatibility code, we inline the code of the overridden method here.
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- ++insnCount;
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- checkStartCode();
- checkEndCode();
- checkMethodIdentifier(version, name, "name");
- checkMethodDesc(desc);
- if (bsm.getTag() != Opcodes.H_INVOKESTATIC
- && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
- throw new IllegalArgumentException("invalid handle tag "
- + bsm.getTag());
- }
- for (int i = 0; i < bsmArgs.length; i++) {
- checkLDCConstant(bsmArgs[i]);
- }
- super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- ++insnCount;
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- checkStartCode();
- checkEndCode();
- checkOpcode(opcode, 6);
- checkLabel(label, false, "label");
- checkNonDebugLabel(label);
- super.visitJumpInsn(opcode, label);
- usedLabels.add(label);
- ++insnCount;
- }
-
- @Override
- public void visitLabel(final Label label) {
- checkStartCode();
- checkEndCode();
- checkLabel(label, false, "label");
- if (labels.get(label) != null) {
- throw new IllegalArgumentException("Already visited label");
- }
- labels.put(label, insnCount);
- super.visitLabel(label);
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- checkStartCode();
- checkEndCode();
- checkLDCConstant(cst);
- super.visitLdcInsn(cst);
- ++insnCount;
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- checkStartCode();
- checkEndCode();
- checkUnsignedShort(var, "Invalid variable index");
- checkSignedShort(increment, "Invalid increment");
- super.visitIincInsn(var, increment);
- ++insnCount;
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- checkStartCode();
- checkEndCode();
- if (max < min) {
- throw new IllegalArgumentException("Max = " + max
- + " must be greater than or equal to min = " + min);
- }
- checkLabel(dflt, false, "default label");
- checkNonDebugLabel(dflt);
- if (labels == null || labels.length != max - min + 1) {
- throw new IllegalArgumentException(
- "There must be max - min + 1 labels");
- }
- for (int i = 0; i < labels.length; ++i) {
- checkLabel(labels[i], false, "label at index " + i);
- checkNonDebugLabel(labels[i]);
- }
- super.visitTableSwitchInsn(min, max, dflt, labels);
- for (int i = 0; i < labels.length; ++i) {
- usedLabels.add(labels[i]);
- }
- ++insnCount;
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- checkEndCode();
- checkStartCode();
- checkLabel(dflt, false, "default label");
- checkNonDebugLabel(dflt);
- if (keys == null || labels == null || keys.length != labels.length) {
- throw new IllegalArgumentException(
- "There must be the same number of keys and labels");
- }
- for (int i = 0; i < labels.length; ++i) {
- checkLabel(labels[i], false, "label at index " + i);
- checkNonDebugLabel(labels[i]);
- }
- super.visitLookupSwitchInsn(dflt, keys, labels);
- usedLabels.add(dflt);
- for (int i = 0; i < labels.length; ++i) {
- usedLabels.add(labels[i]);
- }
- ++insnCount;
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- checkStartCode();
- checkEndCode();
- checkDesc(desc, false);
- if (desc.charAt(0) != '[') {
- throw new IllegalArgumentException(
- "Invalid descriptor (must be an array type descriptor): "
- + desc);
- }
- if (dims < 1) {
- throw new IllegalArgumentException(
- "Invalid dimensions (must be greater than 0): " + dims);
- }
- if (dims > desc.lastIndexOf('[') + 1) {
- throw new IllegalArgumentException(
- "Invalid dimensions (must not be greater than dims(desc)): "
- + dims);
- }
- super.visitMultiANewArrayInsn(desc, dims);
- ++insnCount;
- }
-
- @Override
- public AnnotationVisitor visitInsnAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- checkStartCode();
- checkEndCode();
- int sort = typeRef >>> 24;
- if (sort != TypeReference.INSTANCEOF && sort != TypeReference.NEW
- && sort != TypeReference.CONSTRUCTOR_REFERENCE
- && sort != TypeReference.METHOD_REFERENCE
- && sort != TypeReference.CAST
- && sort != TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
- && sort != TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT
- && sort != TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
- && sort != TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT) {
- throw new IllegalArgumentException("Invalid type reference sort 0x"
- + Integer.toHexString(sort));
- }
- CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
- CheckMethodAdapter.checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitInsnAnnotation(typeRef,
- typePath, desc, visible));
- }
-
- @Override
- public void visitTryCatchBlock(final Label start, final Label end,
- final Label handler, final String type) {
- checkStartCode();
- checkEndCode();
- checkLabel(start, false, "start label");
- checkLabel(end, false, "end label");
- checkLabel(handler, false, "handler label");
- checkNonDebugLabel(start);
- checkNonDebugLabel(end);
- checkNonDebugLabel(handler);
- if (labels.get(start) != null || labels.get(end) != null
- || labels.get(handler) != null) {
- throw new IllegalStateException(
- "Try catch blocks must be visited before their labels");
- }
- if (type != null) {
- checkInternalName(type, "type");
- }
- super.visitTryCatchBlock(start, end, handler, type);
- handlers.add(start);
- handlers.add(end);
- }
-
- @Override
- public AnnotationVisitor visitTryCatchAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- checkStartCode();
- checkEndCode();
- int sort = typeRef >>> 24;
- if (sort != TypeReference.EXCEPTION_PARAMETER) {
- throw new IllegalArgumentException("Invalid type reference sort 0x"
- + Integer.toHexString(sort));
- }
- CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
- CheckMethodAdapter.checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitTryCatchAnnotation(
- typeRef, typePath, desc, visible));
- }
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- checkStartCode();
- checkEndCode();
- checkUnqualifiedName(version, name, "name");
- checkDesc(desc, false);
- checkLabel(start, true, "start label");
- checkLabel(end, true, "end label");
- checkUnsignedShort(index, "Invalid variable index");
- int s = labels.get(start).intValue();
- int e = labels.get(end).intValue();
- if (e < s) {
- throw new IllegalArgumentException(
- "Invalid start and end labels (end must be greater than start)");
- }
- super.visitLocalVariable(name, desc, signature, start, end, index);
- }
-
- @Override
- public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
- TypePath typePath, Label[] start, Label[] end, int[] index,
- String desc, boolean visible) {
- checkStartCode();
- checkEndCode();
- int sort = typeRef >>> 24;
- if (sort != TypeReference.LOCAL_VARIABLE
- && sort != TypeReference.RESOURCE_VARIABLE) {
- throw new IllegalArgumentException("Invalid type reference sort 0x"
- + Integer.toHexString(sort));
- }
- CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
- checkDesc(desc, false);
- if (start == null || end == null || index == null
- || end.length != start.length || index.length != start.length) {
- throw new IllegalArgumentException(
- "Invalid start, end and index arrays (must be non null and of identical length");
- }
- for (int i = 0; i < start.length; ++i) {
- checkLabel(start[i], true, "start label");
- checkLabel(end[i], true, "end label");
- checkUnsignedShort(index[i], "Invalid variable index");
- int s = labels.get(start[i]).intValue();
- int e = labels.get(end[i]).intValue();
- if (e < s) {
- throw new IllegalArgumentException(
- "Invalid start and end labels (end must be greater than start)");
- }
- }
- return super.visitLocalVariableAnnotation(typeRef, typePath, start,
- end, index, desc, visible);
- }
-
- @Override
- public void visitLineNumber(final int line, final Label start) {
- checkStartCode();
- checkEndCode();
- checkUnsignedShort(line, "Invalid line number");
- checkLabel(start, true, "start label");
- super.visitLineNumber(line, start);
- }
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- checkStartCode();
- checkEndCode();
- endCode = true;
- for (Label l : usedLabels) {
- if (labels.get(l) == null) {
- throw new IllegalStateException("Undefined label used");
- }
- }
- for (int i = 0; i < handlers.size();) {
- Integer start = labels.get(handlers.get(i++));
- Integer end = labels.get(handlers.get(i++));
- if (start == null || end == null) {
- throw new IllegalStateException(
- "Undefined try catch block labels");
- }
- if (end.intValue() <= start.intValue()) {
- throw new IllegalStateException(
- "Emty try catch block handler range");
- }
- }
- checkUnsignedShort(maxStack, "Invalid max stack");
- checkUnsignedShort(maxLocals, "Invalid max locals");
- super.visitMaxs(maxStack, maxLocals);
+ if (numLocal > maxNumLocal) {
+ throw new IllegalArgumentException(
+ "Invalid numLocal=" + numLocal + " for frame type " + type);
}
-
- @Override
- public void visitEnd() {
- checkEndMethod();
- endMethod = true;
- super.visitEnd();
+ if (numStack > maxNumStack) {
+ throw new IllegalArgumentException(
+ "Invalid numStack=" + numStack + " for frame type " + type);
}
- // -------------------------------------------------------------------------
-
- /**
- * Checks that the visitCode method has been called.
- */
- void checkStartCode() {
- if (!startCode) {
- throw new IllegalStateException(
- "Cannot visit instructions before visitCode has been called.");
- }
+ if (type != Opcodes.F_CHOP) {
+ if (numLocal > 0 && (local == null || local.length < numLocal)) {
+ throw new IllegalArgumentException("Array local[] is shorter than numLocal");
+ }
+ for (int i = 0; i < numLocal; ++i) {
+ checkFrameValue(local[i]);
+ }
}
-
- /**
- * Checks that the visitMaxs method has not been called.
- */
- void checkEndCode() {
- if (endCode) {
- throw new IllegalStateException(
- "Cannot visit instructions after visitMaxs has been called.");
- }
+ if (numStack > 0 && (stack == null || stack.length < numStack)) {
+ throw new IllegalArgumentException("Array stack[] is shorter than numStack");
}
-
- /**
- * Checks that the visitEnd method has not been called.
- */
- void checkEndMethod() {
- if (endMethod) {
- throw new IllegalStateException(
- "Cannot visit elements after visitEnd has been called.");
- }
+ for (int i = 0; i < numStack; ++i) {
+ checkFrameValue(stack[i]);
}
-
- /**
- * Checks a stack frame value.
- *
- * @param value
- * the value to be checked.
- */
- void checkFrameValue(final Object value) {
- if (value == Opcodes.TOP || value == Opcodes.INTEGER
- || value == Opcodes.FLOAT || value == Opcodes.LONG
- || value == Opcodes.DOUBLE || value == Opcodes.NULL
- || value == Opcodes.UNINITIALIZED_THIS) {
- return;
- }
- if (value instanceof String) {
- checkInternalName((String) value, "Invalid stack frame value");
- return;
- }
- if (!(value instanceof Label)) {
- throw new IllegalArgumentException("Invalid stack frame value: "
- + value);
- } else {
- usedLabels.add((Label) value);
- }
+ if (type == Opcodes.F_NEW) {
+ ++numExpandedFrames;
+ } else {
+ ++numCompressedFrames;
}
-
- /**
- * Checks that the type of the given opcode is equal to the given type.
- *
- * @param opcode
- * the opcode to be checked.
- * @param type
- * the expected opcode type.
- */
- static void checkOpcode(final int opcode, final int type) {
- if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
- throw new IllegalArgumentException("Invalid opcode: " + opcode);
- }
+ if (numExpandedFrames > 0 && numCompressedFrames > 0) {
+ throw new IllegalArgumentException("Expanded and compressed frames must not be mixed.");
}
-
- /**
- * Checks that the given value is a signed byte.
- *
- * @param value
- * the value to be checked.
- * @param msg
- * an message to be used in case of error.
- */
- static void checkSignedByte(final int value, final String msg) {
- if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
- throw new IllegalArgumentException(msg
- + " (must be a signed byte): " + value);
- }
+ super.visitFrame(type, numLocal, local, numStack, stack);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkOpcodeMethod(opcode, Method.VISIT_INSN);
+ super.visitInsn(opcode);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkOpcodeMethod(opcode, Method.VISIT_INT_INSN);
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ checkSignedByte(operand, "Invalid operand");
+ break;
+ case Opcodes.SIPUSH:
+ checkSignedShort(operand, "Invalid operand");
+ break;
+ case Opcodes.NEWARRAY:
+ if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
+ throw new IllegalArgumentException(
+ "Invalid operand (must be an array type code T_...): " + operand);
+ }
+ break;
+ default:
+ throw new AssertionError();
}
-
- /**
- * Checks that the given value is a signed short.
- *
- * @param value
- * the value to be checked.
- * @param msg
- * an message to be used in case of error.
- */
- static void checkSignedShort(final int value, final String msg) {
- if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
- throw new IllegalArgumentException(msg
- + " (must be a signed short): " + value);
- }
+ super.visitIntInsn(opcode, operand);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkOpcodeMethod(opcode, Method.VISIT_VAR_INSN);
+ checkUnsignedShort(var, INVALID_LOCAL_VARIABLE_INDEX);
+ super.visitVarInsn(opcode, var);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkOpcodeMethod(opcode, Method.VISIT_TYPE_INSN);
+ checkInternalName(version, type, "type");
+ if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
+ throw new IllegalArgumentException("NEW cannot be used to create arrays: " + type);
}
-
- /**
- * Checks that the given value is an unsigned short.
- *
- * @param value
- * the value to be checked.
- * @param msg
- * an message to be used in case of error.
- */
- static void checkUnsignedShort(final int value, final String msg) {
- if (value < 0 || value > 65535) {
- throw new IllegalArgumentException(msg
- + " (must be an unsigned short): " + value);
- }
+ super.visitTypeInsn(opcode, type);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkOpcodeMethod(opcode, Method.VISIT_FIELD_INSN);
+ checkInternalName(version, owner, "owner");
+ checkUnqualifiedName(version, name, "name");
+ checkDescriptor(version, descriptor, false);
+ super.visitFieldInsn(opcode, owner, name, descriptor);
+ ++insnCount;
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
}
-
- /**
- * Checks that the given value is an {@link Integer}, a{@link Float}, a
- * {@link Long}, a {@link Double} or a {@link String}.
- *
- * @param cst
- * the value to be checked.
- */
- static void checkConstant(final Object cst) {
- if (!(cst instanceof Integer) && !(cst instanceof Float)
- && !(cst instanceof Long) && !(cst instanceof Double)
- && !(cst instanceof String)) {
- throw new IllegalArgumentException("Invalid constant: " + cst);
- }
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
}
-
- void checkLDCConstant(final Object cst) {
- if (cst instanceof Type) {
- int s = ((Type) cst).getSort();
- if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
- throw new IllegalArgumentException("Illegal LDC constant value");
- }
- if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
- throw new IllegalArgumentException(
- "ldc of a constant class requires at least version 1.5");
- }
- if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
- throw new IllegalArgumentException(
- "ldc of a method type requires at least version 1.7");
- }
- } else if (cst instanceof Handle) {
- if ((version & 0xFFFF) < Opcodes.V1_7) {
- throw new IllegalArgumentException(
- "ldc of a handle requires at least version 1.7");
- }
- int tag = ((Handle) cst).getTag();
- if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
- throw new IllegalArgumentException("invalid handle tag " + tag);
- }
- } else {
- checkConstant(cst);
- }
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkOpcodeMethod(opcode, Method.VISIT_METHOD_INSN);
+ if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
+ checkMethodIdentifier(version, name, "name");
}
-
- /**
- * Checks that the given string is a valid unqualified name.
- *
- * @param version
- * the class version.
- * @param name
- * the string to be checked.
- * @param msg
- * a message to be used in case of error.
- */
- static void checkUnqualifiedName(int version, final String name,
- final String msg) {
- if ((version & 0xFFFF) < Opcodes.V1_5) {
- checkIdentifier(name, msg);
- } else {
- for (int i = 0; i < name.length(); ++i) {
- if (".;[/".indexOf(name.charAt(i)) != -1) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must be a valid unqualified name): " + name);
- }
- }
- }
+ checkInternalName(version, owner, "owner");
+ checkMethodDescriptor(version, descriptor);
+ if (opcode == Opcodes.INVOKEVIRTUAL && isInterface) {
+ throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces");
}
-
- /**
- * Checks that the given string is a valid Java identifier.
- *
- * @param name
- * the string to be checked.
- * @param msg
- * a message to be used in case of error.
- */
- static void checkIdentifier(final String name, final String msg) {
- checkIdentifier(name, 0, -1, msg);
- }
-
- /**
- * Checks that the given substring is a valid Java identifier.
- *
- * @param name
- * the string to be checked.
- * @param start
- * index of the first character of the identifier (inclusive).
- * @param end
- * index of the last character of the identifier (exclusive). -1
- * is equivalent to <tt>name.length()</tt> if name is not
- * <tt>null</tt>.
- * @param msg
- * a message to be used in case of error.
- */
- static void checkIdentifier(final String name, final int start,
- final int end, final String msg) {
- if (name == null || (end == -1 ? name.length() <= start : end <= start)) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not be null or empty)");
- }
- if (!Character.isJavaIdentifierStart(name.charAt(start))) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must be a valid Java identifier): " + name);
- }
- int max = end == -1 ? name.length() : end;
- for (int i = start + 1; i < max; ++i) {
- if (!Character.isJavaIdentifierPart(name.charAt(i))) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must be a valid Java identifier): " + name);
- }
- }
+ if (opcode == Opcodes.INVOKEINTERFACE && !isInterface) {
+ throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes");
}
-
- /**
- * Checks that the given string is a valid Java identifier.
- *
- * @param version
- * the class version.
- * @param name
- * the string to be checked.
- * @param msg
- * a message to be used in case of error.
- */
- static void checkMethodIdentifier(int version, final String name,
- final String msg) {
- if (name == null || name.length() == 0) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not be null or empty)");
- }
- if ((version & 0xFFFF) >= Opcodes.V1_5) {
- for (int i = 0; i < name.length(); ++i) {
- if (".;[/<>".indexOf(name.charAt(i)) != -1) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must be a valid unqualified name): " + name);
- }
- }
- return;
- }
- if (!Character.isJavaIdentifierStart(name.charAt(0))) {
- throw new IllegalArgumentException(
- "Invalid "
- + msg
- + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
- + name);
- }
- for (int i = 1; i < name.length(); ++i) {
- if (!Character.isJavaIdentifierPart(name.charAt(i))) {
- throw new IllegalArgumentException(
- "Invalid "
- + msg
- + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
- + name);
- }
- }
+ if (opcode == Opcodes.INVOKESPECIAL && isInterface && (version & 0xFFFF) < Opcodes.V1_8) {
+ throw new IllegalArgumentException(
+ "INVOKESPECIAL can't be used with interfaces prior to Java 8");
}
- /**
- * Checks that the given string is a valid internal class name.
- *
- * @param name
- * the string to be checked.
- * @param msg
- * a message to be used in case of error.
- */
- static void checkInternalName(final String name, final String msg) {
- if (name == null || name.length() == 0) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not be null or empty)");
- }
- if (name.charAt(0) == '[') {
- checkDesc(name, false);
- } else {
- checkInternalName(name, 0, -1, msg);
- }
+ // Calling super.visitMethodInsn requires to call the correct version depending on this.api
+ // (otherwise infinite loops can occur). To simplify and to make it easier to automatically
+ // remove the backward compatibility code, we inline the code of the overridden method here.
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
-
- /**
- * Checks that the given substring is a valid internal class name.
- *
- * @param name
- * the string to be checked.
- * @param start
- * index of the first character of the identifier (inclusive).
- * @param end
- * index of the last character of the identifier (exclusive). -1
- * is equivalent to <tt>name.length()</tt> if name is not
- * <tt>null</tt>.
- * @param msg
- * a message to be used in case of error.
- */
- static void checkInternalName(final String name, final int start,
- final int end, final String msg) {
- int max = end == -1 ? name.length() : end;
- try {
- int begin = start;
- int slash;
- do {
- slash = name.indexOf('/', begin + 1);
- if (slash == -1 || slash > max) {
- slash = max;
- }
- checkIdentifier(name, begin, slash, null);
- begin = slash + 1;
- } while (slash != max);
- } catch (IllegalArgumentException unused) {
- throw new IllegalArgumentException(
- "Invalid "
- + msg
- + " (must be a fully qualified class name in internal form): "
- + name);
- }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkMethodIdentifier(version, name, "name");
+ checkMethodDescriptor(version, descriptor);
+ if (bootstrapMethodHandle.getTag() != Opcodes.H_INVOKESTATIC
+ && bootstrapMethodHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
+ throw new IllegalArgumentException("invalid handle tag " + bootstrapMethodHandle.getTag());
}
-
- /**
- * Checks that the given string is a valid type descriptor.
- *
- * @param desc
- * the string to be checked.
- * @param canBeVoid
- * <tt>true</tt> if <tt>V</tt> can be considered valid.
- */
- static void checkDesc(final String desc, final boolean canBeVoid) {
- int end = checkDesc(desc, 0, canBeVoid);
- if (end != desc.length()) {
- throw new IllegalArgumentException("Invalid descriptor: " + desc);
- }
+ for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
+ checkLdcConstant(bootstrapMethodArgument);
}
-
- /**
- * Checks that a the given substring is a valid type descriptor.
- *
- * @param desc
- * the string to be checked.
- * @param start
- * index of the first character of the identifier (inclusive).
- * @param canBeVoid
- * <tt>true</tt> if <tt>V</tt> can be considered valid.
- * @return the index of the last character of the type decriptor, plus one.
- */
- static int checkDesc(final String desc, final int start,
- final boolean canBeVoid) {
- if (desc == null || start >= desc.length()) {
- throw new IllegalArgumentException(
- "Invalid type descriptor (must not be null or empty)");
- }
- int index;
- switch (desc.charAt(start)) {
- case 'V':
- if (canBeVoid) {
- return start + 1;
- } else {
- throw new IllegalArgumentException("Invalid descriptor: "
- + desc);
- }
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- case 'F':
- case 'J':
- case 'D':
- return start + 1;
- case '[':
- index = start + 1;
- while (index < desc.length() && desc.charAt(index) == '[') {
- ++index;
- }
- if (index < desc.length()) {
- return checkDesc(desc, index, false);
- } else {
- throw new IllegalArgumentException("Invalid descriptor: "
- + desc);
- }
- case 'L':
- index = desc.indexOf(';', start);
- if (index == -1 || index - start < 2) {
- throw new IllegalArgumentException("Invalid descriptor: "
- + desc);
- }
- try {
- checkInternalName(desc, start + 1, index, null);
- } catch (IllegalArgumentException unused) {
- throw new IllegalArgumentException("Invalid descriptor: "
- + desc);
- }
- return index + 1;
- default:
- throw new IllegalArgumentException("Invalid descriptor: " + desc);
- }
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkOpcodeMethod(opcode, Method.VISIT_JUMP_INSN);
+ checkLabel(label, false, "label");
+ super.visitJumpInsn(opcode, label);
+ referencedLabels.add(label);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkLabel(label, false, "label");
+ if (labelInsnIndices.get(label) != null) {
+ throw new IllegalArgumentException("Already visited label");
+ }
+ labelInsnIndices.put(label, insnCount);
+ super.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkLdcConstant(value);
+ super.visitLdcInsn(value);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkUnsignedShort(var, INVALID_LOCAL_VARIABLE_INDEX);
+ checkSignedShort(increment, "Invalid increment");
+ super.visitIincInsn(var, increment);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ if (max < min) {
+ throw new IllegalArgumentException(
+ "Max = " + max + " must be greater than or equal to min = " + min);
+ }
+ checkLabel(dflt, false, "default label");
+ if (labels == null || labels.length != max - min + 1) {
+ throw new IllegalArgumentException("There must be max - min + 1 labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ }
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ for (Label label : labels) {
+ referencedLabels.add(label);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ checkVisitMaxsNotCalled();
+ checkVisitCodeCalled();
+ checkLabel(dflt, false, "default label");
+ if (keys == null || labels == null || keys.length != labels.length) {
+ throw new IllegalArgumentException("There must be the same number of keys and labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ }
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ referencedLabels.add(dflt);
+ for (Label label : labels) {
+ referencedLabels.add(label);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkDescriptor(version, descriptor, false);
+ if (descriptor.charAt(0) != '[') {
+ throw new IllegalArgumentException(
+ "Invalid descriptor (must be an array type descriptor): " + descriptor);
+ }
+ if (numDimensions < 1) {
+ throw new IllegalArgumentException(
+ "Invalid dimensions (must be greater than 0): " + numDimensions);
}
+ if (numDimensions > descriptor.lastIndexOf('[') + 1) {
+ throw new IllegalArgumentException(
+ "Invalid dimensions (must not be greater than numDimensions(descriptor)): "
+ + numDimensions);
+ }
+ super.visitMultiANewArrayInsn(descriptor, numDimensions);
+ ++insnCount;
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ int sort = new TypeReference(typeRef).getSort();
+ if (sort != TypeReference.INSTANCEOF
+ && sort != TypeReference.NEW
+ && sort != TypeReference.CONSTRUCTOR_REFERENCE
+ && sort != TypeReference.METHOD_REFERENCE
+ && sort != TypeReference.CAST
+ && sort != TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ && sort != TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT
+ && sort != TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ && sort != TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT) {
+ throw new IllegalArgumentException(INVALID_TYPE_REFERENCE + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRef(typeRef);
+ CheckMethodAdapter.checkDescriptor(version, descriptor, false);
+ return new CheckAnnotationAdapter(
+ super.visitInsnAnnotation(typeRef, typePath, descriptor, visible));
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkLabel(start, false, START_LABEL);
+ checkLabel(end, false, END_LABEL);
+ checkLabel(handler, false, "handler label");
+ if (labelInsnIndices.get(start) != null
+ || labelInsnIndices.get(end) != null
+ || labelInsnIndices.get(handler) != null) {
+ throw new IllegalStateException("Try catch blocks must be visited before their labels");
+ }
+ if (type != null) {
+ checkInternalName(version, type, "type");
+ }
+ super.visitTryCatchBlock(start, end, handler, type);
+ handlers.add(start);
+ handlers.add(end);
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ int sort = new TypeReference(typeRef).getSort();
+ if (sort != TypeReference.EXCEPTION_PARAMETER) {
+ throw new IllegalArgumentException(INVALID_TYPE_REFERENCE + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRef(typeRef);
+ CheckMethodAdapter.checkDescriptor(version, descriptor, false);
+ return new CheckAnnotationAdapter(
+ super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible));
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkUnqualifiedName(version, name, "name");
+ checkDescriptor(version, descriptor, false);
+ checkLabel(start, true, START_LABEL);
+ checkLabel(end, true, END_LABEL);
+ checkUnsignedShort(index, INVALID_LOCAL_VARIABLE_INDEX);
+ int startInsnIndex = labelInsnIndices.get(start).intValue();
+ int endInsnIndex = labelInsnIndices.get(end).intValue();
+ if (endInsnIndex < startInsnIndex) {
+ throw new IllegalArgumentException(
+ "Invalid start and end labels (end must be greater than start)");
+ }
+ super.visitLocalVariable(name, descriptor, signature, start, end, index);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ int sort = new TypeReference(typeRef).getSort();
+ if (sort != TypeReference.LOCAL_VARIABLE && sort != TypeReference.RESOURCE_VARIABLE) {
+ throw new IllegalArgumentException(INVALID_TYPE_REFERENCE + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRef(typeRef);
+ checkDescriptor(version, descriptor, false);
+ if (start == null
+ || end == null
+ || index == null
+ || end.length != start.length
+ || index.length != start.length) {
+ throw new IllegalArgumentException(
+ "Invalid start, end and index arrays (must be non null and of identical length");
+ }
+ for (int i = 0; i < start.length; ++i) {
+ checkLabel(start[i], true, START_LABEL);
+ checkLabel(end[i], true, END_LABEL);
+ checkUnsignedShort(index[i], INVALID_LOCAL_VARIABLE_INDEX);
+ int startInsnIndex = labelInsnIndices.get(start[i]).intValue();
+ int endInsnIndex = labelInsnIndices.get(end[i]).intValue();
+ if (endInsnIndex < startInsnIndex) {
+ throw new IllegalArgumentException(
+ "Invalid start and end labels (end must be greater than start)");
+ }
+ }
+ return super.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, index, descriptor, visible);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ checkVisitCodeCalled();
+ checkVisitMaxsNotCalled();
+ checkUnsignedShort(line, "Invalid line number");
+ checkL
<TRUNCATED>
[02/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
deleted file mode 100644
index a04930f..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
+++ /dev/null
@@ -1,1044 +0,0 @@
-/***
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.xml;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.Templates;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.sax.SAXSource;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.tapestry5.internal.plastic.asm.ClassReader;
-import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.ext.LexicalHandler;
-import org.xml.sax.helpers.AttributesImpl;
-import org.xml.sax.helpers.DefaultHandler;
-import org.xml.sax.helpers.XMLReaderFactory;
-
-/**
- * Processor is a command line tool that can be used for bytecode waving
- * directed by XSL transformation.
- * <p>
- * In order to use a concrete XSLT engine, system property
- * <tt>javax.xml.transform.TransformerFactory</tt> must be set to one of the
- * following values.
- *
- * <blockquote>
- * <table border="1" cellspacing="0" cellpadding="3">
- * <tr>
- * <td>jd.xslt</td>
- * <td>jd.xml.xslt.trax.TransformerFactoryImpl</td>
- * </tr>
- *
- * <tr>
- * <td>Saxon</td>
- * <td>net.sf.saxon.TransformerFactoryImpl</td>
- * </tr>
- *
- * <tr>
- * <td>Caucho</td>
- * <td>com.caucho.xsl.Xsl</td>
- * </tr>
- *
- * <tr>
- * <td>Xalan interpeter</td>
- * <td>org.apache.xalan.processor.TransformerFactory</td>
- * </tr>
- *
- * <tr>
- * <td>Xalan xsltc</td>
- * <td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
- * </tr>
- * </table>
- * </blockquote>
- *
- * @author Eugene Kuleshov
- */
-public class Processor {
-
- public static final int BYTECODE = 1;
-
- public static final int MULTI_XML = 2;
-
- public static final int SINGLE_XML = 3;
-
- private static final String SINGLE_XML_NAME = "classes.xml";
-
- private final int inRepresentation;
-
- private final int outRepresentation;
-
- private final InputStream input;
-
- private final OutputStream output;
-
- private final Source xslt;
-
- private int n = 0;
-
- public Processor(final int inRepresenation, final int outRepresentation,
- final InputStream input, final OutputStream output,
- final Source xslt) {
- this.inRepresentation = inRepresenation;
- this.outRepresentation = outRepresentation;
- this.input = input;
- this.output = output;
- this.xslt = xslt;
- }
-
- public int process() throws TransformerException, IOException, SAXException {
- ZipInputStream zis = new ZipInputStream(input);
- final ZipOutputStream zos = new ZipOutputStream(output);
- final OutputStreamWriter osw = new OutputStreamWriter(zos);
-
- Thread.currentThread().setContextClassLoader(
- getClass().getClassLoader());
-
- TransformerFactory tf = TransformerFactory.newInstance();
- if (!tf.getFeature(SAXSource.FEATURE)
- || !tf.getFeature(SAXResult.FEATURE)) {
- return 0;
- }
-
- SAXTransformerFactory saxtf = (SAXTransformerFactory) tf;
- Templates templates = null;
- if (xslt != null) {
- templates = saxtf.newTemplates(xslt);
- }
-
- // configuring outHandlerFactory
- // ///////////////////////////////////////////////////////
-
- EntryElement entryElement = getEntryElement(zos);
-
- ContentHandler outDocHandler = null;
- switch (outRepresentation) {
- case BYTECODE:
- outDocHandler = new OutputSlicingHandler(
- new ASMContentHandlerFactory(zos), entryElement, false);
- break;
-
- case MULTI_XML:
- outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw,
- true), entryElement, true);
- break;
-
- case SINGLE_XML:
- ZipEntry outputEntry = new ZipEntry(SINGLE_XML_NAME);
- zos.putNextEntry(outputEntry);
- outDocHandler = new SAXWriter(osw, false);
- break;
-
- }
-
- // configuring inputDocHandlerFactory
- // /////////////////////////////////////////////////
- ContentHandler inDocHandler;
- if (templates == null) {
- inDocHandler = outDocHandler;
- } else {
- inDocHandler = new InputSlicingHandler("class", outDocHandler,
- new TransformerHandlerFactory(saxtf, templates,
- outDocHandler));
- }
- ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(
- inDocHandler);
-
- if (inDocHandler != null && inRepresentation != SINGLE_XML) {
- inDocHandler.startDocument();
- inDocHandler.startElement("", "classes", "classes",
- new AttributesImpl());
- }
-
- int i = 0;
- ZipEntry ze;
- while ((ze = zis.getNextEntry()) != null) {
- update(ze.getName(), n++);
- if (isClassEntry(ze)) {
- processEntry(zis, ze, inDocHandlerFactory);
- } else {
- OutputStream os = entryElement.openEntry(getName(ze));
- copyEntry(zis, os);
- entryElement.closeEntry();
- }
-
- i++;
- }
-
- if (inDocHandler != null && inRepresentation != SINGLE_XML) {
- inDocHandler.endElement("", "classes", "classes");
- inDocHandler.endDocument();
- }
-
- if (outRepresentation == SINGLE_XML) {
- zos.closeEntry();
- }
- zos.flush();
- zos.close();
-
- return i;
- }
-
- private void copyEntry(final InputStream is, final OutputStream os)
- throws IOException {
- if (outRepresentation == SINGLE_XML) {
- return;
- }
-
- byte[] buff = new byte[2048];
- int i;
- while ((i = is.read(buff)) != -1) {
- os.write(buff, 0, i);
- }
- }
-
- private boolean isClassEntry(final ZipEntry ze) {
- String name = ze.getName();
- return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME)
- || name.endsWith(".class") || name.endsWith(".class.xml");
- }
-
- private void processEntry(final ZipInputStream zis, final ZipEntry ze,
- final ContentHandlerFactory handlerFactory) {
- ContentHandler handler = handlerFactory.createContentHandler();
- try {
-
- // if (CODE2ASM.equals(command)) { // read bytecode and process it
- // // with TraceClassVisitor
- // ClassReader cr = new ClassReader(readEntry(zis, ze));
- // cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
- // false);
- // }
-
- boolean singleInputDocument = inRepresentation == SINGLE_XML;
- if (inRepresentation == BYTECODE) { // read bytecode and process it
- // with handler
- ClassReader cr = new ClassReader(readEntry(zis, ze));
- cr.accept(new SAXClassAdapter(handler, singleInputDocument), 0);
-
- } else { // read XML and process it with handler
- XMLReader reader = XMLReaderFactory.createXMLReader();
- reader.setContentHandler(handler);
- reader.parse(new InputSource(
- singleInputDocument ? (InputStream) new ProtectedInputStream(
- zis) : new ByteArrayInputStream(readEntry(zis,
- ze))));
-
- }
- } catch (Exception ex) {
- update(ze.getName(), 0);
- update(ex, 0);
- }
- }
-
- private EntryElement getEntryElement(final ZipOutputStream zos) {
- if (outRepresentation == SINGLE_XML) {
- return new SingleDocElement(zos);
- }
- return new ZipEntryElement(zos);
- }
-
- // private ContentHandlerFactory getHandlerFactory(
- // OutputStream os,
- // SAXTransformerFactory saxtf,
- // Templates templates)
- // {
- // ContentHandlerFactory factory = null;
- // if (templates == null) {
- // if (outputRepresentation == BYTECODE) { // factory used to write
- // // bytecode
- // factory = new ASMContentHandlerFactory(os, computeMax);
- // } else { // factory used to write XML
- // factory = new SAXWriterFactory(os, true);
- // }
- // } else {
- // if (outputRepresentation == BYTECODE) { // factory used to transform
- // // and then write bytecode
- // factory = new ASMTransformerHandlerFactory(saxtf,
- // templates,
- // os,
- // computeMax);
- // } else { // factory used to transformand then write XML
- // factory = new TransformerHandlerFactory(saxtf,
- // templates,
- // os,
- // outputRepresentation == SINGLE_XML);
- // }
- // }
- // return factory;
- // }
-
- private String getName(final ZipEntry ze) {
- String name = ze.getName();
- if (isClassEntry(ze)) {
- if (inRepresentation != BYTECODE && outRepresentation == BYTECODE) {
- name = name.substring(0, name.length() - 4); // .class.xml to
- // .class
- } else if (inRepresentation == BYTECODE
- && outRepresentation != BYTECODE) {
- name += ".xml"; // .class to .class.xml
- }
- // } else if( CODE2ASM.equals( command)) {
- // name = name.substring( 0, name.length()-6).concat( ".asm");
- }
- return name;
- }
-
- private static byte[] readEntry(final InputStream zis, final ZipEntry ze)
- throws IOException {
- long size = ze.getSize();
- if (size > -1) {
- byte[] buff = new byte[(int) size];
- int k = 0;
- int n;
- while ((n = zis.read(buff, k, buff.length - k)) > 0) {
- k += n;
- }
- return buff;
- }
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- byte[] buff = new byte[4096];
- int i;
- while ((i = zis.read(buff)) != -1) {
- bos.write(buff, 0, i);
- }
- return bos.toByteArray();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
- */
- protected void update(final Object arg, final int n) {
- if (arg instanceof Throwable) {
- ((Throwable) arg).printStackTrace();
- } else {
- if (n % 100 == 0) {
- System.err.println(n + " " + arg);
- }
- }
- }
-
- public static void main(final String[] args) throws Exception {
- if (args.length < 2) {
- showUsage();
- return;
- }
-
- int inRepresentation = getRepresentation(args[0]);
- int outRepresentation = getRepresentation(args[1]);
-
- InputStream is = System.in;
- OutputStream os = new BufferedOutputStream(System.out);
-
- Source xslt = null;
- // boolean computeMax = true;
-
- for (int i = 2; i < args.length; i++) {
- if ("-in".equals(args[i])) {
- is = new FileInputStream(args[++i]);
-
- } else if ("-out".equals(args[i])) {
- os = new BufferedOutputStream(new FileOutputStream(args[++i]));
-
- } else if ("-xslt".equals(args[i])) {
- xslt = new StreamSource(new FileInputStream(args[++i]));
-
- // } else if( "-computemax".equals( args[ i].toLowerCase())) {
- // computeMax = true;
-
- } else {
- showUsage();
- return;
-
- }
- }
-
- if (inRepresentation == 0 || outRepresentation == 0) {
- showUsage();
- return;
- }
-
- Processor m = new Processor(inRepresentation, outRepresentation, is,
- os, xslt);
-
- long l1 = System.currentTimeMillis();
- int n = m.process();
- long l2 = System.currentTimeMillis();
- System.err.println(n);
- System.err.println((l2 - l1) + "ms " + 1000f * n / (l2 - l1)
- + " resources/sec");
- }
-
- private static int getRepresentation(final String s) {
- if ("code".equals(s)) {
- return BYTECODE;
- } else if ("xml".equals(s)) {
- return MULTI_XML;
- } else if ("singlexml".equals(s)) {
- return SINGLE_XML;
- }
- return 0;
- }
-
- private static void showUsage() {
- System.err
- .println("Usage: Main <in format> <out format> [-in <input jar>] [-out <output jar>] [-xslt <xslt fiel>]");
- System.err
- .println(" when -in or -out is omitted sysin and sysout would be used");
- System.err
- .println(" <in format> and <out format> - code | xml | singlexml");
- }
-
- /**
- * IputStream wrapper class used to protect input streams from being closed
- * by some stupid XML parsers.
- */
- private static final class ProtectedInputStream extends InputStream {
- private final InputStream is;
-
- ProtectedInputStream(final InputStream is) {
- this.is = is;
- }
-
- @Override
- public final void close() throws IOException {
- }
-
- @Override
- public final int read() throws IOException {
- return is.read();
- }
-
- @Override
- public final int read(final byte[] b, final int off, final int len)
- throws IOException {
- return is.read(b, off, len);
- }
-
- @Override
- public final int available() throws IOException {
- return is.available();
- }
- }
-
- /**
- * A {@link ContentHandlerFactory ContentHandlerFactory} is used to create
- * {@link org.xml.sax.ContentHandler ContentHandler} instances for concrete
- * context.
- */
- private static interface ContentHandlerFactory {
-
- /**
- * Creates an instance of the content handler.
- *
- * @return content handler
- */
- ContentHandler createContentHandler();
-
- }
-
- /**
- * SAXWriterFactory
- */
- private static final class SAXWriterFactory implements
- ContentHandlerFactory {
- private final Writer w;
-
- private final boolean optimizeEmptyElements;
-
- SAXWriterFactory(final Writer w, final boolean optimizeEmptyElements) {
- this.w = w;
- this.optimizeEmptyElements = optimizeEmptyElements;
- }
-
- public final ContentHandler createContentHandler() {
- return new SAXWriter(w, optimizeEmptyElements);
- }
-
- }
-
- /**
- * ASMContentHandlerFactory
- */
- private static final class ASMContentHandlerFactory implements
- ContentHandlerFactory {
- final OutputStream os;
-
- ASMContentHandlerFactory(final OutputStream os) {
- this.os = os;
- }
-
- public final ContentHandler createContentHandler() {
- final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- return new ASMContentHandler(cw) {
- @Override
- public void endDocument() throws SAXException {
- try {
- os.write(cw.toByteArray());
- } catch (IOException e) {
- throw new SAXException(e);
- }
- }
- };
- }
-
- }
-
- /**
- * TransformerHandlerFactory
- */
- private static final class TransformerHandlerFactory implements
- ContentHandlerFactory {
- private SAXTransformerFactory saxtf;
-
- private final Templates templates;
-
- private ContentHandler outputHandler;
-
- TransformerHandlerFactory(final SAXTransformerFactory saxtf,
- final Templates templates, final ContentHandler outputHandler) {
- this.saxtf = saxtf;
- this.templates = templates;
- this.outputHandler = outputHandler;
- }
-
- public final ContentHandler createContentHandler() {
- try {
- TransformerHandler handler = saxtf
- .newTransformerHandler(templates);
- handler.setResult(new SAXResult(outputHandler));
- return handler;
- } catch (TransformerConfigurationException ex) {
- throw new RuntimeException(ex.toString());
- }
- }
- }
-
- /**
- * SubdocumentHandlerFactory
- */
- private static final class SubdocumentHandlerFactory implements
- ContentHandlerFactory {
- private final ContentHandler subdocumentHandler;
-
- SubdocumentHandlerFactory(final ContentHandler subdocumentHandler) {
- this.subdocumentHandler = subdocumentHandler;
- }
-
- public final ContentHandler createContentHandler() {
- return subdocumentHandler;
- }
-
- }
-
- /**
- * A {@link org.xml.sax.ContentHandler ContentHandler} and
- * {@link org.xml.sax.ext.LexicalHandler LexicalHandler} that serializes XML
- * from SAX 2.0 events into {@link java.io.Writer Writer}.
- *
- * <i><blockquote> This implementation does not support namespaces, entity
- * definitions (uncluding DTD), CDATA and text elements. </blockquote></i>
- */
- private static final class SAXWriter extends DefaultHandler implements
- LexicalHandler {
- private static final char[] OFF = " "
- .toCharArray();
-
- private Writer w;
-
- private final boolean optimizeEmptyElements;
-
- private boolean openElement = false;
-
- private int ident = 0;
-
- /**
- * Creates <code>SAXWriter</code>.
- *
- * @param w
- * writer
- * @param optimizeEmptyElements
- * if set to <code>true</code>, short XML syntax will be used
- * for empty elements
- */
- SAXWriter(final Writer w, final boolean optimizeEmptyElements) {
- this.w = w;
- this.optimizeEmptyElements = optimizeEmptyElements;
- }
-
- @Override
- public final void startElement(final String ns, final String localName,
- final String qName, final Attributes atts) throws SAXException {
- try {
- closeElement();
-
- writeIdent();
- w.write('<' + qName);
- if (atts != null && atts.getLength() > 0) {
- writeAttributes(atts);
- }
-
- if (optimizeEmptyElements) {
- openElement = true;
- } else {
- w.write(">\n");
- }
- ident += 2;
-
- } catch (IOException ex) {
- throw new SAXException(ex);
-
- }
- }
-
- @Override
- public final void endElement(final String ns, final String localName,
- final String qName) throws SAXException {
- ident -= 2;
- try {
- if (openElement) {
- w.write("/>\n");
- openElement = false;
- } else {
- writeIdent();
- w.write("</" + qName + ">\n");
- }
-
- } catch (IOException ex) {
- throw new SAXException(ex);
-
- }
- }
-
- @Override
- public final void endDocument() throws SAXException {
- try {
- w.flush();
-
- } catch (IOException ex) {
- throw new SAXException(ex);
-
- }
- }
-
- public final void comment(final char[] ch, final int off, final int len)
- throws SAXException {
- try {
- closeElement();
-
- writeIdent();
- w.write("<!-- ");
- w.write(ch, off, len);
- w.write(" -->\n");
-
- } catch (IOException ex) {
- throw new SAXException(ex);
-
- }
- }
-
- public final void startDTD(final String arg0, final String arg1,
- final String arg2) throws SAXException {
- }
-
- public final void endDTD() throws SAXException {
- }
-
- public final void startEntity(final String arg0) throws SAXException {
- }
-
- public final void endEntity(final String arg0) throws SAXException {
- }
-
- public final void startCDATA() throws SAXException {
- }
-
- public final void endCDATA() throws SAXException {
- }
-
- private final void writeAttributes(final Attributes atts)
- throws IOException {
- StringBuilder sb = new StringBuilder();
- int len = atts.getLength();
- for (int i = 0; i < len; i++) {
- sb.append(' ').append(atts.getLocalName(i)).append("=\"")
- .append(esc(atts.getValue(i))).append('\"');
- }
- w.write(sb.toString());
- }
-
- /**
- * Encode string with escaping.
- *
- * @param str
- * string to encode.
- * @return encoded string
- */
- private static final String esc(final String str) {
- StringBuilder sb = new StringBuilder(str.length());
- for (int i = 0; i < str.length(); i++) {
- char ch = str.charAt(i);
- switch (ch) {
- case '&':
- sb.append("&");
- break;
-
- case '<':
- sb.append("<");
- break;
-
- case '>':
- sb.append(">");
- break;
-
- case '\"':
- sb.append(""");
- break;
-
- default:
- if (ch > 0x7f) {
- sb.append("&#").append(Integer.toString(ch))
- .append(';');
- } else {
- sb.append(ch);
- }
-
- }
- }
- return sb.toString();
- }
-
- private final void writeIdent() throws IOException {
- int n = ident;
- while (n > 0) {
- if (n > OFF.length) {
- w.write(OFF);
- n -= OFF.length;
- } else {
- w.write(OFF, 0, n);
- n = 0;
- }
- }
- }
-
- private final void closeElement() throws IOException {
- if (openElement) {
- w.write(">\n");
- }
- openElement = false;
- }
-
- }
-
- /**
- * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
- * documents into smaller chunks. Each chunk is processed by the nested
- * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
- * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
- * useful for running XSLT engine against large XML document that will
- * hardly fit into the memory all together.
- * <p>
- * TODO use complete path for subdocumentRoot
- */
- private static final class InputSlicingHandler extends DefaultHandler {
- private String subdocumentRoot;
-
- private final ContentHandler rootHandler;
-
- private ContentHandlerFactory subdocumentHandlerFactory;
-
- private boolean subdocument = false;
-
- private ContentHandler subdocumentHandler;
-
- /**
- * Constructs a new {@link InputSlicingHandler SubdocumentHandler}
- * object.
- *
- * @param subdocumentRoot
- * name/path to the root element of the subdocument
- * @param rootHandler
- * content handler for the entire document (subdocument
- * envelope).
- * @param subdocumentHandlerFactory
- * a {@link ContentHandlerFactory ContentHandlerFactory} used
- * to create {@link ContentHandler ContentHandler} instances
- * for subdocuments.
- */
- InputSlicingHandler(final String subdocumentRoot,
- final ContentHandler rootHandler,
- final ContentHandlerFactory subdocumentHandlerFactory) {
- this.subdocumentRoot = subdocumentRoot;
- this.rootHandler = rootHandler;
- this.subdocumentHandlerFactory = subdocumentHandlerFactory;
- }
-
- @Override
- public final void startElement(final String namespaceURI,
- final String localName, final String qName,
- final Attributes list) throws SAXException {
- if (subdocument) {
- subdocumentHandler.startElement(namespaceURI, localName, qName,
- list);
- } else if (localName.equals(subdocumentRoot)) {
- subdocumentHandler = subdocumentHandlerFactory
- .createContentHandler();
- subdocumentHandler.startDocument();
- subdocumentHandler.startElement(namespaceURI, localName, qName,
- list);
- subdocument = true;
- } else if (rootHandler != null) {
- rootHandler.startElement(namespaceURI, localName, qName, list);
- }
- }
-
- @Override
- public final void endElement(final String namespaceURI,
- final String localName, final String qName) throws SAXException {
- if (subdocument) {
- subdocumentHandler.endElement(namespaceURI, localName, qName);
- if (localName.equals(subdocumentRoot)) {
- subdocumentHandler.endDocument();
- subdocument = false;
- }
- } else if (rootHandler != null) {
- rootHandler.endElement(namespaceURI, localName, qName);
- }
- }
-
- @Override
- public final void startDocument() throws SAXException {
- if (rootHandler != null) {
- rootHandler.startDocument();
- }
- }
-
- @Override
- public final void endDocument() throws SAXException {
- if (rootHandler != null) {
- rootHandler.endDocument();
-
- }
- }
-
- @Override
- public final void characters(final char[] buff, final int offset,
- final int size) throws SAXException {
- if (subdocument) {
- subdocumentHandler.characters(buff, offset, size);
- } else if (rootHandler != null) {
- rootHandler.characters(buff, offset, size);
- }
- }
-
- }
-
- /**
- * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
- * documents into smaller chunks. Each chunk is processed by the nested
- * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
- * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
- * useful for running XSLT engine against large XML document that will
- * hardly fit into the memory all together.
- *
- * <p>
- * TODO use complete path for subdocumentRoot
- */
- private static final class OutputSlicingHandler extends DefaultHandler {
- private final String subdocumentRoot;
-
- private ContentHandlerFactory subdocumentHandlerFactory;
-
- private final EntryElement entryElement;
-
- private boolean isXml;
-
- private boolean subdocument = false;
-
- private ContentHandler subdocumentHandler;
-
- /**
- * Constructs a new {@link OutputSlicingHandler SubdocumentHandler}
- * object.
- *
- * @param subdocumentHandlerFactory
- * a {@link ContentHandlerFactory ContentHandlerFactory} used
- * to create {@link ContentHandler ContentHandler} instances
- * for subdocuments.
- * @param entryElement
- * TODO.
- * @param isXml
- * TODO.
- */
- OutputSlicingHandler(
- final ContentHandlerFactory subdocumentHandlerFactory,
- final EntryElement entryElement, final boolean isXml) {
- this.subdocumentRoot = "class";
- this.subdocumentHandlerFactory = subdocumentHandlerFactory;
- this.entryElement = entryElement;
- this.isXml = isXml;
- }
-
- @Override
- public final void startElement(final String namespaceURI,
- final String localName, final String qName,
- final Attributes list) throws SAXException {
- if (subdocument) {
- subdocumentHandler.startElement(namespaceURI, localName, qName,
- list);
- } else if (localName.equals(subdocumentRoot)) {
- String name = list.getValue("name");
- if (name == null || name.length() == 0) {
- throw new SAXException(
- "Class element without name attribute.");
- }
- try {
- entryElement.openEntry(isXml ? name + ".class.xml" : name
- + ".class");
- } catch (IOException ex) {
- throw new SAXException(ex.toString(), ex);
- }
- subdocumentHandler = subdocumentHandlerFactory
- .createContentHandler();
- subdocumentHandler.startDocument();
- subdocumentHandler.startElement(namespaceURI, localName, qName,
- list);
- subdocument = true;
- }
- }
-
- @Override
- public final void endElement(final String namespaceURI,
- final String localName, final String qName) throws SAXException {
- if (subdocument) {
- subdocumentHandler.endElement(namespaceURI, localName, qName);
- if (localName.equals(subdocumentRoot)) {
- subdocumentHandler.endDocument();
- subdocument = false;
- try {
- entryElement.closeEntry();
- } catch (IOException ex) {
- throw new SAXException(ex.toString(), ex);
- }
- }
- }
- }
-
- @Override
- public final void startDocument() throws SAXException {
- }
-
- @Override
- public final void endDocument() throws SAXException {
- }
-
- @Override
- public final void characters(final char[] buff, final int offset,
- final int size) throws SAXException {
- if (subdocument) {
- subdocumentHandler.characters(buff, offset, size);
- }
- }
-
- }
-
- private static interface EntryElement {
-
- OutputStream openEntry(String name) throws IOException;
-
- void closeEntry() throws IOException;
-
- }
-
- private static final class SingleDocElement implements EntryElement {
- private final OutputStream os;
-
- SingleDocElement(final OutputStream os) {
- this.os = os;
- }
-
- public OutputStream openEntry(final String name) throws IOException {
- return os;
- }
-
- public void closeEntry() throws IOException {
- os.flush();
- }
-
- }
-
- private static final class ZipEntryElement implements EntryElement {
- private ZipOutputStream zos;
-
- ZipEntryElement(final ZipOutputStream zos) {
- this.zos = zos;
- }
-
- public OutputStream openEntry(final String name) throws IOException {
- ZipEntry entry = new ZipEntry(name);
- zos.putNextEntry(entry);
- return zos;
- }
-
- public void closeEntry() throws IOException {
- zos.flush();
- zos.closeEntry();
- }
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
deleted file mode 100644
index 2f49c24..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/***
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.xml;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-/**
- * SAXAdapter
- *
- * @author Eugene Kuleshov
- */
-public class SAXAdapter {
-
- private final ContentHandler h;
-
- protected SAXAdapter(final ContentHandler h) {
- this.h = h;
- }
-
- protected ContentHandler getContentHandler() {
- return h;
- }
-
- protected void addDocumentStart() {
- try {
- h.startDocument();
- } catch (SAXException ex) {
- throw new RuntimeException(ex.getMessage(), ex.getException());
- }
- }
-
- protected void addDocumentEnd() {
- try {
- h.endDocument();
- } catch (SAXException ex) {
- throw new RuntimeException(ex.getMessage(), ex.getException());
- }
- }
-
- protected final void addStart(final String name, final Attributes attrs) {
- try {
- h.startElement("", name, name, attrs);
- } catch (SAXException ex) {
- throw new RuntimeException(ex.getMessage(), ex.getException());
- }
- }
-
- protected final void addEnd(final String name) {
- try {
- h.endElement("", name, name);
- } catch (SAXException ex) {
- throw new RuntimeException(ex.getMessage(), ex.getException());
- }
- }
-
- protected final void addElement(final String name, final Attributes attrs) {
- addStart(name, attrs);
- addEnd(name);
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
deleted file mode 100644
index 76ad91e..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/***
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.xml;
-
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.Type;
-import org.apache.tapestry5.internal.plastic.asm.TypePath;
-import org.xml.sax.helpers.AttributesImpl;
-
-/**
- * SAXAnnotationAdapter
- *
- * @author Eugene Kuleshov
- */
-public final class SAXAnnotationAdapter extends AnnotationVisitor {
-
- SAXAdapter sa;
-
- private final String elementName;
-
- public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
- final int visible, final String name, final String desc) {
- this(Opcodes.ASM6, sa, elementName, visible, desc, name, -1, -1, null,
- null, null, null);
- }
-
- public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
- final int visible, final int parameter, final String desc) {
- this(Opcodes.ASM6, sa, elementName, visible, desc, null, parameter, -1,
- null, null, null, null);
- }
-
- public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
- final int visible, final String name, final String desc,
- final int typeRef, final TypePath typePath) {
- this(Opcodes.ASM6, sa, elementName, visible, desc, name, -1, typeRef,
- typePath, null, null, null);
- }
-
- public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
- final int visible, final String name, final String desc,
- int typeRef, TypePath typePath, final String[] start,
- final String[] end, final int[] index) {
- this(Opcodes.ASM6, sa, elementName, visible, desc, name, -1, typeRef,
- typePath, start, end, index);
- }
-
- protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
- final String elementName, final int visible, final String desc,
- final String name, final int parameter) {
- this(api, sa, elementName, visible, desc, name, parameter, -1, null,
- null, null, null);
- }
-
- protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
- final String elementName, final int visible, final String desc,
- final String name, final int parameter, final int typeRef,
- final TypePath typePath, final String[] start, final String[] end,
- final int[] index) {
- super(api);
- this.sa = sa;
- this.elementName = elementName;
-
- AttributesImpl att = new AttributesImpl();
- if (name != null) {
- att.addAttribute("", "name", "name", "", name);
- }
- if (visible != 0) {
- att.addAttribute("", "visible", "visible", "", visible > 0 ? "true"
- : "false");
- }
- if (parameter != -1) {
- att.addAttribute("", "parameter", "parameter", "",
- Integer.toString(parameter));
- }
- if (desc != null) {
- att.addAttribute("", "desc", "desc", "", desc);
- }
- if (typeRef != -1) {
- att.addAttribute("", "typeRef", "typeRef", "",
- Integer.toString(typeRef));
- }
- if (typePath != null) {
- att.addAttribute("", "typePath", "typePath", "",
- typePath.toString());
- }
- if (start != null) {
- StringBuilder value = new StringBuilder(start[0]);
- for (int i = 1; i < start.length; ++i) {
- value.append(" ").append(start[i]);
- }
- att.addAttribute("", "start", "start", "", value.toString());
- }
- if (end != null) {
- StringBuilder value = new StringBuilder(end[0]);
- for (int i = 1; i < end.length; ++i) {
- value.append(" ").append(end[i]);
- }
- att.addAttribute("", "end", "end", "", value.toString());
- }
- if (index != null) {
- StringBuilder value = new StringBuilder();
- value.append(index[0]);
- for (int i = 1; i < index.length; ++i) {
- value.append(" ").append(index[i]);
- }
- att.addAttribute("", "index", "index", "", value.toString());
- }
-
- sa.addStart(elementName, att);
- }
-
- @Override
- public void visit(final String name, final Object value) {
- Class<?> c = value.getClass();
- if (c.isArray()) {
- AnnotationVisitor av = visitArray(name);
- if (value instanceof byte[]) {
- byte[] b = (byte[]) value;
- for (int i = 0; i < b.length; i++) {
- av.visit(null, b[i]);
- }
-
- } else if (value instanceof char[]) {
- char[] b = (char[]) value;
- for (int i = 0; i < b.length; i++) {
- av.visit(null, b[i]);
- }
-
- } else if (value instanceof short[]) {
- short[] b = (short[]) value;
- for (int i = 0; i < b.length; i++) {
- av.visit(null, b[i]);
- }
-
- } else if (value instanceof boolean[]) {
- boolean[] b = (boolean[]) value;
- for (int i = 0; i < b.length; i++) {
- av.visit(null, Boolean.valueOf(b[i]));
- }
-
- } else if (value instanceof int[]) {
- int[] b = (int[]) value;
- for (int i = 0; i < b.length; i++) {
- av.visit(null, b[i]);
- }
-
- } else if (value instanceof long[]) {
- long[] b = (long[]) value;
- for (int i = 0; i < b.length; i++) {
- av.visit(null, b[i]);
- }
-
- } else if (value instanceof float[]) {
- float[] b = (float[]) value;
- for (int i = 0; i < b.length; i++) {
- av.visit(null, b[i]);
- }
-
- } else if (value instanceof double[]) {
- double[] b = (double[]) value;
- for (int i = 0; i < b.length; i++) {
- av.visit(null, b[i]);
- }
-
- }
- av.visitEnd();
- } else {
- addValueElement("annotationValue", name, Type.getDescriptor(c),
- value.toString());
- }
- }
-
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- addValueElement("annotationValueEnum", name, desc, value);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String name,
- final String desc) {
- return new SAXAnnotationAdapter(sa, "annotationValueAnnotation", 0,
- name, desc);
- }
-
- @Override
- public AnnotationVisitor visitArray(final String name) {
- return new SAXAnnotationAdapter(sa, "annotationValueArray", 0, name,
- null);
- }
-
- @Override
- public void visitEnd() {
- sa.addEnd(elementName);
- }
-
- private void addValueElement(final String element, final String name,
- final String desc, final String value) {
- AttributesImpl att = new AttributesImpl();
- if (name != null) {
- att.addAttribute("", "name", "name", "", name);
- }
- if (desc != null) {
- att.addAttribute("", "desc", "desc", "", desc);
- }
- if (value != null) {
- att.addAttribute("", "value", "value", "",
- SAXClassAdapter.encode(value));
- }
-
- sa.addElement(element, att);
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
deleted file mode 100644
index 8e41508..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/***
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.xml;
-
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
-import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.TypePath;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.helpers.AttributesImpl;
-
-/**
- * A {@link org.objectweb.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
- * events from the visited class. It can feed any kind of
- * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
- * or XQuery engines.
- *
- * @see org.objectweb.asm.xml.Processor
- * @see org.objectweb.asm.xml.ASMContentHandler
- *
- * @author Eugene Kuleshov
- */
-public final class SAXClassAdapter extends ClassVisitor {
-
- SAXAdapter sa;
-
- private final boolean singleDocument;
-
- /**
- * Pseudo access flag used to distinguish class access flags.
- */
- private static final int ACCESS_CLASS = 262144;
-
- /**
- * Pseudo access flag used to distinguish field access flags.
- */
- private static final int ACCESS_FIELD = 524288;
-
- /**
- * Pseudo access flag used to distinguish inner class flags.
- */
- private static final int ACCESS_INNER = 1048576;
-
- /**
- * Pseudo access flag used to distinguish module flags.
- */
- static final int ACCESS_MODULE = 2097152;
-
- /**
- * Pseudo access flag used to distinguish module requires flags.
- */
- static final int ACCESS_MODULE_REQUIRES = 4194304;
-
- /**
- * Constructs a new {@link SAXClassAdapter SAXClassAdapter} object.
- *
- * @param h
- * content handler that will be used to send SAX 2.0 events.
- * @param singleDocument
- * if <tt>true</tt> adapter will not produce
- * {@link ContentHandler#startDocument() startDocument()} and
- * {@link ContentHandler#endDocument() endDocument()} events.
- */
- public SAXClassAdapter(final ContentHandler h, boolean singleDocument) {
- super(Opcodes.ASM6);
- this.sa = new SAXAdapter(h);
- this.singleDocument = singleDocument;
- if (!singleDocument) {
- sa.addDocumentStart();
- }
- }
-
- @Override
- public void visitSource(final String source, final String debug) {
- AttributesImpl att = new AttributesImpl();
- if (source != null) {
- att.addAttribute("", "file", "file", "", encode(source));
- }
- if (debug != null) {
- att.addAttribute("", "debug", "debug", "", encode(debug));
- }
-
- sa.addElement("source", att);
- }
-
- @Override
- public ModuleVisitor visitModule(final String name, final int access,
- final String version) {
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "name", "name", "", name);
- StringBuilder sb = new StringBuilder();
- appendAccess(access | ACCESS_MODULE, sb);
- att.addAttribute("", "access", "access", "", sb.toString());
- if (version != null) {
- att.addAttribute("", "version", "version", "", encode(version));
- }
- sa.addStart("module", att);
- return new SAXModuleAdapter(sa);
- }
-
- @Override
- public void visitOuterClass(final String owner, final String name,
- final String desc) {
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "owner", "owner", "", owner);
- if (name != null) {
- att.addAttribute("", "name", "name", "", name);
- }
- if (desc != null) {
- att.addAttribute("", "desc", "desc", "", desc);
- }
-
- sa.addElement("outerclass", att);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
- null, desc);
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
- null, desc, typeRef, typePath);
- }
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- StringBuilder sb = new StringBuilder();
- appendAccess(access | ACCESS_CLASS, sb);
-
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "access", "access", "", sb.toString());
- if (name != null) {
- att.addAttribute("", "name", "name", "", name);
- }
- if (signature != null) {
- att.addAttribute("", "signature", "signature", "",
- encode(signature));
- }
- if (superName != null) {
- att.addAttribute("", "parent", "parent", "", superName);
- }
- att.addAttribute("", "major", "major", "",
- Integer.toString(version & 0xFFFF));
- att.addAttribute("", "minor", "minor", "",
- Integer.toString(version >>> 16));
- sa.addStart("class", att);
-
- sa.addStart("interfaces", new AttributesImpl());
- if (interfaces != null && interfaces.length > 0) {
- for (int i = 0; i < interfaces.length; i++) {
- AttributesImpl att2 = new AttributesImpl();
- att2.addAttribute("", "name", "name", "", interfaces[i]);
- sa.addElement("interface", att2);
- }
- }
- sa.addEnd("interfaces");
- }
-
- @Override
- public FieldVisitor visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- StringBuilder sb = new StringBuilder();
- appendAccess(access | ACCESS_FIELD, sb);
-
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "access", "access", "", sb.toString());
- att.addAttribute("", "name", "name", "", name);
- att.addAttribute("", "desc", "desc", "", desc);
- if (signature != null) {
- att.addAttribute("", "signature", "signature", "",
- encode(signature));
- }
- if (value != null) {
- att.addAttribute("", "value", "value", "", encode(value.toString()));
- }
-
- return new SAXFieldAdapter(sa, att);
- }
-
- @Override
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- StringBuilder sb = new StringBuilder();
- appendAccess(access, sb);
-
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "access", "access", "", sb.toString());
- att.addAttribute("", "name", "name", "", name);
- att.addAttribute("", "desc", "desc", "", desc);
- if (signature != null) {
- att.addAttribute("", "signature", "signature", "", signature);
- }
- sa.addStart("method", att);
-
- sa.addStart("exceptions", new AttributesImpl());
- if (exceptions != null && exceptions.length > 0) {
- for (int i = 0; i < exceptions.length; i++) {
- AttributesImpl att2 = new AttributesImpl();
- att2.addAttribute("", "name", "name", "", exceptions[i]);
- sa.addElement("exception", att2);
- }
- }
- sa.addEnd("exceptions");
-
- return new SAXCodeAdapter(sa, access);
- }
-
- @Override
- public final void visitInnerClass(final String name,
- final String outerName, final String innerName, final int access) {
- StringBuilder sb = new StringBuilder();
- appendAccess(access | ACCESS_INNER, sb);
-
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "access", "access", "", sb.toString());
- if (name != null) {
- att.addAttribute("", "name", "name", "", name);
- }
- if (outerName != null) {
- att.addAttribute("", "outerName", "outerName", "", outerName);
- }
- if (innerName != null) {
- att.addAttribute("", "innerName", "innerName", "", innerName);
- }
- sa.addElement("innerclass", att);
- }
-
- @Override
- public final void visitEnd() {
- sa.addEnd("class");
- if (!singleDocument) {
- sa.addDocumentEnd();
- }
- }
-
- static final String encode(final String s) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < s.length(); i++) {
- char c = s.charAt(i);
- if (c == '\\') {
- sb.append("\\\\");
- } else if (c < 0x20 || c > 0x7f) {
- sb.append("\\u");
- if (c < 0x10) {
- sb.append("000");
- } else if (c < 0x100) {
- sb.append("00");
- } else if (c < 0x1000) {
- sb.append('0');
- }
- sb.append(Integer.toString(c, 16));
- } else {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- static void appendAccess(final int access, final StringBuilder sb) {
- if ((access & Opcodes.ACC_PUBLIC) != 0) {
- sb.append("public ");
- }
- if ((access & Opcodes.ACC_PRIVATE) != 0) {
- sb.append("private ");
- }
- if ((access & Opcodes.ACC_PROTECTED) != 0) {
- sb.append("protected ");
- }
- if ((access & Opcodes.ACC_FINAL) != 0) {
- if ((access & ACCESS_MODULE) == 0) {
- sb.append("final ");
- } else {
- sb.append("transitive ");
- }
- }
- if ((access & Opcodes.ACC_STATIC) != 0) {
- sb.append("static ");
- }
- if ((access & Opcodes.ACC_SUPER) != 0) {
- if ((access & ACCESS_CLASS) == 0) {
- if ((access & ACCESS_MODULE_REQUIRES) != 0) {
- sb.append("transitive ");
- } else {
- if ((access & ACCESS_MODULE) == 0) {
- sb.append("synchronized ");
- } else {
- sb.append("open ");
- }
- }
- } else {
- sb.append("super ");
- }
- }
- if ((access & Opcodes.ACC_VOLATILE) != 0) {
- if ((access & ACCESS_FIELD) == 0) {
- sb.append("bridge ");
- } else {
- if ((access & ACCESS_MODULE_REQUIRES) == 0) {
- sb.append("volatile ");
- } else {
- sb.append("static ");
- }
- }
- }
- if ((access & Opcodes.ACC_TRANSIENT) != 0) {
- if ((access & ACCESS_FIELD) == 0) {
- sb.append("varargs ");
- } else {
- sb.append("transient ");
- }
- }
- if ((access & Opcodes.ACC_NATIVE) != 0) {
- sb.append("native ");
- }
- if ((access & Opcodes.ACC_STRICT) != 0) {
- sb.append("strict ");
- }
- if ((access & Opcodes.ACC_INTERFACE) != 0) {
- sb.append("interface ");
- }
- if ((access & Opcodes.ACC_ABSTRACT) != 0) {
- sb.append("abstract ");
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- sb.append("synthetic ");
- }
- if ((access & Opcodes.ACC_ANNOTATION) != 0) {
- sb.append("annotation ");
- }
- if ((access & Opcodes.ACC_ENUM) != 0) {
- sb.append("enum ");
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- sb.append("deprecated ");
- }
- if ((access & Opcodes.ACC_MANDATED) != 0) {
- if ((access & ACCESS_CLASS) == 0) {
- sb.append("module ");
- } else {
- sb.append("mandated ");
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
deleted file mode 100644
index 3b96007..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/***
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.xml;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Handle;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.Type;
-import org.apache.tapestry5.internal.plastic.asm.TypePath;
-import org.apache.tapestry5.internal.plastic.asm.util.Printer;
-import org.xml.sax.helpers.AttributesImpl;
-
-/**
- * A {@link MethodVisitor} that generates SAX 2.0 events from the visited
- * method.
- *
- * @see org.objectweb.asm.xml.SAXClassAdapter
- * @see org.objectweb.asm.xml.Processor
- *
- * @author Eugene Kuleshov
- */
-public final class SAXCodeAdapter extends MethodVisitor {
-
- static final String[] TYPES = { "top", "int", "float", "double", "long",
- "null", "uninitializedThis" };
-
- SAXAdapter sa;
-
- int access;
-
- private final Map<Label, String> labelNames;
-
- /**
- * Constructs a new {@link SAXCodeAdapter SAXCodeAdapter} object.
- *
- * @param sa
- * content handler that will be used to send SAX 2.0 events.
- */
- public SAXCodeAdapter(final SAXAdapter sa, final int access) {
- super(Opcodes.ASM6);
- this.sa = sa;
- this.access = access;
- this.labelNames = new HashMap<Label, String>();
- }
-
- @Override
- public void visitParameter(String name, int access) {
- AttributesImpl attrs = new AttributesImpl();
- if (name != null) {
- attrs.addAttribute("", "name", "name", "", name);
- }
- StringBuilder sb = new StringBuilder();
- SAXClassAdapter.appendAccess(access, sb);
- attrs.addAttribute("", "access", "access", "", sb.toString());
- sa.addElement("parameter", attrs);
- }
-
- @Override
- public final void visitCode() {
- if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_NATIVE)) == 0) {
- sa.addStart("code", new AttributesImpl());
- }
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- AttributesImpl attrs = new AttributesImpl();
- switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- if (type == Opcodes.F_NEW) {
- attrs.addAttribute("", "type", "type", "", "NEW");
- } else {
- attrs.addAttribute("", "type", "type", "", "FULL");
- }
- sa.addStart("frame", attrs);
- appendFrameTypes(true, nLocal, local);
- appendFrameTypes(false, nStack, stack);
- break;
- case Opcodes.F_APPEND:
- attrs.addAttribute("", "type", "type", "", "APPEND");
- sa.addStart("frame", attrs);
- appendFrameTypes(true, nLocal, local);
- break;
- case Opcodes.F_CHOP:
- attrs.addAttribute("", "type", "type", "", "CHOP");
- attrs.addAttribute("", "count", "count", "",
- Integer.toString(nLocal));
- sa.addStart("frame", attrs);
- break;
- case Opcodes.F_SAME:
- attrs.addAttribute("", "type", "type", "", "SAME");
- sa.addStart("frame", attrs);
- break;
- case Opcodes.F_SAME1:
- attrs.addAttribute("", "type", "type", "", "SAME1");
- sa.addStart("frame", attrs);
- appendFrameTypes(false, 1, stack);
- break;
- }
- sa.addEnd("frame");
- }
-
- private void appendFrameTypes(final boolean local, final int n,
- final Object[] types) {
- for (int i = 0; i < n; ++i) {
- Object type = types[i];
- AttributesImpl attrs = new AttributesImpl();
- if (type instanceof String) {
- attrs.addAttribute("", "type", "type", "", (String) type);
- } else if (type instanceof Integer) {
- attrs.addAttribute("", "type", "type", "",
- TYPES[((Integer) type).intValue()]);
- } else {
- attrs.addAttribute("", "type", "type", "", "uninitialized");
- attrs.addAttribute("", "label", "label", "",
- getLabel((Label) type));
- }
- sa.addElement(local ? "local" : "stack", attrs);
- }
- }
-
- @Override
- public final void visitInsn(final int opcode) {
- sa.addElement(Printer.OPCODES[opcode], new AttributesImpl());
- }
-
- @Override
- public final void visitIntInsn(final int opcode, final int operand) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "value", "value", "", Integer.toString(operand));
- sa.addElement(Printer.OPCODES[opcode], attrs);
- }
-
- @Override
- public final void visitVarInsn(final int opcode, final int var) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "var", "var", "", Integer.toString(var));
- sa.addElement(Printer.OPCODES[opcode], attrs);
- }
-
- @Override
- public final void visitTypeInsn(final int opcode, final String type) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "desc", "desc", "", type);
- sa.addElement(Printer.OPCODES[opcode], attrs);
- }
-
- @Override
- public final void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "owner", "owner", "", owner);
- attrs.addAttribute("", "name", "name", "", name);
- attrs.addAttribute("", "desc", "desc", "", desc);
- sa.addElement(Printer.OPCODES[opcode], attrs);
- }
-
- @Override
- public final void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "owner", "owner", "", owner);
- attrs.addAttribute("", "name", "name", "", name);
- attrs.addAttribute("", "desc", "desc", "", desc);
- attrs.addAttribute("", "itf", "itf", "", itf ? "true" : "false");
- sa.addElement(Printer.OPCODES[opcode], attrs);
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "name", "name", "", name);
- attrs.addAttribute("", "desc", "desc", "", desc);
- attrs.addAttribute("", "bsm", "bsm", "",
- SAXClassAdapter.encode(bsm.toString()));
- sa.addStart("INVOKEDYNAMIC", attrs);
- for (int i = 0; i < bsmArgs.length; i++) {
- sa.addElement("bsmArg", getConstantAttribute(bsmArgs[i]));
- }
- sa.addEnd("INVOKEDYNAMIC");
- }
-
- @Override
- public final void visitJumpInsn(final int opcode, final Label label) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "label", "label", "", getLabel(label));
- sa.addElement(Printer.OPCODES[opcode], attrs);
- }
-
- @Override
- public final void visitLabel(final Label label) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "name", "name", "", getLabel(label));
- sa.addElement("Label", attrs);
- }
-
- @Override
- public final void visitLdcInsn(final Object cst) {
- sa.addElement(Printer.OPCODES[Opcodes.LDC], getConstantAttribute(cst));
- }
-
- private static AttributesImpl getConstantAttribute(final Object cst) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "cst", "cst", "",
- SAXClassAdapter.encode(cst.toString()));
- attrs.addAttribute("", "desc", "desc", "",
- Type.getDescriptor(cst.getClass()));
- return attrs;
- }
-
- @Override
- public final void visitIincInsn(final int var, final int increment) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "var", "var", "", Integer.toString(var));
- attrs.addAttribute("", "inc", "inc", "", Integer.toString(increment));
- sa.addElement(Printer.OPCODES[Opcodes.IINC], attrs);
- }
-
- @Override
- public final void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "min", "min", "", Integer.toString(min));
- attrs.addAttribute("", "max", "max", "", Integer.toString(max));
- attrs.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
- String o = Printer.OPCODES[Opcodes.TABLESWITCH];
- sa.addStart(o, attrs);
- for (int i = 0; i < labels.length; i++) {
- AttributesImpl att2 = new AttributesImpl();
- att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
- sa.addElement("label", att2);
- }
- sa.addEnd(o);
- }
-
- @Override
- public final void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- AttributesImpl att = new AttributesImpl();
- att.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
- String o = Printer.OPCODES[Opcodes.LOOKUPSWITCH];
- sa.addStart(o, att);
- for (int i = 0; i < labels.length; i++) {
- AttributesImpl att2 = new AttributesImpl();
- att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
- att2.addAttribute("", "key", "key", "", Integer.toString(keys[i]));
- sa.addElement("label", att2);
- }
- sa.addEnd(o);
- }
-
- @Override
- public final void visitMultiANewArrayInsn(final String desc, final int dims) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "desc", "desc", "", desc);
- attrs.addAttribute("", "dims", "dims", "", Integer.toString(dims));
- sa.addElement(Printer.OPCODES[Opcodes.MULTIANEWARRAY], attrs);
- }
-
- @Override
- public final void visitTryCatchBlock(final Label start, final Label end,
- final Label handler, final String type) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "start", "start", "", getLabel(start));
- attrs.addAttribute("", "end", "end", "", getLabel(end));
- attrs.addAttribute("", "handler", "handler", "", getLabel(handler));
- if (type != null) {
- attrs.addAttribute("", "type", "type", "", type);
- }
- sa.addElement("TryCatch", attrs);
- }
-
- @Override
- public final void visitMaxs(final int maxStack, final int maxLocals) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "maxStack", "maxStack", "",
- Integer.toString(maxStack));
- attrs.addAttribute("", "maxLocals", "maxLocals", "",
- Integer.toString(maxLocals));
- sa.addElement("Max", attrs);
-
- sa.addEnd("code");
- }
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "name", "name", "", name);
- attrs.addAttribute("", "desc", "desc", "", desc);
- if (signature != null) {
- attrs.addAttribute("", "signature", "signature", "",
- SAXClassAdapter.encode(signature));
- }
- attrs.addAttribute("", "start", "start", "", getLabel(start));
- attrs.addAttribute("", "end", "end", "", getLabel(end));
- attrs.addAttribute("", "var", "var", "", Integer.toString(index));
- sa.addElement("LocalVar", attrs);
- }
-
- @Override
- public final void visitLineNumber(final int line, final Label start) {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "line", "line", "", Integer.toString(line));
- attrs.addAttribute("", "start", "start", "", getLabel(start));
- sa.addElement("LineNumber", attrs);
- }
-
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- return new SAXAnnotationAdapter(sa, "annotationDefault", 0, null, null);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
- null, desc);
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
- null, desc, typeRef, typePath);
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- return new SAXAnnotationAdapter(sa, "parameterAnnotation", visible ? 1
- : -1, parameter, desc);
- }
-
- @Override
- public AnnotationVisitor visitInsnAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- return new SAXAnnotationAdapter(sa, "insnAnnotation", visible ? 1 : -1,
- null, desc, typeRef, typePath);
- }
-
- @Override
- public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- return new SAXAnnotationAdapter(sa, "tryCatchAnnotation", visible ? 1
- : -1, null, desc, typeRef, typePath);
- }
-
- @Override
- public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
- TypePath typePath, Label[] start, Label[] end, int[] index,
- String desc, boolean visible) {
- String[] s = new String[start.length];
- String[] e = new String[end.length];
- for (int i = 0; i < s.length; ++i) {
- s[i] = getLabel(start[i]);
- }
- for (int i = 0; i < e.length; ++i) {
- e[i] = getLabel(end[i]);
- }
- return new SAXAnnotationAdapter(sa, "localVariableAnnotation",
- visible ? 1 : -1, null, desc, typeRef, typePath, s, e, index);
- }
-
- @Override
- public void visitEnd() {
- sa.addEnd("method");
- }
-
- private final String getLabel(final Label label) {
- String name = labelNames.get(label);
- if (name == null) {
- name = Integer.toString(labelNames.size());
- labelNames.put(label, name);
- }
- return name;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
deleted file mode 100644
index 7f0b90e..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/***
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.xml;
-
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.TypePath;
-import org.xml.sax.Attributes;
-
-/**
- * SAXFieldAdapter
- *
- * @author Eugene Kuleshov
- */
-public final class SAXFieldAdapter extends FieldVisitor {
-
- SAXAdapter sa;
-
- public SAXFieldAdapter(final SAXAdapter sa, final Attributes att) {
- super(Opcodes.ASM6);
- this.sa = sa;
- sa.addStart("field", att);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
- null, desc);
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
- null, desc, typeRef, typePath);
- }
-
- @Override
- public void visitEnd() {
- sa.addEnd("field");
- }
-}
[11/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
old mode 100644
new mode 100755
index f66971c..c0b129c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
@@ -1,1035 +1,1066 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
+import org.apache.tapestry5.internal.plastic.asm.*;
+import org.apache.tapestry5.internal.plastic.asm.tree.ClassNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.*;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Frame;
+
import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Attribute;
-import org.apache.tapestry5.internal.plastic.asm.ClassReader;
-import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
-import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.Type;
-import org.apache.tapestry5.internal.plastic.asm.TypePath;
-import org.apache.tapestry5.internal.plastic.asm.TypeReference;
-import org.apache.tapestry5.internal.plastic.asm.tree.ClassNode;
-import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
-import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
-import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
-import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Frame;
-import org.apache.tapestry5.internal.plastic.asm.tree.analysis.SimpleVerifier;
-
/**
- * A {@link ClassVisitor} that checks that its methods are properly used. More
- * precisely this class adapter checks each method call individually, based
- * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>
- * of method calls. For example, the invalid sequence
- * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
- * "i", "D", null)</tt> will <i>not</i> be detected by this class adapter.
- *
- * <p>
- * <code>CheckClassAdapter</code> can be also used to verify bytecode
- * transformations in order to make sure transformed bytecode is sane. For
- * example:
- *
+ * A {@link ClassVisitor} that checks that its methods are properly used. More precisely this class
+ * adapter checks each method call individually, based <i>only</i> on its arguments, but does
+ * <i>not</i> check the <i>sequence</i> of method calls. For example, the invalid sequence {@code
+ * visitField(ACC_PUBLIC, "i", "I", null)} {@code visitField(ACC_PUBLIC, "i", "D", null)} will
+ * <i>not</i> be detected by this class adapter.
+ *
+ * <p><code>CheckClassAdapter</code> can be also used to verify bytecode transformations in order to
+ * make sure that the transformed bytecode is sane. For example:
+ *
* <pre>
- * InputStream is = ...; // get bytes for the source class
- * ClassReader cr = new ClassReader(is);
- * ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
- * ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw));
- * cr.accept(cv, 0);
- *
- * StringWriter sw = new StringWriter();
- * PrintWriter pw = new PrintWriter(sw);
- * CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);
- * assertTrue(sw.toString(), sw.toString().length()==0);
+ * InputStream inputStream = ...; // get bytes for the source class
+ * ClassReader classReader = new ClassReader(inputStream);
+ * ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
+ * ClassVisitor classVisitor = new <b>MyClassAdapter</b>(new CheckClassAdapter(classWriter, true));
+ * classReader.accept(classVisitor, 0);
+ *
+ * StringWriter stringWriter = new StringWriter();
+ * PrintWriter printWriter = new PrintWriter(stringWriter);
+ * CheckClassAdapter.verify(new ClassReader(classWriter.toByteArray()), false, printWriter);
+ * assertTrue(stringWriter.toString().isEmpty());
* </pre>
- *
- * Above code runs transformed bytecode trough the
- * <code>CheckClassAdapter</code>. It won't be exactly the same verification as
- * JVM does, but it run data flow analysis for the code of each method and
- * checks that expectations are met for each method instruction.
- *
- * <p>
- * If method bytecode has errors, assertion text will show the erroneous
- * instruction number and dump of the failed method with information about
- * locals and stack slot for each instruction. For example (format is -
- * insnNumber locals : stack):
- *
+ *
+ * <p>The above code pass the transformed bytecode through a <code>CheckClassAdapter</code>, with
+ * data flow checks enabled. These checks are not exactly the same as the JVM verification, but
+ * provide some basic type checking for each method instruction. If the bytecode has errors, the
+ * output text shows the erroneous instruction number, and a dump of the failed method with
+ * information about the type of the local variables and of the operand stack slots for each
+ * instruction. For example (format is - insnNumber locals : stack):
+ *
* <pre>
- * org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
- * at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)
- * at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135)
+ * org.apache.tapestry5.internal.plastic.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
+ * at org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer.analyze(Analyzer.java:...)
+ * at org.apache.tapestry5.internal.plastic.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:...)
* ...
* remove()V
- * 00000 LinkedBlockingQueue$Itr . . . . . . . . :
- * ICONST_0
- * 00001 LinkedBlockingQueue$Itr . . . . . . . . : I
- * ISTORE 2
+ * 00000 LinkedBlockingQueue$Itr . . . . . . . . : ICONST_0
+ * 00001 LinkedBlockingQueue$Itr . . . . . . . . : I ISTORE 2
* 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
* ...
- *
- * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
- * ILOAD 1
- * 00072 <b>?</b>
- * INVOKESPECIAL java/lang/Integer.<init> (I)V
+ * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . : ILOAD 1
+ * 00072 <b>?</b> INVOKESPECIAL java/lang/Integer.<init> (I)V
* ...
* </pre>
- *
- * In the above output you can see that variable 1 loaded by
- * <code>ILOAD 1</code> instruction at position <code>00071</code> is not
- * initialized. You can also see that at the beginning of the method (code
- * inserted by the transformation) variable 2 is initialized.
- *
- * <p>
- * Note that when used like that, <code>CheckClassAdapter.verify()</code> can
- * trigger additional class loading, because it is using
- * <code>SimpleVerifier</code>.
- *
+ *
+ * <p>The above output shows that the local variable 1, loaded by the <code>ILOAD 1</code>
+ * instruction at position <code>00071</code> is not initialized, whereas the local variable 2 is
+ * initialized and contains an int value.
+ *
* @author Eric Bruneton
*/
public class CheckClassAdapter extends ClassVisitor {
- /**
- * The class version number.
- */
- private int version;
-
- /**
- * <tt>true</tt> if the visit method has been called.
- */
- private boolean start;
-
- /**
- * <tt>true</tt> if the visitSource method has been called.
- */
- private boolean source;
-
- /**
- * <tt>true</tt> if the visitOuterClass method has been called.
- */
- private boolean outer;
-
- /**
- * <tt>true</tt> if the visitEnd method has been called.
- */
- private boolean end;
-
- /**
- * <tt>true</tt> if the visitModule method has been called.
- */
- private boolean module;
-
- /**
- * The already visited labels. This map associate Integer values to Label
- * keys.
- */
- private Map<Label, Integer> labels;
-
- /**
- * <tt>true</tt> if the method code must be checked with a BasicVerifier.
- */
- private boolean checkDataFlow;
-
- /**
- * Checks a given class.
- * <p>
- * Usage: CheckClassAdapter <binary class name or class file name>
- *
- * @param args
- * the command line arguments.
- *
- * @throws Exception
- * if the class cannot be found, or if an IO exception occurs.
- */
- public static void main(final String[] args) throws Exception {
- if (args.length != 1) {
- System.err.println("Verifies the given class.");
- System.err.println("Usage: CheckClassAdapter "
- + "<fully qualified class name or class file name>");
- return;
- }
- ClassReader cr;
- if (args[0].endsWith(".class")) {
- cr = new ClassReader(new FileInputStream(args[0]));
- } else {
- cr = new ClassReader(args[0]);
- }
+ private static final String ERROR_AT = ": error at index ";
- verify(cr, false, new PrintWriter(System.err));
- }
-
- /**
- * Checks a given class.
- *
- * @param cr
- * a <code>ClassReader</code> that contains bytecode for the
- * analysis.
- * @param loader
- * a <code>ClassLoader</code> which will be used to load
- * referenced classes. This is useful if you are verifiying
- * multiple interdependent classes.
- * @param dump
- * true if bytecode should be printed out not only when errors
- * are found.
- * @param pw
- * write where results going to be printed
- */
- public static void verify(final ClassReader cr, final ClassLoader loader,
- final boolean dump, final PrintWriter pw) {
- ClassNode cn = new ClassNode();
- cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
-
- Type syperType = cn.superName == null ? null : Type
- .getObjectType(cn.superName);
- List<MethodNode> methods = cn.methods;
-
- List<Type> interfaces = new ArrayList<Type>();
- for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) {
- interfaces.add(Type.getObjectType(i.next()));
- }
+ /** Whether the bytecode must be checked with a BasicVerifier. */
+ private boolean checkDataFlow;
- for (int i = 0; i < methods.size(); ++i) {
- MethodNode method = methods.get(i);
- SimpleVerifier verifier = new SimpleVerifier(
- Type.getObjectType(cn.name), syperType, interfaces,
- (cn.access & Opcodes.ACC_INTERFACE) != 0);
- Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier);
- if (loader != null) {
- verifier.setClassLoader(loader);
- }
- try {
- a.analyze(cn.name, method);
- if (!dump) {
- continue;
- }
- } catch (Exception e) {
- e.printStackTrace(pw);
- }
- printAnalyzerResult(method, a, pw);
- }
- pw.flush();
- }
-
- /**
- * Checks a given class
- *
- * @param cr
- * a <code>ClassReader</code> that contains bytecode for the
- * analysis.
- * @param dump
- * true if bytecode should be printed out not only when errors
- * are found.
- * @param pw
- * write where results going to be printed
- */
- public static void verify(final ClassReader cr, final boolean dump,
- final PrintWriter pw) {
- verify(cr, null, dump, pw);
- }
-
- static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a,
- final PrintWriter pw) {
- Frame<BasicValue>[] frames = a.getFrames();
- Textifier t = new Textifier();
- TraceMethodVisitor mv = new TraceMethodVisitor(t);
-
- pw.println(method.name + method.desc);
- for (int j = 0; j < method.instructions.size(); ++j) {
- method.instructions.get(j).accept(mv);
-
- StringBuilder sb = new StringBuilder();
- Frame<BasicValue> f = frames[j];
- if (f == null) {
- sb.append('?');
- } else {
- for (int k = 0; k < f.getLocals(); ++k) {
- sb.append(getShortName(f.getLocal(k).toString()))
- .append(' ');
- }
- sb.append(" : ");
- for (int k = 0; k < f.getStackSize(); ++k) {
- sb.append(getShortName(f.getStack(k).toString()))
- .append(' ');
- }
- }
- while (sb.length() < method.maxStack + method.maxLocals + 1) {
- sb.append(' ');
- }
- pw.print(Integer.toString(j + 100000).substring(1));
- pw.print(" " + sb + " : " + t.text.get(t.text.size() - 1));
- }
- for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
- method.tryCatchBlocks.get(j).accept(mv);
- pw.print(" " + t.text.get(t.text.size() - 1));
- }
- pw.println();
+ /** The class version number. */
+ private int version;
+
+ /** Whether the {@link #visit} method has been called. */
+ private boolean visitCalled;
+
+ /** Whether the {@link #visitModule} method has been called. */
+ private boolean visitModuleCalled;
+
+ /** Whether the {@link #visitSource} method has been called. */
+ private boolean visitSourceCalled;
+
+ /** Whether the {@link #visitOuterClass} method has been called. */
+ private boolean visitOuterClassCalled;
+
+ /** Whether the {@link #visitNestHost} method has been called. */
+ private boolean visitNestHostCalled;
+
+ /**
+ * The common package of all the nest members. Not {@literal null} if the visitNestMember method
+ * has been called.
+ */
+ private String nestMemberPackageName;
+
+ /** Whether the {@link #visitEnd} method has been called. */
+ private boolean visitEndCalled;
+
+ /** The index of the instruction designated by each visited label so far. */
+ private Map<Label, Integer> labelInsnIndices;
+
+ // -----------------------------------------------------------------------------------------------
+ // Constructors
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+ *
+ * @param classVisitor the class visitor to which this adapter must delegate calls.
+ */
+ public CheckClassAdapter(final ClassVisitor classVisitor) {
+ this(classVisitor, true);
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+ *
+ * @param classVisitor the class visitor to which this adapter must delegate calls.
+ * @param checkDataFlow whether to perform basic data flow checks. This option requires valid
+ * maxLocals and maxStack values.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public CheckClassAdapter(final ClassVisitor classVisitor, final boolean checkDataFlow) {
+ this(Opcodes.ASM7, classVisitor, checkDataFlow);
+ if (getClass() != CheckClassAdapter.class) {
+ throw new IllegalStateException();
}
+ }
- private static String getShortName(final String name) {
- int n = name.lastIndexOf('/');
- int k = name.length();
- if (name.charAt(k - 1) == ';') {
- k--;
- }
- return n == -1 ? name : name.substring(n + 1, k);
- }
-
- /**
- * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
- * this constructor</i>. Instead, they must use the
- * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
- *
- * @param cv
- * the class visitor to which this adapter must delegate calls.
- */
- public CheckClassAdapter(final ClassVisitor cv) {
- this(cv, true);
- }
-
- /**
- * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
- * this constructor</i>. Instead, they must use the
- * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
- *
- * @param cv
- * the class visitor to which this adapter must delegate calls.
- * @param checkDataFlow
- * <tt>true</tt> to perform basic data flow checks, or
- * <tt>false</tt> to not perform any data flow check (see
- * {@link CheckMethodAdapter}). This option requires valid
- * maxLocals and maxStack values.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
- this(Opcodes.ASM6, cv, checkDataFlow);
- if (getClass() != CheckClassAdapter.class) {
- throw new IllegalStateException();
- }
+ /**
+ * Constructs a new {@link CheckClassAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param classVisitor the class visitor to which this adapter must delegate calls.
+ * @param checkDataFlow {@literal true} to perform basic data flow checks, or {@literal false} to
+ * not perform any data flow check (see {@link CheckMethodAdapter}). This option requires
+ * valid maxLocals and maxStack values.
+ */
+ protected CheckClassAdapter(
+ final int api, final ClassVisitor classVisitor, final boolean checkDataFlow) {
+ super(api, classVisitor);
+ this.labelInsnIndices = new HashMap<Label, Integer>();
+ this.checkDataFlow = checkDataFlow;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ if (visitCalled) {
+ throw new IllegalStateException("visit must be called only once");
+ }
+ visitCalled = true;
+ checkState();
+ checkAccess(
+ access,
+ Opcodes.ACC_PUBLIC
+ | Opcodes.ACC_FINAL
+ | Opcodes.ACC_SUPER
+ | Opcodes.ACC_INTERFACE
+ | Opcodes.ACC_ABSTRACT
+ | Opcodes.ACC_SYNTHETIC
+ | Opcodes.ACC_ANNOTATION
+ | Opcodes.ACC_ENUM
+ | Opcodes.ACC_DEPRECATED
+ | Opcodes.ACC_MODULE);
+ if (name == null) {
+ throw new IllegalArgumentException("Illegal class name (null)");
+ }
+ if (!name.endsWith("package-info") && !name.endsWith("module-info")) {
+ CheckMethodAdapter.checkInternalName(version, name, "class name");
+ }
+ if ("java/lang/Object".equals(name)) {
+ if (superName != null) {
+ throw new IllegalArgumentException(
+ "The super class name of the Object class must be 'null'");
+ }
+ } else if (name.endsWith("module-info")) {
+ if (superName != null) {
+ throw new IllegalArgumentException(
+ "The super class name of a module-info class must be 'null'");
+ }
+ } else {
+ CheckMethodAdapter.checkInternalName(version, superName, "super class name");
}
+ if (signature != null) {
+ checkClassSignature(signature);
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0 && !"java/lang/Object".equals(superName)) {
+ throw new IllegalArgumentException(
+ "The super class name of interfaces must be 'java/lang/Object'");
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ CheckMethodAdapter.checkInternalName(
+ version, interfaces[i], "interface name at index " + i);
+ }
+ }
+ this.version = version;
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
- /**
- * Constructs a new {@link CheckClassAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param cv
- * the class visitor to which this adapter must delegate calls.
- * @param checkDataFlow
- * <tt>true</tt> to perform basic data flow checks, or
- * <tt>false</tt> to not perform any data flow check (see
- * {@link CheckMethodAdapter}). This option requires valid
- * maxLocals and maxStack values.
- */
- protected CheckClassAdapter(final int api, final ClassVisitor cv,
- final boolean checkDataFlow) {
- super(api, cv);
- this.labels = new HashMap<Label, Integer>();
- this.checkDataFlow = checkDataFlow;
- }
-
- // ------------------------------------------------------------------------
- // Implementation of the ClassVisitor interface
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- if (start) {
- throw new IllegalStateException("visit must be called only once");
- }
- start = true;
- checkState();
- checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
- + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
- + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
- + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
- + Opcodes.ACC_DEPRECATED + Opcodes.ACC_MODULE
- + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- if (name == null) {
- throw new IllegalArgumentException("Illegal class name (null)");
- }
- if (!name.endsWith("package-info")) {
- CheckMethodAdapter.checkInternalName(name, "class name");
- }
- if ("java/lang/Object".equals(name)) {
- if (superName != null) {
- throw new IllegalArgumentException(
- "The super class name of the Object class must be 'null'");
- }
- } else {
- CheckMethodAdapter.checkInternalName(superName, "super class name");
- }
- if (signature != null) {
- checkClassSignature(signature);
- }
- if ((access & Opcodes.ACC_INTERFACE) != 0) {
- if (!"java/lang/Object".equals(superName)) {
- throw new IllegalArgumentException(
- "The super class name of interfaces must be 'java/lang/Object'");
- }
- }
- if (interfaces != null) {
- for (int i = 0; i < interfaces.length; ++i) {
- CheckMethodAdapter.checkInternalName(interfaces[i],
- "interface name at index " + i);
- }
- }
- this.version = version;
- super.visit(version, access, name, signature, superName, interfaces);
+ @Override
+ public void visitSource(final String file, final String debug) {
+ checkState();
+ if (visitSourceCalled) {
+ throw new IllegalStateException("visitSource can be called only once.");
}
+ visitSourceCalled = true;
+ super.visitSource(file, debug);
+ }
- @Override
- public void visitSource(final String file, final String debug) {
- checkState();
- if (source) {
- throw new IllegalStateException(
- "visitSource can be called only once.");
- }
- source = true;
- super.visitSource(file, debug);
+ @Override
+ public ModuleVisitor visitModule(final String name, final int access, final String version) {
+ checkState();
+ if (visitModuleCalled) {
+ throw new IllegalStateException("visitModule can be called only once.");
}
+ visitModuleCalled = true;
+ checkFullyQualifiedName(this.version, name, "module name");
+ checkAccess(access, Opcodes.ACC_OPEN | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED);
+ CheckModuleAdapter checkModuleAdapter =
+ new CheckModuleAdapter(
+ api, super.visitModule(name, access, version), (access & Opcodes.ACC_OPEN) != 0);
+ checkModuleAdapter.classVersion = this.version;
+ return checkModuleAdapter;
+ }
- @Override
- public ModuleVisitor visitModule(String name, int access, String version) {
- checkState();
- if (module) {
- throw new IllegalStateException(
- "visitModule can be called only once.");
- }
- module = true;
- if (name == null) {
- throw new IllegalArgumentException("Illegal module name (null)");
- }
- checkAccess(access, Opcodes.ACC_OPEN | Opcodes.ACC_SYNTHETIC);
- return new CheckModuleAdapter(super.visitModule(name, access, version),
- (access & Opcodes.ACC_OPEN) != 0);
- }
-
- @Override
- public void visitOuterClass(final String owner, final String name,
- final String desc) {
- checkState();
- if (outer) {
- throw new IllegalStateException(
- "visitOuterClass can be called only once.");
- }
- outer = true;
- if (owner == null) {
- throw new IllegalArgumentException("Illegal outer class owner");
- }
- if (desc != null) {
- CheckMethodAdapter.checkMethodDesc(desc);
- }
- super.visitOuterClass(owner, name, desc);
+ @Override
+ public void visitNestHost(final String nestHost) {
+ checkState();
+ CheckMethodAdapter.checkInternalName(version, nestHost, "nestHost");
+ if (visitNestHostCalled) {
+ throw new IllegalStateException("visitNestHost can be called only once.");
}
+ if (nestMemberPackageName != null) {
+ throw new IllegalStateException("visitNestHost and visitNestMember are mutually exclusive.");
+ }
+ visitNestHostCalled = true;
+ super.visitNestHost(nestHost);
+ }
- @Override
- public void visitInnerClass(final String name, final String outerName,
- final String innerName, final int access) {
- checkState();
- CheckMethodAdapter.checkInternalName(name, "class name");
- if (outerName != null) {
- CheckMethodAdapter.checkInternalName(outerName, "outer class name");
- }
- if (innerName != null) {
- int start = 0;
- while (start < innerName.length()
- && Character.isDigit(innerName.charAt(start))) {
- start++;
- }
- if (start == 0 || start < innerName.length()) {
- CheckMethodAdapter.checkIdentifier(innerName, start, -1,
- "inner class name");
- }
- }
- checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
- + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
- + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
- + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
- + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
- super.visitInnerClass(name, outerName, innerName, access);
- }
-
- @Override
- public FieldVisitor visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- checkState();
- checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
- + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
- + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
- + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
- + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
- CheckMethodAdapter.checkDesc(desc, false);
- if (signature != null) {
- checkFieldSignature(signature);
- }
- if (value != null) {
- CheckMethodAdapter.checkConstant(value);
- }
- FieldVisitor av = super
- .visitField(access, name, desc, signature, value);
- return new CheckFieldAdapter(av);
- }
-
- @Override
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- checkState();
- checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
- + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
- + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
- + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
- + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
- + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
- CheckMethodAdapter.checkMethodIdentifier(version, name,
- "method name");
- }
- CheckMethodAdapter.checkMethodDesc(desc);
- if (signature != null) {
- checkMethodSignature(signature);
- }
- if (exceptions != null) {
- for (int i = 0; i < exceptions.length; ++i) {
- CheckMethodAdapter.checkInternalName(exceptions[i],
- "exception name at index " + i);
- }
- }
- CheckMethodAdapter cma;
- if (checkDataFlow) {
- cma = new CheckMethodAdapter(access, name, desc, super.visitMethod(
- access, name, desc, signature, exceptions), labels);
- } else {
- cma = new CheckMethodAdapter(super.visitMethod(access, name, desc,
- signature, exceptions), labels);
- }
- cma.version = version;
- return cma;
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- checkState();
- CheckMethodAdapter.checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- checkState();
- int sort = typeRef >>> 24;
- if (sort != TypeReference.CLASS_TYPE_PARAMETER
- && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND
- && sort != TypeReference.CLASS_EXTENDS) {
- throw new IllegalArgumentException("Invalid type reference sort 0x"
- + Integer.toHexString(sort));
- }
- checkTypeRefAndPath(typeRef, typePath);
- CheckMethodAdapter.checkDesc(desc, false);
- return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
- typePath, desc, visible));
- }
-
- @Override
- public void visitAttribute(final Attribute attr) {
- checkState();
- if (attr == null) {
- throw new IllegalArgumentException(
- "Invalid attribute (must not be null)");
- }
- super.visitAttribute(attr);
+ @Override
+ public void visitNestMember(final String nestMember) {
+ checkState();
+ CheckMethodAdapter.checkInternalName(version, nestMember, "nestMember");
+ if (visitNestHostCalled) {
+ throw new IllegalStateException(
+ "visitMemberOfNest and visitNestHost are mutually exclusive.");
+ }
+ String packageName = packageName(nestMember);
+ if (nestMemberPackageName == null) {
+ nestMemberPackageName = packageName;
+ } else if (!nestMemberPackageName.equals(packageName)) {
+ throw new IllegalStateException(
+ "nest member " + nestMember + " should be in the package " + nestMemberPackageName);
}
+ super.visitNestMember(nestMember);
+ }
- @Override
- public void visitEnd() {
- checkState();
- end = true;
- super.visitEnd();
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ checkState();
+ if (visitOuterClassCalled) {
+ throw new IllegalStateException("visitOuterClass can be called only once.");
+ }
+ visitOuterClassCalled = true;
+ if (owner == null) {
+ throw new IllegalArgumentException("Illegal outer class owner");
}
+ if (descriptor != null) {
+ CheckMethodAdapter.checkMethodDescriptor(version, descriptor);
+ }
+ super.visitOuterClass(owner, name, descriptor);
+ }
- // ------------------------------------------------------------------------
- // Utility methods
- // ------------------------------------------------------------------------
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ checkState();
+ CheckMethodAdapter.checkInternalName(version, name, "class name");
+ if (outerName != null) {
+ CheckMethodAdapter.checkInternalName(version, outerName, "outer class name");
+ }
+ if (innerName != null) {
+ int startIndex = 0;
+ while (startIndex < innerName.length() && Character.isDigit(innerName.charAt(startIndex))) {
+ startIndex++;
+ }
+ if (startIndex == 0 || startIndex < innerName.length()) {
+ CheckMethodAdapter.checkIdentifier(version, innerName, startIndex, -1, "inner class name");
+ }
+ }
+ checkAccess(
+ access,
+ Opcodes.ACC_PUBLIC
+ | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED
+ | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL
+ | Opcodes.ACC_INTERFACE
+ | Opcodes.ACC_ABSTRACT
+ | Opcodes.ACC_SYNTHETIC
+ | Opcodes.ACC_ANNOTATION
+ | Opcodes.ACC_ENUM);
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
- /**
- * Checks that the visit method has been called and that visitEnd has not
- * been called.
- */
- private void checkState() {
- if (!start) {
- throw new IllegalStateException(
- "Cannot visit member before visit has been called.");
- }
- if (end) {
- throw new IllegalStateException(
- "Cannot visit member after visitEnd has been called.");
- }
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ checkState();
+ checkAccess(
+ access,
+ Opcodes.ACC_PUBLIC
+ | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED
+ | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL
+ | Opcodes.ACC_VOLATILE
+ | Opcodes.ACC_TRANSIENT
+ | Opcodes.ACC_SYNTHETIC
+ | Opcodes.ACC_ENUM
+ | Opcodes.ACC_DEPRECATED);
+ CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
+ CheckMethodAdapter.checkDescriptor(version, descriptor, /* canBeVoid = */ false);
+ if (signature != null) {
+ checkFieldSignature(signature);
}
+ if (value != null) {
+ CheckMethodAdapter.checkConstant(value);
+ }
+ return new CheckFieldAdapter(api, super.visitField(access, name, descriptor, signature, value));
+ }
- /**
- * Checks that the given access flags do not contain invalid flags. This
- * method also checks that mutually incompatible flags are not set
- * simultaneously.
- *
- * @param access
- * the access flags to be checked
- * @param possibleAccess
- * the valid access flags.
- */
- static void checkAccess(final int access, final int possibleAccess) {
- if ((access & ~possibleAccess) != 0) {
- throw new IllegalArgumentException("Invalid access flags: "
- + access);
- }
- int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
- int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
- int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
- if (pub + pri + pro > 1) {
- throw new IllegalArgumentException(
- "public private and protected are mutually exclusive: "
- + access);
- }
- int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
- int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
- if (fin + abs > 1) {
- throw new IllegalArgumentException(
- "final and abstract are mutually exclusive: " + access);
- }
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ checkState();
+ checkAccess(
+ access,
+ Opcodes.ACC_PUBLIC
+ | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED
+ | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL
+ | Opcodes.ACC_SYNCHRONIZED
+ | Opcodes.ACC_BRIDGE
+ | Opcodes.ACC_VARARGS
+ | Opcodes.ACC_NATIVE
+ | Opcodes.ACC_ABSTRACT
+ | Opcodes.ACC_STRICT
+ | Opcodes.ACC_SYNTHETIC
+ | Opcodes.ACC_DEPRECATED);
+ if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
+ CheckMethodAdapter.checkMethodIdentifier(version, name, "method name");
+ }
+ CheckMethodAdapter.checkMethodDescriptor(version, descriptor);
+ if (signature != null) {
+ checkMethodSignature(signature);
+ }
+ if (exceptions != null) {
+ for (int i = 0; i < exceptions.length; ++i) {
+ CheckMethodAdapter.checkInternalName(
+ version, exceptions[i], "exception name at index " + i);
+ }
+ }
+ CheckMethodAdapter checkMethodAdapter;
+ if (checkDataFlow) {
+ checkMethodAdapter =
+ new CheckMethodAdapter(
+ api,
+ access,
+ name,
+ descriptor,
+ super.visitMethod(access, name, descriptor, signature, exceptions),
+ labelInsnIndices);
+ } else {
+ checkMethodAdapter =
+ new CheckMethodAdapter(
+ api,
+ super.visitMethod(access, name, descriptor, signature, exceptions),
+ labelInsnIndices);
}
+ checkMethodAdapter.version = version;
+ return checkMethodAdapter;
+ }
- /**
- * Checks a class signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- */
- public static void checkClassSignature(final String signature) {
- // ClassSignature:
- // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ checkState();
+ CheckMethodAdapter.checkDescriptor(version, descriptor, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(descriptor, visible));
+ }
- int pos = 0;
- if (getChar(signature, 0) == '<') {
- pos = checkFormalTypeParameters(signature, pos);
- }
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ checkState();
+ int sort = new TypeReference(typeRef).getSort();
+ if (sort != TypeReference.CLASS_TYPE_PARAMETER
+ && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND
+ && sort != TypeReference.CLASS_EXTENDS) {
+ throw new IllegalArgumentException(
+ "Invalid type reference sort 0x" + Integer.toHexString(sort));
+ }
+ checkTypeRef(typeRef);
+ CheckMethodAdapter.checkDescriptor(version, descriptor, false);
+ return new CheckAnnotationAdapter(
+ super.visitTypeAnnotation(typeRef, typePath, descriptor, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ checkState();
+ if (attribute == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkState();
+ visitEndCalled = true;
+ super.visitEnd();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
+
+ /** Checks that the visit method has been called and that visitEnd has not been called. */
+ private void checkState() {
+ if (!visitCalled) {
+ throw new IllegalStateException("Cannot visit member before visit has been called.");
+ }
+ if (visitEndCalled) {
+ throw new IllegalStateException("Cannot visit member after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks that the given access flags do not contain invalid flags. This method also checks that
+ * mutually incompatible flags are not set simultaneously.
+ *
+ * @param access the access flags to be checked.
+ * @param possibleAccess the valid access flags.
+ */
+ static void checkAccess(final int access, final int possibleAccess) {
+ if ((access & ~possibleAccess) != 0) {
+ throw new IllegalArgumentException("Invalid access flags: " + access);
+ }
+ int publicProtectedPrivate = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE;
+ if (Integer.bitCount(access & publicProtectedPrivate) > 1) {
+ throw new IllegalArgumentException(
+ "public, protected and private are mutually exclusive: " + access);
+ }
+ if (Integer.bitCount(access & (Opcodes.ACC_FINAL | Opcodes.ACC_ABSTRACT)) > 1) {
+ throw new IllegalArgumentException("final and abstract are mutually exclusive: " + access);
+ }
+ }
+
+ /**
+ * Checks that the given name is a fully qualified name, using dots.
+ *
+ * @param version the class version.
+ * @param name the name to be checked.
+ * @param source the source of 'name' (e.g 'module' for a module name).
+ */
+ static void checkFullyQualifiedName(final int version, final String name, final String source) {
+ try {
+ int startIndex = 0;
+ int dotIndex;
+ while ((dotIndex = name.indexOf('.', startIndex + 1)) != -1) {
+ CheckMethodAdapter.checkIdentifier(version, name, startIndex, dotIndex, null);
+ startIndex = dotIndex + 1;
+ }
+ CheckMethodAdapter.checkIdentifier(version, name, startIndex, name.length(), null);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(
+ "Invalid " + source + " (must be a fully qualified name): " + name, e);
+ }
+ }
+
+ /**
+ * Checks a class signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ public static void checkClassSignature(final String signature) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // ClassSignature:
+ // [TypeParameters] SuperclassSignature SuperinterfaceSignature*
+ // SuperclassSignature:
+ // ClassTypeSignature
+ // SuperinterfaceSignature:
+ // ClassTypeSignature
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkTypeParameters(signature, pos);
+ }
+ pos = checkClassTypeSignature(signature, pos);
+ while (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ERROR_AT + pos);
+ }
+ }
+
+ /**
+ * Checks a method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ public static void checkMethodSignature(final String signature) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // MethodSignature:
+ // [TypeParameters] ( JavaTypeSignature* ) Result ThrowsSignature*
+ // Result:
+ // JavaTypeSignature
+ // VoidDescriptor
+ // ThrowsSignature:
+ // ^ ClassTypeSignature
+ // ^ TypeVariableSignature
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkTypeParameters(signature, pos);
+ }
+ pos = checkChar('(', signature, pos);
+ while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkJavaTypeSignature(signature, pos);
+ }
+ pos = checkChar(')', signature, pos);
+ if (getChar(signature, pos) == 'V') {
+ ++pos;
+ } else {
+ pos = checkJavaTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == '^') {
+ ++pos;
+ if (getChar(signature, pos) == 'L') {
pos = checkClassTypeSignature(signature, pos);
- while (getChar(signature, pos) == 'L') {
- pos = checkClassTypeSignature(signature, pos);
- }
- if (pos != signature.length()) {
- throw new IllegalArgumentException(signature + ": error at index "
- + pos);
- }
+ } else {
+ pos = checkTypeVariableSignature(signature, pos);
+ }
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ERROR_AT + pos);
}
+ }
- /**
- * Checks a method signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- */
- public static void checkMethodSignature(final String signature) {
- // MethodTypeSignature:
- // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
- // ^ClassTypeSignature | ^TypeVariableSignature )*
-
- int pos = 0;
- if (getChar(signature, 0) == '<') {
- pos = checkFormalTypeParameters(signature, pos);
- }
- pos = checkChar('(', signature, pos);
- while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
- pos = checkTypeSignature(signature, pos);
- }
- pos = checkChar(')', signature, pos);
- if (getChar(signature, pos) == 'V') {
- ++pos;
- } else {
- pos = checkTypeSignature(signature, pos);
- }
- while (getChar(signature, pos) == '^') {
- ++pos;
- if (getChar(signature, pos) == 'L') {
- pos = checkClassTypeSignature(signature, pos);
- } else {
- pos = checkTypeVariableSignature(signature, pos);
- }
- }
- if (pos != signature.length()) {
- throw new IllegalArgumentException(signature + ": error at index "
- + pos);
- }
+ /**
+ * Checks a field signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ public static void checkFieldSignature(final String signature) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // FieldSignature:
+ // ReferenceTypeSignature
+ int pos = checkReferenceTypeSignature(signature, 0);
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ERROR_AT + pos);
}
+ }
- /**
- * Checks a field signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- */
- public static void checkFieldSignature(final String signature) {
- int pos = checkFieldTypeSignature(signature, 0);
- if (pos != signature.length()) {
- throw new IllegalArgumentException(signature + ": error at index "
- + pos);
- }
+ /**
+ * Checks the type parameters of a class or method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param startPos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeParameters(final String signature, final int startPos) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // TypeParameters:
+ // < TypeParameter TypeParameter* >
+ int pos = startPos;
+ pos = checkChar('<', signature, pos);
+ pos = checkTypeParameter(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkTypeParameter(signature, pos);
}
+ return pos + 1;
+ }
- /**
- * Checks the reference to a type in a type annotation.
- *
- * @param typeRef
- * a reference to an annotated type.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- */
- static void checkTypeRefAndPath(int typeRef, TypePath typePath) {
- int mask = 0;
- switch (typeRef >>> 24) {
- case TypeReference.CLASS_TYPE_PARAMETER:
- case TypeReference.METHOD_TYPE_PARAMETER:
- case TypeReference.METHOD_FORMAL_PARAMETER:
- mask = 0xFFFF0000;
- break;
- case TypeReference.FIELD:
- case TypeReference.METHOD_RETURN:
- case TypeReference.METHOD_RECEIVER:
- case TypeReference.LOCAL_VARIABLE:
- case TypeReference.RESOURCE_VARIABLE:
- case TypeReference.INSTANCEOF:
- case TypeReference.NEW:
- case TypeReference.CONSTRUCTOR_REFERENCE:
- case TypeReference.METHOD_REFERENCE:
- mask = 0xFF000000;
- break;
- case TypeReference.CLASS_EXTENDS:
- case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
- case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
- case TypeReference.THROWS:
- case TypeReference.EXCEPTION_PARAMETER:
- mask = 0xFFFFFF00;
- break;
- case TypeReference.CAST:
- case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
- case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
- case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
- case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
- mask = 0xFF0000FF;
- break;
- default:
- throw new IllegalArgumentException("Invalid type reference sort 0x"
- + Integer.toHexString(typeRef >>> 24));
- }
- if ((typeRef & ~mask) != 0) {
- throw new IllegalArgumentException("Invalid type reference 0x"
- + Integer.toHexString(typeRef));
- }
- if (typePath != null) {
- for (int i = 0; i < typePath.getLength(); ++i) {
- int step = typePath.getStep(i);
- if (step != TypePath.ARRAY_ELEMENT
- && step != TypePath.INNER_TYPE
- && step != TypePath.TYPE_ARGUMENT
- && step != TypePath.WILDCARD_BOUND) {
- throw new IllegalArgumentException(
- "Invalid type path step " + i + " in " + typePath);
- }
- if (step != TypePath.TYPE_ARGUMENT
- && typePath.getStepArgument(i) != 0) {
- throw new IllegalArgumentException(
- "Invalid type path step argument for step " + i
- + " in " + typePath);
- }
- }
- }
+ /**
+ * Checks a type parameter of a class or method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param startPos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeParameter(final String signature, final int startPos) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // TypeParameter:
+ // Identifier ClassBound InterfaceBound*
+ // ClassBound:
+ // : [ReferenceTypeSignature]
+ // InterfaceBound:
+ // : ReferenceTypeSignature
+ int pos = startPos;
+ pos = checkSignatureIdentifier(signature, pos);
+ pos = checkChar(':', signature, pos);
+ if ("L[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkReferenceTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == ':') {
+ pos = checkReferenceTypeSignature(signature, pos + 1);
}
+ return pos;
+ }
- /**
- * Checks the formal type parameters of a class or method signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkFormalTypeParameters(final String signature, int pos) {
- // FormalTypeParameters:
- // < FormalTypeParameter+ >
-
- pos = checkChar('<', signature, pos);
- pos = checkFormalTypeParameter(signature, pos);
- while (getChar(signature, pos) != '>') {
- pos = checkFormalTypeParameter(signature, pos);
- }
- return pos + 1;
+ /**
+ * Checks a reference type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkReferenceTypeSignature(final String signature, final int pos) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // ReferenceTypeSignature:
+ // ClassTypeSignature
+ // TypeVariableSignature
+ // ArrayTypeSignature
+ // ArrayTypeSignature:
+ // [ JavaTypeSignature
+ switch (getChar(signature, pos)) {
+ case 'L':
+ return checkClassTypeSignature(signature, pos);
+ case '[':
+ return checkJavaTypeSignature(signature, pos + 1);
+ default:
+ return checkTypeVariableSignature(signature, pos);
}
+ }
- /**
- * Checks a formal type parameter of a class or method signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkFormalTypeParameter(final String signature, int pos) {
- // FormalTypeParameter:
- // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
-
- pos = checkIdentifier(signature, pos);
- pos = checkChar(':', signature, pos);
- if ("L[T".indexOf(getChar(signature, pos)) != -1) {
- pos = checkFieldTypeSignature(signature, pos);
- }
- while (getChar(signature, pos) == ':') {
- pos = checkFieldTypeSignature(signature, pos + 1);
- }
- return pos;
- }
-
- /**
- * Checks a field type signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkFieldTypeSignature(final String signature, int pos) {
- // FieldTypeSignature:
- // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
- //
- // ArrayTypeSignature:
- // [ TypeSignature
-
- switch (getChar(signature, pos)) {
- case 'L':
- return checkClassTypeSignature(signature, pos);
- case '[':
- return checkTypeSignature(signature, pos + 1);
- default:
- return checkTypeVariableSignature(signature, pos);
- }
+ /**
+ * Checks a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param startPos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkClassTypeSignature(final String signature, final int startPos) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // ClassTypeSignature:
+ // L [PackageSpecifier] SimpleClassTypeSignature ClassTypeSignatureSuffix* ;
+ // PackageSpecifier:
+ // Identifier / PackageSpecifier*
+ // SimpleClassTypeSignature:
+ // Identifier [TypeArguments]
+ // ClassTypeSignatureSuffix:
+ // . SimpleClassTypeSignature
+ int pos = startPos;
+ pos = checkChar('L', signature, pos);
+ pos = checkSignatureIdentifier(signature, pos);
+ while (getChar(signature, pos) == '/') {
+ pos = checkSignatureIdentifier(signature, pos + 1);
}
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ while (getChar(signature, pos) == '.') {
+ pos = checkSignatureIdentifier(signature, pos + 1);
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ }
+ return checkChar(';', signature, pos);
+ }
- /**
- * Checks a class type signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkClassTypeSignature(final String signature, int pos) {
- // ClassTypeSignature:
- // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
- // TypeArguments? )* ;
-
- pos = checkChar('L', signature, pos);
- pos = checkIdentifier(signature, pos);
- while (getChar(signature, pos) == '/') {
- pos = checkIdentifier(signature, pos + 1);
- }
- if (getChar(signature, pos) == '<') {
- pos = checkTypeArguments(signature, pos);
- }
- while (getChar(signature, pos) == '.') {
- pos = checkIdentifier(signature, pos + 1);
- if (getChar(signature, pos) == '<') {
- pos = checkTypeArguments(signature, pos);
- }
- }
- return checkChar(';', signature, pos);
- }
-
- /**
- * Checks the type arguments in a class type signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkTypeArguments(final String signature, int pos) {
- // TypeArguments:
- // < TypeArgument+ >
-
- pos = checkChar('<', signature, pos);
- pos = checkTypeArgument(signature, pos);
- while (getChar(signature, pos) != '>') {
- pos = checkTypeArgument(signature, pos);
- }
+ /**
+ * Checks the type arguments in a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param startPos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArguments(final String signature, final int startPos) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // TypeArguments:
+ // < TypeArgument TypeArgument* >
+ int pos = startPos;
+ pos = checkChar('<', signature, pos);
+ pos = checkTypeArgument(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkTypeArgument(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a type argument in a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param startPos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArgument(final String signature, final int startPos) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // TypeArgument:
+ // [WildcardIndicator] ReferenceTypeSignature
+ // *
+ // WildcardIndicator:
+ // +
+ // -
+ int pos = startPos;
+ char c = getChar(signature, pos);
+ if (c == '*') {
+ return pos + 1;
+ } else if (c == '+' || c == '-') {
+ pos++;
+ }
+ return checkReferenceTypeSignature(signature, pos);
+ }
+
+ /**
+ * Checks a type variable signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param startPos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeVariableSignature(final String signature, final int startPos) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // TypeVariableSignature:
+ // T Identifier ;
+ int pos = startPos;
+ pos = checkChar('T', signature, pos);
+ pos = checkSignatureIdentifier(signature, pos);
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks a Java type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param startPos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkJavaTypeSignature(final String signature, final int startPos) {
+ // From https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1:
+ // JavaTypeSignature:
+ // ReferenceTypeSignature
+ // BaseType
+ // BaseType:
+ // (one of)
+ // B C D F I J S Z
+ int pos = startPos;
+ switch (getChar(signature, pos)) {
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z':
return pos + 1;
+ default:
+ return checkReferenceTypeSignature(signature, pos);
}
+ }
- /**
- * Checks a type argument in a class type signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkTypeArgument(final String signature, int pos) {
- // TypeArgument:
- // * | ( ( + | - )? FieldTypeSignature )
-
- char c = getChar(signature, pos);
- if (c == '*') {
- return pos + 1;
- } else if (c == '+' || c == '-') {
- pos++;
- }
- return checkFieldTypeSignature(signature, pos);
- }
-
- /**
- * Checks a type variable signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkTypeVariableSignature(final String signature,
- int pos) {
- // TypeVariableSignature:
- // T Identifier ;
-
- pos = checkChar('T', signature, pos);
- pos = checkIdentifier(signature, pos);
- return checkChar(';', signature, pos);
- }
-
- /**
- * Checks a type signature.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkTypeSignature(final String signature, int pos) {
- // TypeSignature:
- // Z | C | B | S | I | F | J | D | FieldTypeSignature
-
- switch (getChar(signature, pos)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- case 'F':
- case 'J':
- case 'D':
- return pos + 1;
- default:
- return checkFieldTypeSignature(signature, pos);
- }
+ /**
+ * Checks an identifier.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param startPos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkSignatureIdentifier(final String signature, final int startPos) {
+ int pos = startPos;
+ while (pos < signature.length() && ".;[/<>:".indexOf(signature.codePointAt(pos)) == -1) {
+ pos = signature.offsetByCodePoints(pos, 1);
+ }
+ if (pos == startPos) {
+ throw new IllegalArgumentException(signature + ": identifier expected at index " + startPos);
}
+ return pos;
+ }
- /**
- * Checks an identifier.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkIdentifier(final String signature, int pos) {
- if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
- throw new IllegalArgumentException(signature
- + ": identifier expected at index " + pos);
- }
- ++pos;
- while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
- ++pos;
+ /**
+ * Checks a single character.
+ *
+ * @param c a character.
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkChar(final char c, final String signature, final int pos) {
+ if (getChar(signature, pos) == c) {
+ return pos + 1;
+ }
+ throw new IllegalArgumentException(signature + ": '" + c + "' expected at index " + pos);
+ }
+
+ /**
+ * Returns the string character at the given index, or 0.
+ *
+ * @param string a string.
+ * @param pos an index in 'string'.
+ * @return the character at the given index, or 0 if there is no such character.
+ */
+ private static char getChar(final String string, final int pos) {
+ return pos < string.length() ? string.charAt(pos) : (char) 0;
+ }
+
+ /**
+ * Checks the reference to a type in a type annotation.
+ *
+ * @param typeRef a reference to an annotated type.
+ */
+ static void checkTypeRef(final int typeRef) {
+ int mask = 0;
+ switch (typeRef >>> 24) {
+ case TypeReference.CLASS_TYPE_PARAMETER:
+ case TypeReference.METHOD_TYPE_PARAMETER:
+ case TypeReference.METHOD_FORMAL_PARAMETER:
+ mask = 0xFFFF0000;
+ break;
+ case TypeReference.FIELD:
+ case TypeReference.METHOD_RETURN:
+ case TypeReference.METHOD_RECEIVER:
+ case TypeReference.LOCAL_VARIABLE:
+ case TypeReference.RESOURCE_VARIABLE:
+ case TypeReference.INSTANCEOF:
+ case TypeReference.NEW:
+ case TypeReference.CONSTRUCTOR_REFERENCE:
+ case TypeReference.METHOD_REFERENCE:
+ mask = 0xFF000000;
+ break;
+ case TypeReference.CLASS_EXTENDS:
+ case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+ case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+ case TypeReference.THROWS:
+ case TypeReference.EXCEPTION_PARAMETER:
+ mask = 0xFFFFFF00;
+ break;
+ case TypeReference.CAST:
+ case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+ case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+ case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+ case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+ mask = 0xFF0000FF;
+ break;
+ default:
+ throw new AssertionError();
+ }
+ if ((typeRef & ~mask) != 0) {
+ throw new IllegalArgumentException(
+ "Invalid type reference 0x" + Integer.toHexString(typeRef));
+ }
+ }
+
+ /**
+ * Returns the package name of an internal name.
+ *
+ * @param name an internal name.
+ * @return the package name or "" if there is no package.
+ */
+ private static String packageName(final String name) {
+ int index = name.lastIndexOf('/');
+ if (index == -1) {
+ return "";
+ }
+ return name.substring(0, index);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Static verification methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Checks the given class.
+ *
+ * <p>Usage: CheckClassAdapter <binary class name or class file name>
+ *
+ * @param args the command line arguments.
+ * @throws IOException if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws IOException {
+ if (args.length != 1) {
+ System.err.println(
+ "Verifies the given class.\n"
+ + "Usage: CheckClassAdapter <fully qualified class name or class file name>");
+ return;
+ }
+
+ ClassReader classReader;
+ if (args[0].endsWith(".class")) {
+ InputStream inputStream =
+ new FileInputStream(args[0]); // NOPMD(AvoidFileStream): can't fix for 1.5 compatibility
+ classReader = new ClassReader(inputStream);
+ } else {
+ classReader = new ClassReader(args[0]);
+ }
+
+ verify(classReader, false, new PrintWriter(System.err));
+ }
+
+ /**
+ * Checks the given class.
+ *
+ * @param classReader the class to be checked.
+ * @param printResults whether to print the results of the bytecode verification.
+ * @param printWriter where the results (or the stack trace in case of error) must be printed.
+ */
+ public static void verify(
+ final ClassReader classReader, final boolean printResults, final PrintWriter printWriter) {
+ verify(classReader, null, printResults, printWriter);
+ }
+
+ /**
+ * Checks the given class.
+ *
+ * @param classReader the class to be checked.
+ * @param loader a <code>ClassLoader</code> which will be used to load referenced classes. May be
+ * {@literal null}.
+ * @param printResults whether to print the results of the bytecode verification.
+ * @param printWriter where the results (or the stack trace in case of error) must be printed.
+ */
+ public static void verify(
+ final ClassReader classReader,
+ final ClassLoader loader,
+ final boolean printResults,
+ final PrintWriter printWriter) {
+ ClassNode classNode = new ClassNode();
+ classReader.accept(
+ new CheckClassAdapter(Opcodes.ASM7, classNode, false) {}, ClassReader.SKIP_DEBUG);
+
+ Type syperType = classNode.superName == null ? null : Type.getObjectType(classNode.superName);
+ List<MethodNode> methods = classNode.methods;
+
+ List<Type> interfaces = new ArrayList<Type>();
+ for (String interfaceName : classNode.interfaces) {
+ interfaces.add(Type.getObjectType(interfaceName));
+ }
+
+ for (MethodNode method : methods) {
+ SimpleVerifier verifier =
+ new SimpleVerifier(
+ Type.getObjectType(classNode.name),
+ syperType,
+ interfaces,
+ (classNode.access & Opcodes.ACC_INTERFACE) != 0);
+ Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(verifier);
+ if (loader != null) {
+ verifier.setClassLoader(loader);
+ }
+ try {
+ analyzer.analyze(classNode.name, method);
+ } catch (AnalyzerException e) {
+ e.printStackTrace(printWriter);
+ }
+ if (printResults) {
+ printAnalyzerResult(method, analyzer, printWriter);
+ }
+ }
+ printWriter.flush();
+ }
+
+ static void printAnalyzerResult(
+ final MethodNode method, final Analyzer<BasicValue> analyzer, final PrintWriter printWriter) {
+ Textifier textifier = new Textifier();
+ TraceMethodVisitor traceMethodVisitor = new TraceMethodVisitor(textifier);
+
+ printWriter.println(method.name + method.desc);
+ for (int i = 0; i < method.instructions.size(); ++i) {
+ method.instructions.get(i).accept(traceMethodVisitor);
+
+ StringBuilder stringBuilder = new StringBuilder();
+ Frame<BasicValue> frame = analyzer.getFrames()[i];
+ if (frame == null) {
+ stringBuilder.append('?');
+ } else {
+ for (int j = 0; j < frame.getLocals(); ++j) {
+ stringBuilder.append(getUnqualifiedName(frame.getLocal(j).toString())).append(' ');
}
- return pos;
- }
-
- /**
- * Checks a single character.
- *
- * @param signature
- * a string containing the signature that must be checked.
- * @param pos
- * index of first character to be checked.
- * @return the index of the first character after the checked part.
- */
- private static int checkChar(final char c, final String signature, int pos) {
- if (getChar(signature, pos) == c) {
- return pos + 1;
+ stringBuilder.append(" : ");
+ for (int j = 0; j < frame.getStackSize(); ++j) {
+ stringBuilder.append(getUnqualifiedName(frame.getStack(j).toString())).append(' ');
}
- throw new IllegalArgumentException(signature + ": '" + c
- + "' expected at index " + pos);
- }
-
- /**
- * Returns the signature car at the given index.
- *
- * @param signature
- * a signature.
- * @param pos
- * an index in signature.
- * @return the character at the given index, or 0 if there is no such
- * character.
- */
- private static char getChar(final String signature, int pos) {
- return pos < signature.length() ? signature.charAt(pos) : (char) 0;
+ }
+ while (stringBuilder.length() < method.maxStack + method.maxLocals + 1) {
+ stringBuilder.append(' ');
+ }
+ printWriter.print(Integer.toString(i + 100000).substring(1));
+ printWriter.print(
+ " " + stringBuilder + " : " + textifier.text.get(textifier.text.size() - 1));
+ }
+ for (TryCatchBlockNode tryCatchBlock : method.tryCatchBlocks) {
+ tryCatchBlock.accept(traceMethodVisitor);
+ printWriter.print(" " + textifier.text.get(textifier.text.size() - 1));
+ }
+ printWriter.println();
+ }
+
+ private static String getUnqualifiedName(final String name) {
+ int lastSlashIndex = name.lastIndexOf('/');
+ if (lastSlashIndex == -1) {
+ return name;
+ } else {
+ int endIndex = name.length();
+ if (name.charAt(endIndex - 1) == ';') {
+ endIndex--;
+ }
+ return name.substring(lastSlashIndex + 1, endIndex);
}
+ }
}
[18/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleOpenNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleOpenNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleOpenNode.java
old mode 100644
new mode 100755
index 957340d..46585aa
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleOpenNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleOpenNode.java
@@ -1,82 +1,79 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
/**
- * A node that represents an opened package with its name and the module that can access to it.
- *
+ * A node that represents an opened package with its name and the module that can access it.
+ *
* @author Remi Forax
*/
public class ModuleOpenNode {
- /**
- * The package name.
- */
- public String packaze;
-
- /**
- * The access flags (see {@link org.objectweb.asm.Opcodes}).
- * Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
- */
- public int access;
- /**
- * A list of modules that can access to this exported package.
- * May be <tt>null</tt>.
- */
- public List<String> modules;
+ /** The internal name of the opened package. */
+ public String packaze;
+
+ /**
+ * The access flag of the opened package, valid values are among {@code ACC_SYNTHETIC} and {@code
+ * ACC_MANDATED}.
+ */
+ public int access;
+
+ /**
+ * The fully qualified names (using dots) of the modules that can use deep reflection to the
+ * classes of the open package, or {@literal null}.
+ */
+ public List<String> modules;
- /**
- * Constructs a new {@link ModuleOpenNode}.
- *
- * @param packaze
- * the parameter's name.
- * @param modules
- * a list of modules that can access to this open package.
- */
- public ModuleOpenNode(final String packaze, final int access, final List<String> modules) {
- this.packaze = packaze;
- this.access = access;
- this.modules = modules;
- }
+ /**
+ * Constructs a new {@link ModuleOpenNode}.
+ *
+ * @param packaze the internal name of the opened package.
+ * @param access the access flag of the opened package, valid values are among {@code
+ * ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ * @param modules the fully qualified names (using dots) of the modules that can use deep
+ * reflection to the classes of the open package, or {@literal null}.
+ */
+ public ModuleOpenNode(final String packaze, final int access, final List<String> modules) {
+ this.packaze = packaze;
+ this.access = access;
+ this.modules = modules;
+ }
- /**
- * Makes the given module visitor visit this open declaration.
- *
- * @param mv
- * a module visitor.
- */
- public void accept(final ModuleVisitor mv) {
- mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0]));
- }
+ /**
+ * Makes the given module visitor visit this opened package.
+ *
+ * @param moduleVisitor a module visitor.
+ */
+ public void accept(final ModuleVisitor moduleVisitor) {
+ moduleVisitor.visitOpen(
+ packaze, access, modules == null ? null : modules.toArray(new String[0]));
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleProvideNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleProvideNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleProvideNode.java
old mode 100644
new mode 100755
index 4225f56..33ce668
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleProvideNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleProvideNode.java
@@ -1,74 +1,66 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
/**
* A node that represents a service and its implementation provided by the current module.
- *
+ *
* @author Remi Forax
*/
public class ModuleProvideNode {
- /**
- * The service name (in its internal form).
- */
- public String service;
- /**
- * The service provider names (in their internal form).
- */
- public List<String> providers;
+ /** The internal name of the service. */
+ public String service;
+
+ /** The internal names of the implementations of the service (there is at least one provider). */
+ public List<String> providers;
- /**
- * Constructs a new {@link ModuleProvideNode}.
- *
- * @param service
- * the service name (in its internal form).
- * @param providers
- * the service provider names (in their internal form).
- */
- public ModuleProvideNode(final String service, final List<String> providers) {
- this.service = service;
- this.providers = providers;
- }
+ /**
+ * Constructs a new {@link ModuleProvideNode}.
+ *
+ * @param service the internal name of the service.
+ * @param providers the internal names of the implementations of the service (there is at least
+ * one provider).
+ */
+ public ModuleProvideNode(final String service, final List<String> providers) {
+ this.service = service;
+ this.providers = providers;
+ }
- /**
- * Makes the given module visitor visit this require declaration.
- *
- * @param mv
- * a module visitor.
- */
- public void accept(final ModuleVisitor mv) {
- mv.visitProvide(service, providers.toArray(new String[0]));
- }
+ /**
+ * Makes the given module visitor visit this require declaration.
+ *
+ * @param moduleVisitor a module visitor.
+ */
+ public void accept(final ModuleVisitor moduleVisitor) {
+ moduleVisitor.visitProvide(service, providers.toArray(new String[0]));
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleRequireNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleRequireNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleRequireNode.java
old mode 100644
new mode 100755
index 83e8897..6d94c0c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleRequireNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleRequireNode.java
@@ -1,87 +1,73 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
/**
* A node that represents a required module with its name and access of a module descriptor.
- *
+ *
* @author Remi Forax
*/
public class ModuleRequireNode {
- /**
- * The name of the required module.
- */
- public String module;
- /**
- * The access flags (see {@link org.objectweb.asm.Opcodes}).
- * Valid values are <tt>ACC_TRANSITIVE</tt>, <tt>ACC_STATIC_PHASE</tt>,
- * <tt>ACC_SYNTHETIC</tt> and <tt>ACC_MANDATED</tt>.
- */
- public int access;
-
- /**
- * Version at compile time of the required module or null.
- */
- public String version;
+ /** The fully qualified name (using dots) of the dependence. */
+ public String module;
+
+ /**
+ * The access flag of the dependence among {@code ACC_TRANSITIVE}, {@code ACC_STATIC_PHASE},
+ * {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ */
+ public int access;
+
+ /** The module version at compile time, or {@literal null}. */
+ public String version;
- /**
- * Constructs a new {@link ModuleRequireNode}.
- *
- * @param module
- * the name of the required module.
- * @param access
- * The access flags. Valid values are
- * <tt>ACC_TRANSITIVE</tt>, <tt>ACC_STATIC_PHASE</tt>,
- * <tt>ACC_SYNTHETIC</tt> and <tt>ACC_MANDATED</tt>
- * (see {@link org.objectweb.asm.Opcodes}).
- * @param version
- * Version of the required module at compile time,
- * null if not defined.
- */
- public ModuleRequireNode(final String module, final int access,
- final String version) {
- this.module = module;
- this.access = access;
- this.version = version;
- }
+ /**
+ * Constructs a new {@link ModuleRequireNode}.
+ *
+ * @param module the fully qualified name (using dots) of the dependence.
+ * @param access the access flag of the dependence among {@code ACC_TRANSITIVE}, {@code
+ * ACC_STATIC_PHASE}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ * @param version the module version at compile time, or {@literal null}.
+ */
+ public ModuleRequireNode(final String module, final int access, final String version) {
+ this.module = module;
+ this.access = access;
+ this.version = version;
+ }
- /**
- * Makes the given module visitor visit this require directive.
- *
- * @param mv
- * a module visitor.
- */
- public void accept(final ModuleVisitor mv) {
- mv.visitRequire(module, access, version);
- }
+ /**
+ * Makes the given module visitor visit this require directive.
+ *
+ * @param moduleVisitor a module visitor.
+ */
+ public void accept(final ModuleVisitor moduleVisitor) {
+ moduleVisitor.visitRequire(module, access, version);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
old mode 100644
new mode 100755
index 065ad59..6cb8d8c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
@@ -1,84 +1,74 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A node that represents a MULTIANEWARRAY instruction.
- *
+ *
* @author Eric Bruneton
*/
public class MultiANewArrayInsnNode extends AbstractInsnNode {
- /**
- * An array type descriptor (see {@link org.objectweb.asm.Type}).
- */
- public String desc;
-
- /**
- * Number of dimensions of the array to allocate.
- */
- public int dims;
+ /** An array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}). */
+ public String desc;
- /**
- * Constructs a new {@link MultiANewArrayInsnNode}.
- *
- * @param desc
- * an array type descriptor (see {@link org.objectweb.asm.Type}).
- * @param dims
- * number of dimensions of the array to allocate.
- */
- public MultiANewArrayInsnNode(final String desc, final int dims) {
- super(Opcodes.MULTIANEWARRAY);
- this.desc = desc;
- this.dims = dims;
- }
+ /** Number of dimensions of the array to allocate. */
+ public int dims;
- @Override
- public int getType() {
- return MULTIANEWARRAY_INSN;
- }
+ /**
+ * Constructs a new {@link MultiANewArrayInsnNode}.
+ *
+ * @param descriptor an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param numDimensions the number of dimensions of the array to allocate.
+ */
+ public MultiANewArrayInsnNode(final String descriptor, final int numDimensions) {
+ super(Opcodes.MULTIANEWARRAY);
+ this.desc = descriptor;
+ this.dims = numDimensions;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitMultiANewArrayInsn(desc, dims);
- acceptAnnotations(mv);
- }
+ @Override
+ public int getType() {
+ return MULTIANEWARRAY_INSN;
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitMultiANewArrayInsn(desc, dims);
+ acceptAnnotations(methodVisitor);
+ }
-}
\ No newline at end of file
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
old mode 100644
new mode 100755
index 001ddb9..2c584ad
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
@@ -1,76 +1,68 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
- * A node that represents a parameter access and name.
- *
+ * A node that represents a parameter of a method.
+ *
* @author Remi Forax
*/
public class ParameterNode {
- /**
- * The parameter's name.
- */
- public String name;
- /**
- * The parameter's access flags (see {@link org.objectweb.asm.Opcodes}).
- * Valid values are <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> and
- * <tt>ACC_MANDATED</tt>.
- */
- public int access;
+ /** The parameter's name. */
+ public String name;
+
+ /**
+ * The parameter's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). Valid values are {@code
+ * ACC_FINAL}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ */
+ public int access;
- /**
- * Constructs a new {@link ParameterNode}.
- *
- * @param access
- * The parameter's access flags. Valid values are
- * <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> or/and
- * <tt>ACC_MANDATED</tt> (see {@link org.objectweb.asm.Opcodes}).
- * @param name
- * the parameter's name.
- */
- public ParameterNode(final String name, final int access) {
- this.name = name;
- this.access = access;
- }
+ /**
+ * Constructs a new {@link ParameterNode}.
+ *
+ * @param access The parameter's access flags. Valid values are {@code ACC_FINAL}, {@code
+ * ACC_SYNTHETIC} or/and {@code ACC_MANDATED} (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+ * @param name the parameter's name.
+ */
+ public ParameterNode(final String name, final int access) {
+ this.name = name;
+ this.access = access;
+ }
- /**
- * Makes the given visitor visit this parameter declaration.
- *
- * @param mv
- * a method visitor.
- */
- public void accept(final MethodVisitor mv) {
- mv.visitParameter(name, access);
- }
+ /**
+ * Makes the given visitor visit this parameter declaration.
+ *
+ * @param methodVisitor a method visitor.
+ */
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitParameter(name, access);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
old mode 100644
new mode 100755
index e9ef6f2..12e7e68
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
@@ -1,114 +1,93 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A node that represents a TABLESWITCH instruction.
- *
+ *
* @author Eric Bruneton
*/
public class TableSwitchInsnNode extends AbstractInsnNode {
- /**
- * The minimum key value.
- */
- public int min;
+ /** The minimum key value. */
+ public int min;
- /**
- * The maximum key value.
- */
- public int max;
+ /** The maximum key value. */
+ public int max;
- /**
- * Beginning of the default handler block.
- */
- public LabelNode dflt;
+ /** Beginning of the default handler block. */
+ public LabelNode dflt;
- /**
- * Beginnings of the handler blocks. This list is a list of
- * {@link LabelNode} objects.
- */
- public List<LabelNode> labels;
+ /** Beginnings of the handler blocks. This list is a list of {@link LabelNode} objects. */
+ public List<LabelNode> labels;
- /**
- * Constructs a new {@link TableSwitchInsnNode}.
- *
- * @param min
- * the minimum key value.
- * @param max
- * the maximum key value.
- * @param dflt
- * beginning of the default handler block.
- * @param labels
- * beginnings of the handler blocks. <tt>labels[i]</tt> is the
- * beginning of the handler block for the <tt>min + i</tt> key.
- */
- public TableSwitchInsnNode(final int min, final int max,
- final LabelNode dflt, final LabelNode... labels) {
- super(Opcodes.TABLESWITCH);
- this.min = min;
- this.max = max;
- this.dflt = dflt;
- this.labels = new ArrayList<LabelNode>();
- if (labels != null) {
- this.labels.addAll(Arrays.asList(labels));
- }
- }
+ /**
+ * Constructs a new {@link TableSwitchInsnNode}.
+ *
+ * @param min the minimum key value.
+ * @param max the maximum key value.
+ * @param dflt beginning of the default handler block.
+ * @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the
+ * handler block for the {@code min + i} key.
+ */
+ public TableSwitchInsnNode(
+ final int min, final int max, final LabelNode dflt, final LabelNode... labels) {
+ super(Opcodes.TABLESWITCH);
+ this.min = min;
+ this.max = max;
+ this.dflt = dflt;
+ this.labels = Util.asArrayList(labels);
+ }
- @Override
- public int getType() {
- return TABLESWITCH_INSN;
- }
+ @Override
+ public int getType() {
+ return TABLESWITCH_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- Label[] labels = new Label[this.labels.size()];
- for (int i = 0; i < labels.length; ++i) {
- labels[i] = this.labels.get(i).getLabel();
- }
- mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
- acceptAnnotations(mv);
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ Label[] labelsArray = new Label[this.labels.size()];
+ for (int i = 0, n = labelsArray.length; i < n; ++i) {
+ labelsArray[i] = this.labels.get(i).getLabel();
}
+ methodVisitor.visitTableSwitchInsn(min, max, dflt.getLabel(), labelsArray);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone(
- this.labels, labels)).cloneAnnotations(this);
- }
-}
\ No newline at end of file
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new TableSwitchInsnNode(min, max, clone(dflt, clonedLabels), clone(labels, clonedLabels))
+ .cloneAnnotations(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
old mode 100644
new mode 100755
index a4c8dde..aa98364
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
@@ -1,153 +1,126 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents a try catch block.
- *
+ *
* @author Eric Bruneton
*/
public class TryCatchBlockNode {
- /**
- * Beginning of the exception handler's scope (inclusive).
- */
- public LabelNode start;
+ /** The beginning of the exception handler's scope (inclusive). */
+ public LabelNode start;
- /**
- * End of the exception handler's scope (exclusive).
- */
- public LabelNode end;
+ /** The end of the exception handler's scope (exclusive). */
+ public LabelNode end;
- /**
- * Beginning of the exception handler's code.
- */
- public LabelNode handler;
+ /** The beginning of the exception handler's code. */
+ public LabelNode handler;
- /**
- * Internal name of the type of exceptions handled by the handler. May be
- * <tt>null</tt> to catch any exceptions (for "finally" blocks).
- */
- public String type;
+ /**
+ * The internal name of the type of exceptions handled by the handler. May be {@literal null} to
+ * catch any exceptions (for "finally" blocks).
+ */
+ public String type;
- /**
- * The runtime visible type annotations on the exception handler type. This
- * list is a list of {@link TypeAnnotationNode} objects. May be
- * <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label visible
- */
- public List<TypeAnnotationNode> visibleTypeAnnotations;
+ /** The runtime visible type annotations on the exception handler type. May be {@literal null}. */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
- /**
- * The runtime invisible type annotations on the exception handler type.
- * This list is a list of {@link TypeAnnotationNode} objects. May be
- * <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label invisible
- */
- public List<TypeAnnotationNode> invisibleTypeAnnotations;
+ /**
+ * The runtime invisible type annotations on the exception handler type. May be {@literal null}.
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
- /**
- * Constructs a new {@link TryCatchBlockNode}.
- *
- * @param start
- * beginning of the exception handler's scope (inclusive).
- * @param end
- * end of the exception handler's scope (exclusive).
- * @param handler
- * beginning of the exception handler's code.
- * @param type
- * internal name of the type of exceptions handled by the
- * handler, or <tt>null</tt> to catch any exceptions (for
- * "finally" blocks).
- */
- public TryCatchBlockNode(final LabelNode start, final LabelNode end,
- final LabelNode handler, final String type) {
- this.start = start;
- this.end = end;
- this.handler = handler;
- this.type = type;
- }
+ /**
+ * Constructs a new {@link TryCatchBlockNode}.
+ *
+ * @param start the beginning of the exception handler's scope (inclusive).
+ * @param end the end of the exception handler's scope (exclusive).
+ * @param handler the beginning of the exception handler's code.
+ * @param type the internal name of the type of exceptions handled by the handler, or {@literal
+ * null} to catch any exceptions (for "finally" blocks).
+ */
+ public TryCatchBlockNode(
+ final LabelNode start, final LabelNode end, final LabelNode handler, final String type) {
+ this.start = start;
+ this.end = end;
+ this.handler = handler;
+ this.type = type;
+ }
- /**
- * Updates the index of this try catch block in the method's list of try
- * catch block nodes. This index maybe stored in the 'target' field of the
- * type annotations of this block.
- *
- * @param index
- * the new index of this try catch block in the method's list of
- * try catch block nodes.
- */
- public void updateIndex(final int index) {
- int newTypeRef = 0x42000000 | (index << 8);
- if (visibleTypeAnnotations != null) {
- for (TypeAnnotationNode tan : visibleTypeAnnotations) {
- tan.typeRef = newTypeRef;
- }
- }
- if (invisibleTypeAnnotations != null) {
- for (TypeAnnotationNode tan : invisibleTypeAnnotations) {
- tan.typeRef = newTypeRef;
- }
- }
+ /**
+ * Updates the index of this try catch block in the method's list of try catch block nodes. This
+ * index maybe stored in the 'target' field of the type annotations of this block.
+ *
+ * @param index the new index of this try catch block in the method's list of try catch block
+ * nodes.
+ */
+ public void updateIndex(final int index) {
+ int newTypeRef = 0x42000000 | (index << 8);
+ if (visibleTypeAnnotations != null) {
+ for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
+ visibleTypeAnnotations.get(i).typeRef = newTypeRef;
+ }
}
+ if (invisibleTypeAnnotations != null) {
+ for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
+ invisibleTypeAnnotations.get(i).typeRef = newTypeRef;
+ }
+ }
+ }
- /**
- * Makes the given visitor visit this try catch block.
- *
- * @param mv
- * a method visitor.
- */
- public void accept(final MethodVisitor mv) {
- mv.visitTryCatchBlock(start.getLabel(), end.getLabel(),
- handler == null ? null : handler.getLabel(), type);
- int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
- .size();
- for (int i = 0; i < n; ++i) {
- TypeAnnotationNode an = visibleTypeAnnotations.get(i);
- an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
- an.desc, true));
- }
- n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
- .size();
- for (int i = 0; i < n; ++i) {
- TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
- an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
- an.desc, false));
- }
+ /**
+ * Makes the given visitor visit this try catch block.
+ *
+ * @param methodVisitor a method visitor.
+ */
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitTryCatchBlock(
+ start.getLabel(), end.getLabel(), handler == null ? null : handler.getLabel(), type);
+ if (visibleTypeAnnotations != null) {
+ for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ methodVisitor.visitTryCatchAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
+ }
+ }
+ if (invisibleTypeAnnotations != null) {
+ for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ methodVisitor.visitTryCatchAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
+ }
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
old mode 100644
new mode 100755
index 43445ae..e3c58cd
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
@@ -1,100 +1,85 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.tree;
-
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.TypePath;
-import org.apache.tapestry5.internal.plastic.asm.TypeReference;
-
-/**
- * A node that represents a type annotationn.
- *
- * @author Eric Bruneton
- */
-public class TypeAnnotationNode extends AnnotationNode {
-
- /**
- * A reference to the annotated type. See {@link TypeReference}.
- */
- public int typeRef;
-
- /**
- * The path to the annotated type argument, wildcard bound, array element
- * type, or static outer type within the referenced type. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- */
- public TypePath typePath;
-
- /**
- * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
- *
- * @param typeRef
- * a reference to the annotated type. See {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public TypeAnnotationNode(final int typeRef, final TypePath typePath,
- final String desc) {
- this(Opcodes.ASM6, typeRef, typePath, desc);
- if (getClass() != TypeAnnotationNode.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Constructs a new {@link AnnotationNode}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param typeRef
- * a reference to the annotated type. See {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- */
- public TypeAnnotationNode(final int api, final int typeRef,
- final TypePath typePath, final String desc) {
- super(api, desc);
- this.typeRef = typeRef;
- this.typePath = typePath;
- }
-}
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.apache.tapestry5.internal.plastic.asm.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A node that represents a type annotation.
+ *
+ * @author Eric Bruneton
+ */
+public class TypeAnnotationNode extends AnnotationNode {
+
+ /** A reference to the annotated type. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}. */
+ public int typeRef;
+
+ /**
+ * The path to the annotated type argument, wildcard bound, array element type, or static outer
+ * type within the referenced type. May be {@literal null} if the annotation targets 'typeRef' as
+ * a whole.
+ */
+ public TypePath typePath;
+
+ /**
+ * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
+ *
+ * @param typeRef a reference to the annotated type. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public TypeAnnotationNode(final int typeRef, final TypePath typePath, final String descriptor) {
+ this(Opcodes.ASM7, typeRef, typePath, descriptor);
+ if (getClass() != TypeAnnotationNode.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param typeRef a reference to the annotated type. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ */
+ public TypeAnnotationNode(
+ final int api, final int typeRef, final TypePath typePath, final String descriptor) {
+ super(api, descriptor);
+ this.typeRef = typeRef;
+ this.typePath = typePath;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
old mode 100644
new mode 100755
index 9811d25..d97d940
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
@@ -1,91 +1,85 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
- * A node that represents a type instruction. A type instruction is an
- * instruction that takes a type descriptor as parameter.
- *
+ * A node that represents a type instruction. A type instruction is an instruction that takes a type
+ * descriptor as parameter.
+ *
* @author Eric Bruneton
*/
public class TypeInsnNode extends AbstractInsnNode {
- /**
- * The operand of this instruction. This operand is an internal name (see
- * {@link org.objectweb.asm.Type}).
- */
- public String desc;
+ /**
+ * The operand of this instruction. This operand is an internal name (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type}).
+ */
+ public String desc;
- /**
- * Constructs a new {@link TypeInsnNode}.
- *
- * @param opcode
- * the opcode of the type instruction to be constructed. This
- * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param desc
- * the operand of the instruction to be constructed. This operand
- * is an internal name (see {@link org.objectweb.asm.Type}).
- */
- public TypeInsnNode(final int opcode, final String desc) {
- super(opcode);
- this.desc = desc;
- }
+ /**
+ * Constructs a new {@link TypeInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This opcode must be NEW,
+ * ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param descriptor the operand of the instruction to be constructed. This operand is an internal
+ * name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ */
+ public TypeInsnNode(final int opcode, final String descriptor) {
+ super(opcode);
+ this.desc = descriptor;
+ }
- /**
- * Sets the opcode of this instruction.
- *
- * @param opcode
- * the new instruction opcode. This opcode must be NEW,
- * ANEWARRAY, CHECKCAST or INSTANCEOF.
- */
- public void setOpcode(final int opcode) {
- this.opcode = opcode;
- }
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be NEW, ANEWARRAY, CHECKCAST or
+ * INSTANCEOF.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
- @Override
- public int getType() {
- return TYPE_INSN;
- }
+ @Override
+ public int getType() {
+ return TYPE_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitTypeInsn(opcode, desc);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitTypeInsn(opcode, desc);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
- }
-}
\ No newline at end of file
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/UnsupportedClassVersionException.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/UnsupportedClassVersionException.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/UnsupportedClassVersionException.java
new file mode 100755
index 0000000..dc2161e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/UnsupportedClassVersionException.java
@@ -0,0 +1,14 @@
+package org.apache.tapestry5.internal.plastic.asm.tree;
+
+/**
+ * Exception thrown in {@link AnnotationNode#check}, {@link ClassNode#check}, {@link
+ * FieldNode#check} and {@link MethodNode#check} when these nodes (or their children, recursively)
+ * contain elements that were introduced in more recent versions of the ASM API than version passed
+ * to these methods.
+ *
+ * @author Eric Bruneton
+ */
+public class UnsupportedClassVersionException extends RuntimeException {
+
+ private static final long serialVersionUID = -3502347765891805831L;
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/Util.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/Util.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/Util.java
new file mode 100755
index 0000000..bf5d75f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/Util.java
@@ -0,0 +1,157 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.apache.tapestry5.internal.plastic.asm.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility methods to convert an array of primitive or object values to a mutable ArrayList, not
+ * baked by the array (unlike {@link java.util.Arrays#asList}).
+ *
+ * @author Eric Bruneton
+ */
+final class Util {
+
+ private Util() {}
+
+ static <T> List<T> asArrayList(final int length) {
+ List<T> list = new ArrayList<T>(length);
+ for (int i = 0; i < length; ++i) {
+ list.add(null);
+ }
+ return list;
+ }
+
+ static <T> List<T> asArrayList(final T[] array) {
+ if (array == null) {
+ return new ArrayList<T>();
+ }
+ ArrayList<T> list = new ArrayList<T>(array.length);
+ for (T t : array) {
+ list.add(t);
+ }
+ return list;
+ }
+
+ static List<Byte> asArrayList(final byte[] byteArray) {
+ if (byteArray == null) {
+ return new ArrayList<Byte>();
+ }
+ ArrayList<Byte> byteList = new ArrayList<Byte>(byteArray.length);
+ for (byte b : byteArray) {
+ byteList.add(b);
+ }
+ return byteList;
+ }
+
+ static List<Boolean> asArrayList(final boolean[] booleanArray) {
+ if (booleanArray == null) {
+ return new ArrayList<Boolean>();
+ }
+ ArrayList<Boolean> booleanList = new ArrayList<Boolean>(booleanArray.length);
+ for (boolean b : booleanArray) {
+ booleanList.add(b);
+ }
+ return booleanList;
+ }
+
+ static List<Short> asArrayList(final short[] shortArray) {
+ if (shortArray == null) {
+ return new ArrayList<Short>();
+ }
+ ArrayList<Short> shortList = new ArrayList<Short>(shortArray.length);
+ for (short s : shortArray) {
+ shortList.add(s);
+ }
+ return shortList;
+ }
+
+ static List<Character> asArrayList(final char[] charArray) {
+ if (charArray == null) {
+ return new ArrayList<Character>();
+ }
+ ArrayList<Character> charList = new ArrayList<Character>(charArray.length);
+ for (char c : charArray) {
+ charList.add(c);
+ }
+ return charList;
+ }
+
+ static List<Integer> asArrayList(final int[] intArray) {
+ if (intArray == null) {
+ return new ArrayList<Integer>();
+ }
+ ArrayList<Integer> intList = new ArrayList<Integer>(intArray.length);
+ for (int i : intArray) {
+ intList.add(i);
+ }
+ return intList;
+ }
+
+ static List<Float> asArrayList(final float[] floatArray) {
+ if (floatArray == null) {
+ return new ArrayList<Float>();
+ }
+ ArrayList<Float> floatList = new ArrayList<Float>(floatArray.length);
+ for (float f : floatArray) {
+ floatList.add(f);
+ }
+ return floatList;
+ }
+
+ static List<Long> asArrayList(final long[] longArray) {
+ if (longArray == null) {
+ return new ArrayList<Long>();
+ }
+ ArrayList<Long> longList = new ArrayList<Long>(longArray.length);
+ for (long l : longArray) {
+ longList.add(l);
+ }
+ return longList;
+ }
+
+ static List<Double> asArrayList(final double[] doubleArray) {
+ if (doubleArray == null) {
+ return new ArrayList<Double>();
+ }
+ ArrayList<Double> doubleList = new ArrayList<Double>(doubleArray.length);
+ for (double d : doubleArray) {
+ doubleList.add(d);
+ }
+ return doubleList;
+ }
+
+ static <T> List<T> asArrayList(final int length, final T[] array) {
+ List<T> list = new ArrayList<T>(length);
+ for (int i = 0; i < length; ++i) {
+ list.add(array[i]); // NOPMD(UseArraysAsList): we convert a part of the array.
+ }
+ return list;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
old mode 100644
new mode 100755
index 58552de..1208c17
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
@@ -1,94 +1,82 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
- * A node that represents a local variable instruction. A local variable
- * instruction is an instruction that loads or stores the value of a local
- * variable.
- *
+ * A node that represents a local variable instruction. A local variable instruction is an
+ * instruction that loads or stores the value of a local variable.
+ *
* @author Eric Bruneton
*/
public class VarInsnNode extends AbstractInsnNode {
- /**
- * The operand of this instruction. This operand is the index of a local
- * variable.
- */
- public int var;
+ /** The operand of this instruction. This operand is the index of a local variable. */
+ public int var;
- /**
- * Constructs a new {@link VarInsnNode}.
- *
- * @param opcode
- * the opcode of the local variable instruction to be
- * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
- * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var
- * the operand of the instruction to be constructed. This operand
- * is the index of a local variable.
- */
- public VarInsnNode(final int opcode, final int var) {
- super(opcode);
- this.var = var;
- }
+ /**
+ * Constructs a new {@link VarInsnNode}.
+ *
+ * @param opcode the opcode of the local variable instruction to be constructed. This opcode must
+ * be ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var the operand of the instruction to be constructed. This operand is the index of a
+ * local variable.
+ */
+ public VarInsnNode(final int opcode, final int var) {
+ super(opcode);
+ this.var = var;
+ }
- /**
- * Sets the opcode of this instruction.
- *
- * @param opcode
- * the new instruction opcode. This opcode must be ILOAD, LLOAD,
- * FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or
- * RET.
- */
- public void setOpcode(final int opcode) {
- this.opcode = opcode;
- }
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
+ * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
- @Override
- public int getType() {
- return VAR_INSN;
- }
+ @Override
+ public int getType() {
+ return VAR_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitVarInsn(opcode, var);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitVarInsn(opcode, var);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new VarInsnNode(opcode, var).cloneAnnotations(this);
- }
-}
\ No newline at end of file
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new VarInsnNode(opcode, var).cloneAnnotations(this);
+ }
+}
[38/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
old mode 100644
new mode 100755
index 57d771c..906ab98
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
@@ -1,564 +1,621 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A label represents a position in the bytecode of a method. Labels are used
- * for jump, goto, and switch instructions, and for try catch blocks. A label
- * designates the <i>instruction</i> that is just after. Note however that there
- * can be other elements between a label and the instruction it designates (such
+ * A position in the bytecode of a method. Labels are used for jump, goto, and switch instructions,
+ * and for try catch blocks. A label designates the <i>instruction</i> that is just after. Note
+ * however that there can be other elements between a label and the instruction it designates (such
* as other labels, stack map frames, line numbers, etc.).
- *
+ *
* @author Eric Bruneton
*/
public class Label {
- /**
- * Indicates if this label is only used for debug attributes. Such a label
- * is not the start of a basic block, the target of a jump instruction, or
- * an exception handler. It can be safely ignored in control flow graph
- * analysis algorithms (for optimization purposes).
- */
- static final int DEBUG = 1;
-
- /**
- * Indicates if the position of this label is known.
- */
- static final int RESOLVED = 2;
-
- /**
- * Indicates if this label has been updated, after instruction resizing.
- */
- static final int RESIZED = 4;
-
- /**
- * Indicates if this basic block has been pushed in the basic block stack.
- * See {@link MethodWriter#visitMaxs visitMaxs}.
- */
- static final int PUSHED = 8;
-
- /**
- * Indicates if this label is the target of a jump instruction, or the start
- * of an exception handler.
- */
- static final int TARGET = 16;
-
- /**
- * Indicates if a stack map frame must be stored for this label.
- */
- static final int STORE = 32;
-
- /**
- * Indicates if this label corresponds to a reachable basic block.
- */
- static final int REACHABLE = 64;
-
- /**
- * Indicates if this basic block ends with a JSR instruction.
- */
- static final int JSR = 128;
-
- /**
- * Indicates if this basic block ends with a RET instruction.
- */
- static final int RET = 256;
-
- /**
- * Indicates if this basic block is the start of a subroutine.
- */
- static final int SUBROUTINE = 512;
-
- /**
- * Indicates if this subroutine basic block has been visited by a
- * visitSubroutine(null, ...) call.
- */
- static final int VISITED = 1024;
-
- /**
- * Indicates if this subroutine basic block has been visited by a
- * visitSubroutine(!null, ...) call.
- */
- static final int VISITED2 = 2048;
-
- /**
- * Field used to associate user information to a label. Warning: this field
- * is used by the ASM tree package. In order to use it with the ASM tree
- * package you must override the
- * {@link org.objectweb.asm.tree.MethodNode#getLabelNode} method.
- */
- public Object info;
-
- /**
- * Flags that indicate the status of this label.
- *
- * @see #DEBUG
- * @see #RESOLVED
- * @see #RESIZED
- * @see #PUSHED
- * @see #TARGET
- * @see #STORE
- * @see #REACHABLE
- * @see #JSR
- * @see #RET
- */
- int status;
-
- /**
- * The line number corresponding to this label, if known. If there are
- * several lines, each line is stored in a separate label, all linked via
- * their next field (these links are created in ClassReader and removed just
- * before visitLabel is called, so that this does not impact the rest of the
- * code).
- */
- int line;
-
- /**
- * The position of this label in the code, if known.
- */
- int position;
-
- /**
- * Number of forward references to this label, times two.
- */
- private int referenceCount;
-
- /**
- * Informations about forward references. Each forward reference is
- * described by two consecutive integers in this array: the first one is the
- * position of the first byte of the bytecode instruction that contains the
- * forward reference, while the second is the position of the first byte of
- * the forward reference itself. In fact the sign of the first integer
- * indicates if this reference uses 2 or 4 bytes, and its absolute value
- * gives the position of the bytecode instruction. This array is also used
- * as a bitset to store the subroutines to which a basic block belongs. This
- * information is needed in {@linked MethodWriter#visitMaxs}, after all
- * forward references have been resolved. Hence the same array can be used
- * for both purposes without problems.
- */
- private int[] srcAndRefPositions;
-
- // ------------------------------------------------------------------------
-
- /*
- * Fields for the control flow and data flow graph analysis algorithms (used
- * to compute the maximum stack size or the stack map frames). A control
- * flow graph contains one node per "basic block", and one edge per "jump"
- * from one basic block to another. Each node (i.e., each basic block) is
- * represented by the Label object that corresponds to the first instruction
- * of this basic block. Each node also stores the list of its successors in
- * the graph, as a linked list of Edge objects.
- *
- * The control flow analysis algorithms used to compute the maximum stack
- * size or the stack map frames are similar and use two steps. The first
- * step, during the visit of each instruction, builds information about the
- * state of the local variables and the operand stack at the end of each
- * basic block, called the "output frame", <i>relatively</i> to the frame
- * state at the beginning of the basic block, which is called the "input
- * frame", and which is <i>unknown</i> during this step. The second step, in
- * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
- * information about the input frame of each basic block, from the input
- * state of the first basic block (known from the method signature), and by
- * the using the previously computed relative output frames.
- *
- * The algorithm used to compute the maximum stack size only computes the
- * relative output and absolute input stack heights, while the algorithm
- * used to compute stack map frames computes relative output frames and
- * absolute input frames.
- */
-
- /**
- * Start of the output stack relatively to the input stack. The exact
- * semantics of this field depends on the algorithm that is used.
- *
- * When only the maximum stack size is computed, this field is the number of
- * elements in the input stack.
- *
- * When the stack map frames are completely computed, this field is the
- * offset of the first output stack element relatively to the top of the
- * input stack. This offset is always negative or null. A null offset means
- * that the output stack must be appended to the input stack. A -n offset
- * means that the first n output stack elements must replace the top n input
- * stack elements, and that the other elements must be appended to the input
- * stack.
- */
- int inputStackTop;
-
- /**
- * Maximum height reached by the output stack, relatively to the top of the
- * input stack. This maximum is always positive or null.
- */
- int outputStackMax;
-
- /**
- * Information about the input and output stack map frames of this basic
- * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}
- * option is used.
- */
- Frame frame;
-
- /**
- * The successor of this label, in the order they are visited. This linked
- * list does not include labels used for debug info only. If
- * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it
- * does not contain successive labels that denote the same bytecode position
- * (in this case only the first label appears in this list).
- */
- Label successor;
-
- /**
- * The successors of this node in the control flow graph. These successors
- * are stored in a linked list of {@link Edge Edge} objects, linked to each
- * other by their {@link Edge#next} field.
- */
- Edge successors;
-
- /**
- * The next basic block in the basic block stack. This stack is used in the
- * main loop of the fix point algorithm used in the second step of the
- * control flow analysis algorithms. It is also used in
- * {@link #visitSubroutine} to avoid using a recursive method, and in
- * ClassReader to temporarily store multiple source lines for a label.
- *
- * @see MethodWriter#visitMaxs
- */
- Label next;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new label.
- */
- public Label() {
+ /**
+ * A flag indicating that a label is only used for debug attributes. Such a label is not the start
+ * of a basic block, the target of a jump instruction, or an exception handler. It can be safely
+ * ignored in control flow graph analysis algorithms (for optimization purposes).
+ */
+ static final int FLAG_DEBUG_ONLY = 1;
+
+ /**
+ * A flag indicating that a label is the target of a jump instruction, or the start of an
+ * exception handler.
+ */
+ static final int FLAG_JUMP_TARGET = 2;
+
+ /** A flag indicating that the bytecode offset of a label is known. */
+ static final int FLAG_RESOLVED = 4;
+
+ /** A flag indicating that a label corresponds to a reachable basic block. */
+ static final int FLAG_REACHABLE = 8;
+
+ /**
+ * A flag indicating that the basic block corresponding to a label ends with a subroutine call. By
+ * construction in {@link MethodWriter#visitJumpInsn}, labels with this flag set have at least two
+ * outgoing edges:
+ *
+ * <ul>
+ * <li>the first one corresponds to the instruction that follows the jsr instruction in the
+ * bytecode, i.e. where execution continues when it returns from the jsr call. This is a
+ * virtual control flow edge, since execution never goes directly from the jsr to the next
+ * instruction. Instead, it goes to the subroutine and eventually returns to the instruction
+ * following the jsr. This virtual edge is used to compute the real outgoing edges of the
+ * basic blocks ending with a ret instruction, in {@link #addSubroutineRetSuccessors}.
+ * <li>the second one corresponds to the target of the jsr instruction,
+ * </ul>
+ */
+ static final int FLAG_SUBROUTINE_CALLER = 16;
+
+ /**
+ * A flag indicating that the basic block corresponding to a label is the start of a subroutine.
+ */
+ static final int FLAG_SUBROUTINE_START = 32;
+
+ /** A flag indicating that the basic block corresponding to a label is the end of a subroutine. */
+ static final int FLAG_SUBROUTINE_END = 64;
+
+ /**
+ * The number of elements to add to the {@link #otherLineNumbers} array when it needs to be
+ * resized to store a new source line number.
+ */
+ static final int LINE_NUMBERS_CAPACITY_INCREMENT = 4;
+
+ /**
+ * The number of elements to add to the {@link #forwardReferences} array when it needs to be
+ * resized to store a new forward reference.
+ */
+ static final int FORWARD_REFERENCES_CAPACITY_INCREMENT = 6;
+
+ /**
+ * The bit mask to extract the type of a forward reference to this label. The extracted type is
+ * either {@link #FORWARD_REFERENCE_TYPE_SHORT} or {@link #FORWARD_REFERENCE_TYPE_WIDE}.
+ *
+ * @see #forwardReferences
+ */
+ static final int FORWARD_REFERENCE_TYPE_MASK = 0xF0000000;
+
+ /**
+ * The type of forward references stored with two bytes in the bytecode. This is the case, for
+ * instance, of a forward reference from an ifnull instruction.
+ */
+ static final int FORWARD_REFERENCE_TYPE_SHORT = 0x10000000;
+
+ /**
+ * The type of forward references stored in four bytes in the bytecode. This is the case, for
+ * instance, of a forward reference from a lookupswitch instruction.
+ */
+ static final int FORWARD_REFERENCE_TYPE_WIDE = 0x20000000;
+
+ /**
+ * The bit mask to extract the 'handle' of a forward reference to this label. The extracted handle
+ * is the bytecode offset where the forward reference value is stored (using either 2 or 4 bytes,
+ * as indicated by the {@link #FORWARD_REFERENCE_TYPE_MASK}).
+ *
+ * @see #forwardReferences
+ */
+ static final int FORWARD_REFERENCE_HANDLE_MASK = 0x0FFFFFFF;
+
+ /**
+ * A sentinel element used to indicate the end of a list of labels.
+ *
+ * @see #nextListElement
+ */
+ static final Label EMPTY_LIST = new Label();
+
+ /**
+ * A user managed state associated with this label. Warning: this field is used by the ASM tree
+ * package. In order to use it with the ASM tree package you must override the getLabelNode method
+ * in MethodNode.
+ */
+ public Object info;
+
+ /**
+ * The type and status of this label or its corresponding basic block. Must be zero or more of
+ * {@link #FLAG_DEBUG_ONLY}, {@link #FLAG_JUMP_TARGET}, {@link #FLAG_RESOLVED}, {@link
+ * #FLAG_REACHABLE}, {@link #FLAG_SUBROUTINE_CALLER}, {@link #FLAG_SUBROUTINE_START}, {@link
+ * #FLAG_SUBROUTINE_END}.
+ */
+ short flags;
+
+ /**
+ * The source line number corresponding to this label, or 0. If there are several source line
+ * numbers corresponding to this label, the first one is stored in this field, and the remaining
+ * ones are stored in {@link #otherLineNumbers}.
+ */
+ private short lineNumber;
+
+ /**
+ * The source line numbers corresponding to this label, in addition to {@link #lineNumber}, or
+ * null. The first element of this array is the number n of source line numbers it contains, which
+ * are stored between indices 1 and n (inclusive).
+ */
+ private int[] otherLineNumbers;
+
+ /**
+ * The offset of this label in the bytecode of its method, in bytes. This value is set if and only
+ * if the {@link #FLAG_RESOLVED} flag is set.
+ */
+ int bytecodeOffset;
+
+ /**
+ * The forward references to this label. The first element is the number of forward references,
+ * times 2 (this corresponds to the index of the last element actually used in this array). Then,
+ * each forward reference is described with two consecutive integers noted
+ * 'sourceInsnBytecodeOffset' and 'reference':
+ *
+ * <ul>
+ * <li>'sourceInsnBytecodeOffset' is the bytecode offset of the instruction that contains the
+ * forward reference,
+ * <li>'reference' contains the type and the offset in the bytecode where the forward reference
+ * value must be stored, which can be extracted with {@link #FORWARD_REFERENCE_TYPE_MASK}
+ * and {@link #FORWARD_REFERENCE_HANDLE_MASK}.
+ * </ul>
+ *
+ * <p>For instance, for an ifnull instruction at bytecode offset x, 'sourceInsnBytecodeOffset' is
+ * equal to x, and 'reference' is of type {@link #FORWARD_REFERENCE_TYPE_SHORT} with value x + 1
+ * (because the ifnull instruction uses a 2 bytes bytecode offset operand stored one byte after
+ * the start of the instruction itself). For the default case of a lookupswitch instruction at
+ * bytecode offset x, 'sourceInsnBytecodeOffset' is equal to x, and 'reference' is of type {@link
+ * #FORWARD_REFERENCE_TYPE_WIDE} with value between x + 1 and x + 4 (because the lookupswitch
+ * instruction uses a 4 bytes bytecode offset operand stored one to four bytes after the start of
+ * the instruction itself).
+ */
+ private int[] forwardReferences;
+
+ // -----------------------------------------------------------------------------------------------
+
+ // Fields for the control flow and data flow graph analysis algorithms (used to compute the
+ // maximum stack size or the stack map frames). A control flow graph contains one node per "basic
+ // block", and one edge per "jump" from one basic block to another. Each node (i.e., each basic
+ // block) is represented with the Label object that corresponds to the first instruction of this
+ // basic block. Each node also stores the list of its successors in the graph, as a linked list of
+ // Edge objects.
+ //
+ // The control flow analysis algorithms used to compute the maximum stack size or the stack map
+ // frames are similar and use two steps. The first step, during the visit of each instruction,
+ // builds information about the state of the local variables and the operand stack at the end of
+ // each basic block, called the "output frame", <i>relatively</i> to the frame state at the
+ // beginning of the basic block, which is called the "input frame", and which is <i>unknown</i>
+ // during this step. The second step, in {@link MethodWriter#computeAllFrames} and {@link
+ // MethodWriter#computeMaxStackAndLocal}, is a fix point algorithm
+ // that computes information about the input frame of each basic block, from the input state of
+ // the first basic block (known from the method signature), and by the using the previously
+ // computed relative output frames.
+ //
+ // The algorithm used to compute the maximum stack size only computes the relative output and
+ // absolute input stack heights, while the algorithm used to compute stack map frames computes
+ // relative output frames and absolute input frames.
+
+ /**
+ * The number of elements in the input stack of the basic block corresponding to this label. This
+ * field is computed in {@link MethodWriter#computeMaxStackAndLocal}.
+ */
+ short inputStackSize;
+
+ /**
+ * The number of elements in the output stack, at the end of the basic block corresponding to this
+ * label. This field is only computed for basic blocks that end with a RET instruction.
+ */
+ short outputStackSize;
+
+ /**
+ * The maximum height reached by the output stack, relatively to the top of the input stack, in
+ * the basic block corresponding to this label. This maximum is always positive or null.
+ */
+ short outputStackMax;
+
+ /**
+ * The id of the subroutine to which this basic block belongs, or 0. If the basic block belongs to
+ * several subroutines, this is the id of the "oldest" subroutine that contains it (with the
+ * convention that a subroutine calling another one is "older" than the callee). This field is
+ * computed in {@link MethodWriter#computeMaxStackAndLocal}, if the method contains JSR
+ * instructions.
+ */
+ short subroutineId;
+
+ /**
+ * The input and output stack map frames of the basic block corresponding to this label. This
+ * field is only used when the {@link MethodWriter#COMPUTE_ALL_FRAMES} or {@link
+ * MethodWriter#COMPUTE_INSERTED_FRAMES} option is used.
+ */
+ Frame frame;
+
+ /**
+ * The successor of this label, in the order they are visited in {@link MethodVisitor#visitLabel}.
+ * This linked list does not include labels used for debug info only. If the {@link
+ * MethodWriter#COMPUTE_ALL_FRAMES} or {@link MethodWriter#COMPUTE_INSERTED_FRAMES} option is used
+ * then it does not contain either successive labels that denote the same bytecode offset (in this
+ * case only the first label appears in this list).
+ */
+ Label nextBasicBlock;
+
+ /**
+ * The outgoing edges of the basic block corresponding to this label, in the control flow graph of
+ * its method. These edges are stored in a linked list of {@link Edge} objects, linked to each
+ * other by their {@link Edge#nextEdge} field.
+ */
+ Edge outgoingEdges;
+
+ /**
+ * The next element in the list of labels to which this label belongs, or null if it does not
+ * belong to any list. All lists of labels must end with the {@link #EMPTY_LIST} sentinel, in
+ * order to ensure that this field is null if and only if this label does not belong to a list of
+ * labels. Note that there can be several lists of labels at the same time, but that a label can
+ * belong to at most one list at a time (unless some lists share a common tail, but this is not
+ * used in practice).
+ *
+ * <p>List of labels are used in {@link MethodWriter#computeAllFrames} and {@link
+ * MethodWriter#computeMaxStackAndLocal} to compute stack map frames and the maximum stack size,
+ * respectively, as well as in {@link #markSubroutine} and {@link #addSubroutineRetSuccessors} to
+ * compute the basic blocks belonging to subroutines and their outgoing edges. Outside of these
+ * methods, this field should be null (this property is a precondition and a postcondition of
+ * these methods).
+ */
+ Label nextListElement;
+
+ // -----------------------------------------------------------------------------------------------
+ // Constructor and accessors
+ // -----------------------------------------------------------------------------------------------
+
+ /** Constructs a new label. */
+ public Label() {
+ // Nothing to do.
+ }
+
+ /**
+ * Returns the bytecode offset corresponding to this label. This offset is computed from the start
+ * of the method's bytecode. <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @return the bytecode offset corresponding to this label.
+ * @throws IllegalStateException if this label is not resolved yet.
+ */
+ public int getOffset() {
+ if ((flags & FLAG_RESOLVED) == 0) {
+ throw new IllegalStateException("Label offset position has not been resolved yet");
}
-
- // ------------------------------------------------------------------------
- // Methods to compute offsets and to manage forward references
- // ------------------------------------------------------------------------
-
- /**
- * Returns the offset corresponding to this label. This offset is computed
- * from the start of the method's bytecode. <i>This method is intended for
- * {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @return the offset corresponding to this label.
- * @throws IllegalStateException
- * if this label is not resolved yet.
- */
- public int getOffset() {
- if ((status & RESOLVED) == 0) {
- throw new IllegalStateException(
- "Label offset position has not been resolved yet");
- }
- return position;
+ return bytecodeOffset;
+ }
+
+ /**
+ * Returns the "canonical" {@link Label} instance corresponding to this label's bytecode offset,
+ * if known, otherwise the label itself. The canonical instance is the first label (in the order
+ * of their visit by {@link MethodVisitor#visitLabel}) corresponding to this bytecode offset. It
+ * cannot be known for labels which have not been visited yet.
+ *
+ * <p><i>This method should only be used when the {@link MethodWriter#COMPUTE_ALL_FRAMES} option
+ * is used.</i>
+ *
+ * @return the label itself if {@link #frame} is null, otherwise the Label's frame owner. This
+ * corresponds to the "canonical" label instance described above thanks to the way the label
+ * frame is set in {@link MethodWriter#visitLabel}.
+ */
+ final Label getCanonicalInstance() {
+ return frame == null ? this : frame.owner;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods to manage line numbers
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Adds a source line number corresponding to this label.
+ *
+ * @param lineNumber a source line number (which should be strictly positive).
+ */
+ final void addLineNumber(final int lineNumber) {
+ if (this.lineNumber == 0) {
+ this.lineNumber = (short) lineNumber;
+ } else {
+ if (otherLineNumbers == null) {
+ otherLineNumbers = new int[LINE_NUMBERS_CAPACITY_INCREMENT];
+ }
+ int otherLineNumberIndex = ++otherLineNumbers[0];
+ if (otherLineNumberIndex >= otherLineNumbers.length) {
+ int[] newLineNumbers = new int[otherLineNumbers.length + LINE_NUMBERS_CAPACITY_INCREMENT];
+ System.arraycopy(otherLineNumbers, 0, newLineNumbers, 0, otherLineNumbers.length);
+ otherLineNumbers = newLineNumbers;
+ }
+ otherLineNumbers[otherLineNumberIndex] = lineNumber;
}
-
- /**
- * Puts a reference to this label in the bytecode of a method. If the
- * position of the label is known, the offset is computed and written
- * directly. Otherwise, a null offset is written and a new forward reference
- * is declared for this label.
- *
- * @param owner
- * the code writer that calls this method.
- * @param out
- * the bytecode of the method.
- * @param source
- * the position of first byte of the bytecode instruction that
- * contains this label.
- * @param wideOffset
- * <tt>true</tt> if the reference must be stored in 4 bytes, or
- * <tt>false</tt> if it must be stored with 2 bytes.
- * @throws IllegalArgumentException
- * if this label has not been created by the given code writer.
- */
- void put(final MethodWriter owner, final ByteVector out, final int source,
- final boolean wideOffset) {
- if ((status & RESOLVED) == 0) {
- if (wideOffset) {
- addReference(-1 - source, out.length);
- out.putInt(-1);
- } else {
- addReference(source, out.length);
- out.putShort(-1);
- }
- } else {
- if (wideOffset) {
- out.putInt(position - source);
- } else {
- out.putShort(position - source);
- }
+ }
+
+ /**
+ * Makes the given visitor visit this label and its source line numbers, if applicable.
+ *
+ * @param methodVisitor a method visitor.
+ * @param visitLineNumbers whether to visit of the label's source line numbers, if any.
+ */
+ final void accept(final MethodVisitor methodVisitor, final boolean visitLineNumbers) {
+ methodVisitor.visitLabel(this);
+ if (visitLineNumbers && lineNumber != 0) {
+ methodVisitor.visitLineNumber(lineNumber & 0xFFFF, this);
+ if (otherLineNumbers != null) {
+ for (int i = 1; i <= otherLineNumbers[0]; ++i) {
+ methodVisitor.visitLineNumber(otherLineNumbers[i], this);
}
+ }
}
-
- /**
- * Adds a forward reference to this label. This method must be called only
- * for a true forward reference, i.e. only if this label is not resolved
- * yet. For backward references, the offset of the reference can be, and
- * must be, computed and stored directly.
- *
- * @param sourcePosition
- * the position of the referencing instruction. This position
- * will be used to compute the offset of this forward reference.
- * @param referencePosition
- * the position where the offset for this forward reference must
- * be stored.
- */
- private void addReference(final int sourcePosition,
- final int referencePosition) {
- if (srcAndRefPositions == null) {
- srcAndRefPositions = new int[6];
- }
- if (referenceCount >= srcAndRefPositions.length) {
- int[] a = new int[srcAndRefPositions.length + 6];
- System.arraycopy(srcAndRefPositions, 0, a, 0,
- srcAndRefPositions.length);
- srcAndRefPositions = a;
- }
- srcAndRefPositions[referenceCount++] = sourcePosition;
- srcAndRefPositions[referenceCount++] = referencePosition;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods to compute offsets and to manage forward references
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Puts a reference to this label in the bytecode of a method. If the bytecode offset of the label
+ * is known, the relative bytecode offset between the label and the instruction referencing it is
+ * computed and written directly. Otherwise, a null relative offset is written and a new forward
+ * reference is declared for this label.
+ *
+ * @param code the bytecode of the method. This is where the reference is appended.
+ * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the
+ * reference to be appended.
+ * @param wideReference whether the reference must be stored in 4 bytes (instead of 2 bytes).
+ */
+ final void put(
+ final ByteVector code, final int sourceInsnBytecodeOffset, final boolean wideReference) {
+ if ((flags & FLAG_RESOLVED) == 0) {
+ if (wideReference) {
+ addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_WIDE, code.length);
+ code.putInt(-1);
+ } else {
+ addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_SHORT, code.length);
+ code.putShort(-1);
+ }
+ } else {
+ if (wideReference) {
+ code.putInt(bytecodeOffset - sourceInsnBytecodeOffset);
+ } else {
+ code.putShort(bytecodeOffset - sourceInsnBytecodeOffset);
+ }
}
-
- /**
- * Resolves all forward references to this label. This method must be called
- * when this label is added to the bytecode of the method, i.e. when its
- * position becomes known. This method fills in the blanks that where left
- * in the bytecode by each forward reference previously added to this label.
- *
- * @param owner
- * the code writer that calls this method.
- * @param position
- * the position of this label in the bytecode.
- * @param data
- * the bytecode of the method.
- * @return <tt>true</tt> if a blank that was left for this label was too
- * small to store the offset. In such a case the corresponding jump
- * instruction is replaced with a pseudo instruction (using unused
- * opcodes) using an unsigned two bytes offset. These pseudo
- * instructions will be replaced with standard bytecode instructions
- * with wider offsets (4 bytes instead of 2), in ClassReader.
- * @throws IllegalArgumentException
- * if this label has already been resolved, or if it has not
- * been created by the given code writer.
- */
- boolean resolve(final MethodWriter owner, final int position,
- final byte[] data) {
- boolean needUpdate = false;
- this.status |= RESOLVED;
- this.position = position;
- int i = 0;
- while (i < referenceCount) {
- int source = srcAndRefPositions[i++];
- int reference = srcAndRefPositions[i++];
- int offset;
- if (source >= 0) {
- offset = position - source;
- if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
- /*
- * changes the opcode of the jump instruction, in order to
- * be able to find it later (see resizeInstructions in
- * MethodWriter). These temporary opcodes are similar to
- * jump instruction opcodes, except that the 2 bytes offset
- * is unsigned (and can therefore represent values from 0 to
- * 65535, which is sufficient since the size of a method is
- * limited to 65535 bytes).
- */
- int opcode = data[reference - 1] & 0xFF;
- if (opcode <= Opcodes.JSR) {
- // changes IFEQ ... JSR to opcodes 202 to 217
- data[reference - 1] = (byte) (opcode + 49);
- } else {
- // changes IFNULL and IFNONNULL to opcodes 218 and 219
- data[reference - 1] = (byte) (opcode + 20);
- }
- needUpdate = true;
- }
- data[reference++] = (byte) (offset >>> 8);
- data[reference] = (byte) offset;
- } else {
- offset = position + source + 1;
- data[reference++] = (byte) (offset >>> 24);
- data[reference++] = (byte) (offset >>> 16);
- data[reference++] = (byte) (offset >>> 8);
- data[reference] = (byte) offset;
- }
- }
- return needUpdate;
+ }
+
+ /**
+ * Adds a forward reference to this label. This method must be called only for a true forward
+ * reference, i.e. only if this label is not resolved yet. For backward references, the relative
+ * bytecode offset of the reference can be, and must be, computed and stored directly.
+ *
+ * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the
+ * reference stored at referenceHandle.
+ * @param referenceType either {@link #FORWARD_REFERENCE_TYPE_SHORT} or {@link
+ * #FORWARD_REFERENCE_TYPE_WIDE}.
+ * @param referenceHandle the offset in the bytecode where the forward reference value must be
+ * stored.
+ */
+ private void addForwardReference(
+ final int sourceInsnBytecodeOffset, final int referenceType, final int referenceHandle) {
+ if (forwardReferences == null) {
+ forwardReferences = new int[FORWARD_REFERENCES_CAPACITY_INCREMENT];
}
-
- /**
- * Returns the first label of the series to which this label belongs. For an
- * isolated label or for the first label in a series of successive labels,
- * this method returns the label itself. For other labels it returns the
- * first label of the series.
- *
- * @return the first label of the series to which this label belongs.
- */
- Label getFirst() {
- return frame == null ? this : frame.owner;
+ int lastElementIndex = forwardReferences[0];
+ if (lastElementIndex + 2 >= forwardReferences.length) {
+ int[] newValues = new int[forwardReferences.length + FORWARD_REFERENCES_CAPACITY_INCREMENT];
+ System.arraycopy(forwardReferences, 0, newValues, 0, forwardReferences.length);
+ forwardReferences = newValues;
}
-
- // ------------------------------------------------------------------------
- // Methods related to subroutines
- // ------------------------------------------------------------------------
-
- /**
- * Returns true is this basic block belongs to the given subroutine.
- *
- * @param id
- * a subroutine id.
- * @return true is this basic block belongs to the given subroutine.
- */
- boolean inSubroutine(final long id) {
- if ((status & Label.VISITED) != 0) {
- return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
- }
- return false;
+ forwardReferences[++lastElementIndex] = sourceInsnBytecodeOffset;
+ forwardReferences[++lastElementIndex] = referenceType | referenceHandle;
+ forwardReferences[0] = lastElementIndex;
+ }
+
+ /**
+ * Sets the bytecode offset of this label to the given value and resolves the forward references
+ * to this label, if any. This method must be called when this label is added to the bytecode of
+ * the method, i.e. when its bytecode offset becomes known. This method fills in the blanks that
+ * where left in the bytecode by each forward reference previously added to this label.
+ *
+ * @param code the bytecode of the method.
+ * @param bytecodeOffset the bytecode offset of this label.
+ * @return {@literal true} if a blank that was left for this label was too small to store the
+ * offset. In such a case the corresponding jump instruction is replaced with an equivalent
+ * ASM specific instruction using an unsigned two bytes offset. These ASM specific
+ * instructions are later replaced with standard bytecode instructions with wider offsets (4
+ * bytes instead of 2), in ClassReader.
+ */
+ final boolean resolve(final byte[] code, final int bytecodeOffset) {
+ this.flags |= FLAG_RESOLVED;
+ this.bytecodeOffset = bytecodeOffset;
+ if (forwardReferences == null) {
+ return false;
}
-
- /**
- * Returns true if this basic block and the given one belong to a common
- * subroutine.
- *
- * @param block
- * another basic block.
- * @return true if this basic block and the given one belong to a common
- * subroutine.
- */
- boolean inSameSubroutine(final Label block) {
- if ((status & VISITED) == 0 || (block.status & VISITED) == 0) {
- return false;
- }
- for (int i = 0; i < srcAndRefPositions.length; ++i) {
- if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
- return true;
- }
+ boolean hasAsmInstructions = false;
+ for (int i = forwardReferences[0]; i > 0; i -= 2) {
+ final int sourceInsnBytecodeOffset = forwardReferences[i - 1];
+ final int reference = forwardReferences[i];
+ final int relativeOffset = bytecodeOffset - sourceInsnBytecodeOffset;
+ int handle = reference & FORWARD_REFERENCE_HANDLE_MASK;
+ if ((reference & FORWARD_REFERENCE_TYPE_MASK) == FORWARD_REFERENCE_TYPE_SHORT) {
+ if (relativeOffset < Short.MIN_VALUE || relativeOffset > Short.MAX_VALUE) {
+ // Change the opcode of the jump instruction, in order to be able to find it later in
+ // ClassReader. These ASM specific opcodes are similar to jump instruction opcodes, except
+ // that the 2 bytes offset is unsigned (and can therefore represent values from 0 to
+ // 65535, which is sufficient since the size of a method is limited to 65535 bytes).
+ int opcode = code[sourceInsnBytecodeOffset] & 0xFF;
+ if (opcode < Opcodes.IFNULL) {
+ // Change IFEQ ... JSR to ASM_IFEQ ... ASM_JSR.
+ code[sourceInsnBytecodeOffset] = (byte) (opcode + Constants.ASM_OPCODE_DELTA);
+ } else {
+ // Change IFNULL and IFNONNULL to ASM_IFNULL and ASM_IFNONNULL.
+ code[sourceInsnBytecodeOffset] = (byte) (opcode + Constants.ASM_IFNULL_OPCODE_DELTA);
+ }
+ hasAsmInstructions = true;
}
- return false;
+ code[handle++] = (byte) (relativeOffset >>> 8);
+ code[handle] = (byte) relativeOffset;
+ } else {
+ code[handle++] = (byte) (relativeOffset >>> 24);
+ code[handle++] = (byte) (relativeOffset >>> 16);
+ code[handle++] = (byte) (relativeOffset >>> 8);
+ code[handle] = (byte) relativeOffset;
+ }
}
-
- /**
- * Marks this basic block as belonging to the given subroutine.
- *
- * @param id
- * a subroutine id.
- * @param nbSubroutines
- * the total number of subroutines in the method.
- */
- void addToSubroutine(final long id, final int nbSubroutines) {
- if ((status & VISITED) == 0) {
- status |= VISITED;
- srcAndRefPositions = new int[nbSubroutines / 32 + 1];
- }
- srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
+ return hasAsmInstructions;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods related to subroutines
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Finds the basic blocks that belong to the subroutine starting with the basic block
+ * corresponding to this label, and marks these blocks as belonging to this subroutine. This
+ * method follows the control flow graph to find all the blocks that are reachable from the
+ * current basic block WITHOUT following any jsr target.
+ *
+ * <p>Note: a precondition and postcondition of this method is that all labels must have a null
+ * {@link #nextListElement}.
+ *
+ * @param subroutineId the id of the subroutine starting with the basic block corresponding to
+ * this label.
+ */
+ final void markSubroutine(final short subroutineId) {
+ // Data flow algorithm: put this basic block in a list of blocks to process (which are blocks
+ // belonging to subroutine subroutineId) and, while there are blocks to process, remove one from
+ // the list, mark it as belonging to the subroutine, and add its successor basic blocks in the
+ // control flow graph to the list of blocks to process (if not already done).
+ Label listOfBlocksToProcess = this;
+ listOfBlocksToProcess.nextListElement = EMPTY_LIST;
+ while (listOfBlocksToProcess != EMPTY_LIST) {
+ // Remove a basic block from the list of blocks to process.
+ Label basicBlock = listOfBlocksToProcess;
+ listOfBlocksToProcess = listOfBlocksToProcess.nextListElement;
+ basicBlock.nextListElement = null;
+
+ // If it is not already marked as belonging to a subroutine, mark it as belonging to
+ // subroutineId and add its successors to the list of blocks to process (unless already done).
+ if (basicBlock.subroutineId == 0) {
+ basicBlock.subroutineId = subroutineId;
+ listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess);
+ }
}
-
- /**
- * Finds the basic blocks that belong to a given subroutine, and marks these
- * blocks as belonging to this subroutine. This method follows the control
- * flow graph to find all the blocks that are reachable from the current
- * block WITHOUT following any JSR target.
- *
- * @param JSR
- * a JSR block that jumps to this subroutine. If this JSR is not
- * null it is added to the successor of the RET blocks found in
- * the subroutine.
- * @param id
- * the id of this subroutine.
- * @param nbSubroutines
- * the total number of subroutines in the method.
- */
- void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
- // user managed stack of labels, to avoid using a recursive method
- // (recursivity can lead to stack overflow with very large methods)
- Label stack = this;
- while (stack != null) {
- // removes a label l from the stack
- Label l = stack;
- stack = l.next;
- l.next = null;
-
- if (JSR != null) {
- if ((l.status & VISITED2) != 0) {
- continue;
- }
- l.status |= VISITED2;
- // adds JSR to the successors of l, if it is a RET block
- if ((l.status & RET) != 0) {
- if (!l.inSameSubroutine(JSR)) {
- Edge e = new Edge();
- e.info = l.inputStackTop;
- e.successor = JSR.successors.successor;
- e.next = l.successors;
- l.successors = e;
- }
- }
- } else {
- // if the l block already belongs to subroutine 'id', continue
- if (l.inSubroutine(id)) {
- continue;
- }
- // marks the l block as belonging to subroutine 'id'
- l.addToSubroutine(id, nbSubroutines);
- }
- // pushes each successor of l on the stack, except JSR targets
- Edge e = l.successors;
- while (e != null) {
- // if the l block is a JSR block, then 'l.successors.next' leads
- // to the JSR target (see {@link #visitJumpInsn}) and must
- // therefore not be followed
- if ((l.status & Label.JSR) == 0 || e != l.successors.next) {
- // pushes e.successor on the stack if it not already added
- if (e.successor.next == null) {
- e.successor.next = stack;
- stack = e.successor;
- }
- }
- e = e.next;
- }
- }
+ }
+
+ /**
+ * Finds the basic blocks that end a subroutine starting with the basic block corresponding to
+ * this label and, for each one of them, adds an outgoing edge to the basic block following the
+ * given subroutine call. In other words, completes the control flow graph by adding the edges
+ * corresponding to the return from this subroutine, when called from the given caller basic
+ * block.
+ *
+ * <p>Note: a precondition and postcondition of this method is that all labels must have a null
+ * {@link #nextListElement}.
+ *
+ * @param subroutineCaller a basic block that ends with a jsr to the basic block corresponding to
+ * this label. This label is supposed to correspond to the start of a subroutine.
+ */
+ final void addSubroutineRetSuccessors(final Label subroutineCaller) {
+ // Data flow algorithm: put this basic block in a list blocks to process (which are blocks
+ // belonging to a subroutine starting with this label) and, while there are blocks to process,
+ // remove one from the list, put it in a list of blocks that have been processed, add a return
+ // edge to the successor of subroutineCaller if applicable, and add its successor basic blocks
+ // in the control flow graph to the list of blocks to process (if not already done).
+ Label listOfProcessedBlocks = EMPTY_LIST;
+ Label listOfBlocksToProcess = this;
+ listOfBlocksToProcess.nextListElement = EMPTY_LIST;
+ while (listOfBlocksToProcess != EMPTY_LIST) {
+ // Move a basic block from the list of blocks to process to the list of processed blocks.
+ Label basicBlock = listOfBlocksToProcess;
+ listOfBlocksToProcess = basicBlock.nextListElement;
+ basicBlock.nextListElement = listOfProcessedBlocks;
+ listOfProcessedBlocks = basicBlock;
+
+ // Add an edge from this block to the successor of the caller basic block, if this block is
+ // the end of a subroutine and if this block and subroutineCaller do not belong to the same
+ // subroutine.
+ if ((basicBlock.flags & FLAG_SUBROUTINE_END) != 0
+ && basicBlock.subroutineId != subroutineCaller.subroutineId) {
+ basicBlock.outgoingEdges =
+ new Edge(
+ basicBlock.outputStackSize,
+ // By construction, the first outgoing edge of a basic block that ends with a jsr
+ // instruction leads to the jsr continuation block, i.e. where execution continues
+ // when ret is called (see {@link #FLAG_SUBROUTINE_CALLER}).
+ subroutineCaller.outgoingEdges.successor,
+ basicBlock.outgoingEdges);
+ }
+ // Add its successors to the list of blocks to process. Note that {@link #pushSuccessors} does
+ // not push basic blocks which are already in a list. Here this means either in the list of
+ // blocks to process, or in the list of already processed blocks. This second list is
+ // important to make sure we don't reprocess an already processed block.
+ listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess);
}
-
- // ------------------------------------------------------------------------
- // Overriden Object methods
- // ------------------------------------------------------------------------
-
- /**
- * Returns a string representation of this label.
- *
- * @return a string representation of this label.
- */
- @Override
- public String toString() {
- return "L" + System.identityHashCode(this);
+ // Reset the {@link #nextListElement} of all the basic blocks that have been processed to null,
+ // so that this method can be called again with a different subroutine or subroutine caller.
+ while (listOfProcessedBlocks != EMPTY_LIST) {
+ Label newListOfProcessedBlocks = listOfProcessedBlocks.nextListElement;
+ listOfProcessedBlocks.nextListElement = null;
+ listOfProcessedBlocks = newListOfProcessedBlocks;
+ }
+ }
+
+ /**
+ * Adds the successors of this label in the method's control flow graph (except those
+ * corresponding to a jsr target, and those already in a list of labels) to the given list of
+ * blocks to process, and returns the new list.
+ *
+ * @param listOfLabelsToProcess a list of basic blocks to process, linked together with their
+ * {@link #nextListElement} field.
+ * @return the new list of blocks to process.
+ */
+ private Label pushSuccessors(final Label listOfLabelsToProcess) {
+ Label newListOfLabelsToProcess = listOfLabelsToProcess;
+ Edge outgoingEdge = outgoingEdges;
+ while (outgoingEdge != null) {
+ // By construction, the second outgoing edge of a basic block that ends with a jsr instruction
+ // leads to the jsr target (see {@link #FLAG_SUBROUTINE_CALLER}).
+ boolean isJsrTarget =
+ (flags & Label.FLAG_SUBROUTINE_CALLER) != 0 && outgoingEdge == outgoingEdges.nextEdge;
+ if (!isJsrTarget && outgoingEdge.successor.nextListElement == null) {
+ // Add this successor to the list of blocks to process, if it does not already belong to a
+ // list of labels.
+ outgoingEdge.successor.nextListElement = newListOfLabelsToProcess;
+ newListOfLabelsToProcess = outgoingEdge.successor;
+ }
+ outgoingEdge = outgoingEdge.nextEdge;
}
+ return newListOfLabelsToProcess;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Overridden Object methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns a string representation of this label.
+ *
+ * @return a string representation of this label.
+ */
+ @Override
+ public String toString() {
+ return "L" + System.identityHashCode(this);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodTooLargeException.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodTooLargeException.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodTooLargeException.java
new file mode 100755
index 0000000..348de37
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodTooLargeException.java
@@ -0,0 +1,99 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * Exception thrown when the Code attribute of a method produced by a {@link ClassWriter} is too
+ * large.
+ *
+ * @author Jason Zaugg
+ */
+public final class MethodTooLargeException extends IndexOutOfBoundsException {
+ private static final long serialVersionUID = 6807380416709738314L;
+
+ private final String className;
+ private final String methodName;
+ private final String descriptor;
+ private final int codeSize;
+
+ /**
+ * Constructs a new {@link MethodTooLargeException}.
+ *
+ * @param className the internal name of the owner class.
+ * @param methodName the name of the method.
+ * @param descriptor the descriptor of the method.
+ * @param codeSize the size of the method's Code attribute, in bytes.
+ */
+ public MethodTooLargeException(
+ final String className,
+ final String methodName,
+ final String descriptor,
+ final int codeSize) {
+ super("Method too large: " + className + "." + methodName + " " + descriptor);
+ this.className = className;
+ this.methodName = methodName;
+ this.descriptor = descriptor;
+ this.codeSize = codeSize;
+ }
+
+ /**
+ * Returns the internal name of the owner class.
+ *
+ * @return the internal name of the owner class.
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Returns the name of the method.
+ *
+ * @return the name of the method.
+ */
+ public String getMethodName() {
+ return methodName;
+ }
+
+ /**
+ * Returns the descriptor of the method.
+ *
+ * @return the descriptor of the method.
+ */
+ public String getDescriptor() {
+ return descriptor;
+ }
+
+ /**
+ * Returns the size of the method's Code attribute, in bytes.
+ *
+ * @return the size of the method's Code attribute, in bytes.
+ */
+ public int getCodeSize() {
+ return codeSize;
+ }
+}
[26/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
old mode 100644
new mode 100755
index f6f5857..70da1f5
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
@@ -1,282 +1,262 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.HashMap;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Type;
/**
* A named method descriptor.
- *
+ *
* @author Juozas Baliuka
* @author Chris Nokleberg
* @author Eric Bruneton
*/
public class Method {
- /**
- * The method name.
- */
- private final String name;
+ /** The method name. */
+ private final String name;
- /**
- * The method descriptor.
- */
- private final String desc;
+ /** The method descriptor. */
+ private final String descriptor;
- /**
- * Maps primitive Java type names to their descriptors.
- */
- private static final Map<String, String> DESCRIPTORS;
+ /** The descriptors of the primitive Java types (plus void). */
+ private static final Map<String, String> PRIMITIVE_TYPE_DESCRIPTORS;
- static {
- DESCRIPTORS = new HashMap<String, String>();
- DESCRIPTORS.put("void", "V");
- DESCRIPTORS.put("byte", "B");
- DESCRIPTORS.put("char", "C");
- DESCRIPTORS.put("double", "D");
- DESCRIPTORS.put("float", "F");
- DESCRIPTORS.put("int", "I");
- DESCRIPTORS.put("long", "J");
- DESCRIPTORS.put("short", "S");
- DESCRIPTORS.put("boolean", "Z");
- }
+ static {
+ HashMap<String, String> descriptors = new HashMap<String, String>();
+ descriptors.put("void", "V");
+ descriptors.put("byte", "B");
+ descriptors.put("char", "C");
+ descriptors.put("double", "D");
+ descriptors.put("float", "F");
+ descriptors.put("int", "I");
+ descriptors.put("long", "J");
+ descriptors.put("short", "S");
+ descriptors.put("boolean", "Z");
+ PRIMITIVE_TYPE_DESCRIPTORS = descriptors;
+ }
- /**
- * Creates a new {@link Method}.
- *
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor.
- */
- public Method(final String name, final String desc) {
- this.name = name;
- this.desc = desc;
- }
+ /**
+ * Constructs a new {@link Method}.
+ *
+ * @param name the method's name.
+ * @param descriptor the method's descriptor.
+ */
+ public Method(final String name, final String descriptor) {
+ this.name = name;
+ this.descriptor = descriptor;
+ }
- /**
- * Creates a new {@link Method}.
- *
- * @param name
- * the method's name.
- * @param returnType
- * the method's return type.
- * @param argumentTypes
- * the method's argument types.
- */
- public Method(final String name, final Type returnType,
- final Type[] argumentTypes) {
- this(name, Type.getMethodDescriptor(returnType, argumentTypes));
- }
+ /**
+ * Constructs a new {@link Method}.
+ *
+ * @param name the method's name.
+ * @param returnType the method's return type.
+ * @param argumentTypes the method's argument types.
+ */
+ public Method(final String name, final Type returnType, final Type[] argumentTypes) {
+ this(name, Type.getMethodDescriptor(returnType, argumentTypes));
+ }
- /**
- * Creates a new {@link Method}.
- *
- * @param m
- * a java.lang.reflect method descriptor
- * @return a {@link Method} corresponding to the given Java method
- * declaration.
- */
- public static Method getMethod(java.lang.reflect.Method m) {
- return new Method(m.getName(), Type.getMethodDescriptor(m));
- }
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param method a java.lang.reflect method descriptor
+ * @return a {@link Method} corresponding to the given Java method declaration.
+ */
+ public static Method getMethod(final java.lang.reflect.Method method) {
+ return new Method(method.getName(), Type.getMethodDescriptor(method));
+ }
- /**
- * Creates a new {@link Method}.
- *
- * @param c
- * a java.lang.reflect constructor descriptor
- * @return a {@link Method} corresponding to the given Java constructor
- * declaration.
- */
- public static Method getMethod(java.lang.reflect.Constructor<?> c) {
- return new Method("<init>", Type.getConstructorDescriptor(c));
- }
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param constructor a java.lang.reflect constructor descriptor
+ * @return a {@link Method} corresponding to the given Java constructor declaration.
+ */
+ public static Method getMethod(final java.lang.reflect.Constructor<?> constructor) {
+ return new Method("<init>", Type.getConstructorDescriptor(constructor));
+ }
- /**
- * Returns a {@link Method} corresponding to the given Java method
- * declaration.
- *
- * @param method
- * a Java method declaration, without argument names, of the form
- * "returnType name (argumentType1, ... argumentTypeN)", where
- * the types are in plain Java (e.g. "int", "float",
- * "java.util.List", ...). Classes of the java.lang package can
- * be specified by their unqualified name; all other classes
- * names must be fully qualified.
- * @return a {@link Method} corresponding to the given Java method
- * declaration.
- * @throws IllegalArgumentException
- * if <code>method</code> could not get parsed.
- */
- public static Method getMethod(final String method)
- throws IllegalArgumentException {
- return getMethod(method, false);
- }
+ /**
+ * Returns a {@link Method} corresponding to the given Java method declaration.
+ *
+ * @param method a Java method declaration, without argument names, of the form "returnType name
+ * (argumentType1, ... argumentTypeN)", where the types are in plain Java (e.g. "int",
+ * "float", "java.util.List", ...). Classes of the java.lang package can be specified by their
+ * unqualified name; all other classes names must be fully qualified.
+ * @return a {@link Method} corresponding to the given Java method declaration.
+ * @throws IllegalArgumentException if <code>method</code> could not get parsed.
+ */
+ public static Method getMethod(final String method) {
+ return getMethod(method, false);
+ }
- /**
- * Returns a {@link Method} corresponding to the given Java method
- * declaration.
- *
- * @param method
- * a Java method declaration, without argument names, of the form
- * "returnType name (argumentType1, ... argumentTypeN)", where
- * the types are in plain Java (e.g. "int", "float",
- * "java.util.List", ...). Classes of the java.lang package may
- * be specified by their unqualified name, depending on the
- * defaultPackage argument; all other classes names must be fully
- * qualified.
- * @param defaultPackage
- * true if unqualified class names belong to the default package,
- * or false if they correspond to java.lang classes. For instance
- * "Object" means "Object" if this option is true, or
- * "java.lang.Object" otherwise.
- * @return a {@link Method} corresponding to the given Java method
- * declaration.
- * @throws IllegalArgumentException
- * if <code>method</code> could not get parsed.
- */
- public static Method getMethod(final String method,
- final boolean defaultPackage) throws IllegalArgumentException {
- int space = method.indexOf(' ');
- int start = method.indexOf('(', space) + 1;
- int end = method.indexOf(')', start);
- if (space == -1 || start == -1 || end == -1) {
- throw new IllegalArgumentException();
- }
- String returnType = method.substring(0, space);
- String methodName = method.substring(space + 1, start - 1).trim();
- StringBuilder sb = new StringBuilder();
- sb.append('(');
- int p;
- do {
- String s;
- p = method.indexOf(',', start);
- if (p == -1) {
- s = map(method.substring(start, end).trim(), defaultPackage);
- } else {
- s = map(method.substring(start, p).trim(), defaultPackage);
- start = p + 1;
- }
- sb.append(s);
- } while (p != -1);
- sb.append(')');
- sb.append(map(returnType, defaultPackage));
- return new Method(methodName, sb.toString());
+ /**
+ * Returns a {@link Method} corresponding to the given Java method declaration.
+ *
+ * @param method a Java method declaration, without argument names, of the form "returnType name
+ * (argumentType1, ... argumentTypeN)", where the types are in plain Java (e.g. "int",
+ * "float", "java.util.List", ...). Classes of the java.lang package may be specified by their
+ * unqualified name, depending on the defaultPackage argument; all other classes names must be
+ * fully qualified.
+ * @param defaultPackage true if unqualified class names belong to the default package, or false
+ * if they correspond to java.lang classes. For instance "Object" means "Object" if this
+ * option is true, or "java.lang.Object" otherwise.
+ * @return a {@link Method} corresponding to the given Java method declaration.
+ * @throws IllegalArgumentException if <code>method</code> could not get parsed.
+ */
+ public static Method getMethod(final String method, final boolean defaultPackage) {
+ final int spaceIndex = method.indexOf(' ');
+ int currentArgumentStartIndex = method.indexOf('(', spaceIndex) + 1;
+ final int endIndex = method.indexOf(')', currentArgumentStartIndex);
+ if (spaceIndex == -1 || currentArgumentStartIndex == 0 || endIndex == -1) {
+ throw new IllegalArgumentException();
}
+ final String returnType = method.substring(0, spaceIndex);
+ final String methodName =
+ method.substring(spaceIndex + 1, currentArgumentStartIndex - 1).trim();
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append('(');
+ int currentArgumentEndIndex;
+ do {
+ String argumentDescriptor;
+ currentArgumentEndIndex = method.indexOf(',', currentArgumentStartIndex);
+ if (currentArgumentEndIndex == -1) {
+ argumentDescriptor =
+ getDescriptorInternal(
+ method.substring(currentArgumentStartIndex, endIndex).trim(), defaultPackage);
+ } else {
+ argumentDescriptor =
+ getDescriptorInternal(
+ method.substring(currentArgumentStartIndex, currentArgumentEndIndex).trim(),
+ defaultPackage);
+ currentArgumentStartIndex = currentArgumentEndIndex + 1;
+ }
+ stringBuilder.append(argumentDescriptor);
+ } while (currentArgumentEndIndex != -1);
+ stringBuilder.append(')').append(getDescriptorInternal(returnType, defaultPackage));
+ return new Method(methodName, stringBuilder.toString());
+ }
- private static String map(final String type, final boolean defaultPackage) {
- if ("".equals(type)) {
- return type;
- }
+ /**
+ * Returns the descriptor corresponding to the given type name.
+ *
+ * @param type a Java type name.
+ * @param defaultPackage true if unqualified class names belong to the default package, or false
+ * if they correspond to java.lang classes. For instance "Object" means "Object" if this
+ * option is true, or "java.lang.Object" otherwise.
+ * @return the descriptor corresponding to the given type name.
+ */
+ private static String getDescriptorInternal(final String type, final boolean defaultPackage) {
+ if ("".equals(type)) {
+ return type;
+ }
- StringBuilder sb = new StringBuilder();
- int index = 0;
- while ((index = type.indexOf("[]", index) + 1) > 0) {
- sb.append('[');
- }
+ StringBuilder stringBuilder = new StringBuilder();
+ int arrayBracketsIndex = 0;
+ while ((arrayBracketsIndex = type.indexOf("[]", arrayBracketsIndex) + 1) > 0) {
+ stringBuilder.append('[');
+ }
- String t = type.substring(0, type.length() - sb.length() * 2);
- String desc = DESCRIPTORS.get(t);
- if (desc != null) {
- sb.append(desc);
- } else {
- sb.append('L');
- if (t.indexOf('.') < 0) {
- if (!defaultPackage) {
- sb.append("java/lang/");
- }
- sb.append(t);
- } else {
- sb.append(t.replace('.', '/'));
- }
- sb.append(';');
+ String elementType = type.substring(0, type.length() - stringBuilder.length() * 2);
+ String descriptor = PRIMITIVE_TYPE_DESCRIPTORS.get(elementType);
+ if (descriptor != null) {
+ stringBuilder.append(descriptor);
+ } else {
+ stringBuilder.append('L');
+ if (elementType.indexOf('.') < 0) {
+ if (!defaultPackage) {
+ stringBuilder.append("java/lang/");
}
- return sb.toString();
+ stringBuilder.append(elementType);
+ } else {
+ stringBuilder.append(elementType.replace('.', '/'));
+ }
+ stringBuilder.append(';');
}
+ return stringBuilder.toString();
+ }
- /**
- * Returns the name of the method described by this object.
- *
- * @return the name of the method described by this object.
- */
- public String getName() {
- return name;
- }
+ /**
+ * Returns the name of the method described by this object.
+ *
+ * @return the name of the method described by this object.
+ */
+ public String getName() {
+ return name;
+ }
- /**
- * Returns the descriptor of the method described by this object.
- *
- * @return the descriptor of the method described by this object.
- */
- public String getDescriptor() {
- return desc;
- }
+ /**
+ * Returns the descriptor of the method described by this object.
+ *
+ * @return the descriptor of the method described by this object.
+ */
+ public String getDescriptor() {
+ return descriptor;
+ }
- /**
- * Returns the return type of the method described by this object.
- *
- * @return the return type of the method described by this object.
- */
- public Type getReturnType() {
- return Type.getReturnType(desc);
- }
+ /**
+ * Returns the return type of the method described by this object.
+ *
+ * @return the return type of the method described by this object.
+ */
+ public Type getReturnType() {
+ return Type.getReturnType(descriptor);
+ }
- /**
- * Returns the argument types of the method described by this object.
- *
- * @return the argument types of the method described by this object.
- */
- public Type[] getArgumentTypes() {
- return Type.getArgumentTypes(desc);
- }
+ /**
+ * Returns the argument types of the method described by this object.
+ *
+ * @return the argument types of the method described by this object.
+ */
+ public Type[] getArgumentTypes() {
+ return Type.getArgumentTypes(descriptor);
+ }
- @Override
- public String toString() {
- return name + desc;
- }
+ @Override
+ public String toString() {
+ return name + descriptor;
+ }
- @Override
- public boolean equals(final Object o) {
- if (!(o instanceof Method)) {
- return false;
- }
- Method other = (Method) o;
- return name.equals(other.name) && desc.equals(other.desc);
+ @Override
+ public boolean equals(final Object other) {
+ if (!(other instanceof Method)) {
+ return false;
}
+ Method otherMethod = (Method) other;
+ return name.equals(otherMethod.name) && descriptor.equals(otherMethod.descriptor);
+ }
- @Override
- public int hashCode() {
- return name.hashCode() ^ desc.hashCode();
- }
-}
\ No newline at end of file
+ @Override
+ public int hashCode() {
+ return name.hashCode() ^ descriptor.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/MethodRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/MethodRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/MethodRemapper.java
old mode 100644
new mode 100755
index 03e56be..20cfa5a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/MethodRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/MethodRemapper.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -38,188 +36,258 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link LocalVariablesSorter} for type mapping.
- *
+ * A {@link MethodVisitor} that remaps types with a {@link Remapper}.
+ *
* @author Eugene Kuleshov
*/
public class MethodRemapper extends MethodVisitor {
- protected final Remapper remapper;
+ /** The remapper used to remap the types in the visited field. */
+ protected final Remapper remapper;
- public MethodRemapper(final MethodVisitor mv, final Remapper remapper) {
- this(Opcodes.ASM6, mv, remapper);
- }
+ /**
+ * Constructs a new {@link MethodRemapper}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #MethodRemapper(int,MethodVisitor,Remapper)} version.
+ *
+ * @param methodVisitor the method visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited method.
+ */
+ public MethodRemapper(final MethodVisitor methodVisitor, final Remapper remapper) {
+ this(Opcodes.ASM7, methodVisitor, remapper);
+ }
- protected MethodRemapper(final int api, final MethodVisitor mv,
- final Remapper remapper) {
- super(api, mv);
- this.remapper = remapper;
- }
+ /**
+ * Constructs a new {@link MethodRemapper}.
+ *
+ * @param api the ASM API version supported by this remapper. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6}.
+ * @param methodVisitor the method visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited method.
+ */
+ protected MethodRemapper(
+ final int api, final MethodVisitor methodVisitor, final Remapper remapper) {
+ super(api, methodVisitor);
+ this.remapper = remapper;
+ }
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- AnnotationVisitor av = super.visitAnnotationDefault();
- return av == null ? av : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ AnnotationVisitor annotationVisitor = super.visitAnnotationDefault();
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
- visible);
- return av == null ? av : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitAnnotation(remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? av : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
- @Override
- public AnnotationVisitor visitParameterAnnotation(int parameter,
- String desc, boolean visible) {
- AnnotationVisitor av = super.visitParameterAnnotation(parameter,
- remapper.mapDesc(desc), visible);
- return av == null ? av : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitParameterAnnotation(parameter, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
- @Override
- public void visitFrame(int type, int nLocal, Object[] local, int nStack,
- Object[] stack) {
- super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
- remapEntries(nStack, stack));
- }
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ super.visitFrame(
+ type,
+ numLocal,
+ remapFrameTypes(numLocal, local),
+ numStack,
+ remapFrameTypes(numStack, stack));
+ }
- private Object[] remapEntries(int n, Object[] entries) {
- if (entries != null) {
- for (int i = 0; i < n; i++) {
- if (entries[i] instanceof String) {
- Object[] newEntries = new Object[n];
- if (i > 0) {
- System.arraycopy(entries, 0, newEntries, 0, i);
- }
- do {
- Object t = entries[i];
- newEntries[i++] = t instanceof String ? remapper
- .mapType((String) t) : t;
- } while (i < n);
- return newEntries;
- }
- }
+ private Object[] remapFrameTypes(final int numTypes, final Object[] frameTypes) {
+ if (frameTypes == null) {
+ return frameTypes;
+ }
+ Object[] remappedFrameTypes = null;
+ for (int i = 0; i < numTypes; ++i) {
+ if (frameTypes[i] instanceof String) {
+ if (remappedFrameTypes == null) {
+ remappedFrameTypes = new Object[numTypes];
+ System.arraycopy(frameTypes, 0, remappedFrameTypes, 0, numTypes);
}
- return entries;
+ remappedFrameTypes[i] = remapper.mapType((String) frameTypes[i]);
+ }
}
+ return remappedFrameTypes == null ? frameTypes : remappedFrameTypes;
+ }
- @Override
- public void visitFieldInsn(int opcode, String owner, String name,
- String desc) {
- super.visitFieldInsn(opcode, remapper.mapType(owner),
- remapper.mapFieldName(owner, name, desc),
- remapper.mapDesc(desc));
- }
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ super.visitFieldInsn(
+ opcode,
+ remapper.mapType(owner),
+ remapper.mapFieldName(owner, name, descriptor),
+ remapper.mapDesc(descriptor));
+ }
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
}
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
}
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
- private void doVisitMethodInsn(int opcode, String owner, String name,
- String desc, boolean itf) {
- // Calling super.visitMethodInsn requires to call the correct version
- // depending on this.api (otherwise infinite loops can occur). To
- // simplify and to make it easier to automatically remove the backward
- // compatibility code, we inline the code of the overridden method here.
- // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
- // LocalVariableSorter.
- if (mv != null) {
- mv.visitMethodInsn(opcode, remapper.mapType(owner),
- remapper.mapMethodName(owner, name, desc),
- remapper.mapMethodDesc(desc), itf);
- }
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ // Calling super.visitMethodInsn requires to call the correct version depending on this.api
+ // (otherwise infinite loops can occur). To simplify and to make it easier to automatically
+ // remove the backward compatibility code, we inline the code of the overridden method here.
+ if (mv != null) {
+ mv.visitMethodInsn(
+ opcode,
+ remapper.mapType(owner),
+ remapper.mapMethodName(owner, name, descriptor),
+ remapper.mapMethodDesc(descriptor),
+ isInterface);
}
+ }
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- for (int i = 0; i < bsmArgs.length; i++) {
- bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
- }
- super.visitInvokeDynamicInsn(
- remapper.mapInvokeDynamicMethodName(name, desc),
- remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
- bsmArgs);
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArguments.length];
+ for (int i = 0; i < bootstrapMethodArguments.length; ++i) {
+ remappedBootstrapMethodArguments[i] = remapper.mapValue(bootstrapMethodArguments[i]);
}
+ super.visitInvokeDynamicInsn(
+ remapper.mapInvokeDynamicMethodName(name, descriptor),
+ remapper.mapMethodDesc(descriptor),
+ (Handle) remapper.mapValue(bootstrapMethodHandle),
+ remappedBootstrapMethodArguments);
+ }
- @Override
- public void visitTypeInsn(int opcode, String type) {
- super.visitTypeInsn(opcode, remapper.mapType(type));
- }
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ super.visitTypeInsn(opcode, remapper.mapType(type));
+ }
- @Override
- public void visitLdcInsn(Object cst) {
- super.visitLdcInsn(remapper.mapValue(cst));
- }
+ @Override
+ public void visitLdcInsn(final Object value) {
+ super.visitLdcInsn(remapper.mapValue(value));
+ }
- @Override
- public void visitMultiANewArrayInsn(String desc, int dims) {
- super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
- }
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ super.visitMultiANewArrayInsn(remapper.mapDesc(descriptor), numDimensions);
+ }
- @Override
- public AnnotationVisitor visitInsnAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? av : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitInsnAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler,
- String type) {
- super.visitTryCatchBlock(start, end, handler, type == null ? null
- : remapper.mapType(type));
- }
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ super.visitTryCatchBlock(start, end, handler, type == null ? null : remapper.mapType(type));
+ }
- @Override
- public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? av : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTryCatchAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
- @Override
- public void visitLocalVariable(String name, String desc, String signature,
- Label start, Label end, int index) {
- super.visitLocalVariable(name, remapper.mapDesc(desc),
- remapper.mapSignature(signature, true), start, end, index);
- }
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ super.visitLocalVariable(
+ name,
+ remapper.mapDesc(descriptor),
+ remapper.mapSignature(signature, true),
+ start,
+ end,
+ index);
+ }
- @Override
- public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
- TypePath typePath, Label[] start, Label[] end, int[] index,
- String desc, boolean visible) {
- AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
- typePath, start, end, index, remapper.mapDesc(desc), visible);
- return av == null ? av : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, index, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleHashesAttribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleHashesAttribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleHashesAttribute.java
old mode 100644
new mode 100755
index 5a46fa4..62c54c6
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleHashesAttribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleHashesAttribute.java
@@ -1,38 +1,35 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.ArrayList;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.ByteVector;
import org.apache.tapestry5.internal.plastic.asm.ClassReader;
@@ -40,87 +37,103 @@ import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
import org.apache.tapestry5.internal.plastic.asm.Label;
/**
- * ModuleHashes attribute.
- * This attribute is specific to the OpenJDK and may change in the future.
- *
+ * A ModuleHashes attribute. This attribute is specific to the OpenJDK and may change in the future.
+ *
* @author Remi Forax
*/
public final class ModuleHashesAttribute extends Attribute {
- public String algorithm;
- public List<String> modules;
- public List<byte[]> hashes;
-
- /**
- * Creates an attribute with a hashing algorithm, a list of module names,
- * and a list of the same length of hashes.
- * @param algorithm the hashing algorithm name.
- * @param modules a list of module name
- * @param hashes a list of hash, one for each module name.
- */
- public ModuleHashesAttribute(final String algorithm,
- final List<String> modules, final List<byte[]> hashes) {
- super("ModuleHashes");
- this.algorithm = algorithm;
- this.modules = modules;
- this.hashes = hashes;
- }
-
- /**
- * Creates an empty attribute that can be used as prototype
- * to be passed as argument of the method
- * {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
- */
- public ModuleHashesAttribute() {
- this(null, null, null);
- }
-
- @Override
- protected Attribute read(ClassReader cr, int off, int len, char[] buf,
- int codeOff, Label[] labels) {
- String hashAlgorithm = cr.readUTF8(off, buf);
-
- int count = cr.readUnsignedShort(off + 2);
- ArrayList<String> modules = new ArrayList<String>(count);
- ArrayList<byte[]> hashes = new ArrayList<byte[]>(count);
- off += 4;
-
- for (int i = 0; i < count; i++) {
- String module = cr.readModule(off, buf);
- int hashLength = cr.readUnsignedShort(off + 2);
- off += 4;
- byte[] hash = new byte[hashLength];
- for (int j = 0; j < hashLength; j++) {
- hash[j] = (byte) (cr.readByte(off + j) & 0xff);
- }
- off += hashLength;
+ /** The name of the hashing algorithm. */
+ public String algorithm;
+
+ /** A list of module names. */
+ public List<String> modules;
+
+ /** The hash of the modules in {@link #modules}. The two lists must have the same size. */
+ public List<byte[]> hashes;
+
+ /**
+ * Constructs a new {@link ModuleHashesAttribute}.
+ *
+ * @param algorithm the name of the hashing algorithm.
+ * @param modules a list of module names.
+ * @param hashes the hash of the modules in 'modules'. The two lists must have the same size.
+ */
+ public ModuleHashesAttribute(
+ final String algorithm, final List<String> modules, final List<byte[]> hashes) {
+ super("ModuleHashes");
+ this.algorithm = algorithm;
+ this.modules = modules;
+ this.hashes = hashes;
+ }
+
+ /**
+ * Constructs an empty {@link ModuleHashesAttribute}. This object can be passed as a prototype to
+ * the {@link ClassReader#accept(org.apache.tapestry5.internal.plastic.asm.ClassVisitor, Attribute[], int)} method.
+ */
+ public ModuleHashesAttribute() {
+ this(null, null, null);
+ }
+
+ @Override
+ protected Attribute read(
+ final ClassReader classReader,
+ final int offset,
+ final int length,
+ final char[] charBuffer,
+ final int codeAttributeOffset,
+ final Label[] labels) {
+ int currentOffset = offset;
+
+ String hashAlgorithm = classReader.readUTF8(currentOffset, charBuffer);
+ currentOffset += 2;
+
+ int numModules = classReader.readUnsignedShort(currentOffset);
+ currentOffset += 2;
+
+ ArrayList<String> moduleList = new ArrayList<String>(numModules);
+ ArrayList<byte[]> hashList = new ArrayList<byte[]>(numModules);
+
+ for (int i = 0; i < numModules; ++i) {
+ String module = classReader.readModule(currentOffset, charBuffer);
+ currentOffset += 2;
+ moduleList.add(module);
- modules.add(module);
- hashes.add(hash);
- }
- return new ModuleHashesAttribute(hashAlgorithm, modules, hashes);
+ int hashLength = classReader.readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ byte[] hash = new byte[hashLength];
+ for (int j = 0; j < hashLength; ++j) {
+ hash[j] = (byte) (classReader.readByte(currentOffset) & 0xFF);
+ currentOffset += 1;
+ }
+ hashList.add(hash);
}
-
- @Override
- protected ByteVector write(ClassWriter cw, byte[] code, int len,
- int maxStack, int maxLocals) {
- ByteVector v = new ByteVector();
- int index = cw.newUTF8(algorithm);
- v.putShort(index);
+ return new ModuleHashesAttribute(hashAlgorithm, moduleList, hashList);
+ }
- int count = (modules == null)? 0: modules.size();
- v.putShort(count);
-
- for(int i = 0; i < count; i++) {
- String module = modules.get(i);
- v.putShort(cw.newModule(module));
-
- byte[] hash = hashes.get(i);
- v.putShort(hash.length);
- for(byte b: hash) {
- v.putByte(b);
- }
- }
- return v;
+ @Override
+ protected ByteVector write(
+ final ClassWriter classWriter,
+ final byte[] code,
+ final int codeLength,
+ final int maxStack,
+ final int maxLocals) {
+ ByteVector byteVector = new ByteVector();
+ byteVector.putShort(classWriter.newUTF8(algorithm));
+ if (modules == null) {
+ byteVector.putShort(0);
+ } else {
+ int numModules = modules.size();
+ byteVector.putShort(numModules);
+ for (int i = 0; i < numModules; ++i) {
+ String module = modules.get(i);
+ byte[] hash = hashes.get(i);
+ byteVector
+ .putShort(classWriter.newModule(module))
+ .putShort(hash.length)
+ .putByteArray(hash, 0, hash.length);
+ }
}
+ return byteVector;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleRemapper.java
old mode 100644
new mode 100755
index c3fd7a9..8d9eda4
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleRemapper.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -34,73 +32,91 @@ import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * A {@link ModuleVisitor} adapter for type remapping.
- *
+ * A {@link ModuleVisitor} that remaps types with a {@link Remapper}.
+ *
* @author Remi Forax
*/
public class ModuleRemapper extends ModuleVisitor {
- private final Remapper remapper;
- public ModuleRemapper(final ModuleVisitor mv, final Remapper remapper) {
- this(Opcodes.ASM6, mv, remapper);
- }
+ /** The remapper used to remap the types in the visited module. */
+ protected final Remapper remapper;
- protected ModuleRemapper(final int api, final ModuleVisitor mv,
- final Remapper remapper) {
- super(api, mv);
- this.remapper = remapper;
- }
+ /**
+ * Constructs a new {@link ModuleRemapper}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #ModuleRemapper(int,ModuleVisitor,Remapper)} version.
+ *
+ * @param moduleVisitor the module visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited module.
+ */
+ public ModuleRemapper(final ModuleVisitor moduleVisitor, final Remapper remapper) {
+ this(Opcodes.ASM7, moduleVisitor, remapper);
+ }
- @Override
- public void visitMainClass(String mainClass) {
- super.visitMainClass(remapper.mapType(mainClass));
- }
-
- @Override
- public void visitPackage(String packaze) {
- super.visitPackage(remapper.mapPackageName(packaze));
- }
-
- @Override
- public void visitRequire(String module, int access, String version) {
- super.visitRequire(remapper.mapModuleName(module), access, version);
- }
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- String[] newModules = null;
- if (modules != null) {
- newModules = new String[modules.length];
- for (int i = 0 ; i < modules.length; i++) {
- newModules[i] = remapper.mapModuleName(modules[i]);
- }
- }
- super.visitExport(remapper.mapPackageName(packaze), access, newModules);
- }
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- String[] newModules = null;
- if (modules != null) {
- newModules = new String[modules.length];
- for (int i = 0 ; i < modules.length; i++) {
- newModules[i] = remapper.mapModuleName(modules[i]);
- }
- }
- super.visitOpen(remapper.mapPackageName(packaze), access, newModules);
+ /**
+ * Constructs a new {@link ModuleRemapper}.
+ *
+ * @param api the ASM API version supported by this remapper. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6}.
+ * @param moduleVisitor the module visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited module.
+ */
+ protected ModuleRemapper(
+ final int api, final ModuleVisitor moduleVisitor, final Remapper remapper) {
+ super(api, moduleVisitor);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ super.visitMainClass(remapper.mapType(mainClass));
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ super.visitPackage(remapper.mapPackageName(packaze));
+ }
+
+ @Override
+ public void visitRequire(final String module, final int access, final String version) {
+ super.visitRequire(remapper.mapModuleName(module), access, version);
+ }
+
+ @Override
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ String[] remappedModules = null;
+ if (modules != null) {
+ remappedModules = new String[modules.length];
+ for (int i = 0; i < modules.length; ++i) {
+ remappedModules[i] = remapper.mapModuleName(modules[i]);
+ }
}
-
- @Override
- public void visitUse(String service) {
- super.visitUse(remapper.mapType(service));
+ super.visitExport(remapper.mapPackageName(packaze), access, remappedModules);
+ }
+
+ @Override
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ String[] remappedModules = null;
+ if (modules != null) {
+ remappedModules = new String[modules.length];
+ for (int i = 0; i < modules.length; ++i) {
+ remappedModules[i] = remapper.mapModuleName(modules[i]);
+ }
}
-
- @Override
- public void visitProvide(String service, String... providers) {
- String[] newProviders = new String[providers.length];
- for (int i = 0 ; i < providers.length; i++) {
- newProviders[i] = remapper.mapType(providers[i]);
- }
- super.visitProvide(remapper.mapType(service), newProviders);
+ super.visitOpen(remapper.mapPackageName(packaze), access, remappedModules);
+ }
+
+ @Override
+ public void visitUse(final String service) {
+ super.visitUse(remapper.mapType(service));
+ }
+
+ @Override
+ public void visitProvide(final String service, final String... providers) {
+ String[] remappedProviders = new String[providers.length];
+ for (int i = 0; i < providers.length; ++i) {
+ remappedProviders[i] = remapper.mapType(providers[i]);
}
+ super.visitProvide(remapper.mapType(service), remappedProviders);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleResolutionAttribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleResolutionAttribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleResolutionAttribute.java
old mode 100644
new mode 100755
index e2cf83c..27396dc
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleResolutionAttribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleResolutionAttribute.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -37,70 +35,79 @@ import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
import org.apache.tapestry5.internal.plastic.asm.Label;
/**
- * ModuleResolution_attribute.
- * This attribute is specific to the OpenJDK and may change in the future.
- *
+ * A ModuleResolution attribute. This attribute is specific to the OpenJDK and may change in the
+ * future.
+ *
* @author Remi Forax
*/
public final class ModuleResolutionAttribute extends Attribute {
- /**
- * Resolution state of a module meaning that the module is not available
- * from the class-path by default.
- */
- public static final int RESOLUTION_DO_NOT_RESOLVE_BY_DEFAULT = 1;
-
- /**
- * Resolution state of a module meaning the module is marked as deprecated.
- */
- public static final int RESOLUTION_WARN_DEPRECATED = 2;
-
- /**
- * Resolution state of a module meaning the module is marked as deprecated
- * and will be removed in a future release.
- */
- public static final int RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL = 4;
-
- /**
- * Resolution state of a module meaning the module is not yet standardized,
- * so in incubating mode.
- */
- public static final int RESOLUTION_WARN_INCUBATING = 8;
-
- public int resolution;
-
- /**
- * Creates an attribute with a resolution state value.
- * @param resolution the resolution state among
- * {@link #RESOLUTION_WARN_DEPRECATED},
- * {@link #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and
- * {@link #RESOLUTION_WARN_INCUBATING}.
- */
- public ModuleResolutionAttribute(final int resolution) {
- super("ModuleResolution");
- this.resolution = resolution;
- }
-
- /**
- * Creates an empty attribute that can be used as prototype
- * to be passed as argument of the method
- * {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
- */
- public ModuleResolutionAttribute() {
- this(0);
- }
-
- @Override
- protected Attribute read(ClassReader cr, int off, int len, char[] buf,
- int codeOff, Label[] labels) {
- int resolution = cr.readUnsignedShort(off);
- return new ModuleResolutionAttribute(resolution);
- }
-
- @Override
- protected ByteVector write(ClassWriter cw, byte[] code, int len,
- int maxStack, int maxLocals) {
- ByteVector v = new ByteVector();
- v.putShort(resolution);
- return v;
- }
+ /**
+ * The resolution state of a module meaning that the module is not available from the class-path
+ * by default.
+ */
+ public static final int RESOLUTION_DO_NOT_RESOLVE_BY_DEFAULT = 1;
+
+ /** The resolution state of a module meaning the module is marked as deprecated. */
+ public static final int RESOLUTION_WARN_DEPRECATED = 2;
+
+ /**
+ * The resolution state of a module meaning the module is marked as deprecated and will be removed
+ * in a future release.
+ */
+ public static final int RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL = 4;
+
+ /**
+ * The resolution state of a module meaning the module is not yet standardized, so in incubating
+ * mode.
+ */
+ public static final int RESOLUTION_WARN_INCUBATING = 8;
+
+ /**
+ * The resolution state of the module. Must be one of {@link #RESOLUTION_WARN_DEPRECATED}, {@link
+ * #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and {@link #RESOLUTION_WARN_INCUBATING}.
+ */
+ public int resolution;
+
+ /**
+ * Constructs a new {@link ModuleResolutionAttribute}.
+ *
+ * @param resolution the resolution state of the module. Must be one of {@link
+ * #RESOLUTION_WARN_DEPRECATED}, {@link #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and {@link
+ * #RESOLUTION_WARN_INCUBATING}.
+ */
+ public ModuleResolutionAttribute(final int resolution) {
+ super("ModuleResolution");
+ this.resolution = resolution;
+ }
+
+ /**
+ * Constructs an empty {@link ModuleResolutionAttribute}. This object can be passed as a prototype
+ * to the {@link ClassReader#accept(org.apache.tapestry5.internal.plastic.asm.ClassVisitor, Attribute[], int)} method.
+ */
+ public ModuleResolutionAttribute() {
+ this(0);
+ }
+
+ @Override
+ protected Attribute read(
+ final ClassReader classReader,
+ final int offset,
+ final int length,
+ final char[] charBuffer,
+ final int codeOffset,
+ final Label[] labels) {
+ return new ModuleResolutionAttribute(classReader.readUnsignedShort(offset));
+ }
+
+ @Override
+ protected ByteVector write(
+ final ClassWriter classWriter,
+ final byte[] code,
+ final int codeLength,
+ final int maxStack,
+ final int maxLocals) {
+ ByteVector byteVector = new ByteVector();
+ byteVector.putShort(resolution);
+ return byteVector;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleTargetAttribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleTargetAttribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleTargetAttribute.java
old mode 100644
new mode 100755
index 02feb7a..d48b5b1
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleTargetAttribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ModuleTargetAttribute.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -37,45 +35,53 @@ import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
import org.apache.tapestry5.internal.plastic.asm.Label;
/**
- * ModuleTarget attribute.
- * This attribute is specific to the OpenJDK and may change in the future.
- *
+ * A ModuleTarget attribute. This attribute is specific to the OpenJDK and may change in the future.
+ *
* @author Remi Forax
*/
public final class ModuleTargetAttribute extends Attribute {
- public String platform;
-
- /**
- * Creates an attribute with a platform name.
- * @param platform the platform name on which the module can run.
- */
- public ModuleTargetAttribute(final String platform) {
- super("ModuleTarget");
- this.platform = platform;
- }
-
- /**
- * Creates an empty attribute that can be used as prototype
- * to be passed as argument of the method
- * {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
- */
- public ModuleTargetAttribute() {
- this(null);
- }
-
- @Override
- protected Attribute read(ClassReader cr, int off, int len, char[] buf,
- int codeOff, Label[] labels) {
- String platform = cr.readUTF8(off, buf);
- return new ModuleTargetAttribute(platform);
- }
-
- @Override
- protected ByteVector write(ClassWriter cw, byte[] code, int len,
- int maxStack, int maxLocals) {
- ByteVector v = new ByteVector();
- int index = (platform == null)? 0: cw.newUTF8(platform);
- v.putShort(index);
- return v;
- }
+
+ /** The name of the platform on which the module can run. */
+ public String platform;
+
+ /**
+ * Constructs a new {@link ModuleTargetAttribute}.
+ *
+ * @param platform the name of the platform on which the module can run.
+ */
+ public ModuleTargetAttribute(final String platform) {
+ super("ModuleTarget");
+ this.platform = platform;
+ }
+
+ /**
+ * Constructs an empty {@link ModuleTargetAttribute}. This object can be passed as a prototype to
+ * the {@link ClassReader#accept(org.apache.tapestry5.internal.plastic.asm.ClassVisitor, Attribute[], int)} method.
+ */
+ public ModuleTargetAttribute() {
+ this(null);
+ }
+
+ @Override
+ protected Attribute read(
+ final ClassReader classReader,
+ final int offset,
+ final int length,
+ final char[] charBuffer,
+ final int codeOffset,
+ final Label[] labels) {
+ return new ModuleTargetAttribute(classReader.readUTF8(offset, charBuffer));
+ }
+
+ @Override
+ protected ByteVector write(
+ final ClassWriter classWriter,
+ final byte[] code,
+ final int codeLength,
+ final int maxStack,
+ final int maxLocals) {
+ ByteVector byteVector = new ByteVector();
+ byteVector.putShort(platform == null ? 0 : classWriter.newUTF8(platform));
+ return byteVector;
+ }
}
[05/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
old mode 100644
new mode 100755
index 448728a..70a974d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
@@ -1,41 +1,36 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
-import java.io.FileInputStream;
-import java.io.PrintWriter;
+import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Attribute;
-import org.apache.tapestry5.internal.plastic.asm.ClassReader;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
@@ -51,1546 +46,1568 @@ import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
*/
public class Textifier extends Printer {
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for internal
- * type names in bytecode notation.
- */
- public static final int INTERNAL_NAME = 0;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for field
- * descriptors, formatted in bytecode notation
- */
- public static final int FIELD_DESCRIPTOR = 1;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for field
- * signatures, formatted in bytecode notation
- */
- public static final int FIELD_SIGNATURE = 2;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for method
- * descriptors, formatted in bytecode notation
- */
- public static final int METHOD_DESCRIPTOR = 3;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for method
- * signatures, formatted in bytecode notation
- */
- public static final int METHOD_SIGNATURE = 4;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for class
- * signatures, formatted in bytecode notation
- */
- public static final int CLASS_SIGNATURE = 5;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for field or
- * method return value signatures, formatted in default Java notation
- * (non-bytecode)
- */
- public static final int TYPE_DECLARATION = 6;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for class
- * signatures, formatted in default Java notation (non-bytecode)
- */
- public static final int CLASS_DECLARATION = 7;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for method
- * parameter signatures, formatted in default Java notation (non-bytecode)
- */
- public static final int PARAMETERS_DECLARATION = 8;
-
- /**
- * Constant used in {@link #appendDescriptor appendDescriptor} for handle
- * descriptors, formatted in bytecode notation
- */
- public static final int HANDLE_DESCRIPTOR = 9;
-
- /**
- * Tab for class members.
- */
- protected String tab = " ";
-
- /**
- * Tab for bytecode instructions.
- */
- protected String tab2 = " ";
-
- /**
- * Tab for table and lookup switch instructions.
- */
- protected String tab3 = " ";
-
- /**
- * Tab for labels.
- */
- protected String ltab = " ";
-
- /**
- * The label names. This map associate String values to Label keys.
- */
- protected Map<Label, String> labelNames;
-
- /**
- * Class access flags
- */
- private int access;
-
- private int valueNumber = 0;
-
- /**
- * Constructs a new {@link Textifier}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the {@link #Textifier(int)}
- * version.
- *
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public Textifier() {
- this(Opcodes.ASM6);
- if (getClass() != Textifier.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Constructs a new {@link Textifier}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- protected Textifier(final int api) {
- super(api);
- }
-
- /**
- * Prints a disassembled view of the given class to the standard output.
- * <p>
- * Usage: Textifier [-debug] <binary class name or class file name >
- *
- * @param args
- * the command line arguments.
- *
- * @throws Exception
- * if the class cannot be found, or if an IO exception occurs.
- */
- public static void main(final String[] args) throws Exception {
- int i = 0;
- int flags = ClassReader.SKIP_DEBUG;
-
- boolean ok = true;
- if (args.length < 1 || args.length > 2) {
- ok = false;
- }
- if (ok && "-debug".equals(args[0])) {
- i = 1;
- flags = 0;
- if (args.length != 2) {
- ok = false;
- }
- }
- if (!ok) {
- System.err
- .println("Prints a disassembled view of the given class.");
- System.err.println("Usage: Textifier [-debug] "
- + "<fully qualified class name or class file name>");
- return;
- }
- ClassReader cr;
- if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
- || args[i].indexOf('/') > -1) {
- cr = new ClassReader(new FileInputStream(args[i]));
- } else {
- cr = new ClassReader(args[i]);
- }
- cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags);
- }
-
- // ------------------------------------------------------------------------
- // Classes
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- if ((access & Opcodes.ACC_MODULE) != 0) {
- // visitModule will print the module
- return;
- }
- this.access = access;
- int major = version & 0xFFFF;
- int minor = version >>> 16;
- buf.setLength(0);
- buf.append("// class version ").append(major).append('.').append(minor)
- .append(" (").append(version).append(")\n");
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- buf.append("// DEPRECATED\n");
- }
- buf.append("// access flags 0x")
- .append(Integer.toHexString(access).toUpperCase()).append('\n');
-
- appendDescriptor(CLASS_SIGNATURE, signature);
- if (signature != null) {
- TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
- SignatureReader r = new SignatureReader(signature);
- r.accept(sv);
- buf.append("// declaration: ").append(name)
- .append(sv.getDeclaration()).append('\n');
- }
-
- appendAccess(access & ~(Opcodes.ACC_SUPER | Opcodes.ACC_MODULE));
- if ((access & Opcodes.ACC_ANNOTATION) != 0) {
- buf.append("@interface ");
- } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
- buf.append("interface ");
- } else if ((access & Opcodes.ACC_ENUM) == 0) {
- buf.append("class ");
- }
- appendDescriptor(INTERNAL_NAME, name);
-
- if (superName != null && !"java/lang/Object".equals(superName)) {
- buf.append(" extends ");
- appendDescriptor(INTERNAL_NAME, superName);
- buf.append(' ');
- }
- if (interfaces != null && interfaces.length > 0) {
- buf.append(" implements ");
- for (int i = 0; i < interfaces.length; ++i) {
- appendDescriptor(INTERNAL_NAME, interfaces[i]);
- buf.append(' ');
- }
- }
- buf.append(" {\n\n");
-
- text.add(buf.toString());
- }
-
- @Override
- public void visitSource(final String file, final String debug) {
- buf.setLength(0);
- if (file != null) {
- buf.append(tab).append("// compiled from: ").append(file)
- .append('\n');
- }
- if (debug != null) {
- buf.append(tab).append("// debug info: ").append(debug)
- .append('\n');
- }
- if (buf.length() > 0) {
- text.add(buf.toString());
- }
- }
-
- @Override
- public Printer visitModule(final String name, final int access,
- final String version) {
- buf.setLength(0);
- if ((access & Opcodes.ACC_OPEN) != 0) {
- buf.append("open ");
- }
- buf.append("module ")
- .append(name)
- .append(" { ")
- .append(version == null ? "" : "// " + version)
- .append("\n\n");
- text.add(buf.toString());
- Textifier t = createTextifier();
- text.add(t.getText());
- return t;
- }
-
- @Override
- public void visitOuterClass(final String owner, final String name,
- final String desc) {
- buf.setLength(0);
- buf.append(tab).append("OUTERCLASS ");
- appendDescriptor(INTERNAL_NAME, owner);
- buf.append(' ');
- if (name != null) {
- buf.append(name).append(' ');
- }
- appendDescriptor(METHOD_DESCRIPTOR, desc);
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public Textifier visitClassAnnotation(final String desc,
- final boolean visible) {
- text.add("\n");
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath,
- String desc, boolean visible) {
- text.add("\n");
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public void visitClassAttribute(final Attribute attr) {
- text.add("\n");
- visitAttribute(attr);
- }
-
- @Override
- public void visitInnerClass(final String name, final String outerName,
- final String innerName, final int access) {
- buf.setLength(0);
- buf.append(tab).append("// access flags 0x");
- buf.append(
- Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase())
- .append('\n');
- buf.append(tab);
- appendAccess(access);
- buf.append("INNERCLASS ");
- appendDescriptor(INTERNAL_NAME, name);
- buf.append(' ');
- appendDescriptor(INTERNAL_NAME, outerName);
- buf.append(' ');
- appendDescriptor(INTERNAL_NAME, innerName);
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public Textifier visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- buf.setLength(0);
- buf.append('\n');
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- buf.append(tab).append("// DEPRECATED\n");
- }
- buf.append(tab).append("// access flags 0x")
- .append(Integer.toHexString(access).toUpperCase()).append('\n');
- if (signature != null) {
- buf.append(tab);
- appendDescriptor(FIELD_SIGNATURE, signature);
-
- TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
- SignatureReader r = new SignatureReader(signature);
- r.acceptType(sv);
- buf.append(tab).append("// declaration: ")
- .append(sv.getDeclaration()).append('\n');
- }
-
- buf.append(tab);
- appendAccess(access);
-
- appendDescriptor(FIELD_DESCRIPTOR, desc);
- buf.append(' ').append(name);
- if (value != null) {
- buf.append(" = ");
- if (value instanceof String) {
- buf.append('\"').append(value).append('\"');
- } else {
- buf.append(value);
- }
- }
-
- buf.append('\n');
- text.add(buf.toString());
-
- Textifier t = createTextifier();
- text.add(t.getText());
- return t;
- }
-
- @Override
- public Textifier visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- buf.setLength(0);
- buf.append('\n');
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- buf.append(tab).append("// DEPRECATED\n");
- }
- buf.append(tab).append("// access flags 0x")
- .append(Integer.toHexString(access).toUpperCase()).append('\n');
-
- if (signature != null) {
- buf.append(tab);
- appendDescriptor(METHOD_SIGNATURE, signature);
-
- TraceSignatureVisitor v = new TraceSignatureVisitor(0);
- SignatureReader r = new SignatureReader(signature);
- r.accept(v);
- String genericDecl = v.getDeclaration();
- String genericReturn = v.getReturnType();
- String genericExceptions = v.getExceptions();
-
- buf.append(tab).append("// declaration: ").append(genericReturn)
- .append(' ').append(name).append(genericDecl);
- if (genericExceptions != null) {
- buf.append(" throws ").append(genericExceptions);
- }
- buf.append('\n');
- }
-
- buf.append(tab);
- appendAccess(access & ~(Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT));
- if ((access & Opcodes.ACC_NATIVE) != 0) {
- buf.append("native ");
- }
- if ((access & Opcodes.ACC_VARARGS) != 0) {
- buf.append("varargs ");
- }
- if ((access & Opcodes.ACC_BRIDGE) != 0) {
- buf.append("bridge ");
- }
- if ((this.access & Opcodes.ACC_INTERFACE) != 0
- && (access & Opcodes.ACC_ABSTRACT) == 0
- && (access & Opcodes.ACC_STATIC) == 0) {
- buf.append("default ");
- }
-
- buf.append(name);
- appendDescriptor(METHOD_DESCRIPTOR, desc);
- if (exceptions != null && exceptions.length > 0) {
- buf.append(" throws ");
- for (int i = 0; i < exceptions.length; ++i) {
- appendDescriptor(INTERNAL_NAME, exceptions[i]);
- buf.append(' ');
- }
- }
-
- buf.append('\n');
- text.add(buf.toString());
-
- Textifier t = createTextifier();
- text.add(t.getText());
- return t;
- }
-
- @Override
- public void visitClassEnd() {
- text.add("}\n");
- }
-
- // ------------------------------------------------------------------------
- // Module
- // ------------------------------------------------------------------------
-
- @Override
- public void visitMainClass(String mainClass) {
- buf.setLength(0);
- buf.append(" // main class ").append(mainClass).append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitPackage(String packaze) {
- buf.setLength(0);
- buf.append(" // package ").append(packaze).append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitRequire(String require, int access, String version) {
- buf.setLength(0);
- buf.append(tab).append("requires ");
- if ((access & Opcodes.ACC_TRANSITIVE) != 0) {
- buf.append("transitive ");
- }
- if ((access & Opcodes.ACC_STATIC_PHASE) != 0) {
- buf.append("static ");
- }
- buf.append(require)
- .append("; // access flags 0x")
- .append(Integer.toHexString(access).toUpperCase())
- .append('\n');
- if (version != null) {
- buf.append(" // version ")
- .append(version)
- .append('\n');
- }
- text.add(buf.toString());
- }
-
- @Override
- public void visitExport(String export, int access, String... modules) {
- buf.setLength(0);
- buf.append(tab).append("exports ");
- buf.append(export);
- if (modules != null && modules.length > 0) {
- buf.append(" to");
- } else {
- buf.append(';');
- }
- buf.append(" // access flags 0x")
- .append(Integer.toHexString(access).toUpperCase())
- .append('\n');
- if (modules != null && modules.length > 0) {
- for (int i = 0; i < modules.length; ++i) {
- buf.append(tab2).append(modules[i]);
- buf.append(i != modules.length - 1 ? ",\n": ";\n");
- }
- }
- text.add(buf.toString());
- }
-
- @Override
- public void visitOpen(String export, int access, String... modules) {
- buf.setLength(0);
- buf.append(tab).append("opens ");
- buf.append(export);
- if (modules != null && modules.length > 0) {
- buf.append(" to");
- } else {
- buf.append(';');
- }
- buf.append(" // access flags 0x")
- .append(Integer.toHexString(access).toUpperCase())
- .append('\n');
- if (modules != null && modules.length > 0) {
- for (int i = 0; i < modules.length; ++i) {
- buf.append(tab2).append(modules[i]);
- buf.append(i != modules.length - 1 ? ",\n": ";\n");
- }
- }
- text.add(buf.toString());
- }
-
- @Override
- public void visitUse(String use) {
- buf.setLength(0);
- buf.append(tab).append("uses ");
- appendDescriptor(INTERNAL_NAME, use);
- buf.append(";\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitProvide(String provide, String... providers) {
- buf.setLength(0);
- buf.append(tab).append("provides ");
- appendDescriptor(INTERNAL_NAME, provide);
- buf.append(" with\n");
- for (int i = 0; i < providers.length; ++i) {
- buf.append(tab2);
- appendDescriptor(INTERNAL_NAME, providers[i]);
- buf.append(i != providers.length - 1 ? ",\n": ";\n");
- }
- text.add(buf.toString());
- }
-
- @Override
- public void visitModuleEnd() {
- // empty
- }
-
- // ------------------------------------------------------------------------
- // Annotations
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final String name, final Object value) {
- buf.setLength(0);
- appendComa(valueNumber++);
-
- if (name != null) {
- buf.append(name).append('=');
- }
-
+ /** The type of internal names. See {@link #appendDescriptor}. */
+ public static final int INTERNAL_NAME = 0;
+
+ /** The type of field descriptors. See {@link #appendDescriptor}. */
+ public static final int FIELD_DESCRIPTOR = 1;
+
+ /** The type of field signatures. See {@link #appendDescriptor}. */
+ public static final int FIELD_SIGNATURE = 2;
+
+ /** The type of method descriptors. See {@link #appendDescriptor}. */
+ public static final int METHOD_DESCRIPTOR = 3;
+
+ /** The type of method signatures. See {@link #appendDescriptor}. */
+ public static final int METHOD_SIGNATURE = 4;
+
+ /** The type of class signatures. See {@link #appendDescriptor}. */
+ public static final int CLASS_SIGNATURE = 5;
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated this constant has never been used.
+ */
+ @Deprecated public static final int TYPE_DECLARATION = 6;
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated this constant has never been used.
+ */
+ @Deprecated public static final int CLASS_DECLARATION = 7;
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated this constant has never been used.
+ */
+ @Deprecated public static final int PARAMETERS_DECLARATION = 8;
+
+ /** The type of method handle descriptors. See {@link #appendDescriptor}. */
+ public static final int HANDLE_DESCRIPTOR = 9;
+
+ private static final String CLASS_SUFFIX = ".class";
+ private static final String DEPRECATED = "// DEPRECATED\n";
+ private static final String INVISIBLE = " // invisible\n";
+
+ /** The indentation of class members at depth level 1 (e.g. fields, methods). */
+ protected String tab = " ";
+
+ /** The indentation of class elements at depth level 2 (e.g. bytecode instructions in methods). */
+ protected String tab2 = " ";
+
+ /** The indentation of class elements at depth level 3 (e.g. switch cases in methods). */
+ protected String tab3 = " ";
+
+ /** The indentation of labels. */
+ protected String ltab = " ";
+
+ /** The names of the labels. */
+ protected Map<Label, String> labelNames;
+
+ /** The access flags of the visited class. */
+ private int access;
+
+ /** The number of annotation values visited so far. */
+ private int numAnnotationValues;
+
+ /**
+ * Constructs a new {@link Textifier}. <i>Subclasses must not use this constructor</i>. Instead,
+ * they must use the {@link #Textifier(int)} version.
+ *
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public Textifier() {
+ this(Opcodes.ASM7);
+ if (getClass() != Textifier.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link Textifier}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected Textifier(final int api) {
+ super(api);
+ }
+
+ /**
+ * Prints a disassembled view of the given class to the standard output.
+ *
+ * <p>Usage: Textifier [-debug] <binary class name or class file name >
+ *
+ * @param args the command line arguments.
+ * @throws IOException if the class cannot be found, or if an IOException occurs.
+ */
+ public static void main(final String[] args) throws IOException {
+ String usage =
+ "Prints a disassembled view of the given class.\n"
+ + "Usage: Textifier [-debug] <fully qualified class name or class file name>";
+ main(usage, new Textifier(), args);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Classes
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ if ((access & Opcodes.ACC_MODULE) != 0) {
+ // Modules are printed in visitModule.
+ return;
+ }
+ this.access = access;
+ int majorVersion = version & 0xFFFF;
+ int minorVersion = version >>> 16;
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("// class version ")
+ .append(majorVersion)
+ .append('.')
+ .append(minorVersion)
+ .append(" (")
+ .append(version)
+ .append(")\n");
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ stringBuilder.append(DEPRECATED);
+ }
+ appendRawAccess(access);
+
+ appendDescriptor(CLASS_SIGNATURE, signature);
+ if (signature != null) {
+ appendJavaDeclaration(name, signature);
+ }
+
+ appendAccess(access & ~(Opcodes.ACC_SUPER | Opcodes.ACC_MODULE));
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ stringBuilder.append("@interface ");
+ } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ stringBuilder.append("interface ");
+ } else if ((access & Opcodes.ACC_ENUM) == 0) {
+ stringBuilder.append("class ");
+ }
+ appendDescriptor(INTERNAL_NAME, name);
+
+ if (superName != null && !"java/lang/Object".equals(superName)) {
+ stringBuilder.append(" extends ");
+ appendDescriptor(INTERNAL_NAME, superName);
+ }
+ if (interfaces != null && interfaces.length > 0) {
+ stringBuilder.append(" implements ");
+ for (int i = 0; i < interfaces.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, interfaces[i]);
+ if (i != interfaces.length - 1) {
+ stringBuilder.append(' ');
+ }
+ }
+ }
+ stringBuilder.append(" {\n\n");
+
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ stringBuilder.setLength(0);
+ if (file != null) {
+ stringBuilder.append(tab).append("// compiled from: ").append(file).append('\n');
+ }
+ if (debug != null) {
+ stringBuilder.append(tab).append("// debug info: ").append(debug).append('\n');
+ }
+ if (stringBuilder.length() > 0) {
+ text.add(stringBuilder.toString());
+ }
+ }
+
+ @Override
+ public Printer visitModule(final String name, final int access, final String version) {
+ stringBuilder.setLength(0);
+ if ((access & Opcodes.ACC_OPEN) != 0) {
+ stringBuilder.append("open ");
+ }
+ stringBuilder
+ .append("module ")
+ .append(name)
+ .append(" { ")
+ .append(version == null ? "" : "// " + version)
+ .append("\n\n");
+ text.add(stringBuilder.toString());
+ return addNewTextifier(null);
+ }
+
+ @Override
+ public void visitNestHost(final String nestHost) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("NESTHOST ");
+ appendDescriptor(INTERNAL_NAME, nestHost);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("OUTERCLASS ");
+ appendDescriptor(INTERNAL_NAME, owner);
+ stringBuilder.append(' ');
+ if (name != null) {
+ stringBuilder.append(name).append(' ');
+ }
+ appendDescriptor(METHOD_DESCRIPTOR, descriptor);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Textifier visitClassAnnotation(final String descriptor, final boolean visible) {
+ text.add("\n");
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public Printer visitClassTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ text.add("\n");
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitClassAttribute(final Attribute attribute) {
+ text.add("\n");
+ visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitNestMember(final String nestMember) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("NESTMEMBER ");
+ appendDescriptor(INTERNAL_NAME, nestMember);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab);
+ appendRawAccess(access & ~Opcodes.ACC_SUPER);
+ stringBuilder.append(tab);
+ appendAccess(access);
+ stringBuilder.append("INNERCLASS ");
+ appendDescriptor(INTERNAL_NAME, name);
+ stringBuilder.append(' ');
+ appendDescriptor(INTERNAL_NAME, outerName);
+ stringBuilder.append(' ');
+ appendDescriptor(INTERNAL_NAME, innerName);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Textifier visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ stringBuilder.append(tab).append(DEPRECATED);
+ }
+ stringBuilder.append(tab);
+ appendRawAccess(access);
+ if (signature != null) {
+ stringBuilder.append(tab);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+ stringBuilder.append(tab);
+ appendJavaDeclaration(name, signature);
+ }
+
+ stringBuilder.append(tab);
+ appendAccess(access);
+
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append(' ').append(name);
+ if (value != null) {
+ stringBuilder.append(" = ");
+ if (value instanceof String) {
+ stringBuilder.append('\"').append(value).append('\"');
+ } else {
+ stringBuilder.append(value);
+ }
+ }
+
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ return addNewTextifier(null);
+ }
+
+ @Override
+ public Textifier visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ stringBuilder.setLength(0);
+ stringBuilder.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ stringBuilder.append(tab).append(DEPRECATED);
+ }
+ stringBuilder.append(tab);
+ appendRawAccess(access);
+
+ if (signature != null) {
+ stringBuilder.append(tab);
+ appendDescriptor(METHOD_SIGNATURE, signature);
+ stringBuilder.append(tab);
+ appendJavaDeclaration(name, signature);
+ }
+
+ stringBuilder.append(tab);
+ appendAccess(access & ~(Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT));
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ stringBuilder.append("native ");
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0) {
+ stringBuilder.append("varargs ");
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0) {
+ stringBuilder.append("bridge ");
+ }
+ if ((this.access & Opcodes.ACC_INTERFACE) != 0
+ && (access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC)) == 0) {
+ stringBuilder.append("default ");
+ }
+
+ stringBuilder.append(name);
+ appendDescriptor(METHOD_DESCRIPTOR, descriptor);
+ if (exceptions != null && exceptions.length > 0) {
+ stringBuilder.append(" throws ");
+ for (String exception : exceptions) {
+ appendDescriptor(INTERNAL_NAME, exception);
+ stringBuilder.append(' ');
+ }
+ }
+
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ return addNewTextifier(null);
+ }
+
+ @Override
+ public void visitClassEnd() {
+ text.add("}\n");
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Modules
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(" // main class ").append(mainClass).append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(" // package ").append(packaze).append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitRequire(final String require, final int access, final String version) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("requires ");
+ if ((access & Opcodes.ACC_TRANSITIVE) != 0) {
+ stringBuilder.append("transitive ");
+ }
+ if ((access & Opcodes.ACC_STATIC_PHASE) != 0) {
+ stringBuilder.append("static ");
+ }
+ stringBuilder.append(require).append(';');
+ appendRawAccess(access);
+ if (version != null) {
+ stringBuilder.append(" // version ").append(version).append('\n');
+ }
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitExport(final String export, final int access, final String... modules) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("exports ");
+ stringBuilder.append(export);
+ if (modules != null && modules.length > 0) {
+ stringBuilder.append(" to");
+ } else {
+ stringBuilder.append(';');
+ }
+ appendRawAccess(access);
+ if (modules != null && modules.length > 0) {
+ for (int i = 0; i < modules.length; ++i) {
+ stringBuilder.append(tab2).append(modules[i]);
+ stringBuilder.append(i != modules.length - 1 ? ",\n" : ";\n");
+ }
+ }
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitOpen(final String export, final int access, final String... modules) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("opens ");
+ stringBuilder.append(export);
+ if (modules != null && modules.length > 0) {
+ stringBuilder.append(" to");
+ } else {
+ stringBuilder.append(';');
+ }
+ appendRawAccess(access);
+ if (modules != null && modules.length > 0) {
+ for (int i = 0; i < modules.length; ++i) {
+ stringBuilder.append(tab2).append(modules[i]);
+ stringBuilder.append(i != modules.length - 1 ? ",\n" : ";\n");
+ }
+ }
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitUse(final String use) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("uses ");
+ appendDescriptor(INTERNAL_NAME, use);
+ stringBuilder.append(";\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitProvide(final String provide, final String... providers) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("provides ");
+ appendDescriptor(INTERNAL_NAME, provide);
+ stringBuilder.append(" with\n");
+ for (int i = 0; i < providers.length; ++i) {
+ stringBuilder.append(tab2);
+ appendDescriptor(INTERNAL_NAME, providers[i]);
+ stringBuilder.append(i != providers.length - 1 ? ",\n" : ";\n");
+ }
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitModuleEnd() {
+ // Nothing to do.
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Annotations
+ // -----------------------------------------------------------------------------------------------
+
+ // DontCheck(OverloadMethodsDeclarationOrder): overloads are semantically different.
+ @Override
+ public void visit(final String name, final Object value) {
+ visitAnnotationValue(name);
+ if (value instanceof String) {
+ visitString((String) value);
+ } else if (value instanceof Type) {
+ visitType((Type) value);
+ } else if (value instanceof Byte) {
+ visitByte(((Byte) value).byteValue());
+ } else if (value instanceof Boolean) {
+ visitBoolean(((Boolean) value).booleanValue());
+ } else if (value instanceof Short) {
+ visitShort(((Short) value).shortValue());
+ } else if (value instanceof Character) {
+ visitChar(((Character) value).charValue());
+ } else if (value instanceof Integer) {
+ visitInt(((Integer) value).intValue());
+ } else if (value instanceof Float) {
+ visitFloat(((Float) value).floatValue());
+ } else if (value instanceof Long) {
+ visitLong(((Long) value).longValue());
+ } else if (value instanceof Double) {
+ visitDouble(((Double) value).doubleValue());
+ } else if (value.getClass().isArray()) {
+ stringBuilder.append('{');
+ if (value instanceof byte[]) {
+ byte[] byteArray = (byte[]) value;
+ for (int i = 0; i < byteArray.length; i++) {
+ maybeAppendComma(i);
+ visitByte(byteArray[i]);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] booleanArray = (boolean[]) value;
+ for (int i = 0; i < booleanArray.length; i++) {
+ maybeAppendComma(i);
+ visitBoolean(booleanArray[i]);
+ }
+ } else if (value instanceof short[]) {
+ short[] shortArray = (short[]) value;
+ for (int i = 0; i < shortArray.length; i++) {
+ maybeAppendComma(i);
+ visitShort(shortArray[i]);
+ }
+ } else if (value instanceof char[]) {
+ char[] charArray = (char[]) value;
+ for (int i = 0; i < charArray.length; i++) {
+ maybeAppendComma(i);
+ visitChar(charArray[i]);
+ }
+ } else if (value instanceof int[]) {
+ int[] intArray = (int[]) value;
+ for (int i = 0; i < intArray.length; i++) {
+ maybeAppendComma(i);
+ visitInt(intArray[i]);
+ }
+ } else if (value instanceof long[]) {
+ long[] longArray = (long[]) value;
+ for (int i = 0; i < longArray.length; i++) {
+ maybeAppendComma(i);
+ visitLong(longArray[i]);
+ }
+ } else if (value instanceof float[]) {
+ float[] floatArray = (float[]) value;
+ for (int i = 0; i < floatArray.length; i++) {
+ maybeAppendComma(i);
+ visitFloat(floatArray[i]);
+ }
+ } else if (value instanceof double[]) {
+ double[] doubleArray = (double[]) value;
+ for (int i = 0; i < doubleArray.length; i++) {
+ maybeAppendComma(i);
+ visitDouble(doubleArray[i]);
+ }
+ }
+ stringBuilder.append('}');
+ }
+ text.add(stringBuilder.toString());
+ }
+
+ private void visitInt(final int value) {
+ stringBuilder.append(value);
+ }
+
+ private void visitLong(final long value) {
+ stringBuilder.append(value).append('L');
+ }
+
+ private void visitFloat(final float value) {
+ stringBuilder.append(value).append('F');
+ }
+
+ private void visitDouble(final double value) {
+ stringBuilder.append(value).append('D');
+ }
+
+ private void visitChar(final char value) {
+ stringBuilder.append("(char)").append((int) value);
+ }
+
+ private void visitShort(final short value) {
+ stringBuilder.append("(short)").append(value);
+ }
+
+ private void visitByte(final byte value) {
+ stringBuilder.append("(byte)").append(value);
+ }
+
+ private void visitBoolean(final boolean value) {
+ stringBuilder.append(value);
+ }
+
+ private void visitString(final String value) {
+ appendString(stringBuilder, value);
+ }
+
+ private void visitType(final Type value) {
+ stringBuilder.append(value.getClassName()).append(CLASS_SUFFIX);
+ }
+
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ visitAnnotationValue(name);
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append('.').append(value);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Textifier visitAnnotation(final String name, final String descriptor) {
+ visitAnnotationValue(name);
+ stringBuilder.append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append('(');
+ text.add(stringBuilder.toString());
+ return addNewTextifier(")");
+ }
+
+ @Override
+ public Textifier visitArray(final String name) {
+ visitAnnotationValue(name);
+ stringBuilder.append('{');
+ text.add(stringBuilder.toString());
+ return addNewTextifier("}");
+ }
+
+ @Override
+ public void visitAnnotationEnd() {
+ // Nothing to do.
+ }
+
+ private void visitAnnotationValue(final String name) {
+ stringBuilder.setLength(0);
+ maybeAppendComma(numAnnotationValues++);
+ if (name != null) {
+ stringBuilder.append(name).append('=');
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Fields
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public Textifier visitFieldAnnotation(final String descriptor, final boolean visible) {
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public Printer visitFieldTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitFieldAttribute(final Attribute attribute) {
+ visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitFieldEnd() {
+ // Nothing to do.
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visitParameter(final String name, final int access) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("// parameter ");
+ appendAccess(access);
+ stringBuilder.append(' ').append((name == null) ? "<no name>" : name).append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Textifier visitAnnotationDefault() {
+ text.add(tab2 + "default=");
+ return addNewTextifier("\n");
+ }
+
+ @Override
+ public Textifier visitMethodAnnotation(final String descriptor, final boolean visible) {
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public Printer visitMethodTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public Textifier visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("// annotable parameter count: ");
+ stringBuilder.append(parameterCount);
+ stringBuilder.append(visible ? " (visible)\n" : " (invisible)\n");
+ text.add(stringBuilder.toString());
+ return this;
+ }
+
+ @Override
+ public Textifier visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append('(');
+ text.add(stringBuilder.toString());
+
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(visible ? ") // parameter " : ") // invisible, parameter ")
+ .append(parameter)
+ .append('\n');
+ return addNewTextifier(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMethodAttribute(final Attribute attribute) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("ATTRIBUTE ");
+ appendDescriptor(-1, attribute.type);
+
+ if (attribute instanceof Textifiable) {
+ StringBuffer stringBuffer = new StringBuffer();
+ ((Textifiable) attribute).textify(stringBuffer, labelNames);
+ stringBuilder.append(stringBuffer.toString());
+ } else {
+ stringBuilder.append(" : unknown\n");
+ }
+
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitCode() {
+ // Nothing to do.
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(ltab);
+ stringBuilder.append("FRAME ");
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ stringBuilder.append("FULL [");
+ appendFrameTypes(numLocal, local);
+ stringBuilder.append("] [");
+ appendFrameTypes(numStack, stack);
+ stringBuilder.append(']');
+ break;
+ case Opcodes.F_APPEND:
+ stringBuilder.append("APPEND [");
+ appendFrameTypes(numLocal, local);
+ stringBuilder.append(']');
+ break;
+ case Opcodes.F_CHOP:
+ stringBuilder.append("CHOP ").append(numLocal);
+ break;
+ case Opcodes.F_SAME:
+ stringBuilder.append("SAME");
+ break;
+ case Opcodes.F_SAME1:
+ stringBuilder.append("SAME1 ");
+ appendFrameTypes(1, stack);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append(OPCODES[opcode]).append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(tab2)
+ .append(OPCODES[opcode])
+ .append(' ')
+ .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer.toString(operand))
+ .append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append(OPCODES[opcode]).append(' ').append(var).append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, type);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, owner);
+ stringBuilder.append('.').append(name).append(" : ");
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, owner);
+ stringBuilder.append('.').append(name).append(' ');
+ appendDescriptor(METHOD_DESCRIPTOR, descriptor);
+ if (isInterface) {
+ stringBuilder.append(" (itf)");
+ }
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("INVOKEDYNAMIC").append(' ');
+ stringBuilder.append(name);
+ appendDescriptor(METHOD_DESCRIPTOR, descriptor);
+ stringBuilder.append(" [");
+ stringBuilder.append('\n');
+ stringBuilder.append(tab3);
+ appendHandle(bootstrapMethodHandle);
+ stringBuilder.append('\n');
+ stringBuilder.append(tab3).append("// arguments:");
+ if (bootstrapMethodArguments.length == 0) {
+ stringBuilder.append(" none");
+ } else {
+ stringBuilder.append('\n');
+ for (Object value : bootstrapMethodArguments) {
+ stringBuilder.append(tab3);
if (value instanceof String) {
- visitString((String) value);
+ Printer.appendString(stringBuilder, (String) value);
} else if (value instanceof Type) {
- visitType((Type) value);
- } else if (value instanceof Byte) {
- visitByte(((Byte) value).byteValue());
- } else if (value instanceof Boolean) {
- visitBoolean(((Boolean) value).booleanValue());
- } else if (value instanceof Short) {
- visitShort(((Short) value).shortValue());
- } else if (value instanceof Character) {
- visitChar(((Character) value).charValue());
- } else if (value instanceof Integer) {
- visitInt(((Integer) value).intValue());
- } else if (value instanceof Float) {
- visitFloat(((Float) value).floatValue());
- } else if (value instanceof Long) {
- visitLong(((Long) value).longValue());
- } else if (value instanceof Double) {
- visitDouble(((Double) value).doubleValue());
- } else if (value.getClass().isArray()) {
- buf.append('{');
- if (value instanceof byte[]) {
- byte[] v = (byte[]) value;
- for (int i = 0; i < v.length; i++) {
- appendComa(i);
- visitByte(v[i]);
- }
- } else if (value instanceof boolean[]) {
- boolean[] v = (boolean[]) value;
- for (int i = 0; i < v.length; i++) {
- appendComa(i);
- visitBoolean(v[i]);
- }
- } else if (value instanceof short[]) {
- short[] v = (short[]) value;
- for (int i = 0; i < v.length; i++) {
- appendComa(i);
- visitShort(v[i]);
- }
- } else if (value instanceof char[]) {
- char[] v = (char[]) value;
- for (int i = 0; i < v.length; i++) {
- appendComa(i);
- visitChar(v[i]);
- }
- } else if (value instanceof int[]) {
- int[] v = (int[]) value;
- for (int i = 0; i < v.length; i++) {
- appendComa(i);
- visitInt(v[i]);
- }
- } else if (value instanceof long[]) {
- long[] v = (long[]) value;
- for (int i = 0; i < v.length; i++) {
- appendComa(i);
- visitLong(v[i]);
- }
- } else if (value instanceof float[]) {
- float[] v = (float[]) value;
- for (int i = 0; i < v.length; i++) {
- appendComa(i);
- visitFloat(v[i]);
- }
- } else if (value instanceof double[]) {
- double[] v = (double[]) value;
- for (int i = 0; i < v.length; i++) {
- appendComa(i);
- visitDouble(v[i]);
- }
- }
- buf.append('}');
- }
-
- text.add(buf.toString());
- }
-
- private void visitInt(final int value) {
- buf.append(value);
- }
-
- private void visitLong(final long value) {
- buf.append(value).append('L');
- }
-
- private void visitFloat(final float value) {
- buf.append(value).append('F');
- }
-
- private void visitDouble(final double value) {
- buf.append(value).append('D');
- }
-
- private void visitChar(final char value) {
- buf.append("(char)").append((int) value);
- }
-
- private void visitShort(final short value) {
- buf.append("(short)").append(value);
- }
-
- private void visitByte(final byte value) {
- buf.append("(byte)").append(value);
- }
-
- private void visitBoolean(final boolean value) {
- buf.append(value);
- }
-
- private void visitString(final String value) {
- appendString(buf, value);
- }
-
- private void visitType(final Type value) {
- buf.append(value.getClassName()).append(".class");
- }
-
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- buf.setLength(0);
- appendComa(valueNumber++);
- if (name != null) {
- buf.append(name).append('=');
- }
- appendDescriptor(FIELD_DESCRIPTOR, desc);
- buf.append('.').append(value);
- text.add(buf.toString());
- }
-
- @Override
- public Textifier visitAnnotation(final String name, final String desc) {
- buf.setLength(0);
- appendComa(valueNumber++);
- if (name != null) {
- buf.append(name).append('=');
- }
- buf.append('@');
- appendDescriptor(FIELD_DESCRIPTOR, desc);
- buf.append('(');
- text.add(buf.toString());
- Textifier t = createTextifier();
- text.add(t.getText());
- text.add(")");
- return t;
- }
-
- @Override
- public Textifier visitArray(final String name) {
- buf.setLength(0);
- appendComa(valueNumber++);
- if (name != null) {
- buf.append(name).append('=');
- }
- buf.append('{');
- text.add(buf.toString());
- Textifier t = createTextifier();
- text.add(t.getText());
- text.add("}");
- return t;
- }
-
- @Override
- public void visitAnnotationEnd() {
- }
-
- // ------------------------------------------------------------------------
- // Fields
- // ------------------------------------------------------------------------
-
- @Override
- public Textifier visitFieldAnnotation(final String desc,
- final boolean visible) {
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath,
- String desc, boolean visible) {
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public void visitFieldAttribute(final Attribute attr) {
- visitAttribute(attr);
- }
-
- @Override
- public void visitFieldEnd() {
- }
-
- // ------------------------------------------------------------------------
- // Methods
- // ------------------------------------------------------------------------
-
- @Override
- public void visitParameter(final String name, final int access) {
- buf.setLength(0);
- buf.append(tab2).append("// parameter ");
- appendAccess(access);
- buf.append(' ').append((name == null) ? "<no name>" : name)
- .append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public Textifier visitAnnotationDefault() {
- text.add(tab2 + "default=");
- Textifier t = createTextifier();
- text.add(t.getText());
- text.add("\n");
- return t;
- }
-
- @Override
- public Textifier visitMethodAnnotation(final String desc,
- final boolean visible) {
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath,
- String desc, boolean visible) {
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public Textifier visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- buf.setLength(0);
- buf.append(tab2).append('@');
- appendDescriptor(FIELD_DESCRIPTOR, desc);
- buf.append('(');
- text.add(buf.toString());
- Textifier t = createTextifier();
- text.add(t.getText());
- text.add(visible ? ") // parameter " : ") // invisible, parameter ");
- text.add(parameter);
- text.add("\n");
- return t;
- }
-
- @Override
- public void visitMethodAttribute(final Attribute attr) {
- buf.setLength(0);
- buf.append(tab).append("ATTRIBUTE ");
- appendDescriptor(-1, attr.type);
-
- if (attr instanceof Textifiable) {
- ((Textifiable) attr).textify(buf, labelNames);
+ Type type = (Type) value;
+ if (type.getSort() == Type.METHOD) {
+ appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
+ } else {
+ visitType(type);
+ }
+ } else if (value instanceof Handle) {
+ appendHandle((Handle) value);
} else {
- buf.append(" : unknown\n");
- }
-
- text.add(buf.toString());
- }
-
- @Override
- public void visitCode() {
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- buf.setLength(0);
- buf.append(ltab);
- buf.append("FRAME ");
- switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- buf.append("FULL [");
- appendFrameTypes(nLocal, local);
- buf.append("] [");
- appendFrameTypes(nStack, stack);
- buf.append(']');
- break;
- case Opcodes.F_APPEND:
- buf.append("APPEND [");
- appendFrameTypes(nLocal, local);
- buf.append(']');
- break;
- case Opcodes.F_CHOP:
- buf.append("CHOP ").append(nLocal);
- break;
- case Opcodes.F_SAME:
- buf.append("SAME");
- break;
- case Opcodes.F_SAME1:
- buf.append("SAME1 ");
- appendFrameTypes(1, stack);
- break;
- }
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitInsn(final int opcode) {
- buf.setLength(0);
- buf.append(tab2).append(OPCODES[opcode]).append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- buf.setLength(0);
- buf.append(tab2)
- .append(OPCODES[opcode])
- .append(' ')
- .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
- .toString(operand)).append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- buf.setLength(0);
- buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var)
- .append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- buf.setLength(0);
- buf.append(tab2).append(OPCODES[opcode]).append(' ');
- appendDescriptor(INTERNAL_NAME, type);
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- buf.setLength(0);
- buf.append(tab2).append(OPCODES[opcode]).append(' ');
- appendDescriptor(INTERNAL_NAME, owner);
- buf.append('.').append(name).append(" : ");
- appendDescriptor(FIELD_DESCRIPTOR, desc);
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
- }
-
- private void doVisitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- buf.setLength(0);
- buf.append(tab2).append(OPCODES[opcode]).append(' ');
- appendDescriptor(INTERNAL_NAME, owner);
- buf.append('.').append(name).append(' ');
- appendDescriptor(METHOD_DESCRIPTOR, desc);
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- buf.setLength(0);
- buf.append(tab2).append("INVOKEDYNAMIC").append(' ');
- buf.append(name);
- appendDescriptor(METHOD_DESCRIPTOR, desc);
- buf.append(" [");
- buf.append('\n');
- buf.append(tab3);
- appendHandle(bsm);
- buf.append('\n');
- buf.append(tab3).append("// arguments:");
- if (bsmArgs.length == 0) {
- buf.append(" none");
- } else {
- buf.append('\n');
- for (int i = 0; i < bsmArgs.length; i++) {
- buf.append(tab3);
- Object cst = bsmArgs[i];
- if (cst instanceof String) {
- Printer.appendString(buf, (String) cst);
- } else if (cst instanceof Type) {
- Type type = (Type) cst;
- if(type.getSort() == Type.METHOD){
- appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
- } else {
- buf.append(type.getDescriptor()).append(".class");
- }
- } else if (cst instanceof Handle) {
- appendHandle((Handle) cst);
- } else {
- buf.append(cst);
- }
- buf.append(", \n");
- }
- buf.setLength(buf.length() - 3);
- }
- buf.append('\n');
- buf.append(tab2).append("]\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- buf.setLength(0);
- buf.append(tab2).append(OPCODES[opcode]).append(' ');
- appendLabel(label);
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitLabel(final Label label) {
- buf.setLength(0);
- buf.append(ltab);
- appendLabel(label);
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- buf.setLength(0);
- buf.append(tab2).append("LDC ");
- if (cst instanceof String) {
- Printer.appendString(buf, (String) cst);
- } else if (cst instanceof Type) {
- buf.append(((Type) cst).getDescriptor()).append(".class");
+ stringBuilder.append(value);
+ }
+ stringBuilder.append(", \n");
+ }
+ stringBuilder.setLength(stringBuilder.length() - 3);
+ }
+ stringBuilder.append('\n');
+ stringBuilder.append(tab2).append("]\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendLabel(label);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(ltab);
+ appendLabel(label);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("LDC ");
+ if (value instanceof String) {
+ Printer.appendString(stringBuilder, (String) value);
+ } else if (value instanceof Type) {
+ stringBuilder.append(((Type) value).getDescriptor()).append(CLASS_SUFFIX);
+ } else {
+ stringBuilder.append(value);
+ }
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(tab2)
+ .append("IINC ")
+ .append(var)
+ .append(' ')
+ .append(increment)
+ .append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("TABLESWITCH\n");
+ for (int i = 0; i < labels.length; ++i) {
+ stringBuilder.append(tab3).append(min + i).append(": ");
+ appendLabel(labels[i]);
+ stringBuilder.append('\n');
+ }
+ stringBuilder.append(tab3).append("default: ");
+ appendLabel(dflt);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("LOOKUPSWITCH\n");
+ for (int i = 0; i < labels.length; ++i) {
+ stringBuilder.append(tab3).append(keys[i]).append(": ");
+ appendLabel(labels[i]);
+ stringBuilder.append('\n');
+ }
+ stringBuilder.append(tab3).append("default: ");
+ appendLabel(dflt);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("MULTIANEWARRAY ");
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append(' ').append(numDimensions).append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Printer visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("TRYCATCHBLOCK ");
+ appendLabel(start);
+ stringBuilder.append(' ');
+ appendLabel(end);
+ stringBuilder.append(' ');
+ appendLabel(handler);
+ stringBuilder.append(' ');
+ appendDescriptor(INTERNAL_NAME, type);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Printer visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("TRYCATCHBLOCK @");
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append('(');
+ text.add(stringBuilder.toString());
+
+ stringBuilder.setLength(0);
+ stringBuilder.append(") : ");
+ appendTypeReference(typeRef);
+ stringBuilder.append(", ").append(typePath);
+ stringBuilder.append(visible ? "\n" : INVISIBLE);
+ return addNewTextifier(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append(' ');
+ appendLabel(start);
+ stringBuilder.append(' ');
+ appendLabel(end);
+ stringBuilder.append(' ').append(index).append('\n');
+
+ if (signature != null) {
+ stringBuilder.append(tab2);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+ stringBuilder.append(tab2);
+ appendJavaDeclaration(name, signature);
+ }
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Printer visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("LOCALVARIABLE @");
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append('(');
+ text.add(stringBuilder.toString());
+
+ stringBuilder.setLength(0);
+ stringBuilder.append(") : ");
+ appendTypeReference(typeRef);
+ stringBuilder.append(", ").append(typePath);
+ for (int i = 0; i < start.length; ++i) {
+ stringBuilder.append(" [ ");
+ appendLabel(start[i]);
+ stringBuilder.append(" - ");
+ appendLabel(end[i]);
+ stringBuilder.append(" - ").append(index[i]).append(" ]");
+ }
+ stringBuilder.append(visible ? "\n" : INVISIBLE);
+ return addNewTextifier(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("LINENUMBER ").append(line).append(' ');
+ appendLabel(start);
+ stringBuilder.append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n');
+ text.add(stringBuilder.toString());
+
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n');
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMethodEnd() {
+ // Nothing to do.
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Common methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Prints a disassembled view of the given annotation.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ // DontCheck(OverloadMethodsDeclarationOrder): overloads are semantically different.
+ public Textifier visitAnnotation(final String descriptor, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append('(');
+ text.add(stringBuilder.toString());
+ return addNewTextifier(visible ? ")\n" : ") // invisible\n");
+ }
+
+ /**
+ * Prints a disassembled view of the given type annotation.
+ *
+ * @param typeRef a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ public Textifier visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
+ stringBuilder.append('(');
+ text.add(stringBuilder.toString());
+
+ stringBuilder.setLength(0);
+ stringBuilder.append(") : ");
+ appendTypeReference(typeRef);
+ stringBuilder.append(", ").append(typePath);
+ stringBuilder.append(visible ? "\n" : INVISIBLE);
+ return addNewTextifier(stringBuilder.toString());
+ }
+
+ /**
+ * Prints a disassembled view of the given attribute.
+ *
+ * @param attribute an attribute.
+ */
+ public void visitAttribute(final Attribute attribute) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(tab).append("ATTRIBUTE ");
+ appendDescriptor(-1, attribute.type);
+
+ if (attribute instanceof Textifiable) {
+ StringBuffer stringBuffer = new StringBuffer();
+ ((Textifiable) attribute).textify(stringBuffer, null);
+ stringBuilder.append(stringBuffer.toString());
+ } else {
+ stringBuilder.append(" : unknown\n");
+ }
+
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Appends a string representation of the given access flags to {@link #stringBuilder}.
+ *
+ * @param accessFlags some access flags.
+ */
+ private void appendAccess(final int accessFlags) {
+ if ((accessFlags & Opcodes.ACC_PUBLIC) != 0) {
+ stringBuilder.append("public ");
+ }
+ if ((accessFlags & Opcodes.ACC_PRIVATE) != 0) {
+ stringBuilder.append("private ");
+ }
+ if ((accessFlags & Opcodes.ACC_PROTECTED) != 0) {
+ stringBuilder.append("protected ");
+ }
+ if ((accessFlags & Opcodes.ACC_FINAL) != 0) {
+ stringBuilder.append("final ");
+ }
+ if ((accessFlags & Opcodes.ACC_STATIC) != 0) {
+ stringBuilder.append("static ");
+ }
+ if ((accessFlags & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ stringBuilder.append("synchronized ");
+ }
+ if ((accessFlags & Opcodes.ACC_VOLATILE) != 0) {
+ stringBuilder.append("volatile ");
+ }
+ if ((accessFlags & Opcodes.ACC_TRANSIENT) != 0) {
+ stringBuilder.append("transient ");
+ }
+ if ((accessFlags & Opcodes.ACC_ABSTRACT) != 0) {
+ stringBuilder.append("abstract ");
+ }
+ if ((accessFlags & Opcodes.ACC_STRICT) != 0) {
+ stringBuilder.append("strictfp ");
+ }
+ if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0) {
+ stringBuilder.append("synthetic ");
+ }
+ if ((accessFlags & Opcodes.ACC_MANDATED) != 0) {
+ stringBuilder.append("mandated ");
+ }
+ if ((accessFlags & Opcodes.ACC_ENUM) != 0) {
+ stringBuilder.append("enum ");
+ }
+ }
+
+ /**
+ * Appends the hexadecimal value of the given access flags to {@link #stringBuilder}.
+ *
+ * @param accessFlags some access flags.
+ */
+ private void appendRawAccess(final int accessFlags) {
+ stringBuilder
+ .append("// access flags 0x")
+ .append(Integer.toHexString(accessFlags).toUpperCase())
+ .append('\n');
+ }
+
+ /**
+ * Appends an internal name, a type descriptor or a type signature to {@link #stringBuilder}.
+ *
+ * @param type the type of 'value'. Must be one of {@link #INTERNAL_NAME}, {@link
+ * #FIELD_DESCRIPTOR}, {@link #FIELD_SIGNATURE}, {@link #METHOD_DESCRIPTOR}, {@link
+ * #METHOD_SIGNATURE}, {@link #CLASS_SIGNATURE}, {@link #TYPE_DECLARATION}, {@link
+ * #CLASS_DECLARATION}, {@link #PARAMETERS_DECLARATION} of {@link #HANDLE_DESCRIPTOR}.
+ * @param value an internal name, type descriptor or a type signature. May be {@literal null}.
+ */
+ protected void appendDescriptor(final int type, final String value) {
+ if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE || type == METHOD_SIGNATURE) {
+ if (value != null) {
+ stringBuilder.append("// signature ").append(value).append('\n');
+ }
+ } else {
+ stringBuilder.append(value);
+ }
+ }
+
+ /**
+ * Appends the Java generic type declaration corresponding to the given signature.
+ *
+ * @param name a class, field or method name.
+ * @param signature a class, field or method signature.
+ */
+ private void appendJavaDeclaration(final String name, final String signature) {
+ TraceSignatureVisitor traceSignatureVisitor = new TraceSignatureVisitor(access);
+ new SignatureReader(signature).accept(traceSignatureVisitor);
+ stringBuilder.append("// declaration: ");
+ if (traceSignatureVisitor.getReturnType() != null) {
+ stringBuilder.append(traceSignatureVisitor.getReturnType());
+ stringBuilder.append(' ');
+ }
+ stringBuilder.append(name);
+ stringBuilder.append(traceSignatureVisitor.getDeclaration());
+ if (traceSignatureVisitor.getExceptions() != null) {
+ stringBuilder.append(" throws ").append(traceSignatureVisitor.getExceptions());
+ }
+ stringBuilder.append('\n');
+ }
+
+ /**
+ * Appends the name of the given label to {@link #stringBuilder}. Constructs a new label name if
+ * the given label does not yet have one.
+ *
+ * @param label a label.
+ */
+ protected void appendLabel(final Label label) {
+ if (labelNames == null) {
+ labelNames = new HashMap<Label, String>();
+ }
+ String name = labelNames.get(label);
+ if (name == null) {
+ name = "L" + labelNames.size();
+ labelNames.put(label, name);
+ }
+ stringBuilder.append(name);
+ }
+
+ /**
+ * Appends a string representation of the given handle to {@link #stringBuilder}.
+ *
+ * @param handle a handle.
+ */
+ protected void appendHandle(final Handle handle) {
+ int tag = handle.getTag();
+ stringBuilder.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
+ boolean isMethodHandle = false;
+ switch (tag) {
+ case Opcodes.H_GETFIELD:
+ stringBuilder.append("GETFIELD");
+ break;
+ case Opcodes.H_GETSTATIC:
+ stringBuilder.append("GETSTATIC");
+ break;
+ case Opcodes.H_PUTFIELD:
+ stringBuilder.append("PUTFIELD");
+ break;
+ case Opcodes.H_PUTSTATIC:
+ stringBuilder.append("PUTSTATIC");
+ break;
+ case Opcodes.H_INVOKEINTERFACE:
+ stringBuilder.append("INVOKEINTERFACE");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKESPECIAL:
+ stringBuilder.append("INVOKESPECIAL");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKESTATIC:
+ stringBuilder.append("INVOKESTATIC");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKEVIRTUAL:
+ stringBuilder.append("INVOKEVIRTUAL");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_NEWINVOKESPECIAL:
+ stringBuilder.append("NEWINVOKESPECIAL");
+ isMethodHandle = true;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ stringBuilder.append('\n');
+ stringBuilder.append(tab3);
+ appendDescriptor(INTERNAL_NAME, handle.getOwner());
+ stringBuilder.append('.');
+ stringBuilder.append(handle.getName());
+ if (!isMethodHandle) {
+ stringBuilder.append('(');
+ }
+ appendDescriptor(HANDLE_DESCRIPTOR, handle.getDesc());
+ if (!isMethodHandle) {
+ stringBuilder.append(')');
+ }
+ if (handle.isInterface()) {
+ stringBuilder.append(" itf");
+ }
+ }
+
+ /**
+ * Appends a comma to {@link #stringBuilder} if the given number is strictly positive.
+ *
+ * @param numValues a number of 'values visited so far', for instance the number of annotation
+ * values visited so far in an annotation visitor.
+ */
+ private void maybeAppendComma(final int numValues) {
+ if (numValues > 0) {
+ stringBuilder.append(", ");
+ }
+ }
+
+ /**
+ * Appends a string representation of the given type reference to {@link #stringBuilder}.
+ *
+ * @param typeRef a type reference. See {@link TypeReference}.
+ */
+ private void appendTypeReference(final int typeRef) {
+ TypeReference typeReference = new TypeReference(typeRef);
+ switch (typeReference.getSort()) {
+ case TypeReference.CLASS_TYPE_PARAMETER:
+ stringBuilder.append("CLASS_TYPE_PARAMETER ").append(typeReference.getTypeParameterIndex());
+ break;
+ case TypeReference.METHOD_TYPE_PARAMETER:
+ stringBuilder
+ .append("METHOD_TYPE_PARAMETER ")
+ .append(typeReference.getTypeParameterIndex());
+ break;
+ case TypeReference.CLASS_EXTENDS:
+ stringBuilder.append("CLASS_EXTENDS ").append(typeReference.getSuperTypeIndex());
+ break;
+ case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+ stringBuilder
+ .append("CLASS_TYPE_PARAMETER_BOUND ")
+ .append(typeReference.getTypeParameterIndex())
+ .append(", ")
+ .append(typeReference.getTypeParameterBoundIndex());
+ break;
+ case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+ stringBuilder
+ .append("METHOD_TYPE_PARAMETER_BOUND ")
+ .append(typeReference.getTypeParameterIndex())
+ .append(", ")
+ .append(typeReference.getTypeParameterBoundIndex());
+ break;
+ case TypeReference.FIELD:
+ stringBuilder.append("FIELD");
+ break;
+ case TypeReference.METHOD_RETURN:
+ stringBuilder.append("METHOD_RETURN");
+ break;
+ case TypeReference.METHOD_RECEIVER:
+ stringBuilder.append("METHOD_RECEIVER");
+ break;
+ case TypeReference.METHOD_FORMAL_PARAMETER:
+ stringBuilder
+ .append("METHOD_FORMAL_PARAMETER ")
+ .append(typeReference.getFormalParameterIndex());
+ break;
+ case TypeReference.THROWS:
+ stringBuilder.append("THROWS ").append(typeReference.getExceptionIndex());
+ break;
+ case TypeReference.LOCAL_VARIABLE:
+ stringBuilder.append("LOCAL_VARIABLE");
+ break;
+ case TypeReference.RESOURCE_VARIABLE:
+ stringBuilder.append("RESOURCE_VARIABLE");
+ break;
+ case TypeReference.EXCEPTION_PARAMETER:
+ stringBuilder.append("EXCEPTION_PARAMETER ").append(typeReference.getTryCatchBlockIndex());
+ break;
+ case TypeReference.INSTANCEOF:
+ stringBuilder.append("INSTANCEOF");
+ break;
+ case TypeReference.NEW:
+ stringBuilder.append("NEW");
+ break;
+ case TypeReference.CONSTRUCTOR_REFERENCE:
+ stringBuilder.append("CONSTRUCTOR_REFERENCE");
+ break;
+ case TypeReference.METHOD_REFERENCE:
+ stringBuilder.append("METHOD_REFERENCE");
+ break;
+ case TypeReference.CAST:
+ stringBuilder.append("CAST ").append(typeReference.getTypeArgumentIndex());
+ break;
+ case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+ stringBuilder
+ .append("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ")
+ .append(typeReference.getTypeArgumentIndex());
+ break;
+ case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+ stringBuilder
+ .append("METHOD_INVOCATION_TYPE_ARGUMENT ")
+ .append(typeReference.getTypeArgumentIndex());
+ break;
+ case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+ stringBuilder
+ .append("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ")
+ .append(typeReference.getTypeArgumentIndex());
+ break;
+ case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+ stringBuilder
+ .append("METHOD_REFERENCE_TYPE_ARGUMENT ")
+ .append(typeReference.getTypeArgumentIndex());
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Appends the given stack map frame types to {@link #stringBuilder}.
+ *
+ * @param numTypes the number of stack map frame types in 'frameTypes'.
+ * @param frameTypes an array of stack map frame types, in the format described in {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+ */
+ private void appendFrameTypes(final int numTypes, final Object[] frameTypes) {
+ for (int i = 0; i < numTypes; ++i) {
+ if (i > 0) {
+ stringBuilder.append(' ');
+ }
+ if (frameTypes[i] instanceof String) {
+ String descriptor = (String) frameTypes[i];
+ if (descriptor.charAt(0) == '[') {
+ appendDescriptor(FIELD_DESCRIPTOR, descriptor);
} else {
- buf.append(cst);
- }
- buf.append('\n');
- text.add(buf.toString());
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- buf.setLength(0);
- buf.append(tab2).append("IINC ").append(var).append(' ')
- .append(increment).append('\n');
- text.add(buf.toStrin
<TRUNCATED>
[41/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ConstantDynamic.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ConstantDynamic.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ConstantDynamic.java
new file mode 100755
index 0000000..9ae46ca
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ConstantDynamic.java
@@ -0,0 +1,178 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.apache.tapestry5.internal.plastic.asm;
+
+import java.util.Arrays;
+
+/**
+ * A constant whose value is computed at runtime, with a bootstrap method.
+ *
+ * @author Remi Forax
+ */
+public final class ConstantDynamic {
+
+ /** The constant name (can be arbitrary). */
+ private final String name;
+
+ /** The constant type (must be a field descriptor). */
+ private final String descriptor;
+
+ /** The bootstrap method to use to compute the constant value at runtime. */
+ private final Handle bootstrapMethod;
+
+ /**
+ * The arguments to pass to the bootstrap method, in order to compute the constant value at
+ * runtime.
+ */
+ private final Object[] bootstrapMethodArguments;
+
+ /**
+ * Constructs a new {@link ConstantDynamic}.
+ *
+ * @param name the constant name (can be arbitrary).
+ * @param descriptor the constant type (must be a field descriptor).
+ * @param bootstrapMethod the bootstrap method to use to compute the constant value at runtime.
+ * @param bootstrapMethodArguments the arguments to pass to the bootstrap method, in order to
+ * compute the constant value at runtime.
+ */
+ public ConstantDynamic(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethod,
+ final Object... bootstrapMethodArguments) {
+ this.name = name;
+ this.descriptor = descriptor;
+ this.bootstrapMethod = bootstrapMethod;
+ this.bootstrapMethodArguments = bootstrapMethodArguments;
+ }
+
+ /**
+ * Returns the name of this constant.
+ *
+ * @return the name of this constant.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the type of this constant.
+ *
+ * @return the type of this constant, as a field descriptor.
+ */
+ public String getDescriptor() {
+ return descriptor;
+ }
+
+ /**
+ * Returns the bootstrap method used to compute the value of this constant.
+ *
+ * @return the bootstrap method used to compute the value of this constant.
+ */
+ public Handle getBootstrapMethod() {
+ return bootstrapMethod;
+ }
+
+ /**
+ * Returns the number of arguments passed to the bootstrap method, in order to compute the value
+ * of this constant.
+ *
+ * @return the number of arguments passed to the bootstrap method, in order to compute the value
+ * of this constant.
+ */
+ public int getBootstrapMethodArgumentCount() {
+ return bootstrapMethodArguments.length;
+ }
+
+ /**
+ * Returns an argument passed to the bootstrap method, in order to compute the value of this
+ * constant.
+ *
+ * @param index an argument index, between 0 and {@link #getBootstrapMethodArgumentCount()}
+ * (exclusive).
+ * @return the argument passed to the bootstrap method, with the given index.
+ */
+ public Object getBootstrapMethodArgument(final int index) {
+ return bootstrapMethodArguments[index];
+ }
+
+ /**
+ * Returns the arguments to pass to the bootstrap method, in order to compute the value of this
+ * constant. WARNING: this array must not be modified, and must not be returned to the user.
+ *
+ * @return the arguments to pass to the bootstrap method, in order to compute the value of this
+ * constant.
+ */
+ Object[] getBootstrapMethodArgumentsUnsafe() {
+ return bootstrapMethodArguments;
+ }
+
+ /**
+ * Returns the size of this constant.
+ *
+ * @return the size of this constant, i.e., 2 for {@code long} and {@code double}, 1 otherwise.
+ */
+ public int getSize() {
+ char firstCharOfDescriptor = descriptor.charAt(0);
+ return (firstCharOfDescriptor == 'J' || firstCharOfDescriptor == 'D') ? 2 : 1;
+ }
+
+ @Override
+ public boolean equals(final Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (!(object instanceof ConstantDynamic)) {
+ return false;
+ }
+ ConstantDynamic constantDynamic = (ConstantDynamic) object;
+ return name.equals(constantDynamic.name)
+ && descriptor.equals(constantDynamic.descriptor)
+ && bootstrapMethod.equals(constantDynamic.bootstrapMethod)
+ && Arrays.equals(bootstrapMethodArguments, constantDynamic.bootstrapMethodArguments);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode()
+ ^ Integer.rotateLeft(descriptor.hashCode(), 8)
+ ^ Integer.rotateLeft(bootstrapMethod.hashCode(), 16)
+ ^ Integer.rotateLeft(Arrays.hashCode(bootstrapMethodArguments), 24);
+ }
+
+ @Override
+ public String toString() {
+ return name
+ + " : "
+ + descriptor
+ + ' '
+ + bootstrapMethod
+ + ' '
+ + Arrays.toString(bootstrapMethodArguments);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Constants.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Constants.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Constants.java
new file mode 100755
index 0000000..7d99004
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Constants.java
@@ -0,0 +1,177 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * Defines additional JVM opcodes, access flags and constants which are not part of the ASM public
+ * API.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
+ * @author Eric Bruneton
+ */
+final class Constants implements Opcodes {
+
+ // The ClassFile attribute names, in the order they are defined in
+ // https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300.
+
+ static final String CONSTANT_VALUE = "ConstantValue";
+ static final String CODE = "Code";
+ static final String STACK_MAP_TABLE = "StackMapTable";
+ static final String EXCEPTIONS = "Exceptions";
+ static final String INNER_CLASSES = "InnerClasses";
+ static final String ENCLOSING_METHOD = "EnclosingMethod";
+ static final String SYNTHETIC = "Synthetic";
+ static final String SIGNATURE = "Signature";
+ static final String SOURCE_FILE = "SourceFile";
+ static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
+ static final String LINE_NUMBER_TABLE = "LineNumberTable";
+ static final String LOCAL_VARIABLE_TABLE = "LocalVariableTable";
+ static final String LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable";
+ static final String DEPRECATED = "Deprecated";
+ static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
+ static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
+ static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
+ static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS =
+ "RuntimeInvisibleParameterAnnotations";
+ static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
+ static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations";
+ static final String ANNOTATION_DEFAULT = "AnnotationDefault";
+ static final String BOOTSTRAP_METHODS = "BootstrapMethods";
+ static final String METHOD_PARAMETERS = "MethodParameters";
+ static final String MODULE = "Module";
+ static final String MODULE_PACKAGES = "ModulePackages";
+ static final String MODULE_MAIN_CLASS = "ModuleMainClass";
+ static final String NEST_HOST = "NestHost";
+ static final String NEST_MEMBERS = "NestMembers";
+
+ // ASM specific access flags.
+ // WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
+ // access flags, and also to make sure that these flags are automatically filtered out when
+ // written in class files (because access flags are stored using 16 bits only).
+
+ static final int ACC_CONSTRUCTOR = 0x40000; // method access flag.
+
+ // ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.
+
+ /**
+ * A frame inserted between already existing frames. This internal stack map frame type (in
+ * addition to the ones declared in {@link Opcodes}) can only be used if the frame content can be
+ * computed from the previous existing frame and from the instructions between this existing frame
+ * and the inserted one, without any knowledge of the type hierarchy. This kind of frame is only
+ * used when an unconditional jump is inserted in a method while expanding an ASM specific
+ * instruction. Keep in sync with Opcodes.java.
+ */
+ static final int F_INSERT = 256;
+
+ // The JVM opcode values which are not part of the ASM public API.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
+
+ static final int LDC_W = 19;
+ static final int LDC2_W = 20;
+ static final int ILOAD_0 = 26;
+ static final int ILOAD_1 = 27;
+ static final int ILOAD_2 = 28;
+ static final int ILOAD_3 = 29;
+ static final int LLOAD_0 = 30;
+ static final int LLOAD_1 = 31;
+ static final int LLOAD_2 = 32;
+ static final int LLOAD_3 = 33;
+ static final int FLOAD_0 = 34;
+ static final int FLOAD_1 = 35;
+ static final int FLOAD_2 = 36;
+ static final int FLOAD_3 = 37;
+ static final int DLOAD_0 = 38;
+ static final int DLOAD_1 = 39;
+ static final int DLOAD_2 = 40;
+ static final int DLOAD_3 = 41;
+ static final int ALOAD_0 = 42;
+ static final int ALOAD_1 = 43;
+ static final int ALOAD_2 = 44;
+ static final int ALOAD_3 = 45;
+ static final int ISTORE_0 = 59;
+ static final int ISTORE_1 = 60;
+ static final int ISTORE_2 = 61;
+ static final int ISTORE_3 = 62;
+ static final int LSTORE_0 = 63;
+ static final int LSTORE_1 = 64;
+ static final int LSTORE_2 = 65;
+ static final int LSTORE_3 = 66;
+ static final int FSTORE_0 = 67;
+ static final int FSTORE_1 = 68;
+ static final int FSTORE_2 = 69;
+ static final int FSTORE_3 = 70;
+ static final int DSTORE_0 = 71;
+ static final int DSTORE_1 = 72;
+ static final int DSTORE_2 = 73;
+ static final int DSTORE_3 = 74;
+ static final int ASTORE_0 = 75;
+ static final int ASTORE_1 = 76;
+ static final int ASTORE_2 = 77;
+ static final int ASTORE_3 = 78;
+ static final int WIDE = 196;
+ static final int GOTO_W = 200;
+ static final int JSR_W = 201;
+
+ // Constants to convert between normal and wide jump instructions.
+
+ // The delta between the GOTO_W and JSR_W opcodes and GOTO and JUMP.
+ static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - GOTO;
+
+ // Constants to convert JVM opcodes to the equivalent ASM specific opcodes, and vice versa.
+
+ // The delta between the ASM_IFEQ, ..., ASM_IF_ACMPNE, ASM_GOTO and ASM_JSR opcodes
+ // and IFEQ, ..., IF_ACMPNE, GOTO and JSR.
+ static final int ASM_OPCODE_DELTA = 49;
+
+ // The delta between the ASM_IFNULL and ASM_IFNONNULL opcodes and IFNULL and IFNONNULL.
+ static final int ASM_IFNULL_OPCODE_DELTA = 20;
+
+ // ASM specific opcodes, used for long forward jump instructions.
+
+ static final int ASM_IFEQ = IFEQ + ASM_OPCODE_DELTA;
+ static final int ASM_IFNE = IFNE + ASM_OPCODE_DELTA;
+ static final int ASM_IFLT = IFLT + ASM_OPCODE_DELTA;
+ static final int ASM_IFGE = IFGE + ASM_OPCODE_DELTA;
+ static final int ASM_IFGT = IFGT + ASM_OPCODE_DELTA;
+ static final int ASM_IFLE = IFLE + ASM_OPCODE_DELTA;
+ static final int ASM_IF_ICMPEQ = IF_ICMPEQ + ASM_OPCODE_DELTA;
+ static final int ASM_IF_ICMPNE = IF_ICMPNE + ASM_OPCODE_DELTA;
+ static final int ASM_IF_ICMPLT = IF_ICMPLT + ASM_OPCODE_DELTA;
+ static final int ASM_IF_ICMPGE = IF_ICMPGE + ASM_OPCODE_DELTA;
+ static final int ASM_IF_ICMPGT = IF_ICMPGT + ASM_OPCODE_DELTA;
+ static final int ASM_IF_ICMPLE = IF_ICMPLE + ASM_OPCODE_DELTA;
+ static final int ASM_IF_ACMPEQ = IF_ACMPEQ + ASM_OPCODE_DELTA;
+ static final int ASM_IF_ACMPNE = IF_ACMPNE + ASM_OPCODE_DELTA;
+ static final int ASM_GOTO = GOTO + ASM_OPCODE_DELTA;
+ static final int ASM_JSR = JSR + ASM_OPCODE_DELTA;
+ static final int ASM_IFNULL = IFNULL + ASM_IFNULL_OPCODE_DELTA;
+ static final int ASM_IFNONNULL = IFNONNULL + ASM_IFNULL_OPCODE_DELTA;
+ static final int ASM_GOTO_W = 220;
+
+ private Constants() {}
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
old mode 100644
new mode 100755
index 27983d6..35e7f0b
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
@@ -1,145 +1,137 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.apache.tapestry5.internal.plastic.asm;
-
-/**
- * Information about a class being parsed in a {@link ClassReader}.
- *
- * @author Eric Bruneton
- */
-class Context {
-
- /**
- * Prototypes of the attributes that must be parsed for this class.
- */
- Attribute[] attrs;
-
- /**
- * The {@link ClassReader} option flags for the parsing of this class.
- */
- int flags;
-
- /**
- * The buffer used to read strings.
- */
- char[] buffer;
-
- /**
- * The start index of each bootstrap method.
- */
- int[] bootstrapMethods;
-
- /**
- * The access flags of the method currently being parsed.
- */
- int access;
-
- /**
- * The name of the method currently being parsed.
- */
- String name;
-
- /**
- * The descriptor of the method currently being parsed.
- */
- String desc;
-
- /**
- * The label objects, indexed by bytecode offset, of the method currently
- * being parsed (only bytecode offsets for which a label is needed have a
- * non null associated Label object).
- */
- Label[] labels;
-
- /**
- * The target of the type annotation currently being parsed.
- */
- int typeRef;
-
- /**
- * The path of the type annotation currently being parsed.
- */
- TypePath typePath;
-
- /**
- * The offset of the latest stack map frame that has been parsed.
- */
- int offset;
-
- /**
- * The labels corresponding to the start of the local variable ranges in the
- * local variable type annotation currently being parsed.
- */
- Label[] start;
-
- /**
- * The labels corresponding to the end of the local variable ranges in the
- * local variable type annotation currently being parsed.
- */
- Label[] end;
-
- /**
- * The local variable indices for each local variable range in the local
- * variable type annotation currently being parsed.
- */
- int[] index;
-
- /**
- * The encoding of the latest stack map frame that has been parsed.
- */
- int mode;
-
- /**
- * The number of locals in the latest stack map frame that has been parsed.
- */
- int localCount;
-
- /**
- * The number locals in the latest stack map frame that has been parsed,
- * minus the number of locals in the previous frame.
- */
- int localDiff;
-
- /**
- * The local values of the latest stack map frame that has been parsed.
- */
- Object[] local;
-
- /**
- * The stack size of the latest stack map frame that has been parsed.
- */
- int stackCount;
-
- /**
- * The stack values of the latest stack map frame that has been parsed.
- */
- Object[] stack;
-}
\ No newline at end of file
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * Information about a class being parsed in a {@link ClassReader}.
+ *
+ * @author Eric Bruneton
+ */
+final class Context {
+
+ /** The prototypes of the attributes that must be parsed in this class. */
+ Attribute[] attributePrototypes;
+
+ /**
+ * The options used to parse this class. One or more of {@link ClassReader#SKIP_CODE}, {@link
+ * ClassReader#SKIP_DEBUG}, {@link ClassReader#SKIP_FRAMES}, {@link ClassReader#EXPAND_FRAMES} or
+ * {@link ClassReader#EXPAND_ASM_INSNS}.
+ */
+ int parsingOptions;
+
+ /** The buffer used to read strings in the constant pool. */
+ char[] charBuffer;
+
+ // Information about the current method, i.e. the one read in the current (or latest) call
+ // to {@link ClassReader#readMethod()}.
+
+ /** The access flags of the current method. */
+ int currentMethodAccessFlags;
+
+ /** The name of the current method. */
+ String currentMethodName;
+
+ /** The descriptor of the current method. */
+ String currentMethodDescriptor;
+
+ /**
+ * The labels of the current method, indexed by bytecode offset (only bytecode offsets for which a
+ * label is needed have a non null associated Label).
+ */
+ Label[] currentMethodLabels;
+
+ // Information about the current type annotation target, i.e. the one read in the current
+ // (or latest) call to {@link ClassReader#readAnnotationTarget()}.
+
+ /**
+ * The target_type and target_info of the current type annotation target, encoded as described in
+ * {@link TypeReference}.
+ */
+ int currentTypeAnnotationTarget;
+
+ /** The target_path of the current type annotation target. */
+ TypePath currentTypeAnnotationTargetPath;
+
+ /** The start of each local variable range in the current local variable annotation. */
+ Label[] currentLocalVariableAnnotationRangeStarts;
+
+ /** The end of each local variable range in the current local variable annotation. */
+ Label[] currentLocalVariableAnnotationRangeEnds;
+
+ /**
+ * The local variable index of each local variable range in the current local variable annotation.
+ */
+ int[] currentLocalVariableAnnotationRangeIndices;
+
+ // Information about the current stack map frame, i.e. the one read in the current (or latest)
+ // call to {@link ClassReader#readFrame()}.
+
+ /** The bytecode offset of the current stack map frame. */
+ int currentFrameOffset;
+
+ /**
+ * The type of the current stack map frame. One of {@link Opcodes#F_FULL}, {@link
+ * Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or {@link Opcodes#F_SAME1}.
+ */
+ int currentFrameType;
+
+ /**
+ * The number of local variable types in the current stack map frame. Each type is represented
+ * with a single array element (even long and double).
+ */
+ int currentFrameLocalCount;
+
+ /**
+ * The delta number of local variable types in the current stack map frame (each type is
+ * represented with a single array element - even long and double). This is the number of local
+ * variable types in this frame, minus the number of local variable types in the previous frame.
+ */
+ int currentFrameLocalCountDelta;
+
+ /**
+ * The types of the local variables in the current stack map frame. Each type is represented with
+ * a single array element (even long and double), using the format described in {@link
+ * MethodVisitor#visitFrame}. Depending on {@link #currentFrameType}, this contains the types of
+ * all the local variables, or only those of the additional ones (compared to the previous frame).
+ */
+ Object[] currentFrameLocalTypes;
+
+ /**
+ * The number stack element types in the current stack map frame. Each type is represented with a
+ * single array element (even long and double).
+ */
+ int currentFrameStackCount;
+
+ /**
+ * The types of the stack elements in the current stack map frame. Each type is represented with a
+ * single array element (even long and double), using the format described in {@link
+ * MethodVisitor#visitFrame}.
+ */
+ Object[] currentFrameStackTypes;
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/CurrentFrame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/CurrentFrame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/CurrentFrame.java
old mode 100644
new mode 100755
index 457a4eb..384a71f
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/CurrentFrame.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/CurrentFrame.java
@@ -1,56 +1,56 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.apache.tapestry5.internal.plastic.asm;
-
-/**
- * Information about the input stack map frame at the "current" instruction of a
- * method. This is implemented as a Frame subclass for a "basic block"
- * containing only one instruction.
- *
- * @author Eric Bruneton
- */
-class CurrentFrame extends Frame {
-
- /**
- * Sets this CurrentFrame to the input stack map frame of the next "current"
- * instruction, i.e. the instruction just after the given one. It is assumed
- * that the value of this object when this method is called is the stack map
- * frame status just before the given instruction is executed.
- */
- @Override
- void execute(int opcode, int arg, ClassWriter cw, Item item) {
- super.execute(opcode, arg, cw, item);
- Frame successor = new Frame();
- merge(cw, successor, 0);
- set(successor);
- owner.inputStackTop = 0;
- }
-}
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * Information about the input stack map frame at the "current" instruction of a method. This is
+ * implemented as a Frame subclass for a "basic block" containing only one instruction.
+ *
+ * @author Eric Bruneton
+ */
+final class CurrentFrame extends Frame {
+
+ CurrentFrame(final Label owner) {
+ super(owner);
+ }
+
+ /**
+ * Sets this CurrentFrame to the input stack map frame of the next "current" instruction, i.e. the
+ * instruction just after the given one. It is assumed that the value of this object when this
+ * method is called is the stack map frame status just before the given instruction is executed.
+ */
+ @Override
+ void execute(
+ final int opcode, final int arg, final Symbol symbolArg, final SymbolTable symbolTable) {
+ super.execute(opcode, arg, symbolArg, symbolTable);
+ Frame successor = new Frame(null);
+ merge(symbolTable, successor, 0);
+ copyFrom(successor);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
old mode 100644
new mode 100755
index 9347888..c81f12b
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
@@ -1,75 +1,91 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * An edge in the control flow graph of a method body. See {@link Label Label}.
- *
+ * An edge in the control flow graph of a method. Each node of this graph is a basic block,
+ * represented with the Label corresponding to its first instruction. Each edge goes from one node
+ * to another, i.e. from one basic block to another (called the predecessor and successor blocks,
+ * respectively). An edge corresponds either to a jump or ret instruction or to an exception
+ * handler.
+ *
+ * @see Label
* @author Eric Bruneton
*/
-class Edge {
+final class Edge {
+
+ /**
+ * A control flow graph edge corresponding to a jump or ret instruction. Only used with {@link
+ * ClassWriter#COMPUTE_FRAMES}.
+ */
+ static final int JUMP = 0;
- /**
- * Denotes a normal control flow graph edge.
- */
- static final int NORMAL = 0;
+ /**
+ * A control flow graph edge corresponding to an exception handler. Only used with {@link
+ * ClassWriter#COMPUTE_MAXS}.
+ */
+ static final int EXCEPTION = 0x7FFFFFFF;
- /**
- * Denotes a control flow graph edge corresponding to an exception handler.
- * More precisely any {@link Edge} whose {@link #info} is strictly positive
- * corresponds to an exception handler. The actual value of {@link #info} is
- * the index, in the {@link ClassWriter} type table, of the exception that
- * is catched.
- */
- static final int EXCEPTION = 0x7FFFFFFF;
+ /**
+ * Information about this control flow graph edge.
+ *
+ * <ul>
+ * <li>If {@link ClassWriter#COMPUTE_MAXS} is used, this field contains either a stack size
+ * delta (for an edge corresponding to a jump instruction), or the value EXCEPTION (for an
+ * edge corresponding to an exception handler). The stack size delta is the stack size just
+ * after the jump instruction, minus the stack size at the beginning of the predecessor
+ * basic block, i.e. the one containing the jump instruction.
+ * <li>If {@link ClassWriter#COMPUTE_FRAMES} is used, this field contains either the value JUMP
+ * (for an edge corresponding to a jump instruction), or the index, in the {@link
+ * ClassWriter} type table, of the exception type that is handled (for an edge corresponding
+ * to an exception handler).
+ * </ul>
+ */
+ final int info;
- /**
- * Information about this control flow graph edge. If
- * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
- * stack size in the basic block from which this edge originates. This size
- * is equal to the stack size at the "jump" instruction to which this edge
- * corresponds, relatively to the stack size at the beginning of the
- * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
- * this field is the kind of this control flow graph edge (i.e. NORMAL or
- * EXCEPTION).
- */
- int info;
+ /** The successor block of this control flow graph edge. */
+ final Label successor;
- /**
- * The successor block of the basic block from which this edge originates.
- */
- Label successor;
+ /**
+ * The next edge in the list of outgoing edges of a basic block. See {@link Label#outgoingEdges}.
+ */
+ Edge nextEdge;
- /**
- * The next edge in the list of successors of the originating basic block.
- * See {@link Label#successors successors}.
- */
- Edge next;
+ /**
+ * Constructs a new Edge.
+ *
+ * @param info see {@link #info}.
+ * @param successor see {@link #successor}.
+ * @param nextEdge see {@link #nextEdge}.
+ */
+ Edge(final int info, final Label successor, final Edge nextEdge) {
+ this.info = info;
+ this.successor = successor;
+ this.nextEdge = nextEdge;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
old mode 100644
new mode 100755
index 9dbca0b..26b235d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
@@ -1,150 +1,133 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java field. The methods of this class must be called in
- * the following order: ( <tt>visitAnnotation</tt> |
- * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
- *
+ * A visitor to visit a Java field. The methods of this class must be called in the following order:
+ * ( {@code visitAnnotation} | {@code visitTypeAnnotation} | {@code visitAttribute} )* {@code
+ * visitEnd}.
+ *
* @author Eric Bruneton
*/
public abstract class FieldVisitor {
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- protected final int api;
+ /**
+ * The ASM API version implemented by this visitor. The value of this field must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected final int api;
- /**
- * The field visitor to which this visitor must delegate method calls. May
- * be null.
- */
- protected FieldVisitor fv;
+ /** The field visitor to which this visitor must delegate method calls. May be null. */
+ protected FieldVisitor fv;
- /**
- * Constructs a new {@link FieldVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public FieldVisitor(final int api) {
- this(api, null);
- }
+ /**
+ * Constructs a new {@link FieldVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public FieldVisitor(final int api) {
+ this(api, null);
+ }
- /**
- * Constructs a new {@link FieldVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param fv
- * the field visitor to which this visitor must delegate method
- * calls. May be null.
- */
- public FieldVisitor(final int api, final FieldVisitor fv) {
- if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.fv = fv;
+ /**
+ * Constructs a new {@link FieldVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param fieldVisitor the field visitor to which this visitor must delegate method calls. May be
+ * null.
+ */
+ public FieldVisitor(final int api, final FieldVisitor fieldVisitor) {
+ if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
+ throw new IllegalArgumentException();
}
+ this.api = api;
+ this.fv = fieldVisitor;
+ }
- /**
- * Visits an annotation of the field.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (fv != null) {
- return fv.visitAnnotation(desc, visible);
- }
- return null;
+ /**
+ * Visits an annotation of the field.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ if (fv != null) {
+ return fv.visitAnnotation(descriptor, visible);
}
+ return null;
+ }
- /**
- * Visits an annotation on the type of the field.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be {@link TypeReference#FIELD FIELD}. See
- * {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- if (api < Opcodes.ASM5) {
- throw new RuntimeException();
- }
- if (fv != null) {
- return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
- return null;
+ /**
+ * Visits an annotation on the type of the field.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link TypeReference#FIELD}. See {@link TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new UnsupportedOperationException("This feature requires ASM5");
+ }
+ if (fv != null) {
+ return fv.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
}
+ return null;
+ }
- /**
- * Visits a non standard attribute of the field.
- *
- * @param attr
- * an attribute.
- */
- public void visitAttribute(Attribute attr) {
- if (fv != null) {
- fv.visitAttribute(attr);
- }
+ /**
+ * Visits a non standard attribute of the field.
+ *
+ * @param attribute an attribute.
+ */
+ public void visitAttribute(final Attribute attribute) {
+ if (fv != null) {
+ fv.visitAttribute(attribute);
}
+ }
- /**
- * Visits the end of the field. This method, which is the last one to be
- * called, is used to inform the visitor that all the annotations and
- * attributes of the field have been visited.
- */
- public void visitEnd() {
- if (fv != null) {
- fv.visitEnd();
- }
+ /**
+ * Visits the end of the field. This method, which is the last one to be called, is used to inform
+ * the visitor that all the annotations and attributes of the field have been visited.
+ */
+ public void visitEnd() {
+ if (fv != null) {
+ fv.visitEnd();
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
old mode 100644
new mode 100755
index f7bbe98..008525c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
@@ -1,323 +1,346 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * An {@link FieldVisitor} that generates Java fields in bytecode form.
- *
+ * A {@link FieldVisitor} that generates a corresponding 'field_info' structure, as defined in the
+ * Java Virtual Machine Specification (JVMS).
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.5">JVMS
+ * 4.5</a>
* @author Eric Bruneton
*/
final class FieldWriter extends FieldVisitor {
- /**
- * The class writer to which this field must be added.
- */
- private final ClassWriter cw;
+ /** Where the constants used in this FieldWriter must be stored. */
+ private final SymbolTable symbolTable;
+
+ // Note: fields are ordered as in the field_info structure, and those related to attributes are
+ // ordered as in Section 4.7 of the JVMS.
- /**
- * Access flags of this field.
- */
- private final int access;
+ /**
+ * The access_flags field of the field_info JVMS structure. This field can contain ASM specific
+ * access flags, such as {@link Opcodes#ACC_DEPRECATED}, which are removed when generating the
+ * ClassFile structure.
+ */
+ private final int accessFlags;
- /**
- * The index of the constant pool item that contains the name of this
- * method.
- */
- private final int name;
+ /** The name_index field of the field_info JVMS structure. */
+ private final int nameIndex;
- /**
- * The index of the constant pool item that contains the descriptor of this
- * field.
- */
- private final int desc;
+ /** The descriptor_index field of the field_info JVMS structure. */
+ private final int descriptorIndex;
- /**
- * The index of the constant pool item that contains the signature of this
- * field.
- */
- private int signature;
+ /**
+ * The signature_index field of the Signature attribute of this field_info, or 0 if there is no
+ * Signature attribute.
+ */
+ private int signatureIndex;
- /**
- * The index of the constant pool item that contains the constant value of
- * this field.
- */
- private int value;
+ /**
+ * The constantvalue_index field of the ConstantValue attribute of this field_info, or 0 if there
+ * is no ConstantValue attribute.
+ */
+ private int constantValueIndex;
- /**
- * The runtime visible annotations of this field. May be <tt>null</tt>.
- */
- private AnnotationWriter anns;
+ /**
+ * The last runtime visible annotation of this field. The previous ones can be accessed with the
+ * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeVisibleAnnotation;
- /**
- * The runtime invisible annotations of this field. May be <tt>null</tt>.
- */
- private AnnotationWriter ianns;
+ /**
+ * The last runtime invisible annotation of this field. The previous ones can be accessed with the
+ * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeInvisibleAnnotation;
- /**
- * The runtime visible type annotations of this field. May be <tt>null</tt>.
- */
- private AnnotationWriter tanns;
+ /**
+ * The last runtime visible type annotation of this field. The previous ones can be accessed with
+ * the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
- /**
- * The runtime invisible type annotations of this field. May be
- * <tt>null</tt>.
- */
- private AnnotationWriter itanns;
+ /**
+ * The last runtime invisible type annotation of this field. The previous ones can be accessed
+ * with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeInvisibleTypeAnnotation;
- /**
- * The non standard attributes of this field. May be <tt>null</tt>.
- */
- private Attribute attrs;
+ /**
+ * The first non standard attribute of this field. The next ones can be accessed with the {@link
+ * Attribute#nextAttribute} field. May be {@literal null}.
+ *
+ * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
+ * firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
+ * #putFieldInfo} method writes the attributes in the order defined by this list, i.e. in the
+ * reverse order specified by the user.
+ */
+ private Attribute firstAttribute;
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // Constructor
+ // -----------------------------------------------------------------------------------------------
- /**
- * Constructs a new {@link FieldWriter}.
- *
- * @param cw
- * the class writer to which this field must be added.
- * @param access
- * the field's access flags (see {@link Opcodes}).
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link Type}).
- * @param signature
- * the field's signature. May be <tt>null</tt>.
- * @param value
- * the field's constant value. May be <tt>null</tt>.
- */
- FieldWriter(final ClassWriter cw, final int access, final String name,
- final String desc, final String signature, final Object value) {
- super(Opcodes.ASM6);
- if (cw.firstField == null) {
- cw.firstField = this;
- } else {
- cw.lastField.fv = this;
- }
- cw.lastField = this;
- this.cw = cw;
- this.access = access;
- this.name = cw.newUTF8(name);
- this.desc = cw.newUTF8(desc);
- if (signature != null) {
- this.signature = cw.newUTF8(signature);
- }
- if (value != null) {
- this.value = cw.newConstItem(value).index;
- }
+ /**
+ * Constructs a new {@link FieldWriter}.
+ *
+ * @param symbolTable where the constants used in this FieldWriter must be stored.
+ * @param access the field's access flags (see {@link Opcodes}).
+ * @param name the field's name.
+ * @param descriptor the field's descriptor (see {@link Type}).
+ * @param signature the field's signature. May be {@literal null}.
+ * @param constantValue the field's constant value. May be {@literal null}.
+ */
+ FieldWriter(
+ final SymbolTable symbolTable,
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object constantValue) {
+ super(Opcodes.ASM7);
+ this.symbolTable = symbolTable;
+ this.accessFlags = access;
+ this.nameIndex = symbolTable.addConstantUtf8(name);
+ this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
+ if (signature != null) {
+ this.signatureIndex = symbolTable.addConstantUtf8(signature);
}
+ if (constantValue != null) {
+ this.constantValueIndex = symbolTable.addConstant(constantValue).index;
+ }
+ }
- // ------------------------------------------------------------------------
- // Implementation of the FieldVisitor abstract class
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the FieldVisitor abstract class
+ // -----------------------------------------------------------------------------------------------
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- ByteVector bv = new ByteVector();
- // write type, and reserve space for values count
- bv.putShort(cw.newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
- if (visible) {
- aw.next = anns;
- anns = aw;
- } else {
- aw.next = ianns;
- ianns = aw;
- }
- return aw;
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ // Create a ByteVector to hold an 'annotation' JVMS structure.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
+ ByteVector annotation = new ByteVector();
+ // Write type_index and reserve space for num_element_value_pairs.
+ annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
+ if (visible) {
+ return lastRuntimeVisibleAnnotation =
+ new AnnotationWriter(symbolTable, annotation, lastRuntimeVisibleAnnotation);
+ } else {
+ return lastRuntimeInvisibleAnnotation =
+ new AnnotationWriter(symbolTable, annotation, lastRuntimeInvisibleAnnotation);
}
+ }
- @Override
- public AnnotationVisitor visitTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- ByteVector bv = new ByteVector();
- // write target_type and target_info
- AnnotationWriter.putTarget(typeRef, typePath, bv);
- // write type, and reserve space for values count
- bv.putShort(cw.newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
- bv.length - 2);
- if (visible) {
- aw.next = tanns;
- tanns = aw;
- } else {
- aw.next = itanns;
- itanns = aw;
- }
- return aw;
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ // Create a ByteVector to hold a 'type_annotation' JVMS structure.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.
+ ByteVector typeAnnotation = new ByteVector();
+ // Write target_type, target_info, and target_path.
+ TypeReference.putTarget(typeRef, typeAnnotation);
+ TypePath.put(typePath, typeAnnotation);
+ // Write type_index and reserve space for num_element_value_pairs.
+ typeAnnotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
+ if (visible) {
+ return lastRuntimeVisibleTypeAnnotation =
+ new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeVisibleTypeAnnotation);
+ } else {
+ return lastRuntimeInvisibleTypeAnnotation =
+ new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeInvisibleTypeAnnotation);
}
+ }
- @Override
- public void visitAttribute(final Attribute attr) {
- attr.next = attrs;
- attrs = attr;
- }
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ // Store the attributes in the <i>reverse</i> order of their visit by this method.
+ attribute.nextAttribute = firstAttribute;
+ firstAttribute = attribute;
+ }
- @Override
- public void visitEnd() {
- }
+ @Override
+ public void visitEnd() {
+ // Nothing to do.
+ }
- // ------------------------------------------------------------------------
- // Utility methods
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
- /**
- * Returns the size of this field.
- *
- * @return the size of this field.
- */
- int getSize() {
- int size = 8;
- if (value != 0) {
- cw.newUTF8("ConstantValue");
- size += 8;
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- cw.newUTF8("Synthetic");
- size += 6;
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- cw.newUTF8("Deprecated");
- size += 6;
- }
- if (signature != 0) {
- cw.newUTF8("Signature");
- size += 8;
- }
- if (anns != null) {
- cw.newUTF8("RuntimeVisibleAnnotations");
- size += 8 + anns.getSize();
- }
- if (ianns != null) {
- cw.newUTF8("RuntimeInvisibleAnnotations");
- size += 8 + ianns.getSize();
- }
- if (tanns != null) {
- cw.newUTF8("RuntimeVisibleTypeAnnotations");
- size += 8 + tanns.getSize();
- }
- if (itanns != null) {
- cw.newUTF8("RuntimeInvisibleTypeAnnotations");
- size += 8 + itanns.getSize();
- }
- if (attrs != null) {
- size += attrs.getSize(cw, null, 0, -1, -1);
- }
- return size;
+ /**
+ * Returns the size of the field_info JVMS structure generated by this FieldWriter. Also adds the
+ * names of the attributes of this field in the constant pool.
+ *
+ * @return the size in bytes of the field_info JVMS structure.
+ */
+ int computeFieldInfoSize() {
+ // The access_flags, name_index, descriptor_index and attributes_count fields use 8 bytes.
+ int size = 8;
+ // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
+ if (constantValueIndex != 0) {
+ // ConstantValue attributes always use 8 bytes.
+ symbolTable.addConstantUtf8(Constants.CONSTANT_VALUE);
+ size += 8;
+ }
+ // Before Java 1.5, synthetic fields are represented with a Synthetic attribute.
+ if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0
+ && symbolTable.getMajorVersion() < Opcodes.V1_5) {
+ // Synthetic attributes always use 6 bytes.
+ symbolTable.addConstantUtf8(Constants.SYNTHETIC);
+ size += 6;
}
+ if (signatureIndex != 0) {
+ // Signature attributes always use 8 bytes.
+ symbolTable.addConstantUtf8(Constants.SIGNATURE);
+ size += 8;
+ }
+ // ACC_DEPRECATED is ASM specific, the ClassFile format uses a Deprecated attribute instead.
+ if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
+ // Deprecated attributes always use 6 bytes.
+ symbolTable.addConstantUtf8(Constants.DEPRECATED);
+ size += 6;
+ }
+ if (lastRuntimeVisibleAnnotation != null) {
+ size +=
+ lastRuntimeVisibleAnnotation.computeAnnotationsSize(
+ Constants.RUNTIME_VISIBLE_ANNOTATIONS);
+ }
+ if (lastRuntimeInvisibleAnnotation != null) {
+ size +=
+ lastRuntimeInvisibleAnnotation.computeAnnotationsSize(
+ Constants.RUNTIME_INVISIBLE_ANNOTATIONS);
+ }
+ if (lastRuntimeVisibleTypeAnnotation != null) {
+ size +=
+ lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize(
+ Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
+ }
+ if (lastRuntimeInvisibleTypeAnnotation != null) {
+ size +=
+ lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize(
+ Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
+ }
+ if (firstAttribute != null) {
+ size += firstAttribute.computeAttributesSize(symbolTable);
+ }
+ return size;
+ }
- /**
- * Puts the content of this field into the given byte vector.
- *
- * @param out
- * where the content of this field must be put.
- */
- void put(final ByteVector out) {
- final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
- int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
- out.putShort(access & ~mask).putShort(name).putShort(desc);
- int attributeCount = 0;
- if (value != 0) {
- ++attributeCount;
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- ++attributeCount;
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- ++attributeCount;
- }
- if (signature != 0) {
- ++attributeCount;
- }
- if (anns != null) {
- ++attributeCount;
- }
- if (ianns != null) {
- ++attributeCount;
- }
- if (tanns != null) {
- ++attributeCount;
- }
- if (itanns != null) {
- ++attributeCount;
- }
- if (attrs != null) {
- attributeCount += attrs.getCount();
- }
- out.putShort(attributeCount);
- if (value != 0) {
- out.putShort(cw.newUTF8("ConstantValue"));
- out.putInt(2).putShort(value);
- }
- if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
- if ((cw.version & 0xFFFF) < Opcodes.V1_5
- || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
- out.putShort(cw.newUTF8("Synthetic")).putInt(0);
- }
- }
- if ((access & Opcodes.ACC_DEPRECATED) != 0) {
- out.putShort(cw.newUTF8("Deprecated")).putInt(0);
- }
- if (signature != 0) {
- out.putShort(cw.newUTF8("Signature"));
- out.putInt(2).putShort(signature);
- }
- if (anns != null) {
- out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
- anns.put(out);
- }
- if (ianns != null) {
- out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
- ianns.put(out);
- }
- if (tanns != null) {
- out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
- tanns.put(out);
- }
- if (itanns != null) {
- out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
- itanns.put(out);
- }
- if (attrs != null) {
- attrs.put(cw, null, 0, -1, -1, out);
- }
+ /**
+ * Puts the content of the field_info JVMS structure generated by this FieldWriter into the given
+ * ByteVector.
+ *
+ * @param output where the field_info structure must be put.
+ */
+ void putFieldInfo(final ByteVector output) {
+ boolean useSyntheticAttribute = symbolTable.getMajorVersion() < Opcodes.V1_5;
+ // Put the access_flags, name_index and descriptor_index fields.
+ int mask = useSyntheticAttribute ? Opcodes.ACC_SYNTHETIC : 0;
+ output.putShort(accessFlags & ~mask).putShort(nameIndex).putShort(descriptorIndex);
+ // Compute and put the attributes_count field.
+ // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
+ int attributesCount = 0;
+ if (constantValueIndex != 0) {
+ ++attributesCount;
+ }
+ if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && useSyntheticAttribute) {
+ ++attributesCount;
}
+ if (signatureIndex != 0) {
+ ++attributesCount;
+ }
+ if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributesCount;
+ }
+ if (lastRuntimeVisibleAnnotation != null) {
+ ++attributesCount;
+ }
+ if (lastRuntimeInvisibleAnnotation != null) {
+ ++attributesCount;
+ }
+ if (lastRuntimeVisibleTypeAnnotation != null) {
+ ++attributesCount;
+ }
+ if (lastRuntimeInvisibleTypeAnnotation != null) {
+ ++attributesCount;
+ }
+ if (firstAttribute != null) {
+ attributesCount += firstAttribute.getAttributeCount();
+ }
+ output.putShort(attributesCount);
+ // Put the field_info attributes.
+ // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
+ if (constantValueIndex != 0) {
+ output
+ .putShort(symbolTable.addConstantUtf8(Constants.CONSTANT_VALUE))
+ .putInt(2)
+ .putShort(constantValueIndex);
+ }
+ if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && useSyntheticAttribute) {
+ output.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0);
+ }
+ if (signatureIndex != 0) {
+ output
+ .putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE))
+ .putInt(2)
+ .putShort(signatureIndex);
+ }
+ if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
+ output.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0);
+ }
+ if (lastRuntimeVisibleAnnotation != null) {
+ lastRuntimeVisibleAnnotation.putAnnotations(
+ symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_ANNOTATIONS), output);
+ }
+ if (lastRuntimeInvisibleAnnotation != null) {
+ lastRuntimeInvisibleAnnotation.putAnnotations(
+ symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_ANNOTATIONS), output);
+ }
+ if (lastRuntimeVisibleTypeAnnotation != null) {
+ lastRuntimeVisibleTypeAnnotation.putAnnotations(
+ symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS), output);
+ }
+ if (lastRuntimeInvisibleTypeAnnotation != null) {
+ lastRuntimeInvisibleTypeAnnotation.putAnnotations(
+ symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS), output);
+ }
+ if (firstAttribute != null) {
+ firstAttribute.putAttributes(symbolTable, output);
+ }
+ }
+
+ /**
+ * Collects the attributes of this field into the given set of attribute prototypes.
+ *
+ * @param attributePrototypes a set of attribute prototypes.
+ */
+ final void collectAttributePrototypes(final Attribute.Set attributePrototypes) {
+ attributePrototypes.addAttributes(firstAttribute);
+ }
}
[22/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
old mode 100644
new mode 100755
index c25ab8c..3cc051f
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
@@ -1,291 +1,230 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.ArrayList;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A node that represents an annotation.
- *
+ *
* @author Eric Bruneton
*/
public class AnnotationNode extends AnnotationVisitor {
- /**
- * The class descriptor of the annotation class.
- */
- public String desc;
-
- /**
- * The name value pairs of this annotation. Each name value pair is stored
- * as two consecutive elements in the list. The name is a {@link String},
- * and the value may be a {@link Byte}, {@link Boolean}, {@link Character},
- * {@link Short}, {@link Integer}, {@link Long}, {@link Float},
- * {@link Double}, {@link String} or {@link org.objectweb.asm.Type}, or a
- * two elements String array (for enumeration values), an
- * {@link AnnotationNode}, or a {@link List} of values of one of the
- * preceding types. The list may be <tt>null</tt> if there is no name value
- * pair.
- */
- public List<Object> values;
-
- /**
- * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #AnnotationNode(int, String)} version.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public AnnotationNode(final String desc) {
- this(Opcodes.ASM6, desc);
- if (getClass() != AnnotationNode.class) {
- throw new IllegalStateException();
- }
+ /** The class descriptor of the annotation class. */
+ public String desc;
+
+ /**
+ * The name value pairs of this annotation. Each name value pair is stored as two consecutive
+ * elements in the list. The name is a {@link String}, and the value may be a {@link Byte}, {@link
+ * Boolean}, {@link Character}, {@link Short}, {@link Integer}, {@link Long}, {@link Float},
+ * {@link Double}, {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.Type}, or a two elements String
+ * array (for enumeration values), an {@link AnnotationNode}, or a {@link List} of values of one
+ * of the preceding types. The list may be {@literal null} if there is no name value pair.
+ */
+ public List<Object> values;
+
+ /**
+ * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #AnnotationNode(int, String)} version.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public AnnotationNode(final String descriptor) {
+ this(Opcodes.ASM7, descriptor);
+ if (getClass() != AnnotationNode.class) {
+ throw new IllegalStateException();
}
-
- /**
- * Constructs a new {@link AnnotationNode}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param desc
- * the class descriptor of the annotation class.
- */
- public AnnotationNode(final int api, final String desc) {
- super(api);
- this.desc = desc;
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param descriptor the class descriptor of the annotation class.
+ */
+ public AnnotationNode(final int api, final String descriptor) {
+ super(api);
+ this.desc = descriptor;
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode} to visit an array value.
+ *
+ * @param values where the visited values must be stored.
+ */
+ AnnotationNode(final List<Object> values) {
+ super(Opcodes.ASM7);
+ this.values = values;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ if (values == null) {
+ values = new ArrayList<Object>(this.desc != null ? 2 : 1);
}
-
- /**
- * Constructs a new {@link AnnotationNode} to visit an array value.
- *
- * @param values
- * where the visited values must be stored.
- */
- AnnotationNode(final List<Object> values) {
- super(Opcodes.ASM6);
- this.values = values;
+ if (this.desc != null) {
+ values.add(name);
}
-
- // ------------------------------------------------------------------------
- // Implementation of the AnnotationVisitor abstract class
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final String name, final Object value) {
- if (values == null) {
- values = new ArrayList<Object>(this.desc != null ? 2 : 1);
- }
- if (this.desc != null) {
- values.add(name);
- }
- if (value instanceof byte[]) {
- byte[] v = (byte[]) value;
- ArrayList<Byte> l = new ArrayList<Byte>(v.length);
- for (byte b : v) {
- l.add(b);
- }
- values.add(l);
- } else if (value instanceof boolean[]) {
- boolean[] v = (boolean[]) value;
- ArrayList<Boolean> l = new ArrayList<Boolean>(v.length);
- for (boolean b : v) {
- l.add(b);
- }
- values.add(l);
- } else if (value instanceof short[]) {
- short[] v = (short[]) value;
- ArrayList<Short> l = new ArrayList<Short>(v.length);
- for (short s : v) {
- l.add(s);
- }
- values.add(l);
- } else if (value instanceof char[]) {
- char[] v = (char[]) value;
- ArrayList<Character> l = new ArrayList<Character>(v.length);
- for (char c : v) {
- l.add(c);
- }
- values.add(l);
- } else if (value instanceof int[]) {
- int[] v = (int[]) value;
- ArrayList<Integer> l = new ArrayList<Integer>(v.length);
- for (int i : v) {
- l.add(i);
- }
- values.add(l);
- } else if (value instanceof long[]) {
- long[] v = (long[]) value;
- ArrayList<Long> l = new ArrayList<Long>(v.length);
- for (long lng : v) {
- l.add(lng);
- }
- values.add(l);
- } else if (value instanceof float[]) {
- float[] v = (float[]) value;
- ArrayList<Float> l = new ArrayList<Float>(v.length);
- for (float f : v) {
- l.add(f);
- }
- values.add(l);
- } else if (value instanceof double[]) {
- double[] v = (double[]) value;
- ArrayList<Double> l = new ArrayList<Double>(v.length);
- for (double d : v) {
- l.add(d);
- }
- values.add(l);
- } else {
- values.add(value);
- }
+ if (value instanceof byte[]) {
+ values.add(Util.asArrayList((byte[]) value));
+ } else if (value instanceof boolean[]) {
+ values.add(Util.asArrayList((boolean[]) value));
+ } else if (value instanceof short[]) {
+ values.add(Util.asArrayList((short[]) value));
+ } else if (value instanceof char[]) {
+ values.add(Util.asArrayList((char[]) value));
+ } else if (value instanceof int[]) {
+ values.add(Util.asArrayList((int[]) value));
+ } else if (value instanceof long[]) {
+ values.add(Util.asArrayList((long[]) value));
+ } else if (value instanceof float[]) {
+ values.add(Util.asArrayList((float[]) value));
+ } else if (value instanceof double[]) {
+ values.add(Util.asArrayList((double[]) value));
+ } else {
+ values.add(value);
}
+ }
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- if (values == null) {
- values = new ArrayList<Object>(this.desc != null ? 2 : 1);
- }
- if (this.desc != null) {
- values.add(name);
- }
- values.add(new String[] { desc, value });
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ if (values == null) {
+ values = new ArrayList<Object>(this.desc != null ? 2 : 1);
}
-
- @Override
- public AnnotationVisitor visitAnnotation(final String name,
- final String desc) {
- if (values == null) {
- values = new ArrayList<Object>(this.desc != null ? 2 : 1);
- }
- if (this.desc != null) {
- values.add(name);
- }
- AnnotationNode annotation = new AnnotationNode(desc);
- values.add(annotation);
- return annotation;
+ if (this.desc != null) {
+ values.add(name);
}
+ values.add(new String[] {descriptor, value});
+ }
- @Override
- public AnnotationVisitor visitArray(final String name) {
- if (values == null) {
- values = new ArrayList<Object>(this.desc != null ? 2 : 1);
- }
- if (this.desc != null) {
- values.add(name);
- }
- List<Object> array = new ArrayList<Object>();
- values.add(array);
- return new AnnotationNode(array);
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ if (values == null) {
+ values = new ArrayList<Object>(this.desc != null ? 2 : 1);
}
-
- @Override
- public void visitEnd() {
+ if (this.desc != null) {
+ values.add(name);
}
-
- // ------------------------------------------------------------------------
- // Accept methods
- // ------------------------------------------------------------------------
-
- /**
- * Checks that this annotation node is compatible with the given ASM API
- * version. This methods checks that this node, and all its nodes
- * recursively, do not contain elements that were introduced in more recent
- * versions of the ASM API than the given version.
- *
- * @param api
- * an ASM API version. Must be one of {@link Opcodes#ASM4},
- * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public void check(final int api) {
- // nothing to do
+ AnnotationNode annotation = new AnnotationNode(descriptor);
+ values.add(annotation);
+ return annotation;
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ if (values == null) {
+ values = new ArrayList<Object>(this.desc != null ? 2 : 1);
}
-
- /**
- * Makes the given visitor visit this annotation.
- *
- * @param av
- * an annotation visitor. Maybe <tt>null</tt>.
- */
- public void accept(final AnnotationVisitor av) {
- if (av != null) {
- if (values != null) {
- for (int i = 0; i < values.size(); i += 2) {
- String name = (String) values.get(i);
- Object value = values.get(i + 1);
- accept(av, name, value);
- }
- }
- av.visitEnd();
+ if (this.desc != null) {
+ values.add(name);
+ }
+ List<Object> array = new ArrayList<Object>();
+ values.add(array);
+ return new AnnotationNode(array);
+ }
+
+ @Override
+ public void visitEnd() {
+ // Nothing to do.
+ }
+
+ // ------------------------------------------------------------------------
+ // Accept methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that this annotation node is compatible with the given ASM API version. This method
+ * checks that this node, and all its children recursively, do not contain elements that were
+ * introduced in more recent versions of the ASM API than the given version.
+ *
+ * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5},
+ * {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public void check(final int api) {
+ // nothing to do
+ }
+
+ /**
+ * Makes the given visitor visit this annotation.
+ *
+ * @param annotationVisitor an annotation visitor. Maybe {@literal null}.
+ */
+ public void accept(final AnnotationVisitor annotationVisitor) {
+ if (annotationVisitor != null) {
+ if (values != null) {
+ for (int i = 0, n = values.size(); i < n; i += 2) {
+ String name = (String) values.get(i);
+ Object value = values.get(i + 1);
+ accept(annotationVisitor, name, value);
}
+ }
+ annotationVisitor.visitEnd();
}
-
- /**
- * Makes the given visitor visit a given annotation value.
- *
- * @param av
- * an annotation visitor. Maybe <tt>null</tt>.
- * @param name
- * the value name.
- * @param value
- * the actual value.
- */
- public static void accept(final AnnotationVisitor av, final String name,
- final Object value) {
- if (av != null) {
- if (value instanceof String[]) {
- String[] typeconst = (String[]) value;
- av.visitEnum(name, typeconst[0], typeconst[1]);
- } else if (value instanceof AnnotationNode) {
- AnnotationNode an = (AnnotationNode) value;
- an.accept(av.visitAnnotation(name, an.desc));
- } else if (value instanceof List) {
- AnnotationVisitor v = av.visitArray(name);
- if (v != null) {
- List<?> array = (List<?>) value;
- for (int j = 0; j < array.size(); ++j) {
- accept(v, null, array.get(j));
- }
- v.visitEnd();
- }
- } else {
- av.visit(name, value);
- }
+ }
+
+ /**
+ * Makes the given visitor visit a given annotation value.
+ *
+ * @param annotationVisitor an annotation visitor. Maybe {@literal null}.
+ * @param name the value name.
+ * @param value the actual value.
+ */
+ public static void accept(
+ final AnnotationVisitor annotationVisitor, final String name, final Object value) {
+ if (annotationVisitor != null) {
+ if (value instanceof String[]) {
+ String[] typeValue = (String[]) value;
+ annotationVisitor.visitEnum(name, typeValue[0], typeValue[1]);
+ } else if (value instanceof AnnotationNode) {
+ AnnotationNode annotationValue = (AnnotationNode) value;
+ annotationValue.accept(annotationVisitor.visitAnnotation(name, annotationValue.desc));
+ } else if (value instanceof List) {
+ AnnotationVisitor arrayAnnotationVisitor = annotationVisitor.visitArray(name);
+ if (arrayAnnotationVisitor != null) {
+ List<?> arrayValue = (List<?>) value;
+ for (int i = 0, n = arrayValue.size(); i < n; ++i) {
+ accept(arrayAnnotationVisitor, null, arrayValue.get(i));
+ }
+ arrayAnnotationVisitor.visitEnd();
}
+ } else {
+ annotationVisitor.visit(name, value);
+ }
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
old mode 100644
new mode 100755
index 386161c..83cf5d4
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
@@ -1,38 +1,34 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
@@ -44,414 +40,391 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A node that represents a class.
- *
+ *
* @author Eric Bruneton
*/
public class ClassNode extends ClassVisitor {
- /**
- * The class version.
- */
- public int version;
-
- /**
- * The class's access flags (see {@link org.objectweb.asm.Opcodes}). This
- * field also indicates if the class is deprecated.
- */
- public int access;
-
- /**
- * The internal name of the class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- */
- public String name;
-
- /**
- * The signature of the class. May be <tt>null</tt>.
- */
- public String signature;
-
- /**
- * The internal of name of the super class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). For
- * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
- * only for the {@link Object} class.
- */
- public String superName;
-
- /**
- * The internal names of the class's interfaces (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). This
- * list is a list of {@link String} objects.
- */
- public List<String> interfaces;
-
- /**
- * The name of the source file from which this class was compiled. May be
- * <tt>null</tt>.
- */
- public String sourceFile;
-
- /**
- * Debug information to compute the correspondence between source and
- * compiled elements of the class. May be <tt>null</tt>.
- */
- public String sourceDebug;
-
- /**
- * Module information. May be <tt>null</tt>.
- */
- public ModuleNode module;
-
- /**
- * The internal name of the enclosing class of the class. May be
- * <tt>null</tt>.
- */
- public String outerClass;
-
- /**
- * The name of the method that contains the class, or <tt>null</tt> if the
- * class is not enclosed in a method.
- */
- public String outerMethod;
-
- /**
- * The descriptor of the method that contains the class, or <tt>null</tt> if
- * the class is not enclosed in a method.
- */
- public String outerMethodDesc;
-
- /**
- * The runtime visible annotations of this class. This list is a list of
- * {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.AnnotationNode
- * @label visible
- */
- public List<AnnotationNode> visibleAnnotations;
-
- /**
- * The runtime invisible annotations of this class. This list is a list of
- * {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.AnnotationNode
- * @label invisible
- */
- public List<AnnotationNode> invisibleAnnotations;
-
- /**
- * The runtime visible type annotations of this class. This list is a list
- * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label visible
- */
- public List<TypeAnnotationNode> visibleTypeAnnotations;
-
- /**
- * The runtime invisible type annotations of this class. This list is a list
- * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label invisible
- */
- public List<TypeAnnotationNode> invisibleTypeAnnotations;
-
- /**
- * The non standard attributes of this class. This list is a list of
- * {@link Attribute} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.Attribute
- */
- public List<Attribute> attrs;
-
- /**
- * Informations about the inner classes of this class. This list is a list
- * of {@link InnerClassNode} objects.
- *
- * @associates org.objectweb.asm.tree.InnerClassNode
- */
- public List<InnerClassNode> innerClasses;
-
- /**
- * The fields of this class. This list is a list of {@link FieldNode}
- * objects.
- *
- * @associates org.objectweb.asm.tree.FieldNode
- */
- public List<FieldNode> fields;
-
- /**
- * The methods of this class. This list is a list of {@link MethodNode}
- * objects.
- *
- * @associates org.objectweb.asm.tree.MethodNode
- */
- public List<MethodNode> methods;
-
- /**
- * Constructs a new {@link ClassNode}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the {@link #ClassNode(int)}
- * version.
- *
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public ClassNode() {
- this(Opcodes.ASM6);
- if (getClass() != ClassNode.class) {
- throw new IllegalStateException();
- }
+ /**
+ * The class version. The minor version is stored in the 16 most significant bits, and the major
+ * version in the 16 least significant bits.
+ */
+ public int version;
+
+ /**
+ * The class's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This field also indicates if
+ * the class is deprecated.
+ */
+ public int access;
+
+ /** The internal name of this class (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName}). */
+ public String name;
+
+ /** The signature of this class. May be {@literal null}. */
+ public String signature;
+
+ /**
+ * The internal of name of the super class (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName}).
+ * For interfaces, the super class is {@link Object}. May be {@literal null}, but only for the
+ * {@link Object} class.
+ */
+ public String superName;
+
+ /**
+ * The internal names of the interfaces directly implemented by this class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName}).
+ */
+ public List<String> interfaces;
+
+ /** The name of the source file from which this class was compiled. May be {@literal null}. */
+ public String sourceFile;
+
+ /**
+ * The correspondence between source and compiled elements of this class. May be {@literal null}.
+ */
+ public String sourceDebug;
+
+ /** The module stored in this class. May be {@literal null}. */
+ public ModuleNode module;
+
+ /** The internal name of the enclosing class of this class. May be {@literal null}. */
+ public String outerClass;
+
+ /**
+ * The name of the method that contains this class, or {@literal null} if this class is not
+ * enclosed in a method.
+ */
+ public String outerMethod;
+
+ /**
+ * The descriptor of the method that contains this class, or {@literal null} if this class is not
+ * enclosed in a method.
+ */
+ public String outerMethodDesc;
+
+ /** The runtime visible annotations of this class. May be {@literal null}. */
+ public List<AnnotationNode> visibleAnnotations;
+
+ /** The runtime invisible annotations of this class. May be {@literal null}. */
+ public List<AnnotationNode> invisibleAnnotations;
+
+ /** The runtime visible type annotations of this class. May be {@literal null}. */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /** The runtime invisible type annotations of this class. May be {@literal null}. */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /** The non standard attributes of this class. May be {@literal null}. */
+ public List<Attribute> attrs;
+
+ /** The inner classes of this class. */
+ public List<InnerClassNode> innerClasses;
+
+ /** The internal name of the nest host class of this class. May be {@literal null}. */
+ public String nestHostClass;
+
+ /** The internal names of the nest members of this class. May be {@literal null}. */
+ public List<String> nestMembers;
+
+ /** The fields of this class. */
+ public List<FieldNode> fields;
+
+ /** The methods of this class. */
+ public List<MethodNode> methods;
+
+ /**
+ * Constructs a new {@link ClassNode}. <i>Subclasses must not use this constructor</i>. Instead,
+ * they must use the {@link #ClassNode(int)} version.
+ *
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public ClassNode() {
+ this(Opcodes.ASM7);
+ if (getClass() != ClassNode.class) {
+ throw new IllegalStateException();
}
-
- /**
- * Constructs a new {@link ClassNode}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public ClassNode(final int api) {
- super(api);
- this.interfaces = new ArrayList<String>();
- this.innerClasses = new ArrayList<InnerClassNode>();
- this.fields = new ArrayList<FieldNode>();
- this.methods = new ArrayList<MethodNode>();
+ }
+
+ /**
+ * Constructs a new {@link ClassNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public ClassNode(final int api) {
+ super(api);
+ this.interfaces = new ArrayList<String>();
+ this.innerClasses = new ArrayList<InnerClassNode>();
+ this.fields = new ArrayList<FieldNode>();
+ this.methods = new ArrayList<MethodNode>();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the ClassVisitor abstract class
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ this.version = version;
+ this.access = access;
+ this.name = name;
+ this.signature = signature;
+ this.superName = superName;
+ this.interfaces = Util.asArrayList(interfaces);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ sourceFile = file;
+ sourceDebug = debug;
+ }
+
+ @Override
+ public ModuleVisitor visitModule(final String name, final int access, final String version) {
+ module = new ModuleNode(name, access, version);
+ return module;
+ }
+
+ @Override
+ public void visitNestHost(final String nestHost) {
+ this.nestHostClass = nestHost;
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ outerClass = owner;
+ outerMethod = name;
+ outerMethodDesc = descriptor;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationNode annotation = new AnnotationNode(descriptor);
+ if (visible) {
+ if (visibleAnnotations == null) {
+ visibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ visibleAnnotations.add(annotation);
+ } else {
+ if (invisibleAnnotations == null) {
+ invisibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ invisibleAnnotations.add(annotation);
+ }
+ return annotation;
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(typeAnnotation);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(typeAnnotation);
}
+ return typeAnnotation;
+ }
- // ------------------------------------------------------------------------
- // Implementation of the ClassVisitor abstract class
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- this.version = version;
- this.access = access;
- this.name = name;
- this.signature = signature;
- this.superName = superName;
- if (interfaces != null) {
- this.interfaces.addAll(Arrays.asList(interfaces));
- }
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ if (attrs == null) {
+ attrs = new ArrayList<Attribute>(1);
}
+ attrs.add(attribute);
+ }
- @Override
- public void visitSource(final String file, final String debug) {
- sourceFile = file;
- sourceDebug = debug;
+ @Override
+ public void visitNestMember(final String nestMember) {
+ if (nestMembers == null) {
+ nestMembers = new ArrayList<String>();
}
-
- @Override
- public ModuleVisitor visitModule(final String name, final int access,
- final String version) {
- return module = new ModuleNode(name, access, version);
+ nestMembers.add(nestMember);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ InnerClassNode innerClass = new InnerClassNode(name, outerName, innerName, access);
+ innerClasses.add(innerClass);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ FieldNode field = new FieldNode(access, name, descriptor, signature, value);
+ fields.add(field);
+ return field;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ MethodNode method = new MethodNode(access, name, descriptor, signature, exceptions);
+ methods.add(method);
+ return method;
+ }
+
+ @Override
+ public void visitEnd() {
+ // Nothing to do.
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Accept method
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Checks that this class node is compatible with the given ASM API version. This method checks
+ * that this node, and all its children recursively, do not contain elements that were introduced
+ * in more recent versions of the ASM API than the given version.
+ *
+ * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5},
+ * {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public void check(final int api) {
+ if (api < Opcodes.ASM7 && (nestHostClass != null || nestMembers != null)) {
+ throw new UnsupportedClassVersionException();
}
-
- @Override
- public void visitOuterClass(final String owner, final String name,
- final String desc) {
- outerClass = owner;
- outerMethod = name;
- outerMethodDesc = desc;
+ if (api < Opcodes.ASM6 && module != null) {
+ throw new UnsupportedClassVersionException();
}
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- AnnotationNode an = new AnnotationNode(desc);
- if (visible) {
- if (visibleAnnotations == null) {
- visibleAnnotations = new ArrayList<AnnotationNode>(1);
- }
- visibleAnnotations.add(an);
- } else {
- if (invisibleAnnotations == null) {
- invisibleAnnotations = new ArrayList<AnnotationNode>(1);
- }
- invisibleAnnotations.add(an);
- }
- return an;
+ if (api < Opcodes.ASM5) {
+ if (visibleTypeAnnotations != null && !visibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
+ if (invisibleTypeAnnotations != null && !invisibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
}
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
- if (visible) {
- if (visibleTypeAnnotations == null) {
- visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
- }
- visibleTypeAnnotations.add(an);
- } else {
- if (invisibleTypeAnnotations == null) {
- invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
- }
- invisibleTypeAnnotations.add(an);
- }
- return an;
+ // Check the annotations.
+ if (visibleAnnotations != null) {
+ for (int i = visibleAnnotations.size() - 1; i >= 0; --i) {
+ visibleAnnotations.get(i).check(api);
+ }
}
-
- @Override
- public void visitAttribute(final Attribute attr) {
- if (attrs == null) {
- attrs = new ArrayList<Attribute>(1);
- }
- attrs.add(attr);
+ if (invisibleAnnotations != null) {
+ for (int i = invisibleAnnotations.size() - 1; i >= 0; --i) {
+ invisibleAnnotations.get(i).check(api);
+ }
}
-
- @Override
- public void visitInnerClass(final String name, final String outerName,
- final String innerName, final int access) {
- InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
- access);
- innerClasses.add(icn);
+ if (visibleTypeAnnotations != null) {
+ for (int i = visibleTypeAnnotations.size() - 1; i >= 0; --i) {
+ visibleTypeAnnotations.get(i).check(api);
+ }
}
-
- @Override
- public FieldVisitor visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- FieldNode fn = new FieldNode(access, name, desc, signature, value);
- fields.add(fn);
- return fn;
+ if (invisibleTypeAnnotations != null) {
+ for (int i = invisibleTypeAnnotations.size() - 1; i >= 0; --i) {
+ invisibleTypeAnnotations.get(i).check(api);
+ }
}
-
- @Override
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- MethodNode mn = new MethodNode(access, name, desc, signature,
- exceptions);
- methods.add(mn);
- return mn;
+ for (int i = fields.size() - 1; i >= 0; --i) {
+ fields.get(i).check(api);
}
-
- @Override
- public void visitEnd() {
+ for (int i = methods.size() - 1; i >= 0; --i) {
+ methods.get(i).check(api);
}
-
- // ------------------------------------------------------------------------
- // Accept method
- // ------------------------------------------------------------------------
-
- /**
- * Checks that this class node is compatible with the given ASM API version.
- * This methods checks that this node, and all its nodes recursively, do not
- * contain elements that were introduced in more recent versions of the ASM
- * API than the given version.
- *
- * @param api
- * an ASM API version. Must be one of {@link Opcodes#ASM4},
- * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public void check(final int api) {
- if (api < Opcodes.ASM6) {
- if (module != null) {
- throw new RuntimeException();
- }
- }
- if (api < Opcodes.ASM5) {
- if (visibleTypeAnnotations != null
- && visibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- if (invisibleTypeAnnotations != null
- && invisibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- }
- // checks attributes
- int i, n;
- n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
- for (i = 0; i < n; ++i) {
- visibleAnnotations.get(i).check(api);
- }
- n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
- for (i = 0; i < n; ++i) {
- invisibleAnnotations.get(i).check(api);
- }
- n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
- for (i = 0; i < n; ++i) {
- visibleTypeAnnotations.get(i).check(api);
- }
- n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
- .size();
- for (i = 0; i < n; ++i) {
- invisibleTypeAnnotations.get(i).check(api);
- }
- for (FieldNode f : fields) {
- f.check(api);
- }
- for (MethodNode m : methods) {
- m.check(api);
- }
+ }
+
+ /**
+ * Makes the given class visitor visit this class.
+ *
+ * @param classVisitor a class visitor.
+ */
+ public void accept(final ClassVisitor classVisitor) {
+ // Visit the header.
+ String[] interfacesArray = new String[this.interfaces.size()];
+ this.interfaces.toArray(interfacesArray);
+ classVisitor.visit(version, access, name, signature, superName, interfacesArray);
+ // Visit the source.
+ if (sourceFile != null || sourceDebug != null) {
+ classVisitor.visitSource(sourceFile, sourceDebug);
}
-
- /**
- * Makes the given class visitor visit this class.
- *
- * @param cv
- * a class visitor.
- */
- public void accept(final ClassVisitor cv) {
- // visits header
- String[] interfaces = new String[this.interfaces.size()];
- this.interfaces.toArray(interfaces);
- cv.visit(version, access, name, signature, superName, interfaces);
- // visits source
- if (sourceFile != null || sourceDebug != null) {
- cv.visitSource(sourceFile, sourceDebug);
- }
- // visits module
- if (module != null) {
- module.accept(cv);
- }
- // visits outer class
- if (outerClass != null) {
- cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
- }
- // visits attributes
- int i, n;
- n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
- for (i = 0; i < n; ++i) {
- AnnotationNode an = visibleAnnotations.get(i);
- an.accept(cv.visitAnnotation(an.desc, true));
- }
- n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
- for (i = 0; i < n; ++i) {
- AnnotationNode an = invisibleAnnotations.get(i);
- an.accept(cv.visitAnnotation(an.desc, false));
- }
- n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
- for (i = 0; i < n; ++i) {
- TypeAnnotationNode an = visibleTypeAnnotations.get(i);
- an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
- true));
- }
- n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
- .size();
- for (i = 0; i < n; ++i) {
- TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
- an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
- false));
- }
- n = attrs == null ? 0 : attrs.size();
- for (i = 0; i < n; ++i) {
- cv.visitAttribute(attrs.get(i));
- }
- // visits inner classes
- for (i = 0; i < innerClasses.size(); ++i) {
- innerClasses.get(i).accept(cv);
- }
- // visits fields
- for (i = 0; i < fields.size(); ++i) {
- fields.get(i).accept(cv);
- }
- // visits methods
- for (i = 0; i < methods.size(); ++i) {
- methods.get(i).accept(cv);
- }
- // visits end
- cv.visitEnd();
+ // Visit the module.
+ if (module != null) {
+ module.accept(classVisitor);
+ }
+ // Visit the nest host class.
+ if (nestHostClass != null) {
+ classVisitor.visitNestHost(nestHostClass);
+ }
+ // Visit the outer class.
+ if (outerClass != null) {
+ classVisitor.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
+ }
+ // Visit the annotations.
+ if (visibleAnnotations != null) {
+ for (int i = 0, n = visibleAnnotations.size(); i < n; ++i) {
+ AnnotationNode annotation = visibleAnnotations.get(i);
+ annotation.accept(classVisitor.visitAnnotation(annotation.desc, true));
+ }
+ }
+ if (invisibleAnnotations != null) {
+ for (int i = 0, n = invisibleAnnotations.size(); i < n; ++i) {
+ AnnotationNode annotation = invisibleAnnotations.get(i);
+ annotation.accept(classVisitor.visitAnnotation(annotation.desc, false));
+ }
+ }
+ if (visibleTypeAnnotations != null) {
+ for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ classVisitor.visitTypeAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
+ }
+ }
+ if (invisibleTypeAnnotations != null) {
+ for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ classVisitor.visitTypeAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
+ }
+ }
+ // Visit the non standard attributes.
+ if (attrs != null) {
+ for (int i = 0, n = attrs.size(); i < n; ++i) {
+ classVisitor.visitAttribute(attrs.get(i));
+ }
+ }
+ // Visit the nest members.
+ if (nestMembers != null) {
+ for (int i = 0, n = nestMembers.size(); i < n; ++i) {
+ classVisitor.visitNestMember(nestMembers.get(i));
+ }
+ }
+ // Visit the inner classes.
+ for (int i = 0, n = innerClasses.size(); i < n; ++i) {
+ innerClasses.get(i).accept(classVisitor);
+ }
+ // Visit the fields.
+ for (int i = 0, n = fields.size(); i < n; ++i) {
+ fields.get(i).accept(classVisitor);
+ }
+ // Visit the methods.
+ for (int i = 0, n = methods.size(); i < n; ++i) {
+ methods.get(i).accept(classVisitor);
}
+ classVisitor.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
old mode 100644
new mode 100755
index 075519e..97bf7b0
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
@@ -1,110 +1,96 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
- * A node that represents a field instruction. A field instruction is an
- * instruction that loads or stores the value of a field of an object.
- *
+ * A node that represents a field instruction. A field instruction is an instruction that loads or
+ * stores the value of a field of an object.
+ *
* @author Eric Bruneton
*/
public class FieldInsnNode extends AbstractInsnNode {
- /**
- * The internal name of the field's owner class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- */
- public String owner;
+ /**
+ * The internal name of the field's owner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName}).
+ */
+ public String owner;
- /**
- * The field's name.
- */
- public String name;
+ /** The field's name. */
+ public String name;
- /**
- * The field's descriptor (see {@link org.objectweb.asm.Type}).
- */
- public String desc;
+ /** The field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}). */
+ public String desc;
- /**
- * Constructs a new {@link FieldInsnNode}.
- *
- * @param opcode
- * the opcode of the type instruction to be constructed. This
- * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner
- * the internal name of the field's owner class (see
- * {@link org.objectweb.asm.Type#getInternalName()
- * getInternalName}).
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link org.objectweb.asm.Type}).
- */
- public FieldInsnNode(final int opcode, final String owner,
- final String name, final String desc) {
- super(opcode);
- this.owner = owner;
- this.name = name;
- this.desc = desc;
- }
+ /**
+ * Constructs a new {@link FieldInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This opcode must be
+ * GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner the internal name of the field's owner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName}).
+ * @param name the field's name.
+ * @param descriptor the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ */
+ public FieldInsnNode(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ super(opcode);
+ this.owner = owner;
+ this.name = name;
+ this.desc = descriptor;
+ }
- /**
- * Sets the opcode of this instruction.
- *
- * @param opcode
- * the new instruction opcode. This opcode must be GETSTATIC,
- * PUTSTATIC, GETFIELD or PUTFIELD.
- */
- public void setOpcode(final int opcode) {
- this.opcode = opcode;
- }
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be GETSTATIC, PUTSTATIC, GETFIELD or
+ * PUTFIELD.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
- @Override
- public int getType() {
- return FIELD_INSN;
- }
+ @Override
+ public int getType() {
+ return FIELD_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitFieldInsn(opcode, owner, name, desc);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitFieldInsn(opcode, owner, name, desc);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new FieldInsnNode(opcode, owner, name, desc)
- .cloneAnnotations(this);
- }
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new FieldInsnNode(opcode, owner, name, desc).cloneAnnotations(this);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
old mode 100644
new mode 100755
index b4e08d8..c1b516c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
@@ -1,37 +1,34 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.ArrayList;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
@@ -41,267 +38,223 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A node that represents a field.
- *
+ *
* @author Eric Bruneton
*/
public class FieldNode extends FieldVisitor {
- /**
- * The field's access flags (see {@link org.objectweb.asm.Opcodes}). This
- * field also indicates if the field is synthetic and/or deprecated.
- */
- public int access;
+ /**
+ * The field's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This field also indicates if
+ * the field is synthetic and/or deprecated.
+ */
+ public int access;
- /**
- * The field's name.
- */
- public String name;
+ /** The field's name. */
+ public String name;
- /**
- * The field's descriptor (see {@link org.objectweb.asm.Type}).
- */
- public String desc;
+ /** The field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}). */
+ public String desc;
- /**
- * The field's signature. May be <tt>null</tt>.
- */
- public String signature;
+ /** The field's signature. May be {@literal null}. */
+ public String signature;
- /**
- * The field's initial value. This field, which may be <tt>null</tt> if the
- * field does not have an initial value, must be an {@link Integer}, a
- * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
- */
- public Object value;
+ /**
+ * The field's initial value. This field, which may be {@literal null} if the field does not have
+ * an initial value, must be an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}
+ * or a {@link String}.
+ */
+ public Object value;
- /**
- * The runtime visible annotations of this field. This list is a list of
- * {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.AnnotationNode
- * @label visible
- */
- public List<AnnotationNode> visibleAnnotations;
+ /** The runtime visible annotations of this field. May be {@literal null}. */
+ public List<AnnotationNode> visibleAnnotations;
- /**
- * The runtime invisible annotations of this field. This list is a list of
- * {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.AnnotationNode
- * @label invisible
- */
- public List<AnnotationNode> invisibleAnnotations;
+ /** The runtime invisible annotations of this field. May be {@literal null}. */
+ public List<AnnotationNode> invisibleAnnotations;
- /**
- * The runtime visible type annotations of this field. This list is a list
- * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label visible
- */
- public List<TypeAnnotationNode> visibleTypeAnnotations;
+ /** The runtime visible type annotations of this field. May be {@literal null}. */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
- /**
- * The runtime invisible type annotations of this field. This list is a list
- * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label invisible
- */
- public List<TypeAnnotationNode> invisibleTypeAnnotations;
+ /** The runtime invisible type annotations of this field. May be {@literal null}. */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
- /**
- * The non standard attributes of this field. This list is a list of
- * {@link Attribute} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.Attribute
- */
- public List<Attribute> attrs;
+ /** The non standard attributes of this field. * May be {@literal null}. */
+ public List<Attribute> attrs;
- /**
- * Constructs a new {@link FieldNode}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #FieldNode(int, int, String, String, String, Object)} version.
- *
- * @param access
- * the field's access flags (see
- * {@link org.objectweb.asm.Opcodes}). This parameter also
- * indicates if the field is synthetic and/or deprecated.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link org.objectweb.asm.Type
- * Type}).
- * @param signature
- * the field's signature.
- * @param value
- * the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value,
- * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public FieldNode(final int access, final String name, final String desc,
- final String signature, final Object value) {
- this(Opcodes.ASM6, access, name, desc, signature, value);
- if (getClass() != FieldNode.class) {
- throw new IllegalStateException();
- }
+ /**
+ * Constructs a new {@link FieldNode}. <i>Subclasses must not use this constructor</i>. Instead,
+ * they must use the {@link #FieldNode(int, int, String, String, String, Object)} version.
+ *
+ * @param access the field's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter
+ * also indicates if the field is synthetic and/or deprecated.
+ * @param name the field's name.
+ * @param descriptor the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param signature the field's signature.
+ * @param value the field's initial value. This parameter, which may be {@literal null} if the
+ * field does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link
+ * Long}, a {@link Double} or a {@link String}.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public FieldNode(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ this(Opcodes.ASM7, access, name, descriptor, signature, value);
+ if (getClass() != FieldNode.class) {
+ throw new IllegalStateException();
}
+ }
- /**
- * Constructs a new {@link FieldNode}. <i>Subclasses must not use this
- * constructor</i>.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
- * @param access
- * the field's access flags (see
- * {@link org.objectweb.asm.Opcodes}). This parameter also
- * indicates if the field is synthetic and/or deprecated.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link org.objectweb.asm.Type
- * Type}).
- * @param signature
- * the field's signature.
- * @param value
- * the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value,
- * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
- */
- public FieldNode(final int api, final int access, final String name,
- final String desc, final String signature, final Object value) {
- super(api);
- this.access = access;
- this.name = name;
- this.desc = desc;
- this.signature = signature;
- this.value = value;
- }
+ /**
+ * Constructs a new {@link FieldNode}. <i>Subclasses must not use this constructor</i>.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4}
+ * or {@link Opcodes#ASM5}.
+ * @param access the field's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter
+ * also indicates if the field is synthetic and/or deprecated.
+ * @param name the field's name.
+ * @param descriptor the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param signature the field's signature.
+ * @param value the field's initial value. This parameter, which may be {@literal null} if the
+ * field does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link
+ * Long}, a {@link Double} or a {@link String}.
+ */
+ public FieldNode(
+ final int api,
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ super(api);
+ this.access = access;
+ this.name = name;
+ this.desc = descriptor;
+ this.signature = signature;
+ this.value = value;
+ }
- // ------------------------------------------------------------------------
- // Implementation of the FieldVisitor abstract class
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the FieldVisitor abstract class
+ // -----------------------------------------------------------------------------------------------
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- AnnotationNode an = new AnnotationNode(desc);
- if (visible) {
- if (visibleAnnotations == null) {
- visibleAnnotations = new ArrayList<AnnotationNode>(1);
- }
- visibleAnnotations.add(an);
- } else {
- if (invisibleAnnotations == null) {
- invisibleAnnotations = new ArrayList<AnnotationNode>(1);
- }
- invisibleAnnotations.add(an);
- }
- return an;
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationNode annotation = new AnnotationNode(descriptor);
+ if (visible) {
+ if (visibleAnnotations == null) {
+ visibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ visibleAnnotations.add(annotation);
+ } else {
+ if (invisibleAnnotations == null) {
+ invisibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ invisibleAnnotations.add(annotation);
}
+ return annotation;
+ }
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
- if (visible) {
- if (visibleTypeAnnotations == null) {
- visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
- }
- visibleTypeAnnotations.add(an);
- } else {
- if (invisibleTypeAnnotations == null) {
- invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
- }
- invisibleTypeAnnotations.add(an);
- }
- return an;
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(typeAnnotation);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(typeAnnotation);
}
+ return typeAnnotation;
+ }
- @Override
- public void visitAttribute(final Attribute attr) {
- if (attrs == null) {
- attrs = new ArrayList<Attribute>(1);
- }
- attrs.add(attr);
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ if (attrs == null) {
+ attrs = new ArrayList<Attribute>(1);
}
+ attrs.add(attribute);
+ }
- @Override
- public void visitEnd() {
- }
+ @Override
+ public void visitEnd() {
+ // Nothing to do.
+ }
- // ------------------------------------------------------------------------
- // Accept methods
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // Accept methods
+ // -----------------------------------------------------------------------------------------------
- /**
- * Checks that this field node is compatible with the given ASM API version.
- * This methods checks that this node, and all its nodes recursively, do not
- * contain elements that were introduced in more recent versions of the ASM
- * API than the given version.
- *
- * @param api
- * an ASM API version. Must be one of {@link Opcodes#ASM4},
- * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public void check(final int api) {
- if (api == Opcodes.ASM4) {
- if (visibleTypeAnnotations != null
- && visibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- if (invisibleTypeAnnotations != null
- && invisibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- }
+ /**
+ * Checks that this field node is compatible with the given ASM API version. This method checks
+ * that this node, and all its children recursively, do not contain elements that were introduced
+ * in more recent versions of the ASM API than the given version.
+ *
+ * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5},
+ * {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public void check(final int api) {
+ if (api == Opcodes.ASM4) {
+ if (visibleTypeAnnotations != null && !visibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
+ if (invisibleTypeAnnotations != null && !invisibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
}
+ }
- /**
- * Makes the given class visitor visit this field.
- *
- * @param cv
- * a class visitor.
- */
- public void accept(final ClassVisitor cv) {
- FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
- if (fv == null) {
- return;
- }
- int i, n;
- n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
- for (i = 0; i < n; ++i) {
- AnnotationNode an = visibleAnnotations.get(i);
- an.accept(fv.visitAnnotation(an.desc, true));
- }
- n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
- for (i = 0; i < n; ++i) {
- AnnotationNode an = invisibleAnnotations.get(i);
- an.accept(fv.visitAnnotation(an.desc, false));
- }
- n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
- for (i = 0; i < n; ++i) {
- TypeAnnotationNode an = visibleTypeAnnotations.get(i);
- an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
- true));
- }
- n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
- .size();
- for (i = 0; i < n; ++i) {
- TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
- an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
- false));
- }
- n = attrs == null ? 0 : attrs.size();
- for (i = 0; i < n; ++i) {
- fv.visitAttribute(attrs.get(i));
- }
- fv.visitEnd();
+ /**
+ * Makes the given class visitor visit this field.
+ *
+ * @param classVisitor a class visitor.
+ */
+ public void accept(final ClassVisitor classVisitor) {
+ FieldVisitor fieldVisitor = classVisitor.visitField(access, name, desc, signature, value);
+ if (fieldVisitor == null) {
+ return;
+ }
+ // Visit the annotations.
+ if (visibleAnnotations != null) {
+ for (int i = 0, n = visibleAnnotations.size(); i < n; ++i) {
+ AnnotationNode annotation = visibleAnnotations.get(i);
+ annotation.accept(fieldVisitor.visitAnnotation(annotation.desc, true));
+ }
+ }
+ if (invisibleAnnotations != null) {
+ for (int i = 0, n = invisibleAnnotations.size(); i < n; ++i) {
+ AnnotationNode annotation = invisibleAnnotations.get(i);
+ annotation.accept(fieldVisitor.visitAnnotation(annotation.desc, false));
+ }
+ }
+ if (visibleTypeAnnotations != null) {
+ for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ fieldVisitor.visitTypeAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
+ }
+ }
+ if (invisibleTypeAnnotations != null) {
+ for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ fieldVisitor.visitTypeAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
+ }
+ }
+ // Visit the non standard attributes.
+ if (attrs != null) {
+ for (int i = 0, n = attrs.size(); i < n; ++i) {
+ fieldVisitor.visitAttribute(attrs.get(i));
+ }
}
+ fieldVisitor.visitEnd();
+ }
}
[32/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
old mode 100644
new mode 100755
index d518864..96bfe33
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
@@ -1,452 +1,436 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2013 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.apache.tapestry5.internal.plastic.asm;
-
-/**
- * A reference to a type appearing in a class, field or method declaration, or
- * on an instruction. Such a reference designates the part of the class where
- * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
- * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
- * declaration, etc).
- *
- * @author Eric Bruneton
- */
-public class TypeReference {
-
- /**
- * The sort of type references that target a type parameter of a generic
- * class. See {@link #getSort getSort}.
- */
- public final static int CLASS_TYPE_PARAMETER = 0x00;
-
- /**
- * The sort of type references that target a type parameter of a generic
- * method. See {@link #getSort getSort}.
- */
- public final static int METHOD_TYPE_PARAMETER = 0x01;
-
- /**
- * The sort of type references that target the super class of a class or one
- * of the interfaces it implements. See {@link #getSort getSort}.
- */
- public final static int CLASS_EXTENDS = 0x10;
-
- /**
- * The sort of type references that target a bound of a type parameter of a
- * generic class. See {@link #getSort getSort}.
- */
- public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
-
- /**
- * The sort of type references that target a bound of a type parameter of a
- * generic method. See {@link #getSort getSort}.
- */
- public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
-
- /**
- * The sort of type references that target the type of a field. See
- * {@link #getSort getSort}.
- */
- public final static int FIELD = 0x13;
-
- /**
- * The sort of type references that target the return type of a method. See
- * {@link #getSort getSort}.
- */
- public final static int METHOD_RETURN = 0x14;
-
- /**
- * The sort of type references that target the receiver type of a method.
- * See {@link #getSort getSort}.
- */
- public final static int METHOD_RECEIVER = 0x15;
-
- /**
- * The sort of type references that target the type of a formal parameter of
- * a method. See {@link #getSort getSort}.
- */
- public final static int METHOD_FORMAL_PARAMETER = 0x16;
-
- /**
- * The sort of type references that target the type of an exception declared
- * in the throws clause of a method. See {@link #getSort getSort}.
- */
- public final static int THROWS = 0x17;
-
- /**
- * The sort of type references that target the type of a local variable in a
- * method. See {@link #getSort getSort}.
- */
- public final static int LOCAL_VARIABLE = 0x40;
-
- /**
- * The sort of type references that target the type of a resource variable
- * in a method. See {@link #getSort getSort}.
- */
- public final static int RESOURCE_VARIABLE = 0x41;
-
- /**
- * The sort of type references that target the type of the exception of a
- * 'catch' clause in a method. See {@link #getSort getSort}.
- */
- public final static int EXCEPTION_PARAMETER = 0x42;
-
- /**
- * The sort of type references that target the type declared in an
- * 'instanceof' instruction. See {@link #getSort getSort}.
- */
- public final static int INSTANCEOF = 0x43;
-
- /**
- * The sort of type references that target the type of the object created by
- * a 'new' instruction. See {@link #getSort getSort}.
- */
- public final static int NEW = 0x44;
-
- /**
- * The sort of type references that target the receiver type of a
- * constructor reference. See {@link #getSort getSort}.
- */
- public final static int CONSTRUCTOR_REFERENCE = 0x45;
-
- /**
- * The sort of type references that target the receiver type of a method
- * reference. See {@link #getSort getSort}.
- */
- public final static int METHOD_REFERENCE = 0x46;
-
- /**
- * The sort of type references that target the type declared in an explicit
- * or implicit cast instruction. See {@link #getSort getSort}.
- */
- public final static int CAST = 0x47;
-
- /**
- * The sort of type references that target a type parameter of a generic
- * constructor in a constructor call. See {@link #getSort getSort}.
- */
- public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
-
- /**
- * The sort of type references that target a type parameter of a generic
- * method in a method call. See {@link #getSort getSort}.
- */
- public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
-
- /**
- * The sort of type references that target a type parameter of a generic
- * constructor in a constructor reference. See {@link #getSort getSort}.
- */
- public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
-
- /**
- * The sort of type references that target a type parameter of a generic
- * method in a method reference. See {@link #getSort getSort}.
- */
- public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
-
- /**
- * The type reference value in Java class file format.
- */
- private int value;
-
- /**
- * Creates a new TypeReference.
- *
- * @param typeRef
- * the int encoded value of the type reference, as received in a
- * visit method related to type annotations, like
- * visitTypeAnnotation.
- */
- public TypeReference(int typeRef) {
- this.value = typeRef;
- }
-
- /**
- * Returns a type reference of the given sort.
- *
- * @param sort
- * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
- * {@link #METHOD_RECEIVER METHOD_RECEIVER},
- * {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
- * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
- * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
- * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
- * {@link #METHOD_REFERENCE METHOD_REFERENCE}.
- * @return a type reference of the given sort.
- */
- public static TypeReference newTypeReference(int sort) {
- return new TypeReference(sort << 24);
- }
-
- /**
- * Returns a reference to a type parameter of a generic class or method.
- *
- * @param sort
- * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
- * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
- * @param paramIndex
- * the type parameter index.
- * @return a reference to the given generic class or method type parameter.
- */
- public static TypeReference newTypeParameterReference(int sort,
- int paramIndex) {
- return new TypeReference((sort << 24) | (paramIndex << 16));
- }
-
- /**
- * Returns a reference to a type parameter bound of a generic class or
- * method.
- *
- * @param sort
- * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
- * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
- * @param paramIndex
- * the type parameter index.
- * @param boundIndex
- * the type bound index within the above type parameters.
- * @return a reference to the given generic class or method type parameter
- * bound.
- */
- public static TypeReference newTypeParameterBoundReference(int sort,
- int paramIndex, int boundIndex) {
- return new TypeReference((sort << 24) | (paramIndex << 16)
- | (boundIndex << 8));
- }
-
- /**
- * Returns a reference to the super class or to an interface of the
- * 'implements' clause of a class.
- *
- * @param itfIndex
- * the index of an interface in the 'implements' clause of a
- * class, or -1 to reference the super class of the class.
- * @return a reference to the given super type of a class.
- */
- public static TypeReference newSuperTypeReference(int itfIndex) {
- itfIndex &= 0xFFFF;
- return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
- }
-
- /**
- * Returns a reference to the type of a formal parameter of a method.
- *
- * @param paramIndex
- * the formal parameter index.
- *
- * @return a reference to the type of the given method formal parameter.
- */
- public static TypeReference newFormalParameterReference(int paramIndex) {
- return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
- | (paramIndex << 16));
- }
-
- /**
- * Returns a reference to the type of an exception, in a 'throws' clause of
- * a method.
- *
- * @param exceptionIndex
- * the index of an exception in a 'throws' clause of a method.
- *
- * @return a reference to the type of the given exception.
- */
- public static TypeReference newExceptionReference(int exceptionIndex) {
- return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
- }
-
- /**
- * Returns a reference to the type of the exception declared in a 'catch'
- * clause of a method.
- *
- * @param tryCatchBlockIndex
- * the index of a try catch block (using the order in which they
- * are visited with visitTryCatchBlock).
- *
- * @return a reference to the type of the given exception.
- */
- public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
- return new TypeReference((EXCEPTION_PARAMETER << 24)
- | (tryCatchBlockIndex << 8));
- }
-
- /**
- * Returns a reference to the type of a type argument in a constructor or
- * method call or reference.
- *
- * @param sort
- * {@link #CAST CAST},
- * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
- * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
- * {@link #METHOD_INVOCATION_TYPE_ARGUMENT
- * METHOD_INVOCATION_TYPE_ARGUMENT},
- * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
- * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
- * {@link #METHOD_REFERENCE_TYPE_ARGUMENT
- * METHOD_REFERENCE_TYPE_ARGUMENT}.
- * @param argIndex
- * the type argument index.
- *
- * @return a reference to the type of the given type argument.
- */
- public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
- return new TypeReference((sort << 24) | argIndex);
- }
-
- /**
- * Returns the sort of this type reference.
- *
- * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
- * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
- * {@link #CLASS_EXTENDS CLASS_EXTENDS},
- * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
- * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
- * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
- * {@link #METHOD_RECEIVER METHOD_RECEIVER},
- * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
- * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
- * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
- * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
- * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
- * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
- * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
- * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
- * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
- * {@link #METHOD_INVOCATION_TYPE_ARGUMENT
- * METHOD_INVOCATION_TYPE_ARGUMENT},
- * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
- * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
- * {@link #METHOD_REFERENCE_TYPE_ARGUMENT
- * METHOD_REFERENCE_TYPE_ARGUMENT}.
- */
- public int getSort() {
- return value >>> 24;
- }
-
- /**
- * Returns the index of the type parameter referenced by this type
- * reference. This method must only be used for type references whose sort
- * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
- * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
- * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
- * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
- *
- * @return a type parameter index.
- */
- public int getTypeParameterIndex() {
- return (value & 0x00FF0000) >> 16;
- }
-
- /**
- * Returns the index of the type parameter bound, within the type parameter
- * {@link #getTypeParameterIndex}, referenced by this type reference. This
- * method must only be used for type references whose sort is
- * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
- * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
- *
- * @return a type parameter bound index.
- */
- public int getTypeParameterBoundIndex() {
- return (value & 0x0000FF00) >> 8;
- }
-
- /**
- * Returns the index of the "super type" of a class that is referenced by
- * this type reference. This method must only be used for type references
- * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
- *
- * @return the index of an interface in the 'implements' clause of a class,
- * or -1 if this type reference references the type of the super
- * class.
- */
- public int getSuperTypeIndex() {
- return (short) ((value & 0x00FFFF00) >> 8);
- }
-
- /**
- * Returns the index of the formal parameter whose type is referenced by
- * this type reference. This method must only be used for type references
- * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
- *
- * @return a formal parameter index.
- */
- public int getFormalParameterIndex() {
- return (value & 0x00FF0000) >> 16;
- }
-
- /**
- * Returns the index of the exception, in a 'throws' clause of a method,
- * whose type is referenced by this type reference. This method must only be
- * used for type references whose sort is {@link #THROWS THROWS}.
- *
- * @return the index of an exception in the 'throws' clause of a method.
- */
- public int getExceptionIndex() {
- return (value & 0x00FFFF00) >> 8;
- }
-
- /**
- * Returns the index of the try catch block (using the order in which they
- * are visited with visitTryCatchBlock), whose 'catch' type is referenced by
- * this type reference. This method must only be used for type references
- * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
- *
- * @return the index of an exception in the 'throws' clause of a method.
- */
- public int getTryCatchBlockIndex() {
- return (value & 0x00FFFF00) >> 8;
- }
-
- /**
- * Returns the index of the type argument referenced by this type reference.
- * This method must only be used for type references whose sort is
- * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
- * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
- * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
- * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
- * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
- * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
- *
- * @return a type parameter index.
- */
- public int getTypeArgumentIndex() {
- return value & 0xFF;
- }
-
- /**
- * Returns the int encoded value of this type reference, suitable for use in
- * visit methods related to type annotations, like visitTypeAnnotation.
- *
- * @return the int encoded value of this type reference.
- */
- public int getValue() {
- return value;
- }
-}
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * A reference to a type appearing in a class, field or method declaration, or on an instruction.
+ * Such a reference designates the part of the class where the referenced type is appearing (e.g. an
+ * 'extends', 'implements' or 'throws' clause, a 'new' instruction, a 'catch' clause, a type cast, a
+ * local variable declaration, etc).
+ *
+ * @author Eric Bruneton
+ */
+public class TypeReference {
+
+ /**
+ * The sort of type references that target a type parameter of a generic class. See {@link
+ * #getSort}.
+ */
+ public static final int CLASS_TYPE_PARAMETER = 0x00;
+
+ /**
+ * The sort of type references that target a type parameter of a generic method. See {@link
+ * #getSort}.
+ */
+ public static final int METHOD_TYPE_PARAMETER = 0x01;
+
+ /**
+ * The sort of type references that target the super class of a class or one of the interfaces it
+ * implements. See {@link #getSort}.
+ */
+ public static final int CLASS_EXTENDS = 0x10;
+
+ /**
+ * The sort of type references that target a bound of a type parameter of a generic class. See
+ * {@link #getSort}.
+ */
+ public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
+
+ /**
+ * The sort of type references that target a bound of a type parameter of a generic method. See
+ * {@link #getSort}.
+ */
+ public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
+
+ /** The sort of type references that target the type of a field. See {@link #getSort}. */
+ public static final int FIELD = 0x13;
+
+ /** The sort of type references that target the return type of a method. See {@link #getSort}. */
+ public static final int METHOD_RETURN = 0x14;
+
+ /**
+ * The sort of type references that target the receiver type of a method. See {@link #getSort}.
+ */
+ public static final int METHOD_RECEIVER = 0x15;
+
+ /**
+ * The sort of type references that target the type of a formal parameter of a method. See {@link
+ * #getSort}.
+ */
+ public static final int METHOD_FORMAL_PARAMETER = 0x16;
+
+ /**
+ * The sort of type references that target the type of an exception declared in the throws clause
+ * of a method. See {@link #getSort}.
+ */
+ public static final int THROWS = 0x17;
+
+ /**
+ * The sort of type references that target the type of a local variable in a method. See {@link
+ * #getSort}.
+ */
+ public static final int LOCAL_VARIABLE = 0x40;
+
+ /**
+ * The sort of type references that target the type of a resource variable in a method. See {@link
+ * #getSort}.
+ */
+ public static final int RESOURCE_VARIABLE = 0x41;
+
+ /**
+ * The sort of type references that target the type of the exception of a 'catch' clause in a
+ * method. See {@link #getSort}.
+ */
+ public static final int EXCEPTION_PARAMETER = 0x42;
+
+ /**
+ * The sort of type references that target the type declared in an 'instanceof' instruction. See
+ * {@link #getSort}.
+ */
+ public static final int INSTANCEOF = 0x43;
+
+ /**
+ * The sort of type references that target the type of the object created by a 'new' instruction.
+ * See {@link #getSort}.
+ */
+ public static final int NEW = 0x44;
+
+ /**
+ * The sort of type references that target the receiver type of a constructor reference. See
+ * {@link #getSort}.
+ */
+ public static final int CONSTRUCTOR_REFERENCE = 0x45;
+
+ /**
+ * The sort of type references that target the receiver type of a method reference. See {@link
+ * #getSort}.
+ */
+ public static final int METHOD_REFERENCE = 0x46;
+
+ /**
+ * The sort of type references that target the type declared in an explicit or implicit cast
+ * instruction. See {@link #getSort}.
+ */
+ public static final int CAST = 0x47;
+
+ /**
+ * The sort of type references that target a type parameter of a generic constructor in a
+ * constructor call. See {@link #getSort}.
+ */
+ public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
+
+ /**
+ * The sort of type references that target a type parameter of a generic method in a method call.
+ * See {@link #getSort}.
+ */
+ public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
+
+ /**
+ * The sort of type references that target a type parameter of a generic constructor in a
+ * constructor reference. See {@link #getSort}.
+ */
+ public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
+
+ /**
+ * The sort of type references that target a type parameter of a generic method in a method
+ * reference. See {@link #getSort}.
+ */
+ public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
+
+ /**
+ * The target_type and target_info structures - as defined in the Java Virtual Machine
+ * Specification (JVMS) - corresponding to this type reference. target_type uses one byte, and all
+ * the target_info union fields use up to 3 bytes (except localvar_target, handled with the
+ * specific method {@link MethodVisitor#visitLocalVariableAnnotation}). Thus, both structures can
+ * be stored in an int.
+ *
+ * <p>This int field stores target_type (called the TypeReference 'sort' in the public API of this
+ * class) in its most significant byte, followed by the target_info fields. Depending on
+ * target_type, 1, 2 or even 3 least significant bytes of this field are unused. target_info
+ * fields which reference bytecode offsets are set to 0 (these offsets are ignored in ClassReader,
+ * and recomputed in MethodWriter).
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS
+ * 4.7.20</a>
+ * @see <a
+ * href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.1">JVMS
+ * 4.7.20.1</a>
+ */
+ private final int targetTypeAndInfo;
+
+ /**
+ * Constructs a new TypeReference.
+ *
+ * @param typeRef the int encoded value of the type reference, as received in a visit method
+ * related to type annotations, such as {@link ClassVisitor#visitTypeAnnotation}.
+ */
+ public TypeReference(final int typeRef) {
+ this.targetTypeAndInfo = typeRef;
+ }
+
+ /**
+ * Returns a type reference of the given sort.
+ *
+ * @param sort one of {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
+ * #LOCAL_VARIABLE}, {@link #RESOURCE_VARIABLE}, {@link #INSTANCEOF}, {@link #NEW}, {@link
+ * #CONSTRUCTOR_REFERENCE}, or {@link #METHOD_REFERENCE}.
+ * @return a type reference of the given sort.
+ */
+ public static TypeReference newTypeReference(final int sort) {
+ return new TypeReference(sort << 24);
+ }
+
+ /**
+ * Returns a reference to a type parameter of a generic class or method.
+ *
+ * @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
+ * @param paramIndex the type parameter index.
+ * @return a reference to the given generic class or method type parameter.
+ */
+ public static TypeReference newTypeParameterReference(final int sort, final int paramIndex) {
+ return new TypeReference((sort << 24) | (paramIndex << 16));
+ }
+
+ /**
+ * Returns a reference to a type parameter bound of a generic class or method.
+ *
+ * @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
+ * @param paramIndex the type parameter index.
+ * @param boundIndex the type bound index within the above type parameters.
+ * @return a reference to the given generic class or method type parameter bound.
+ */
+ public static TypeReference newTypeParameterBoundReference(
+ final int sort, final int paramIndex, final int boundIndex) {
+ return new TypeReference((sort << 24) | (paramIndex << 16) | (boundIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the super class or to an interface of the 'implements' clause of a
+ * class.
+ *
+ * @param itfIndex the index of an interface in the 'implements' clause of a class, or -1 to
+ * reference the super class of the class.
+ * @return a reference to the given super type of a class.
+ */
+ public static TypeReference newSuperTypeReference(final int itfIndex) {
+ return new TypeReference((CLASS_EXTENDS << 24) | ((itfIndex & 0xFFFF) << 8));
+ }
+
+ /**
+ * Returns a reference to the type of a formal parameter of a method.
+ *
+ * @param paramIndex the formal parameter index.
+ * @return a reference to the type of the given method formal parameter.
+ */
+ public static TypeReference newFormalParameterReference(final int paramIndex) {
+ return new TypeReference((METHOD_FORMAL_PARAMETER << 24) | (paramIndex << 16));
+ }
+
+ /**
+ * Returns a reference to the type of an exception, in a 'throws' clause of a method.
+ *
+ * @param exceptionIndex the index of an exception in a 'throws' clause of a method.
+ * @return a reference to the type of the given exception.
+ */
+ public static TypeReference newExceptionReference(final int exceptionIndex) {
+ return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of the exception declared in a 'catch' clause of a method.
+ *
+ * @param tryCatchBlockIndex the index of a try catch block (using the order in which they are
+ * visited with visitTryCatchBlock).
+ * @return a reference to the type of the given exception.
+ */
+ public static TypeReference newTryCatchReference(final int tryCatchBlockIndex) {
+ return new TypeReference((EXCEPTION_PARAMETER << 24) | (tryCatchBlockIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of a type argument in a constructor or method call or
+ * reference.
+ *
+ * @param sort one of {@link #CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link
+ * #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link
+ * #METHOD_REFERENCE_TYPE_ARGUMENT}.
+ * @param argIndex the type argument index.
+ * @return a reference to the type of the given type argument.
+ */
+ public static TypeReference newTypeArgumentReference(final int sort, final int argIndex) {
+ return new TypeReference((sort << 24) | argIndex);
+ }
+
+ /**
+ * Returns the sort of this type reference.
+ *
+ * @return one of {@link #CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER}, {@link
+ * #CLASS_EXTENDS}, {@link #CLASS_TYPE_PARAMETER_BOUND}, {@link #METHOD_TYPE_PARAMETER_BOUND},
+ * {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
+ * #METHOD_FORMAL_PARAMETER}, {@link #THROWS}, {@link #LOCAL_VARIABLE}, {@link
+ * #RESOURCE_VARIABLE}, {@link #EXCEPTION_PARAMETER}, {@link #INSTANCEOF}, {@link #NEW},
+ * {@link #CONSTRUCTOR_REFERENCE}, {@link #METHOD_REFERENCE}, {@link #CAST}, {@link
+ * #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
+ * #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
+ */
+ public int getSort() {
+ return targetTypeAndInfo >>> 24;
+ }
+
+ /**
+ * Returns the index of the type parameter referenced by this type reference. This method must
+ * only be used for type references whose sort is {@link #CLASS_TYPE_PARAMETER}, {@link
+ * #METHOD_TYPE_PARAMETER}, {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
+ * #METHOD_TYPE_PARAMETER_BOUND}.
+ *
+ * @return a type parameter index.
+ */
+ public int getTypeParameterIndex() {
+ return (targetTypeAndInfo & 0x00FF0000) >> 16;
+ }
+
+ /**
+ * Returns the index of the type parameter bound, within the type parameter {@link
+ * #getTypeParameterIndex}, referenced by this type reference. This method must only be used for
+ * type references whose sort is {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
+ * #METHOD_TYPE_PARAMETER_BOUND}.
+ *
+ * @return a type parameter bound index.
+ */
+ public int getTypeParameterBoundIndex() {
+ return (targetTypeAndInfo & 0x0000FF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the "super type" of a class that is referenced by this type reference.
+ * This method must only be used for type references whose sort is {@link #CLASS_EXTENDS}.
+ *
+ * @return the index of an interface in the 'implements' clause of a class, or -1 if this type
+ * reference references the type of the super class.
+ */
+ public int getSuperTypeIndex() {
+ return (short) ((targetTypeAndInfo & 0x00FFFF00) >> 8);
+ }
+
+ /**
+ * Returns the index of the formal parameter whose type is referenced by this type reference. This
+ * method must only be used for type references whose sort is {@link #METHOD_FORMAL_PARAMETER}.
+ *
+ * @return a formal parameter index.
+ */
+ public int getFormalParameterIndex() {
+ return (targetTypeAndInfo & 0x00FF0000) >> 16;
+ }
+
+ /**
+ * Returns the index of the exception, in a 'throws' clause of a method, whose type is referenced
+ * by this type reference. This method must only be used for type references whose sort is {@link
+ * #THROWS}.
+ *
+ * @return the index of an exception in the 'throws' clause of a method.
+ */
+ public int getExceptionIndex() {
+ return (targetTypeAndInfo & 0x00FFFF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the try catch block (using the order in which they are visited with
+ * visitTryCatchBlock), whose 'catch' type is referenced by this type reference. This method must
+ * only be used for type references whose sort is {@link #EXCEPTION_PARAMETER} .
+ *
+ * @return the index of an exception in the 'throws' clause of a method.
+ */
+ public int getTryCatchBlockIndex() {
+ return (targetTypeAndInfo & 0x00FFFF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the type argument referenced by this type reference. This method must only
+ * be used for type references whose sort is {@link #CAST}, {@link
+ * #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
+ * #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
+ *
+ * @return a type parameter index.
+ */
+ public int getTypeArgumentIndex() {
+ return targetTypeAndInfo & 0xFF;
+ }
+
+ /**
+ * Returns the int encoded value of this type reference, suitable for use in visit methods related
+ * to type annotations, like visitTypeAnnotation.
+ *
+ * @return the int encoded value of this type reference.
+ */
+ public int getValue() {
+ return targetTypeAndInfo;
+ }
+
+ /**
+ * Puts the given target_type and target_info JVMS structures into the given ByteVector.
+ *
+ * @param targetTypeAndInfo a target_type and a target_info structures encoded as in {@link
+ * #targetTypeAndInfo}. LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
+ * @param output where the type reference must be put.
+ */
+ static void putTarget(final int targetTypeAndInfo, final ByteVector output) {
+ switch (targetTypeAndInfo >>> 24) {
+ case CLASS_TYPE_PARAMETER:
+ case METHOD_TYPE_PARAMETER:
+ case METHOD_FORMAL_PARAMETER:
+ output.putShort(targetTypeAndInfo >>> 16);
+ break;
+ case FIELD:
+ case METHOD_RETURN:
+ case METHOD_RECEIVER:
+ output.putByte(targetTypeAndInfo >>> 24);
+ break;
+ case CAST:
+ case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+ case METHOD_INVOCATION_TYPE_ARGUMENT:
+ case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+ case METHOD_REFERENCE_TYPE_ARGUMENT:
+ output.putInt(targetTypeAndInfo);
+ break;
+ case CLASS_EXTENDS:
+ case CLASS_TYPE_PARAMETER_BOUND:
+ case METHOD_TYPE_PARAMETER_BOUND:
+ case THROWS:
+ case EXCEPTION_PARAMETER:
+ case INSTANCEOF:
+ case NEW:
+ case CONSTRUCTOR_REFERENCE:
+ case METHOD_REFERENCE:
+ output.put12(targetTypeAndInfo >>> 24, (targetTypeAndInfo & 0xFFFF00) >> 8);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
old mode 100644
new mode 100755
index a0f6880..96e0c48
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
@@ -1,39 +1,37 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
@@ -41,606 +39,621 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
/**
- * A {@link org.objectweb.asm.MethodVisitor} to insert before, after and around
- * advices in methods and constructors.
- * <p>
- * The behavior for constructors is like this:
- * <ol>
- *
- * <li>as long as the INVOKESPECIAL for the object initialization has not been
- * reached, every bytecode instruction is dispatched in the ctor code visitor</li>
- *
- * <li>when this one is reached, it is only added in the ctor code visitor and a
- * JP invoke is added</li>
- *
- * <li>after that, only the other code visitor receives the instructions</li>
- *
- * </ol>
- *
+ * A {@link MethodVisitor} to insert before, after and around advices in methods and constructors.
+ * For constructors, the code keeps track of the elements on the stack in order to detect when the
+ * super class constructor is called (note that there can be multiple such calls in different
+ * branches). {@code onMethodEnter} is called after each super class constructor call, because the
+ * object cannot be used before it is properly initialized.
+ *
* @author Eugene Kuleshov
* @author Eric Bruneton
*/
public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes {
- private static final Object THIS = new Object();
-
- private static final Object OTHER = new Object();
-
- protected int methodAccess;
-
- protected String methodDesc;
-
- private boolean constructor;
-
- private boolean superInitialized;
-
- private List<Object> stackFrame;
-
- private Map<Label, List<Object>> branches;
-
- /**
- * Creates a new {@link AdviceAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param mv
- * the method visitor to which this adapter delegates calls.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- */
- protected AdviceAdapter(final int api, final MethodVisitor mv,
- final int access, final String name, final String desc) {
- super(api, mv, access, name, desc);
- methodAccess = access;
- methodDesc = desc;
- constructor = "<init>".equals(name);
- }
-
- @Override
- public void visitCode() {
- mv.visitCode();
- if (constructor) {
- stackFrame = new ArrayList<Object>();
- branches = new HashMap<Label, List<Object>>();
- } else {
- superInitialized = true;
- onMethodEnter();
- }
- }
-
- @Override
- public void visitLabel(final Label label) {
- mv.visitLabel(label);
- if (constructor && branches != null) {
- List<Object> frame = branches.get(label);
- if (frame != null) {
- stackFrame = frame;
- branches.remove(label);
- }
- }
+ /** The "uninitialized this" value. */
+ private static final Object UNINITIALIZED_THIS = new Object();
+
+ /** Any value other than "uninitialized this". */
+ private static final Object OTHER = new Object();
+
+ /** Prefix of the error message when invalid opcodes are found. */
+ private static final String INVALID_OPCODE = "Invalid opcode ";
+
+ /** The access flags of the visited method. */
+ protected int methodAccess;
+
+ /** The descriptor of the visited method. */
+ protected String methodDesc;
+
+ /** Whether the visited method is a constructor. */
+ private final boolean isConstructor;
+
+ /**
+ * Whether the super class constructor has been called (if the visited method is a constructor),
+ * at the current instruction. There can be multiple call sites to the super constructor (e.g. for
+ * Java code such as {@code super(expr ? value1 : value2);}), in different branches. When scanning
+ * the bytecode linearly, we can move from one branch where the super constructor has been called
+ * to another where it has not been called yet. Therefore, this value can change from false to
+ * true, and vice-versa.
+ */
+ private boolean superClassConstructorCalled;
+
+ /**
+ * The values on the current execution stack frame (long and double are represented by two
+ * elements). Each value is either {@link #UNINITIALIZED_THIS} (for the uninitialized this value),
+ * or {@link #OTHER} (for any other value). This field is only maintained for constructors, in
+ * branches where the super class constructor has not been called yet.
+ */
+ private List<Object> stackFrame;
+
+ /**
+ * The stack map frames corresponding to the labels of the forward jumps made *before* the super
+ * class constructor has been called (note that the Java Virtual Machine forbids backward jumps
+ * before the super class constructor is called). Note that by definition (cf. the 'before'), when
+ * we reach a label from this map, {@link #superClassConstructorCalled} must be reset to false.
+ * This field is only maintained for constructors.
+ */
+ private Map<Label, List<Object>> forwardJumpStackFrames;
+
+ /**
+ * Constructs a new {@link AdviceAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param methodVisitor the method visitor to which this adapter delegates calls.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type Type}).
+ */
+ protected AdviceAdapter(
+ final int api,
+ final MethodVisitor methodVisitor,
+ final int access,
+ final String name,
+ final String descriptor) {
+ super(api, methodVisitor, access, name, descriptor);
+ methodAccess = access;
+ methodDesc = descriptor;
+ isConstructor = "<init>".equals(name);
+ }
+
+ @Override
+ public void visitCode() {
+ super.visitCode();
+ if (isConstructor) {
+ stackFrame = new ArrayList<Object>();
+ forwardJumpStackFrames = new HashMap<Label, List<Object>>();
+ } else {
+ onMethodEnter();
}
-
- @Override
- public void visitInsn(final int opcode) {
- if (constructor) {
- int s;
- switch (opcode) {
- case RETURN: // empty stack
- onMethodExit(opcode);
- break;
- case IRETURN: // 1 before n/a after
- case FRETURN: // 1 before n/a after
- case ARETURN: // 1 before n/a after
- case ATHROW: // 1 before n/a after
- popValue();
- onMethodExit(opcode);
- break;
- case LRETURN: // 2 before n/a after
- case DRETURN: // 2 before n/a after
- popValue();
- popValue();
- onMethodExit(opcode);
- break;
- case NOP:
- case LALOAD: // remove 2 add 2
- case DALOAD: // remove 2 add 2
- case LNEG:
- case DNEG:
- case FNEG:
- case INEG:
- case L2D:
- case D2L:
- case F2I:
- case I2B:
- case I2C:
- case I2S:
- case I2F:
- case ARRAYLENGTH:
- break;
- case ACONST_NULL:
- case ICONST_M1:
- case ICONST_0:
- case ICONST_1:
- case ICONST_2:
- case ICONST_3:
- case ICONST_4:
- case ICONST_5:
- case FCONST_0:
- case FCONST_1:
- case FCONST_2:
- case F2L: // 1 before 2 after
- case F2D:
- case I2L:
- case I2D:
- pushValue(OTHER);
- break;
- case LCONST_0:
- case LCONST_1:
- case DCONST_0:
- case DCONST_1:
- pushValue(OTHER);
- pushValue(OTHER);
- break;
- case IALOAD: // remove 2 add 1
- case FALOAD: // remove 2 add 1
- case AALOAD: // remove 2 add 1
- case BALOAD: // remove 2 add 1
- case CALOAD: // remove 2 add 1
- case SALOAD: // remove 2 add 1
- case POP:
- case IADD:
- case FADD:
- case ISUB:
- case LSHL: // 3 before 2 after
- case LSHR: // 3 before 2 after
- case LUSHR: // 3 before 2 after
- case L2I: // 2 before 1 after
- case L2F: // 2 before 1 after
- case D2I: // 2 before 1 after
- case D2F: // 2 before 1 after
- case FSUB:
- case FMUL:
- case FDIV:
- case FREM:
- case FCMPL: // 2 before 1 after
- case FCMPG: // 2 before 1 after
- case IMUL:
- case IDIV:
- case IREM:
- case ISHL:
- case ISHR:
- case IUSHR:
- case IAND:
- case IOR:
- case IXOR:
- case MONITORENTER:
- case MONITOREXIT:
- popValue();
- break;
- case POP2:
- case LSUB:
- case LMUL:
- case LDIV:
- case LREM:
- case LADD:
- case LAND:
- case LOR:
- case LXOR:
- case DADD:
- case DMUL:
- case DSUB:
- case DDIV:
- case DREM:
- popValue();
- popValue();
- break;
- case IASTORE:
- case FASTORE:
- case AASTORE:
- case BASTORE:
- case CASTORE:
- case SASTORE:
- case LCMP: // 4 before 1 after
- case DCMPL:
- case DCMPG:
- popValue();
- popValue();
- popValue();
- break;
- case LASTORE:
- case DASTORE:
- popValue();
- popValue();
- popValue();
- popValue();
- break;
- case DUP:
- pushValue(peekValue());
- break;
- case DUP_X1:
- s = stackFrame.size();
- stackFrame.add(s - 2, stackFrame.get(s - 1));
- break;
- case DUP_X2:
- s = stackFrame.size();
- stackFrame.add(s - 3, stackFrame.get(s - 1));
- break;
- case DUP2:
- s = stackFrame.size();
- stackFrame.add(s - 2, stackFrame.get(s - 1));
- stackFrame.add(s - 2, stackFrame.get(s - 1));
- break;
- case DUP2_X1:
- s = stackFrame.size();
- stackFrame.add(s - 3, stackFrame.get(s - 1));
- stackFrame.add(s - 3, stackFrame.get(s - 1));
- break;
- case DUP2_X2:
- s = stackFrame.size();
- stackFrame.add(s - 4, stackFrame.get(s - 1));
- stackFrame.add(s - 4, stackFrame.get(s - 1));
- break;
- case SWAP:
- s = stackFrame.size();
- stackFrame.add(s - 2, stackFrame.get(s - 1));
- stackFrame.remove(s);
- break;
- }
- } else {
- switch (opcode) {
- case RETURN:
- case IRETURN:
- case FRETURN:
- case ARETURN:
- case LRETURN:
- case DRETURN:
- case ATHROW:
- onMethodExit(opcode);
- break;
- }
- }
- mv.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ super.visitLabel(label);
+ if (isConstructor && forwardJumpStackFrames != null) {
+ List<Object> labelStackFrame = forwardJumpStackFrames.get(label);
+ if (labelStackFrame != null) {
+ stackFrame = labelStackFrame;
+ superClassConstructorCalled = false;
+ forwardJumpStackFrames.remove(label);
+ }
}
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- super.visitVarInsn(opcode, var);
- if (constructor) {
- switch (opcode) {
- case ILOAD:
- case FLOAD:
- pushValue(OTHER);
- break;
- case LLOAD:
- case DLOAD:
- pushValue(OTHER);
- pushValue(OTHER);
- break;
- case ALOAD:
- pushValue(var == 0 ? THIS : OTHER);
- break;
- case ASTORE:
- case ISTORE:
- case FSTORE:
- popValue();
- break;
- case LSTORE:
- case DSTORE:
- popValue();
- popValue();
- break;
- }
- }
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ if (isConstructor && !superClassConstructorCalled) {
+ int stackSize;
+ switch (opcode) {
+ case IRETURN:
+ case FRETURN:
+ case ARETURN:
+ case LRETURN:
+ case DRETURN:
+ throw new IllegalArgumentException("Invalid return in constructor");
+ case RETURN: // empty stack
+ onMethodExit(opcode);
+ break;
+ case ATHROW: // 1 before n/a after
+ popValue();
+ onMethodExit(opcode);
+ break;
+ case NOP:
+ case LALOAD: // remove 2 add 2
+ case DALOAD: // remove 2 add 2
+ case LNEG:
+ case DNEG:
+ case FNEG:
+ case INEG:
+ case L2D:
+ case D2L:
+ case F2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ case I2F:
+ case ARRAYLENGTH:
+ break;
+ case ACONST_NULL:
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ case F2L: // 1 before 2 after
+ case F2D:
+ case I2L:
+ case I2D:
+ pushValue(OTHER);
+ break;
+ case LCONST_0:
+ case LCONST_1:
+ case DCONST_0:
+ case DCONST_1:
+ pushValue(OTHER);
+ pushValue(OTHER);
+ break;
+ case IALOAD: // remove 2 add 1
+ case FALOAD: // remove 2 add 1
+ case AALOAD: // remove 2 add 1
+ case BALOAD: // remove 2 add 1
+ case CALOAD: // remove 2 add 1
+ case SALOAD: // remove 2 add 1
+ case POP:
+ case IADD:
+ case FADD:
+ case ISUB:
+ case LSHL: // 3 before 2 after
+ case LSHR: // 3 before 2 after
+ case LUSHR: // 3 before 2 after
+ case L2I: // 2 before 1 after
+ case L2F: // 2 before 1 after
+ case D2I: // 2 before 1 after
+ case D2F: // 2 before 1 after
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL: // 2 before 1 after
+ case FCMPG: // 2 before 1 after
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case MONITORENTER:
+ case MONITOREXIT:
+ popValue();
+ break;
+ case POP2:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LADD:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case DADD:
+ case DMUL:
+ case DSUB:
+ case DDIV:
+ case DREM:
+ popValue();
+ popValue();
+ break;
+ case IASTORE:
+ case FASTORE:
+ case AASTORE:
+ case BASTORE:
+ case CASTORE:
+ case SASTORE:
+ case LCMP: // 4 before 1 after
+ case DCMPL:
+ case DCMPG:
+ popValue();
+ popValue();
+ popValue();
+ break;
+ case LASTORE:
+ case DASTORE:
+ popValue();
+ popValue();
+ popValue();
+ popValue();
+ break;
+ case DUP:
+ pushValue(peekValue());
+ break;
+ case DUP_X1:
+ stackSize = stackFrame.size();
+ stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1));
+ break;
+ case DUP_X2:
+ stackSize = stackFrame.size();
+ stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1));
+ break;
+ case DUP2:
+ stackSize = stackFrame.size();
+ stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1));
+ stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1));
+ break;
+ case DUP2_X1:
+ stackSize = stackFrame.size();
+ stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1));
+ stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1));
+ break;
+ case DUP2_X2:
+ stackSize = stackFrame.size();
+ stackFrame.add(stackSize - 4, stackFrame.get(stackSize - 1));
+ stackFrame.add(stackSize - 4, stackFrame.get(stackSize - 1));
+ break;
+ case SWAP:
+ stackSize = stackFrame.size();
+ stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1));
+ stackFrame.remove(stackSize);
+ break;
+ default:
+ throw new IllegalArgumentException(INVALID_OPCODE + opcode);
+ }
+ } else {
+ switch (opcode) {
+ case RETURN:
+ case IRETURN:
+ case FRETURN:
+ case ARETURN:
+ case LRETURN:
+ case DRETURN:
+ case ATHROW:
+ onMethodExit(opcode);
+ break;
+ default:
+ break;
+ }
}
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- mv.visitFieldInsn(opcode, owner, name, desc);
- if (constructor) {
- char c = desc.charAt(0);
- boolean longOrDouble = c == 'J' || c == 'D';
- switch (opcode) {
- case GETSTATIC:
- pushValue(OTHER);
- if (longOrDouble) {
- pushValue(OTHER);
- }
- break;
- case PUTSTATIC:
- popValue();
- if (longOrDouble) {
- popValue();
- }
- break;
- case PUTFIELD:
- popValue();
- popValue();
- if (longOrDouble) {
- popValue();
- }
- break;
- // case GETFIELD:
- default:
- if (longOrDouble) {
- pushValue(OTHER);
- }
- }
- }
+ super.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ super.visitVarInsn(opcode, var);
+ if (isConstructor && !superClassConstructorCalled) {
+ switch (opcode) {
+ case ILOAD:
+ case FLOAD:
+ pushValue(OTHER);
+ break;
+ case LLOAD:
+ case DLOAD:
+ pushValue(OTHER);
+ pushValue(OTHER);
+ break;
+ case ALOAD:
+ pushValue(var == 0 ? UNINITIALIZED_THIS : OTHER);
+ break;
+ case ASTORE:
+ case ISTORE:
+ case FSTORE:
+ popValue();
+ break;
+ case LSTORE:
+ case DSTORE:
+ popValue();
+ popValue();
+ break;
+ default:
+ throw new IllegalArgumentException(INVALID_OPCODE + opcode);
+ }
}
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- mv.visitIntInsn(opcode, operand);
- if (constructor && opcode != NEWARRAY) {
- pushValue(OTHER);
- }
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- mv.visitLdcInsn(cst);
- if (constructor) {
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ super.visitFieldInsn(opcode, owner, name, descriptor);
+ if (isConstructor && !superClassConstructorCalled) {
+ char firstDescriptorChar = descriptor.charAt(0);
+ boolean longOrDouble = firstDescriptorChar == 'J' || firstDescriptorChar == 'D';
+ switch (opcode) {
+ case GETSTATIC:
+ pushValue(OTHER);
+ if (longOrDouble) {
pushValue(OTHER);
- if (cst instanceof Double || cst instanceof Long) {
- pushValue(OTHER);
- }
- }
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- mv.visitMultiANewArrayInsn(desc, dims);
- if (constructor) {
- for (int i = 0; i < dims; i++) {
- popValue();
- }
+ }
+ break;
+ case PUTSTATIC:
+ popValue();
+ if (longOrDouble) {
+ popValue();
+ }
+ break;
+ case PUTFIELD:
+ popValue();
+ popValue();
+ if (longOrDouble) {
+ popValue();
+ }
+ break;
+ case GETFIELD:
+ if (longOrDouble) {
pushValue(OTHER);
- }
+ }
+ break;
+ default:
+ throw new IllegalArgumentException(INVALID_OPCODE + opcode);
+ }
}
+ }
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- mv.visitTypeInsn(opcode, type);
- // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
- if (constructor && opcode == NEW) {
- pushValue(OTHER);
- }
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ super.visitIntInsn(opcode, operand);
+ if (isConstructor && !superClassConstructorCalled && opcode != NEWARRAY) {
+ pushValue(OTHER);
}
-
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ super.visitLdcInsn(value);
+ if (isConstructor && !superClassConstructorCalled) {
+ pushValue(OTHER);
+ if (value instanceof Double
+ || value instanceof Long
+ || (value instanceof ConstantDynamic && ((ConstantDynamic) value).getSize() == 2)) {
+ pushValue(OTHER);
+ }
}
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ super.visitMultiANewArrayInsn(descriptor, numDimensions);
+ if (isConstructor && !superClassConstructorCalled) {
+ for (int i = 0; i < numDimensions; i++) {
+ popValue();
+ }
+ pushValue(OTHER);
}
-
- private void doVisitMethodInsn(int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- mv.visitMethodInsn(opcode, owner, name, desc, itf);
- if (constructor) {
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; i++) {
- popValue();
- if (types[i].getSize() == 2) {
- popValue();
- }
- }
- switch (opcode) {
- // case INVOKESTATIC:
- // break;
- case INVOKEINTERFACE:
- case INVOKEVIRTUAL:
- popValue(); // objectref
- break;
- case INVOKESPECIAL:
- Object type = popValue(); // objectref
- if (type == THIS && !superInitialized) {
- onMethodEnter();
- superInitialized = true;
- // once super has been initialized it is no longer
- // necessary to keep track of stack state
- constructor = false;
- }
- break;
- }
-
- Type returnType = Type.getReturnType(desc);
- if (returnType != Type.VOID_TYPE) {
- pushValue(OTHER);
- if (returnType.getSize() == 2) {
- pushValue(OTHER);
- }
- }
- }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ super.visitTypeInsn(opcode, type);
+ // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack.
+ if (isConstructor && !superClassConstructorCalled && opcode == NEW) {
+ pushValue(OTHER);
}
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- if (constructor) {
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; i++) {
- popValue();
- if (types[i].getSize() == 2) {
- popValue();
- }
- }
-
- Type returnType = Type.getReturnType(desc);
- if (returnType != Type.VOID_TYPE) {
- pushValue(OTHER);
- if (returnType.getSize() == 2) {
- pushValue(OTHER);
- }
- }
- }
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
}
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- mv.visitJumpInsn(opcode, label);
- if (constructor) {
- switch (opcode) {
- case IFEQ:
- case IFNE:
- case IFLT:
- case IFGE:
- case IFGT:
- case IFLE:
- case IFNULL:
- case IFNONNULL:
- popValue();
- break;
- case IF_ICMPEQ:
- case IF_ICMPNE:
- case IF_ICMPLT:
- case IF_ICMPGE:
- case IF_ICMPGT:
- case IF_ICMPLE:
- case IF_ACMPEQ:
- case IF_ACMPNE:
- popValue();
- popValue();
- break;
- case JSR:
- pushValue(OTHER);
- break;
- }
- addBranch(label);
- }
+ mv.visitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ doVisitMethodInsn(opcode, descriptor);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
}
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- if (constructor) {
- popValue();
- addBranches(dflt, labels);
+ mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ doVisitMethodInsn(opcode, descriptor);
+ }
+
+ private void doVisitMethodInsn(final int opcode, final String descriptor) {
+ if (isConstructor && !superClassConstructorCalled) {
+ for (Type argumentType : Type.getArgumentTypes(descriptor)) {
+ popValue();
+ if (argumentType.getSize() == 2) {
+ popValue();
}
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- if (constructor) {
- popValue();
- addBranches(dflt, labels);
- }
- }
-
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler,
- String type) {
- super.visitTryCatchBlock(start, end, handler, type);
- if (constructor && !branches.containsKey(handler)) {
- List<Object> stackFrame = new ArrayList<Object>();
- stackFrame.add(OTHER);
- branches.put(handler, stackFrame);
- }
- }
-
- private void addBranches(final Label dflt, final Label[] labels) {
- addBranch(dflt);
- for (int i = 0; i < labels.length; i++) {
- addBranch(labels[i]);
+ }
+ switch (opcode) {
+ case INVOKEINTERFACE:
+ case INVOKEVIRTUAL:
+ popValue();
+ break;
+ case INVOKESPECIAL:
+ Object value = popValue();
+ if (value == UNINITIALIZED_THIS && !superClassConstructorCalled) {
+ superClassConstructorCalled = true;
+ onMethodEnter();
+ }
+ break;
+ default:
+ break;
+ }
+
+ Type returnType = Type.getReturnType(descriptor);
+ if (returnType != Type.VOID_TYPE) {
+ pushValue(OTHER);
+ if (returnType.getSize() == 2) {
+ pushValue(OTHER);
}
+ }
}
-
- private void addBranch(final Label label) {
- if (branches.containsKey(label)) {
- return;
- }
- branches.put(label, new ArrayList<Object>(stackFrame));
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ doVisitMethodInsn(Opcodes.INVOKEDYNAMIC, descriptor);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ super.visitJumpInsn(opcode, label);
+ if (isConstructor && !superClassConstructorCalled) {
+ switch (opcode) {
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case IFNULL:
+ case IFNONNULL:
+ popValue();
+ break;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ popValue();
+ popValue();
+ break;
+ case JSR:
+ pushValue(OTHER);
+ break;
+ default:
+ break;
+ }
+ addForwardJump(label);
}
-
- private Object popValue() {
- return stackFrame.remove(stackFrame.size() - 1);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ if (isConstructor && !superClassConstructorCalled) {
+ popValue();
+ addForwardJumps(dflt, labels);
}
-
- private Object peekValue() {
- return stackFrame.get(stackFrame.size() - 1);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ if (isConstructor && !superClassConstructorCalled) {
+ popValue();
+ addForwardJumps(dflt, labels);
}
-
- private void pushValue(final Object o) {
- stackFrame.add(o);
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ super.visitTryCatchBlock(start, end, handler, type);
+ // By definition of 'forwardJumpStackFrames', 'handler' should be pushed only if there is an
+ // instruction between 'start' and 'end' at which the super class constructor is not yet
+ // called. Unfortunately, try catch blocks must be visited before their labels, so we have no
+ // way to know this at this point. Instead, we suppose that the super class constructor has not
+ // been called at the start of *any* exception handler. If this is wrong, normally there should
+ // not be a second super class constructor call in the exception handler (an object can't be
+ // initialized twice), so this is not issue (in the sense that there is no risk to emit a wrong
+ // 'onMethodEnter').
+ if (isConstructor && !forwardJumpStackFrames.containsKey(handler)) {
+ List<Object> handlerStackFrame = new ArrayList<Object>();
+ handlerStackFrame.add(OTHER);
+ forwardJumpStackFrames.put(handler, handlerStackFrame);
}
+ }
- /**
- * Called at the beginning of the method or after super class call in
- * the constructor. <br>
- * <br>
- *
- * <i>Custom code can use or change all the local variables, but should not
- * change state of the stack.</i>
- */
- protected void onMethodEnter() {
+ private void addForwardJumps(final Label dflt, final Label[] labels) {
+ addForwardJump(dflt);
+ for (Label label : labels) {
+ addForwardJump(label);
}
+ }
- /**
- * Called before explicit exit from the method using either return or throw.
- * Top element on the stack contains the return value or exception instance.
- * For example:
- *
- * <pre>
- * public void onMethodExit(int opcode) {
- * if(opcode==RETURN) {
- * visitInsn(ACONST_NULL);
- * } else if(opcode==ARETURN || opcode==ATHROW) {
- * dup();
- * } else {
- * if(opcode==LRETURN || opcode==DRETURN) {
- * dup2();
- * } else {
- * dup();
- * }
- * box(Type.getReturnType(this.methodDesc));
- * }
- * visitIntInsn(SIPUSH, opcode);
- * visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
- * }
- *
- * // an actual call back method
- * public static void onExit(Object param, int opcode) {
- * ...
- * </pre>
- *
- * <br>
- * <br>
- *
- * <i>Custom code can use or change all the local variables, but should not
- * change state of the stack.</i>
- *
- * @param opcode
- * one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN
- * or ATHROW
- *
- */
- protected void onMethodExit(int opcode) {
+ private void addForwardJump(final Label label) {
+ if (forwardJumpStackFrames.containsKey(label)) {
+ return;
}
-
- // TODO onException, onMethodCall
+ forwardJumpStackFrames.put(label, new ArrayList<Object>(stackFrame));
+ }
+
+ private Object popValue() {
+ return stackFrame.remove(stackFrame.size() - 1);
+ }
+
+ private Object peekValue() {
+ return stackFrame.get(stackFrame.size() - 1);
+ }
+
+ private void pushValue(final Object value) {
+ stackFrame.add(value);
+ }
+
+ /**
+ * Generates the "before" advice for the visited method. The default implementation of this method
+ * does nothing. Subclasses can use or change all the local variables, but should not change state
+ * of the stack. This method is called at the beginning of the method or after super class
+ * constructor has been called (in constructors).
+ */
+ protected void onMethodEnter() {}
+
+ /**
+ * Generates the "after" advice for the visited method. The default implementation of this method
+ * does nothing. Subclasses can use or change all the local variables, but should not change state
+ * of the stack. This method is called at the end of the method, just before return and athrow
+ * instructions. The top element on the stack contains the return value or the exception instance.
+ * For example:
+ *
+ * <pre>
+ * public void onMethodExit(final int opcode) {
+ * if (opcode == RETURN) {
+ * visitInsn(ACONST_NULL);
+ * } else if (opcode == ARETURN || opcode == ATHROW) {
+ * dup();
+ * } else {
+ * if (opcode == LRETURN || opcode == DRETURN) {
+ * dup2();
+ * } else {
+ * dup();
+ * }
+ * box(Type.getReturnType(this.methodDesc));
+ * }
+ * visitIntInsn(SIPUSH, opcode);
+ * visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
+ * }
+ *
+ * // An actual call back method.
+ * public static void onExit(final Object exitValue, final int opcode) {
+ * ...
+ * }
+ * </pre>
+ *
+ * @param opcode one of {@link Opcodes#RETURN}, {@link Opcodes#IRETURN}, {@link Opcodes#FRETURN},
+ * {@link Opcodes#ARETURN}, {@link Opcodes#LRETURN}, {@link Opcodes#DRETURN} or {@link
+ * Opcodes#ATHROW}.
+ */
+ protected void onMethodExit(final int opcode) {}
}
[16/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
old mode 100644
new mode 100755
index c856b14..8a8f965
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
@@ -1,36 +1,33 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.FieldInsnNode;
@@ -38,396 +35,416 @@ import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
/**
- * An extended {@link BasicInterpreter} that checks that bytecode instructions
- * are correctly used.
- *
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions are correctly used.
+ *
* @author Eric Bruneton
* @author Bing Ran
*/
public class BasicVerifier extends BasicInterpreter {
- public BasicVerifier() {
- super(ASM6);
+ /**
+ * Constructs a new {@link BasicVerifier} for the latest ASM API version. <i>Subclasses must not
+ * use this constructor</i>. Instead, they must use the {@link #BasicVerifier(int)} version.
+ */
+ public BasicVerifier() {
+ super(ASM7);
+ if (getClass() != BasicVerifier.class) {
+ throw new IllegalStateException();
}
+ }
- protected BasicVerifier(final int api) {
- super(api);
- }
+ /**
+ * Constructs a new {@link BasicVerifier}.
+ *
+ * @param api the ASM API version supported by this interpreter. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+ */
+ protected BasicVerifier(final int api) {
+ super(api);
+ }
- @Override
- public BasicValue copyOperation(final AbstractInsnNode insn,
- final BasicValue value) throws AnalyzerException {
- Value expected;
- switch (insn.getOpcode()) {
- case ILOAD:
- case ISTORE:
- expected = BasicValue.INT_VALUE;
- break;
- case FLOAD:
- case FSTORE:
- expected = BasicValue.FLOAT_VALUE;
- break;
- case LLOAD:
- case LSTORE:
- expected = BasicValue.LONG_VALUE;
- break;
- case DLOAD:
- case DSTORE:
- expected = BasicValue.DOUBLE_VALUE;
- break;
- case ALOAD:
- if (!value.isReference()) {
- throw new AnalyzerException(insn, null, "an object reference",
- value);
- }
- return value;
- case ASTORE:
- if (!value.isReference()
- && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
- throw new AnalyzerException(insn, null,
- "an object reference or a return address", value);
- }
- return value;
- default:
- return value;
+ @Override
+ public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value)
+ throws AnalyzerException {
+ Value expected;
+ switch (insn.getOpcode()) {
+ case ILOAD:
+ case ISTORE:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FLOAD:
+ case FSTORE:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LLOAD:
+ case LSTORE:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DLOAD:
+ case DSTORE:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case ALOAD:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn, null, "an object reference", value);
}
- if (!expected.equals(value)) {
- throw new AnalyzerException(insn, null, expected, value);
+ return value;
+ case ASTORE:
+ if (!value.isReference() && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
+ throw new AnalyzerException(insn, null, "an object reference or a return address", value);
}
return value;
+ default:
+ return value;
+ }
+ if (!expected.equals(value)) {
+ throw new AnalyzerException(insn, null, expected, value);
}
+ return value;
+ }
- @Override
- public BasicValue unaryOperation(final AbstractInsnNode insn,
- final BasicValue value) throws AnalyzerException {
- BasicValue expected;
- switch (insn.getOpcode()) {
- case INEG:
- case IINC:
- case I2F:
- case I2L:
- case I2D:
- case I2B:
- case I2C:
- case I2S:
- case IFEQ:
- case IFNE:
- case IFLT:
- case IFGE:
- case IFGT:
- case IFLE:
- case TABLESWITCH:
- case LOOKUPSWITCH:
- case IRETURN:
- case NEWARRAY:
- case ANEWARRAY:
- expected = BasicValue.INT_VALUE;
- break;
- case FNEG:
- case F2I:
- case F2L:
- case F2D:
- case FRETURN:
- expected = BasicValue.FLOAT_VALUE;
- break;
- case LNEG:
- case L2I:
- case L2F:
- case L2D:
- case LRETURN:
- expected = BasicValue.LONG_VALUE;
- break;
- case DNEG:
- case D2I:
- case D2F:
- case D2L:
- case DRETURN:
- expected = BasicValue.DOUBLE_VALUE;
- break;
- case GETFIELD:
- expected = newValue(Type
- .getObjectType(((FieldInsnNode) insn).owner));
- break;
- case CHECKCAST:
- if (!value.isReference()) {
- throw new AnalyzerException(insn, null, "an object reference",
- value);
- }
- return super.unaryOperation(insn, value);
- case ARRAYLENGTH:
- if (!isArrayValue(value)) {
- throw new AnalyzerException(insn, null, "an array reference",
- value);
- }
- return super.unaryOperation(insn, value);
- case ARETURN:
- case ATHROW:
- case INSTANCEOF:
- case MONITORENTER:
- case MONITOREXIT:
- case IFNULL:
- case IFNONNULL:
- if (!value.isReference()) {
- throw new AnalyzerException(insn, null, "an object reference",
- value);
- }
- return super.unaryOperation(insn, value);
- case PUTSTATIC:
- expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
- break;
- default:
- throw new Error("Internal error.");
+ @Override
+ public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value)
+ throws AnalyzerException {
+ BasicValue expected;
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case I2F:
+ case I2L:
+ case I2D:
+ case I2B:
+ case I2C:
+ case I2S:
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case NEWARRAY:
+ case ANEWARRAY:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FNEG:
+ case F2I:
+ case F2L:
+ case F2D:
+ case FRETURN:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LNEG:
+ case L2I:
+ case L2F:
+ case L2D:
+ case LRETURN:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DNEG:
+ case D2I:
+ case D2F:
+ case D2L:
+ case DRETURN:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case GETFIELD:
+ expected = newValue(Type.getObjectType(((FieldInsnNode) insn).owner));
+ break;
+ case ARRAYLENGTH:
+ if (!isArrayValue(value)) {
+ throw new AnalyzerException(insn, null, "an array reference", value);
}
- if (!isSubTypeOf(value, expected)) {
- throw new AnalyzerException(insn, null, expected, value);
+ return super.unaryOperation(insn, value);
+ case CHECKCAST:
+ case ARETURN:
+ case ATHROW:
+ case INSTANCEOF:
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn, null, "an object reference", value);
}
return super.unaryOperation(insn, value);
+ case PUTSTATIC:
+ expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+ break;
+ default:
+ throw new AssertionError();
+ }
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(insn, null, expected, value);
}
+ return super.unaryOperation(insn, value);
+ }
- @Override
- public BasicValue binaryOperation(final AbstractInsnNode insn,
- final BasicValue value1, final BasicValue value2)
- throws AnalyzerException {
- BasicValue expected1;
- BasicValue expected2;
- switch (insn.getOpcode()) {
- case IALOAD:
- expected1 = newValue(Type.getType("[I"));
- expected2 = BasicValue.INT_VALUE;
- break;
- case BALOAD:
- if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
- expected1 = newValue(Type.getType("[Z"));
- } else {
- expected1 = newValue(Type.getType("[B"));
- }
- expected2 = BasicValue.INT_VALUE;
- break;
- case CALOAD:
- expected1 = newValue(Type.getType("[C"));
- expected2 = BasicValue.INT_VALUE;
- break;
- case SALOAD:
- expected1 = newValue(Type.getType("[S"));
- expected2 = BasicValue.INT_VALUE;
- break;
- case LALOAD:
- expected1 = newValue(Type.getType("[J"));
- expected2 = BasicValue.INT_VALUE;
- break;
- case FALOAD:
- expected1 = newValue(Type.getType("[F"));
- expected2 = BasicValue.INT_VALUE;
- break;
- case DALOAD:
- expected1 = newValue(Type.getType("[D"));
- expected2 = BasicValue.INT_VALUE;
- break;
- case AALOAD:
- expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
- expected2 = BasicValue.INT_VALUE;
- break;
- case IADD:
- case ISUB:
- case IMUL:
- case IDIV:
- case IREM:
- case ISHL:
- case ISHR:
- case IUSHR:
- case IAND:
- case IOR:
- case IXOR:
- case IF_ICMPEQ:
- case IF_ICMPNE:
- case IF_ICMPLT:
- case IF_ICMPGE:
- case IF_ICMPGT:
- case IF_ICMPLE:
- expected1 = BasicValue.INT_VALUE;
- expected2 = BasicValue.INT_VALUE;
- break;
- case FADD:
- case FSUB:
- case FMUL:
- case FDIV:
- case FREM:
- case FCMPL:
- case FCMPG:
- expected1 = BasicValue.FLOAT_VALUE;
- expected2 = BasicValue.FLOAT_VALUE;
- break;
- case LADD:
- case LSUB:
- case LMUL:
- case LDIV:
- case LREM:
- case LAND:
- case LOR:
- case LXOR:
- case LCMP:
- expected1 = BasicValue.LONG_VALUE;
- expected2 = BasicValue.LONG_VALUE;
- break;
- case LSHL:
- case LSHR:
- case LUSHR:
- expected1 = BasicValue.LONG_VALUE;
- expected2 = BasicValue.INT_VALUE;
- break;
- case DADD:
- case DSUB:
- case DMUL:
- case DDIV:
- case DREM:
- case DCMPL:
- case DCMPG:
- expected1 = BasicValue.DOUBLE_VALUE;
- expected2 = BasicValue.DOUBLE_VALUE;
- break;
- case IF_ACMPEQ:
- case IF_ACMPNE:
- expected1 = BasicValue.REFERENCE_VALUE;
- expected2 = BasicValue.REFERENCE_VALUE;
- break;
- case PUTFIELD:
- FieldInsnNode fin = (FieldInsnNode) insn;
- expected1 = newValue(Type.getObjectType(fin.owner));
- expected2 = newValue(Type.getType(fin.desc));
- break;
- default:
- throw new Error("Internal error.");
- }
- if (!isSubTypeOf(value1, expected1)) {
- throw new AnalyzerException(insn, "First argument", expected1,
- value1);
- } else if (!isSubTypeOf(value2, expected2)) {
- throw new AnalyzerException(insn, "Second argument", expected2,
- value2);
- }
- if (insn.getOpcode() == AALOAD) {
- return getElementValue(value1);
+ @Override
+ public BasicValue binaryOperation(
+ final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2)
+ throws AnalyzerException {
+ BasicValue expected1;
+ BasicValue expected2;
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ expected1 = newValue(Type.getType("[I"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case BALOAD:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
} else {
- return super.binaryOperation(insn, value1, value2);
+ expected1 = newValue(Type.getType("[B"));
}
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case CALOAD:
+ expected1 = newValue(Type.getType("[C"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case SALOAD:
+ expected1 = newValue(Type.getType("[S"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case LALOAD:
+ expected1 = newValue(Type.getType("[J"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FALOAD:
+ expected1 = newValue(Type.getType("[F"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DALOAD:
+ expected1 = newValue(Type.getType("[D"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case AALOAD:
+ expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ expected1 = BasicValue.INT_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL:
+ case FCMPG:
+ expected1 = BasicValue.FLOAT_VALUE;
+ expected2 = BasicValue.FLOAT_VALUE;
+ break;
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case LCMP:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.LONG_VALUE;
+ break;
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ case DCMPL:
+ case DCMPG:
+ expected1 = BasicValue.DOUBLE_VALUE;
+ expected2 = BasicValue.DOUBLE_VALUE;
+ break;
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ expected1 = BasicValue.REFERENCE_VALUE;
+ expected2 = BasicValue.REFERENCE_VALUE;
+ break;
+ case PUTFIELD:
+ FieldInsnNode fieldInsn = (FieldInsnNode) insn;
+ expected1 = newValue(Type.getObjectType(fieldInsn.owner));
+ expected2 = newValue(Type.getType(fieldInsn.desc));
+ break;
+ default:
+ throw new AssertionError();
}
-
- @Override
- public BasicValue ternaryOperation(final AbstractInsnNode insn,
- final BasicValue value1, final BasicValue value2,
- final BasicValue value3) throws AnalyzerException {
- BasicValue expected1;
- BasicValue expected3;
- switch (insn.getOpcode()) {
- case IASTORE:
- expected1 = newValue(Type.getType("[I"));
- expected3 = BasicValue.INT_VALUE;
- break;
- case BASTORE:
- if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
- expected1 = newValue(Type.getType("[Z"));
- } else {
- expected1 = newValue(Type.getType("[B"));
- }
- expected3 = BasicValue.INT_VALUE;
- break;
- case CASTORE:
- expected1 = newValue(Type.getType("[C"));
- expected3 = BasicValue.INT_VALUE;
- break;
- case SASTORE:
- expected1 = newValue(Type.getType("[S"));
- expected3 = BasicValue.INT_VALUE;
- break;
- case LASTORE:
- expected1 = newValue(Type.getType("[J"));
- expected3 = BasicValue.LONG_VALUE;
- break;
- case FASTORE:
- expected1 = newValue(Type.getType("[F"));
- expected3 = BasicValue.FLOAT_VALUE;
- break;
- case DASTORE:
- expected1 = newValue(Type.getType("[D"));
- expected3 = BasicValue.DOUBLE_VALUE;
- break;
- case AASTORE:
- expected1 = value1;
- expected3 = BasicValue.REFERENCE_VALUE;
- break;
- default:
- throw new Error("Internal error.");
- }
- if (!isSubTypeOf(value1, expected1)) {
- throw new AnalyzerException(insn, "First argument", "a "
- + expected1 + " array reference", value1);
- } else if (!BasicValue.INT_VALUE.equals(value2)) {
- throw new AnalyzerException(insn, "Second argument",
- BasicValue.INT_VALUE, value2);
- } else if (!isSubTypeOf(value3, expected3)) {
- throw new AnalyzerException(insn, "Third argument", expected3,
- value3);
- }
- return null;
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException(insn, "First argument", expected1, value1);
+ } else if (!isSubTypeOf(value2, expected2)) {
+ throw new AnalyzerException(insn, "Second argument", expected2, value2);
+ }
+ if (insn.getOpcode() == AALOAD) {
+ return getElementValue(value1);
+ } else {
+ return super.binaryOperation(insn, value1, value2);
}
+ }
- @Override
- public BasicValue naryOperation(final AbstractInsnNode insn,
- final List<? extends BasicValue> values) throws AnalyzerException {
- int opcode = insn.getOpcode();
- if (opcode == MULTIANEWARRAY) {
- for (int i = 0; i < values.size(); ++i) {
- if (!BasicValue.INT_VALUE.equals(values.get(i))) {
- throw new AnalyzerException(insn, null,
- BasicValue.INT_VALUE, values.get(i));
- }
- }
+ @Override
+ public BasicValue ternaryOperation(
+ final AbstractInsnNode insn,
+ final BasicValue value1,
+ final BasicValue value2,
+ final BasicValue value3)
+ throws AnalyzerException {
+ BasicValue expected1;
+ BasicValue expected3;
+ switch (insn.getOpcode()) {
+ case IASTORE:
+ expected1 = newValue(Type.getType("[I"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case BASTORE:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
} else {
- int i = 0;
- int j = 0;
- if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
- Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
- if (!isSubTypeOf(values.get(i++), newValue(owner))) {
- throw new AnalyzerException(insn, "Method owner",
- newValue(owner), values.get(0));
- }
- }
- String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
- : ((MethodInsnNode) insn).desc;
- Type[] args = Type.getArgumentTypes(desc);
- while (i < values.size()) {
- BasicValue expected = newValue(args[j++]);
- BasicValue encountered = values.get(i++);
- if (!isSubTypeOf(encountered, expected)) {
- throw new AnalyzerException(insn, "Argument " + j,
- expected, encountered);
- }
- }
+ expected1 = newValue(Type.getType("[B"));
}
- return super.naryOperation(insn, values);
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case CASTORE:
+ expected1 = newValue(Type.getType("[C"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case SASTORE:
+ expected1 = newValue(Type.getType("[S"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case LASTORE:
+ expected1 = newValue(Type.getType("[J"));
+ expected3 = BasicValue.LONG_VALUE;
+ break;
+ case FASTORE:
+ expected1 = newValue(Type.getType("[F"));
+ expected3 = BasicValue.FLOAT_VALUE;
+ break;
+ case DASTORE:
+ expected1 = newValue(Type.getType("[D"));
+ expected3 = BasicValue.DOUBLE_VALUE;
+ break;
+ case AASTORE:
+ expected1 = value1;
+ expected3 = BasicValue.REFERENCE_VALUE;
+ break;
+ default:
+ throw new AssertionError();
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException(
+ insn, "First argument", "a " + expected1 + " array reference", value1);
+ } else if (!BasicValue.INT_VALUE.equals(value2)) {
+ throw new AnalyzerException(insn, "Second argument", BasicValue.INT_VALUE, value2);
+ } else if (!isSubTypeOf(value3, expected3)) {
+ throw new AnalyzerException(insn, "Third argument", expected3, value3);
}
+ return null;
+ }
- @Override
- public void returnOperation(final AbstractInsnNode insn,
- final BasicValue value, final BasicValue expected)
- throws AnalyzerException {
- if (!isSubTypeOf(value, expected)) {
- throw new AnalyzerException(insn, "Incompatible return type",
- expected, value);
+ @Override
+ public BasicValue naryOperation(
+ final AbstractInsnNode insn, final List<? extends BasicValue> values)
+ throws AnalyzerException {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ for (BasicValue value : values) {
+ if (!BasicValue.INT_VALUE.equals(value)) {
+ throw new AnalyzerException(insn, null, BasicValue.INT_VALUE, value);
}
+ }
+ } else {
+ int i = 0;
+ int j = 0;
+ if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
+ Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
+ if (!isSubTypeOf(values.get(i++), newValue(owner))) {
+ throw new AnalyzerException(insn, "Method owner", newValue(owner), values.get(0));
+ }
+ }
+ String methodDescriptor =
+ (opcode == INVOKEDYNAMIC)
+ ? ((InvokeDynamicInsnNode) insn).desc
+ : ((MethodInsnNode) insn).desc;
+ Type[] args = Type.getArgumentTypes(methodDescriptor);
+ while (i < values.size()) {
+ BasicValue expected = newValue(args[j++]);
+ BasicValue actual = values.get(i++);
+ if (!isSubTypeOf(actual, expected)) {
+ throw new AnalyzerException(insn, "Argument " + j, expected, actual);
+ }
+ }
}
+ return super.naryOperation(insn, values);
+ }
- protected boolean isArrayValue(final BasicValue value) {
- return value.isReference();
+ @Override
+ public void returnOperation(
+ final AbstractInsnNode insn, final BasicValue value, final BasicValue expected)
+ throws AnalyzerException {
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(insn, "Incompatible return type", expected, value);
}
+ }
- protected BasicValue getElementValue(final BasicValue objectArrayValue)
- throws AnalyzerException {
- return BasicValue.REFERENCE_VALUE;
- }
+ /**
+ * Returns whether the given value corresponds to an array reference.
+ *
+ * @param value a value.
+ * @return whether 'value' corresponds to an array reference.
+ */
+ protected boolean isArrayValue(final BasicValue value) {
+ return value.isReference();
+ }
- protected boolean isSubTypeOf(final BasicValue value,
- final BasicValue expected) {
- return value.equals(expected);
- }
+ /**
+ * Returns the value corresponding to the type of the elements of the given array reference value.
+ *
+ * @param objectArrayValue a value corresponding to array of object (or array) references.
+ * @return the value corresponding to the type of the elements of 'objectArrayValue'.
+ * @throws AnalyzerException if objectArrayValue does not correspond to an array type.
+ */
+ protected BasicValue getElementValue(final BasicValue objectArrayValue) throws AnalyzerException {
+ return BasicValue.REFERENCE_VALUE;
+ }
+
+ /**
+ * Returns whether the type corresponding to the first argument is a subtype of the type
+ * corresponding to the second argument.
+ *
+ * @param value a value.
+ * @param expected another value.
+ * @return whether the type corresponding to 'value' is a subtype of the type corresponding to
+ * 'expected'.
+ */
+ protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
+ return value.equals(expected);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
old mode 100644
new mode 100755
index 9c74a62..09549cd
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
@@ -1,739 +1,730 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.ArrayList;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.IincInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
/**
- * A symbolic execution stack frame. A stack frame contains a set of local
- * variable slots, and an operand stack. Warning: long and double values are
- * represented by <i>two</i> slots in local variables, and by <i>one</i> slot in
- * the operand stack.
- *
- * @param <V>
- * type of the Value used for the analysis.
- *
+ * A symbolic execution stack frame. A stack frame contains a set of local variable slots, and an
+ * operand stack. Warning: long and double values are represented with <i>two</i> slots in local
+ * variables, and with <i>one</i> slot in the operand stack.
+ *
+ * @param <V> type of the Value used for the analysis.
* @author Eric Bruneton
*/
public class Frame<V extends Value> {
- /**
- * The expected return type of the analyzed method, or <tt>null</tt> if the
- * method returns void.
- */
- private V returnValue;
+ /**
+ * The expected return type of the analyzed method, or {@literal null} if the method returns void.
+ */
+ private V returnValue;
- /**
- * The local variables and operand stack of this frame.
- */
- private V[] values;
+ /**
+ * The local variables and the operand stack of this frame. The first {@link #numLocals} elements
+ * correspond to the local variables. The following {@link #numStack} elements correspond to the
+ * operand stack.
+ */
+ private V[] values;
- /**
- * The number of local variables of this frame.
- */
- private int locals;
+ /** The number of local variables of this frame. */
+ private int numLocals;
- /**
- * The number of elements in the operand stack.
- */
- private int top;
+ /** The number of elements in the operand stack. */
+ private int numStack;
- /**
- * Constructs a new frame with the given size.
- *
- * @param nLocals
- * the maximum number of local variables of the frame.
- * @param nStack
- * the maximum stack size of the frame.
- */
- @SuppressWarnings("unchecked")
- public Frame(final int nLocals, final int nStack) {
- this.values = (V[]) new Value[nLocals + nStack];
- this.locals = nLocals;
- }
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param numLocals the maximum number of local variables of the frame.
+ * @param numStack the maximum stack size of the frame.
+ */
+ @SuppressWarnings("unchecked")
+ public Frame(final int numLocals, final int numStack) {
+ this.values = (V[]) new Value[numLocals + numStack];
+ this.numLocals = numLocals;
+ }
- /**
- * Constructs a new frame that is identical to the given frame.
- *
- * @param src
- * a frame.
- */
- public Frame(final Frame<? extends V> src) {
- this(src.locals, src.values.length - src.locals);
- init(src);
- }
+ /**
+ * Constructs a copy of the given Frame.
+ *
+ * @param frame a frame.
+ */
+ public Frame(final Frame<? extends V> frame) {
+ this(frame.numLocals, frame.values.length - frame.numLocals);
+ init(frame); // NOPMD(ConstructorCallsOverridableMethod): can't fix for backward compatibility.
+ }
- /**
- * Copies the state of the given frame into this frame.
- *
- * @param src
- * a frame.
- * @return this frame.
- */
- public Frame<V> init(final Frame<? extends V> src) {
- returnValue = src.returnValue;
- System.arraycopy(src.values, 0, values, 0, values.length);
- top = src.top;
- return this;
- }
+ /**
+ * Copies the state of the given frame into this frame.
+ *
+ * @param frame a frame.
+ * @return this frame.
+ */
+ public Frame<V> init(final Frame<? extends V> frame) {
+ returnValue = frame.returnValue;
+ System.arraycopy(frame.values, 0, values, 0, values.length);
+ numStack = frame.numStack;
+ return this;
+ }
- /**
- * Sets the expected return type of the analyzed method.
- *
- * @param v
- * the expected return type of the analyzed method, or
- * <tt>null</tt> if the method returns void.
- */
- public void setReturn(final V v) {
- returnValue = v;
- }
+ /**
+ * Initializes a frame corresponding to the target or to the successor of a jump instruction. This
+ * method is called by {@link Analyzer#analyze(String, org.apache.tapestry5.internal.plastic.asm.tree.MethodNode)} while
+ * interpreting jump instructions. It is called once for each possible target of the jump
+ * instruction, and once for its successor instruction (except for GOTO and JSR), before the frame
+ * is merged with the existing frame at this location. The default implementation of this method
+ * does nothing.
+ *
+ * <p>Overriding this method and changing the frame values allows implementing branch-sensitive
+ * analyses.
+ *
+ * @param opcode the opcode of the jump instruction. Can be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
+ * IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE,
+ * GOTO, JSR, IFNULL, IFNONNULL, TABLESWITCH or LOOKUPSWITCH.
+ * @param target a target of the jump instruction this frame corresponds to, or {@literal null} if
+ * this frame corresponds to the successor of the jump instruction (i.e. the next instruction
+ * in the instructions sequence).
+ */
+ public void initJumpTarget(final int opcode, final LabelNode target) {}
- /**
- * Returns the maximum number of local variables of this frame.
- *
- * @return the maximum number of local variables of this frame.
- */
- public int getLocals() {
- return locals;
- }
+ /**
+ * Sets the expected return type of the analyzed method.
+ *
+ * @param v the expected return type of the analyzed method, or {@literal null} if the method
+ * returns void.
+ */
+ public void setReturn(final V v) {
+ returnValue = v;
+ }
- /**
- * Returns the maximum stack size of this frame.
- *
- * @return the maximum stack size of this frame.
- */
- public int getMaxStackSize() {
- return values.length - locals;
- }
-
- /**
- * Returns the value of the given local variable.
- *
- * @param i
- * a local variable index.
- * @return the value of the given local variable.
- * @throws IndexOutOfBoundsException
- * if the variable does not exist.
- */
- public V getLocal(final int i) throws IndexOutOfBoundsException {
- if (i >= locals) {
- throw new IndexOutOfBoundsException(
- "Trying to access an inexistant local variable");
- }
- return values[i];
- }
+ /**
+ * Returns the maximum number of local variables of this frame.
+ *
+ * @return the maximum number of local variables of this frame.
+ */
+ public int getLocals() {
+ return numLocals;
+ }
- /**
- * Sets the value of the given local variable.
- *
- * @param i
- * a local variable index.
- * @param value
- * the new value of this local variable.
- * @throws IndexOutOfBoundsException
- * if the variable does not exist.
- */
- public void setLocal(final int i, final V value)
- throws IndexOutOfBoundsException {
- if (i >= locals) {
- throw new IndexOutOfBoundsException(
- "Trying to access an inexistant local variable " + i);
- }
- values[i] = value;
- }
+ /**
+ * Returns the maximum stack size of this frame.
+ *
+ * @return the maximum stack size of this frame.
+ */
+ public int getMaxStackSize() {
+ return values.length - numLocals;
+ }
- /**
- * Returns the number of values in the operand stack of this frame. Long and
- * double values are treated as single values.
- *
- * @return the number of values in the operand stack of this frame.
- */
- public int getStackSize() {
- return top;
+ /**
+ * Returns the value of the given local variable.
+ *
+ * @param index a local variable index.
+ * @return the value of the given local variable.
+ * @throws IndexOutOfBoundsException if the variable does not exist.
+ */
+ public V getLocal(final int index) {
+ if (index >= numLocals) {
+ throw new IndexOutOfBoundsException("Trying to access an inexistant local variable");
}
+ return values[index];
+ }
- /**
- * Returns the value of the given operand stack slot.
- *
- * @param i
- * the index of an operand stack slot.
- * @return the value of the given operand stack slot.
- * @throws IndexOutOfBoundsException
- * if the operand stack slot does not exist.
- */
- public V getStack(final int i) throws IndexOutOfBoundsException {
- return values[i + locals];
+ /**
+ * Sets the value of the given local variable.
+ *
+ * @param index a local variable index.
+ * @param value the new value of this local variable.
+ * @throws IndexOutOfBoundsException if the variable does not exist.
+ */
+ public void setLocal(final int index, final V value) {
+ if (index >= numLocals) {
+ throw new IndexOutOfBoundsException("Trying to access an inexistant local variable " + index);
}
+ values[index] = value;
+ }
- /**
- * Clears the operand stack of this frame.
- */
- public void clearStack() {
- top = 0;
- }
+ /**
+ * Returns the number of values in the operand stack of this frame. Long and double values are
+ * treated as single values.
+ *
+ * @return the number of values in the operand stack of this frame.
+ */
+ public int getStackSize() {
+ return numStack;
+ }
- /**
- * Pops a value from the operand stack of this frame.
- *
- * @return the value that has been popped from the stack.
- * @throws IndexOutOfBoundsException
- * if the operand stack is empty.
- */
- public V pop() throws IndexOutOfBoundsException {
- if (top == 0) {
- throw new IndexOutOfBoundsException(
- "Cannot pop operand off an empty stack.");
- }
- return values[--top + locals];
+ /**
+ * Returns the value of the given operand stack slot.
+ *
+ * @param index the index of an operand stack slot.
+ * @return the value of the given operand stack slot.
+ * @throws IndexOutOfBoundsException if the operand stack slot does not exist.
+ */
+ public V getStack(final int index) {
+ return values[numLocals + index];
+ }
+
+ /**
+ * Sets the value of the given stack slot.
+ *
+ * @param index the index of an operand stack slot.
+ * @param value the new value of the stack slot.
+ * @throws IndexOutOfBoundsException if the stack slot does not exist.
+ */
+ public void setStack(final int index, final V value) throws IndexOutOfBoundsException {
+ values[numLocals + index] = value;
+ }
+
+ /** Clears the operand stack of this frame. */
+ public void clearStack() {
+ numStack = 0;
+ }
+
+ /**
+ * Pops a value from the operand stack of this frame.
+ *
+ * @return the value that has been popped from the stack.
+ * @throws IndexOutOfBoundsException if the operand stack is empty.
+ */
+ public V pop() {
+ if (numStack == 0) {
+ throw new IndexOutOfBoundsException("Cannot pop operand off an empty stack.");
}
+ return values[numLocals + (--numStack)];
+ }
- /**
- * Pushes a value into the operand stack of this frame.
- *
- * @param value
- * the value that must be pushed into the stack.
- * @throws IndexOutOfBoundsException
- * if the operand stack is full.
- */
- public void push(final V value) throws IndexOutOfBoundsException {
- if (top + locals >= values.length) {
- throw new IndexOutOfBoundsException(
- "Insufficient maximum stack size.");
- }
- values[top++ + locals] = value;
+ /**
+ * Pushes a value into the operand stack of this frame.
+ *
+ * @param value the value that must be pushed into the stack.
+ * @throws IndexOutOfBoundsException if the operand stack is full.
+ */
+ public void push(final V value) {
+ if (numLocals + numStack >= values.length) {
+ throw new IndexOutOfBoundsException("Insufficient maximum stack size.");
}
+ values[numLocals + (numStack++)] = value;
+ }
- public void execute(final AbstractInsnNode insn,
- final Interpreter<V> interpreter) throws AnalyzerException {
- V value1, value2, value3, value4;
- List<V> values;
- int var;
+ /**
+ * Simulates the execution of the given instruction on this execution stack frame.
+ *
+ * @param insn the instruction to execute.
+ * @param interpreter the interpreter to use to compute values from other values.
+ * @throws AnalyzerException if the instruction cannot be executed on this execution frame (e.g. a
+ * POP on an empty operand stack).
+ */
+ public void execute(final AbstractInsnNode insn, final Interpreter<V> interpreter)
+ throws AnalyzerException {
+ V value1;
+ V value2;
+ V value3;
+ V value4;
+ int var;
- switch (insn.getOpcode()) {
- case Opcodes.NOP:
- break;
- case Opcodes.ACONST_NULL:
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- case Opcodes.BIPUSH:
- case Opcodes.SIPUSH:
- case Opcodes.LDC:
- push(interpreter.newOperation(insn));
- break;
- case Opcodes.ILOAD:
- case Opcodes.LLOAD:
- case Opcodes.FLOAD:
- case Opcodes.DLOAD:
- case Opcodes.ALOAD:
- push(interpreter.copyOperation(insn,
- getLocal(((VarInsnNode) insn).var)));
- break;
- case Opcodes.IALOAD:
- case Opcodes.LALOAD:
- case Opcodes.FALOAD:
- case Opcodes.DALOAD:
- case Opcodes.AALOAD:
- case Opcodes.BALOAD:
- case Opcodes.CALOAD:
- case Opcodes.SALOAD:
- value2 = pop();
- value1 = pop();
- push(interpreter.binaryOperation(insn, value1, value2));
- break;
- case Opcodes.ISTORE:
- case Opcodes.LSTORE:
- case Opcodes.FSTORE:
- case Opcodes.DSTORE:
- case Opcodes.ASTORE:
- value1 = interpreter.copyOperation(insn, pop());
- var = ((VarInsnNode) insn).var;
- setLocal(var, value1);
- if (value1.getSize() == 2) {
- setLocal(var + 1, interpreter.newValue(null));
- }
- if (var > 0) {
- Value local = getLocal(var - 1);
- if (local != null && local.getSize() == 2) {
- setLocal(var - 1, interpreter.newValue(null));
- }
- }
- break;
- case Opcodes.IASTORE:
- case Opcodes.LASTORE:
- case Opcodes.FASTORE:
- case Opcodes.DASTORE:
- case Opcodes.AASTORE:
- case Opcodes.BASTORE:
- case Opcodes.CASTORE:
- case Opcodes.SASTORE:
+ switch (insn.getOpcode()) {
+ case Opcodes.NOP:
+ break;
+ case Opcodes.ACONST_NULL:
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.LDC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.LLOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.DLOAD:
+ case Opcodes.ALOAD:
+ push(interpreter.copyOperation(insn, getLocal(((VarInsnNode) insn).var)));
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.LSTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.DSTORE:
+ case Opcodes.ASTORE:
+ value1 = interpreter.copyOperation(insn, pop());
+ var = ((VarInsnNode) insn).var;
+ setLocal(var, value1);
+ if (value1.getSize() == 2) {
+ setLocal(var + 1, interpreter.newEmptyValue(var + 1));
+ }
+ if (var > 0) {
+ Value local = getLocal(var - 1);
+ if (local != null && local.getSize() == 2) {
+ setLocal(var - 1, interpreter.newEmptyValue(var - 1));
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.LASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.DASTORE:
+ case Opcodes.AASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ value3 = pop();
+ value2 = pop();
+ value1 = pop();
+ interpreter.ternaryOperation(insn, value1, value2, value3);
+ break;
+ case Opcodes.POP:
+ if (pop().getSize() == 2) {
+ throw new AnalyzerException(insn, "Illegal use of POP");
+ }
+ break;
+ case Opcodes.POP2:
+ if (pop().getSize() == 1 && pop().getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of POP2");
+ }
+ break;
+ case Opcodes.DUP:
+ value1 = pop();
+ if (value1.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of DUP");
+ }
+ push(value1);
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.DUP_X1:
+ value1 = pop();
+ value2 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of DUP_X1");
+ }
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
value3 = pop();
- value2 = pop();
- value1 = pop();
- interpreter.ternaryOperation(insn, value1, value2, value3);
- break;
- case Opcodes.POP:
- if (pop().getSize() == 2) {
- throw new AnalyzerException(insn, "Illegal use of POP");
- }
- break;
- case Opcodes.POP2:
- if (pop().getSize() == 1) {
- if (pop().getSize() != 1) {
- throw new AnalyzerException(insn, "Illegal use of POP2");
- }
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
}
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
break;
- case Opcodes.DUP:
- value1 = pop();
- if (value1.getSize() != 1) {
- throw new AnalyzerException(insn, "Illegal use of DUP");
- }
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP_X2");
+ case Opcodes.DUP2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(value2);
push(value1);
+ push(interpreter.copyOperation(insn, value2));
push(interpreter.copyOperation(insn, value1));
break;
- case Opcodes.DUP_X1:
- value1 = pop();
- value2 = pop();
- if (value1.getSize() != 1 || value2.getSize() != 1) {
- throw new AnalyzerException(insn, "Illegal use of DUP_X1");
+ }
+ } else {
+ push(value1);
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2");
+ case Opcodes.DUP2_X1:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
}
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
push(interpreter.copyOperation(insn, value1));
push(value2);
push(value1);
break;
- case Opcodes.DUP_X2:
- value1 = pop();
- if (value1.getSize() == 1) {
- value2 = pop();
- if (value2.getSize() == 1) {
- value3 = pop();
- if (value3.getSize() == 1) {
- push(interpreter.copyOperation(insn, value1));
- push(value3);
- push(value2);
- push(value1);
- break;
- }
- } else {
- push(interpreter.copyOperation(insn, value1));
- push(value2);
- push(value1);
- break;
- }
- }
- throw new AnalyzerException(insn, "Illegal use of DUP_X2");
- case Opcodes.DUP2:
- value1 = pop();
- if (value1.getSize() == 1) {
- value2 = pop();
- if (value2.getSize() == 1) {
- push(value2);
- push(value1);
- push(interpreter.copyOperation(insn, value2));
- push(interpreter.copyOperation(insn, value1));
- break;
- }
- } else {
- push(value1);
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2_X1");
+ case Opcodes.DUP2_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ value4 = pop();
+ if (value4.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
push(interpreter.copyOperation(insn, value1));
+ push(value4);
+ push(value3);
+ push(value2);
+ push(value1);
break;
- }
- throw new AnalyzerException(insn, "Illegal use of DUP2");
- case Opcodes.DUP2_X1:
- value1 = pop();
- if (value1.getSize() == 1) {
- value2 = pop();
- if (value2.getSize() == 1) {
- value3 = pop();
- if (value3.getSize() == 1) {
- push(interpreter.copyOperation(insn, value2));
- push(interpreter.copyOperation(insn, value1));
- push(value3);
- push(value2);
- push(value1);
- break;
- }
- }
+ }
} else {
- value2 = pop();
- if (value2.getSize() == 1) {
- push(interpreter.copyOperation(insn, value1));
- push(value2);
- push(value1);
- break;
- }
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
}
- throw new AnalyzerException(insn, "Illegal use of DUP2_X1");
- case Opcodes.DUP2_X2:
- value1 = pop();
- if (value1.getSize() == 1) {
- value2 = pop();
- if (value2.getSize() == 1) {
- value3 = pop();
- if (value3.getSize() == 1) {
- value4 = pop();
- if (value4.getSize() == 1) {
- push(interpreter.copyOperation(insn, value2));
- push(interpreter.copyOperation(insn, value1));
- push(value4);
- push(value3);
- push(value2);
- push(value1);
- break;
- }
- } else {
- push(interpreter.copyOperation(insn, value2));
- push(interpreter.copyOperation(insn, value1));
- push(value3);
- push(value2);
- push(value1);
- break;
- }
- }
- } else {
- value2 = pop();
- if (value2.getSize() == 1) {
- value3 = pop();
- if (value3.getSize() == 1) {
- push(interpreter.copyOperation(insn, value1));
- push(value3);
- push(value2);
- push(value1);
- break;
- }
- } else {
- push(interpreter.copyOperation(insn, value1));
- push(value2);
- push(value1);
- break;
- }
- }
- throw new AnalyzerException(insn, "Illegal use of DUP2_X2");
- case Opcodes.SWAP:
- value2 = pop();
- value1 = pop();
- if (value1.getSize() != 1 || value2.getSize() != 1) {
- throw new AnalyzerException(insn, "Illegal use of SWAP");
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
}
- push(interpreter.copyOperation(insn, value2));
+ } else {
push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
break;
- case Opcodes.IADD:
- case Opcodes.LADD:
- case Opcodes.FADD:
- case Opcodes.DADD:
- case Opcodes.ISUB:
- case Opcodes.LSUB:
- case Opcodes.FSUB:
- case Opcodes.DSUB:
- case Opcodes.IMUL:
- case Opcodes.LMUL:
- case Opcodes.FMUL:
- case Opcodes.DMUL:
- case Opcodes.IDIV:
- case Opcodes.LDIV:
- case Opcodes.FDIV:
- case Opcodes.DDIV:
- case Opcodes.IREM:
- case Opcodes.LREM:
- case Opcodes.FREM:
- case Opcodes.DREM:
- value2 = pop();
- value1 = pop();
- push(interpreter.binaryOperation(insn, value1, value2));
- break;
- case Opcodes.INEG:
- case Opcodes.LNEG:
- case Opcodes.FNEG:
- case Opcodes.DNEG:
- push(interpreter.unaryOperation(insn, pop()));
- break;
- case Opcodes.ISHL:
- case Opcodes.LSHL:
- case Opcodes.ISHR:
- case Opcodes.LSHR:
- case Opcodes.IUSHR:
- case Opcodes.LUSHR:
- case Opcodes.IAND:
- case Opcodes.LAND:
- case Opcodes.IOR:
- case Opcodes.LOR:
- case Opcodes.IXOR:
- case Opcodes.LXOR:
- value2 = pop();
- value1 = pop();
- push(interpreter.binaryOperation(insn, value1, value2));
- break;
- case Opcodes.IINC:
- var = ((IincInsnNode) insn).var;
- setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));
- break;
- case Opcodes.I2L:
- case Opcodes.I2F:
- case Opcodes.I2D:
- case Opcodes.L2I:
- case Opcodes.L2F:
- case Opcodes.L2D:
- case Opcodes.F2I:
- case Opcodes.F2L:
- case Opcodes.F2D:
- case Opcodes.D2I:
- case Opcodes.D2L:
- case Opcodes.D2F:
- case Opcodes.I2B:
- case Opcodes.I2C:
- case Opcodes.I2S:
- push(interpreter.unaryOperation(insn, pop()));
- break;
- case Opcodes.LCMP:
- case Opcodes.FCMPL:
- case Opcodes.FCMPG:
- case Opcodes.DCMPL:
- case Opcodes.DCMPG:
- value2 = pop();
- value1 = pop();
- push(interpreter.binaryOperation(insn, value1, value2));
- break;
- case Opcodes.IFEQ:
- case Opcodes.IFNE:
- case Opcodes.IFLT:
- case Opcodes.IFGE:
- case Opcodes.IFGT:
- case Opcodes.IFLE:
- interpreter.unaryOperation(insn, pop());
- break;
- case Opcodes.IF_ICMPEQ:
- case Opcodes.IF_ICMPNE:
- case Opcodes.IF_ICMPLT:
- case Opcodes.IF_ICMPGE:
- case Opcodes.IF_ICMPGT:
- case Opcodes.IF_ICMPLE:
- case Opcodes.IF_ACMPEQ:
- case Opcodes.IF_ACMPNE:
- value2 = pop();
- value1 = pop();
- interpreter.binaryOperation(insn, value1, value2);
- break;
- case Opcodes.GOTO:
- break;
- case Opcodes.JSR:
- push(interpreter.newOperation(insn));
- break;
- case Opcodes.RET:
- break;
- case Opcodes.TABLESWITCH:
- case Opcodes.LOOKUPSWITCH:
- interpreter.unaryOperation(insn, pop());
- break;
- case Opcodes.IRETURN:
- case Opcodes.LRETURN:
- case Opcodes.FRETURN:
- case Opcodes.DRETURN:
- case Opcodes.ARETURN:
- value1 = pop();
- interpreter.unaryOperation(insn, value1);
- interpreter.returnOperation(insn, value1, returnValue);
- break;
- case Opcodes.RETURN:
- if (returnValue != null) {
- throw new AnalyzerException(insn, "Incompatible return type");
- }
- break;
- case Opcodes.GETSTATIC:
- push(interpreter.newOperation(insn));
- break;
- case Opcodes.PUTSTATIC:
- interpreter.unaryOperation(insn, pop());
- break;
- case Opcodes.GETFIELD:
- push(interpreter.unaryOperation(insn, pop()));
- break;
- case Opcodes.PUTFIELD:
- value2 = pop();
- value1 = pop();
- interpreter.binaryOperation(insn, value1, value2);
- break;
- case Opcodes.INVOKEVIRTUAL:
- case Opcodes.INVOKESPECIAL:
- case Opcodes.INVOKESTATIC:
- case Opcodes.INVOKEINTERFACE: {
- values = new ArrayList<V>();
- String desc = ((MethodInsnNode) insn).desc;
- for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
- values.add(0, pop());
- }
- if (insn.getOpcode() != Opcodes.INVOKESTATIC) {
- values.add(0, pop());
- }
- if (Type.getReturnType(desc) == Type.VOID_TYPE) {
- interpreter.naryOperation(insn, values);
- } else {
- push(interpreter.naryOperation(insn, values));
- }
- break;
+ }
}
- case Opcodes.INVOKEDYNAMIC: {
- values = new ArrayList<V>();
- String desc = ((InvokeDynamicInsnNode) insn).desc;
- for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
- values.add(0, pop());
- }
- if (Type.getReturnType(desc) == Type.VOID_TYPE) {
- interpreter.naryOperation(insn, values);
- } else {
- push(interpreter.naryOperation(insn, values));
- }
- break;
+ throw new AnalyzerException(insn, "Illegal use of DUP2_X2");
+ case Opcodes.SWAP:
+ value2 = pop();
+ value1 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of SWAP");
}
- case Opcodes.NEW:
- push(interpreter.newOperation(insn));
- break;
- case Opcodes.NEWARRAY:
- case Opcodes.ANEWARRAY:
- case Opcodes.ARRAYLENGTH:
- push(interpreter.unaryOperation(insn, pop()));
- break;
- case Opcodes.ATHROW:
- interpreter.unaryOperation(insn, pop());
- break;
- case Opcodes.CHECKCAST:
- case Opcodes.INSTANCEOF:
- push(interpreter.unaryOperation(insn, pop()));
- break;
- case Opcodes.MONITORENTER:
- case Opcodes.MONITOREXIT:
- interpreter.unaryOperation(insn, pop());
- break;
- case Opcodes.MULTIANEWARRAY:
- values = new ArrayList<V>();
- for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {
- values.add(0, pop());
- }
- push(interpreter.naryOperation(insn, values));
- break;
- case Opcodes.IFNULL:
- case Opcodes.IFNONNULL:
- interpreter.unaryOperation(insn, pop());
- break;
- default:
- throw new RuntimeException("Illegal opcode " + insn.getOpcode());
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.LALOAD:
+ case Opcodes.FALOAD:
+ case Opcodes.DALOAD:
+ case Opcodes.AALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ case Opcodes.IADD:
+ case Opcodes.LADD:
+ case Opcodes.FADD:
+ case Opcodes.DADD:
+ case Opcodes.ISUB:
+ case Opcodes.LSUB:
+ case Opcodes.FSUB:
+ case Opcodes.DSUB:
+ case Opcodes.IMUL:
+ case Opcodes.LMUL:
+ case Opcodes.FMUL:
+ case Opcodes.DMUL:
+ case Opcodes.IDIV:
+ case Opcodes.LDIV:
+ case Opcodes.FDIV:
+ case Opcodes.DDIV:
+ case Opcodes.IREM:
+ case Opcodes.LREM:
+ case Opcodes.FREM:
+ case Opcodes.DREM:
+ case Opcodes.ISHL:
+ case Opcodes.LSHL:
+ case Opcodes.ISHR:
+ case Opcodes.LSHR:
+ case Opcodes.IUSHR:
+ case Opcodes.LUSHR:
+ case Opcodes.IAND:
+ case Opcodes.LAND:
+ case Opcodes.IOR:
+ case Opcodes.LOR:
+ case Opcodes.IXOR:
+ case Opcodes.LXOR:
+ case Opcodes.LCMP:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.IINC:
+ var = ((IincInsnNode) insn).var;
+ setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));
+ break;
+ case Opcodes.I2L:
+ case Opcodes.I2F:
+ case Opcodes.I2D:
+ case Opcodes.L2I:
+ case Opcodes.L2F:
+ case Opcodes.L2D:
+ case Opcodes.F2I:
+ case Opcodes.F2L:
+ case Opcodes.F2D:
+ case Opcodes.D2I:
+ case Opcodes.D2L:
+ case Opcodes.D2F:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.PUTFIELD:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.GOTO:
+ break;
+ case Opcodes.JSR:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.RET:
+ break;
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IRETURN:
+ case Opcodes.LRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.DRETURN:
+ case Opcodes.ARETURN:
+ value1 = pop();
+ interpreter.unaryOperation(insn, value1);
+ interpreter.returnOperation(insn, value1, returnValue);
+ break;
+ case Opcodes.RETURN:
+ if (returnValue != null) {
+ throw new AnalyzerException(insn, "Incompatible return type");
}
- }
-
- /**
- * Merges this frame with the given frame.
- *
- * @param frame
- * a frame.
- * @param interpreter
- * the interpreter used to merge values.
- * @return <tt>true</tt> if this frame has been changed as a result of the
- * merge operation, or <tt>false</tt> otherwise.
- * @throws AnalyzerException
- * if the frames have incompatible sizes.
- */
- public boolean merge(final Frame<? extends V> frame,
- final Interpreter<V> interpreter) throws AnalyzerException {
- if (top != frame.top) {
- throw new AnalyzerException(null, "Incompatible stack heights");
+ break;
+ case Opcodes.GETSTATIC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.PUTSTATIC:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.GETFIELD:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ {
+ List<V> valueList = new ArrayList<V>();
+ String methodDescriptor = ((MethodInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(methodDescriptor).length; i > 0; --i) {
+ valueList.add(0, pop());
+ }
+ if (insn.getOpcode() != Opcodes.INVOKESTATIC) {
+ valueList.add(0, pop());
+ }
+ if (Type.getReturnType(methodDescriptor) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, valueList);
+ } else {
+ push(interpreter.naryOperation(insn, valueList));
+ }
+ break;
}
- boolean changes = false;
- for (int i = 0; i < locals + top; ++i) {
- V v = interpreter.merge(values[i], frame.values[i]);
- if (!v.equals(values[i])) {
- values[i] = v;
- changes = true;
- }
+ case Opcodes.INVOKEDYNAMIC:
+ {
+ List<V> valueList = new ArrayList<V>();
+ String methodDesccriptor = ((InvokeDynamicInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(methodDesccriptor).length; i > 0; --i) {
+ valueList.add(0, pop());
+ }
+ if (Type.getReturnType(methodDesccriptor) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, valueList);
+ } else {
+ push(interpreter.naryOperation(insn, valueList));
+ }
+ break;
}
- return changes;
+ case Opcodes.NEW:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.NEWARRAY:
+ case Opcodes.ANEWARRAY:
+ case Opcodes.ARRAYLENGTH:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ATHROW:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.CHECKCAST:
+ case Opcodes.INSTANCEOF:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.MULTIANEWARRAY:
+ List<V> valueList = new ArrayList<V>();
+ for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {
+ valueList.add(0, pop());
+ }
+ push(interpreter.naryOperation(insn, valueList));
+ break;
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ default:
+ throw new AnalyzerException(insn, "Illegal opcode " + insn.getOpcode());
}
+ }
- /**
- * Merges this frame with the given frame (case of a RET instruction).
- *
- * @param frame
- * a frame
- * @param access
- * the local variables that have been accessed by the subroutine
- * to which the RET instruction corresponds.
- * @return <tt>true</tt> if this frame has been changed as a result of the
- * merge operation, or <tt>false</tt> otherwise.
- */
- public boolean merge(final Frame<? extends V> frame, final boolean[] access) {
- boolean changes = false;
- for (int i = 0; i < locals; ++i) {
- if (!access[i] && !values[i].equals(frame.values[i])) {
- values[i] = frame.values[i];
- changes = true;
- }
- }
- return changes;
+ /**
+ * Merges the given frame into this frame.
+ *
+ * @param frame a frame. This frame is left unchanged by this method.
+ * @param interpreter the interpreter used to merge values.
+ * @return {@literal true} if this frame has been changed as a result of the merge operation, or
+ * {@literal false} otherwise.
+ * @throws AnalyzerException if the frames have incompatible sizes.
+ */
+ public boolean merge(final Frame<? extends V> frame, final Interpreter<V> interpreter)
+ throws AnalyzerException {
+ if (numStack != frame.numStack) {
+ throw new AnalyzerException(null, "Incompatible stack heights");
}
+ boolean changed = false;
+ for (int i = 0; i < numLocals + numStack; ++i) {
+ V v = interpreter.merge(values[i], frame.values[i]);
+ if (!v.equals(values[i])) {
+ values[i] = v;
+ changed = true;
+ }
+ }
+ return changed;
+ }
- /**
- * Returns a string representation of this frame.
- *
- * @return a string representation of this frame.
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < getLocals(); ++i) {
- sb.append(getLocal(i));
- }
- sb.append(' ');
- for (int i = 0; i < getStackSize(); ++i) {
- sb.append(getStack(i).toString());
- }
- return sb.toString();
+ /**
+ * Merges the given frame into this frame (case of a subroutine). The operand stacks are not
+ * merged, and only the local variables that have not been used by the subroutine are merged.
+ *
+ * @param frame a frame. This frame is left unchanged by this method.
+ * @param localsUsed the local variables that are read or written by the subroutine. The i-th
+ * element is true if and only if the local variable at index i is read or written by the
+ * subroutine.
+ * @return {@literal true} if this frame has been changed as a result of the merge operation, or
+ * {@literal false} otherwise.
+ */
+ public boolean merge(final Frame<? extends V> frame, final boolean[] localsUsed) {
+ boolean changed = false;
+ for (int i = 0; i < numLocals; ++i) {
+ if (!localsUsed[i] && !values[i].equals(frame.values[i])) {
+ values[i] = frame.values[i];
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ /**
+ * Returns a string representation of this frame.
+ *
+ * @return a string representation of this frame.
+ */
+ @Override
+ public String toString() {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < getLocals(); ++i) {
+ stringBuilder.append(getLocal(i));
+ }
+ stringBuilder.append(' ');
+ for (int i = 0; i < getStackSize(); ++i) {
+ stringBuilder.append(getStack(i).toString());
}
+ return stringBuilder.toString();
+ }
}
[25/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
old mode 100644
new mode 100755
index f1cad6f..c6da2a5
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
@@ -1,260 +1,330 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureWriter;
/**
- * A class responsible for remapping types and names. Subclasses can override
- * the following methods:
- *
- * <ul>
- * <li>{@link #map(String)} - map type</li>
- * <li>{@link #mapFieldName(String, String, String)} - map field name</li>
- * <li>{@link #mapMethodName(String, String, String)} - map method name</li>
- * </ul>
- *
+ * A class responsible for remapping types and names.
+ *
* @author Eugene Kuleshov
*/
public abstract class Remapper {
- public String mapDesc(String desc) {
- Type t = Type.getType(desc);
- switch (t.getSort()) {
- case Type.ARRAY:
- String s = mapDesc(t.getElementType().getDescriptor());
- for (int i = 0; i < t.getDimensions(); ++i) {
- s = '[' + s;
- }
- return s;
- case Type.OBJECT:
- String newType = map(t.getInternalName());
- if (newType != null) {
- return 'L' + newType + ';';
- }
- }
- return desc;
- }
+ /**
+ * Returns the given descriptor, remapped with {@link #map(String)}.
+ *
+ * @param descriptor a type descriptor.
+ * @return the given descriptor, with its [array element type] internal name remapped with {@link
+ * #map(String)} (if the descriptor corresponds to an array or object type, otherwise the
+ * descriptor is returned as is).
+ */
+ public String mapDesc(final String descriptor) {
+ return mapType(Type.getType(descriptor)).getDescriptor();
+ }
- private Type mapType(Type t) {
- switch (t.getSort()) {
- case Type.ARRAY:
- String s = mapDesc(t.getElementType().getDescriptor());
- for (int i = 0; i < t.getDimensions(); ++i) {
- s = '[' + s;
- }
- return Type.getType(s);
- case Type.OBJECT:
- s = map(t.getInternalName());
- return s != null ? Type.getObjectType(s) : t;
- case Type.METHOD:
- return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
+ /**
+ * Returns the given {@link Type}, remapped with {@link #map(String)} or {@link
+ * #mapMethodDesc(String)}.
+ *
+ * @param type a type, which can be a method type.
+ * @return the given type, with its [array element type] internal name remapped with {@link
+ * #map(String)} (if the type is an array or object type, otherwise the type is returned as
+ * is) or, of the type is a method type, with its descriptor remapped with {@link
+ * #mapMethodDesc(String)}.
+ */
+ private Type mapType(final Type type) {
+ switch (type.getSort()) {
+ case Type.ARRAY:
+ StringBuilder remappedDescriptor = new StringBuilder();
+ for (int i = 0; i < type.getDimensions(); ++i) {
+ remappedDescriptor.append('[');
}
- return t;
+ remappedDescriptor.append(mapType(type.getElementType()).getDescriptor());
+ return Type.getType(remappedDescriptor.toString());
+ case Type.OBJECT:
+ String remappedInternalName = map(type.getInternalName());
+ return remappedInternalName != null ? Type.getObjectType(remappedInternalName) : type;
+ case Type.METHOD:
+ return Type.getMethodType(mapMethodDesc(type.getDescriptor()));
+ default:
+ return type;
}
+ }
- public String mapType(String type) {
- if (type == null) {
- return null;
- }
- return mapType(Type.getObjectType(type)).getInternalName();
+ /**
+ * Returns the given internal name, remapped with {@link #map(String)}.
+ *
+ * @param internalName the internal name (or array type descriptor) of some (array) class.
+ * @return the given internal name, remapped with {@link #map(String)}.
+ */
+ public String mapType(final String internalName) {
+ if (internalName == null) {
+ return null;
}
+ return mapType(Type.getObjectType(internalName)).getInternalName();
+ }
- public String[] mapTypes(String[] types) {
- String[] newTypes = null;
- boolean needMapping = false;
- for (int i = 0; i < types.length; i++) {
- String type = types[i];
- String newType = map(type);
- if (newType != null && newTypes == null) {
- newTypes = new String[types.length];
- if (i > 0) {
- System.arraycopy(types, 0, newTypes, 0, i);
- }
- needMapping = true;
- }
- if (needMapping) {
- newTypes[i] = newType == null ? type : newType;
- }
+ /**
+ * Returns the given internal names, remapped with {@link #map(String)}.
+ *
+ * @param internalNames the internal names (or array type descriptors) of some (array) classes.
+ * @return the given internal name, remapped with {@link #map(String)}.
+ */
+ public String[] mapTypes(final String[] internalNames) {
+ String[] remappedInternalNames = null;
+ for (int i = 0; i < internalNames.length; ++i) {
+ String internalName = internalNames[i];
+ String remappedInternalName = mapType(internalName);
+ if (remappedInternalName != null) {
+ if (remappedInternalNames == null) {
+ remappedInternalNames = new String[internalNames.length];
+ System.arraycopy(internalNames, 0, remappedInternalNames, 0, internalNames.length);
}
- return needMapping ? newTypes : types;
+ remappedInternalNames[i] = remappedInternalName;
+ }
}
+ return remappedInternalNames != null ? remappedInternalNames : internalNames;
+ }
- public String mapMethodDesc(String desc) {
- if ("()V".equals(desc)) {
- return desc;
- }
-
- Type[] args = Type.getArgumentTypes(desc);
- StringBuilder sb = new StringBuilder("(");
- for (int i = 0; i < args.length; i++) {
- sb.append(mapDesc(args[i].getDescriptor()));
- }
- Type returnType = Type.getReturnType(desc);
- if (returnType == Type.VOID_TYPE) {
- sb.append(")V");
- return sb.toString();
- }
- sb.append(')').append(mapDesc(returnType.getDescriptor()));
- return sb.toString();
+ /**
+ * Returns the given method descriptor, with its argument and return type descriptors remapped
+ * with {@link #mapDesc(String)}.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the given method descriptor, with its argument and return type descriptors remapped
+ * with {@link #mapDesc(String)}.
+ */
+ public String mapMethodDesc(final String methodDescriptor) {
+ if ("()V".equals(methodDescriptor)) {
+ return methodDescriptor;
}
- public Object mapValue(Object value) {
- if (value instanceof Type) {
- return mapType((Type) value);
- }
- if (value instanceof Handle) {
- Handle h = (Handle) value;
- return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
- h.getOwner(), h.getName(), h.getDesc()),
- mapMethodDesc(h.getDesc()), h.isInterface());
- }
- return value;
+ StringBuilder stringBuilder = new StringBuilder("(");
+ for (Type argumentType : Type.getArgumentTypes(methodDescriptor)) {
+ stringBuilder.append(mapType(argumentType).getDescriptor());
}
-
- /**
- * @param signature
- * signature for mapper
- * @param typeSignature
- * true if signature is a FieldTypeSignature, such as the
- * signature parameter of the ClassVisitor.visitField or
- * MethodVisitor.visitLocalVariable methods
- * @return signature rewritten as a string
- */
- public String mapSignature(String signature, boolean typeSignature) {
- if (signature == null) {
- return null;
- }
- SignatureReader r = new SignatureReader(signature);
- SignatureWriter w = new SignatureWriter();
- SignatureVisitor a = createSignatureRemapper(w);
- if (typeSignature) {
- r.acceptType(a);
- } else {
- r.accept(a);
- }
- return w.toString();
+ Type returnType = Type.getReturnType(methodDescriptor);
+ if (returnType == Type.VOID_TYPE) {
+ stringBuilder.append(")V");
+ } else {
+ stringBuilder.append(')').append(mapType(returnType).getDescriptor());
}
+ return stringBuilder.toString();
+ }
- /**
- * @deprecated use {@link #createSignatureRemapper} instead.
- */
- @Deprecated
- protected SignatureVisitor createRemappingSignatureAdapter(
- SignatureVisitor v) {
- return new SignatureRemapper(v, this);
+ /**
+ * Returns the given value, remapped with this remapper. Possible values are {@link Boolean},
+ * {@link Byte}, {@link Short}, {@link Character}, {@link Integer}, {@link Long}, {@link Double},
+ * {@link Float}, {@link String}, {@link Type}, {@link Handle}, {@link ConstantDynamic} or arrays
+ * of primitive types .
+ *
+ * @param value an object. Only {@link Type}, {@link Handle} and {@link ConstantDynamic} values
+ * are remapped.
+ * @return the given value, remapped with this remapper.
+ */
+ public Object mapValue(final Object value) {
+ if (value instanceof Type) {
+ return mapType((Type) value);
}
-
- protected SignatureVisitor createSignatureRemapper(
- SignatureVisitor v) {
- return createRemappingSignatureAdapter(v);
+ if (value instanceof Handle) {
+ Handle handle = (Handle) value;
+ return new Handle(
+ handle.getTag(),
+ mapType(handle.getOwner()),
+ mapMethodName(handle.getOwner(), handle.getName(), handle.getDesc()),
+ handle.getTag() <= Opcodes.H_PUTSTATIC
+ ? mapDesc(handle.getDesc())
+ : mapMethodDesc(handle.getDesc()),
+ handle.isInterface());
}
-
- /**
- * Map method name to the new name. Subclasses can override.
- *
- * @param owner
- * owner of the method.
- * @param name
- * name of the method.
- * @param desc
- * descriptor of the method.
- * @return new name of the method
- */
- public String mapMethodName(String owner, String name, String desc) {
- return name;
+ if (value instanceof ConstantDynamic) {
+ ConstantDynamic constantDynamic = (ConstantDynamic) value;
+ int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
+ Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArgumentCount];
+ for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
+ remappedBootstrapMethodArguments[i] =
+ mapValue(constantDynamic.getBootstrapMethodArgument(i));
+ }
+ String descriptor = constantDynamic.getDescriptor();
+ return new ConstantDynamic(
+ mapInvokeDynamicMethodName(constantDynamic.getName(), descriptor),
+ mapDesc(descriptor),
+ (Handle) mapValue(constantDynamic.getBootstrapMethod()),
+ remappedBootstrapMethodArguments);
}
+ return value;
+ }
- /**
- * Map invokedynamic method name to the new name. Subclasses can override.
- *
- * @param name
- * name of the invokedynamic.
- * @param desc
- * descriptor of the invokedynamic.
- * @return new invokdynamic name.
- */
- public String mapInvokeDynamicMethodName(String name, String desc) {
- return name;
+ /**
+ * Returns the given signature, remapped with the {@link SignatureVisitor} returned by {@link
+ * #createSignatureRemapper(SignatureVisitor)}.
+ *
+ * @param signature a <i>JavaTypeSignature</i>, <i>ClassSignature</i> or <i>MethodSignature</i>.
+ * @param typeSignature whether the given signature is a <i>JavaTypeSignature</i>.
+ * @return signature the given signature, remapped with the {@link SignatureVisitor} returned by
+ * {@link #createSignatureRemapper(SignatureVisitor)}.
+ */
+ public String mapSignature(final String signature, final boolean typeSignature) {
+ if (signature == null) {
+ return null;
}
-
- /**
- * Map field name to the new name. Subclasses can override.
- *
- * @param owner
- * owner of the field.
- * @param name
- * name of the field
- * @param desc
- * descriptor of the field
- * @return new name of the field.
- */
- public String mapFieldName(String owner, String name, String desc) {
- return name;
+ SignatureReader signatureReader = new SignatureReader(signature);
+ SignatureWriter signatureWriter = new SignatureWriter();
+ SignatureVisitor signatureRemapper = createSignatureRemapper(signatureWriter);
+ if (typeSignature) {
+ signatureReader.acceptType(signatureRemapper);
+ } else {
+ signatureReader.accept(signatureRemapper);
}
+ return signatureWriter.toString();
+ }
- /**
- * Map package name to the new name. Subclasses can override.
- *
- * @param name name of the package
- * @return new name of the package
- */
- public String mapPackageName(String name) {
- String fakeName = map(name + ".FakeClassName");
- int index;
- return fakeName == null || (index = fakeName.lastIndexOf('.')) == -1 ? name: fakeName.substring(0, index);
- }
-
- /**
- * Map module name to the new name. Subclasses can override.
- *
- * @param name name of the module
- * @return new name of the module
- */
- public String mapModuleName(String name) {
- return name;
- }
-
- /**
- * Map type name to the new name. Subclasses can override.
- *
- * @param typeName
- * the type name
- * @return new name, default implementation is the identity.
- */
- public String map(String typeName) {
- return typeName;
+ /**
+ * Constructs a new remapper for signatures. The default implementation of this method returns a
+ * new {@link SignatureRemapper}.
+ *
+ * @param signatureVisitor the SignatureVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ * @deprecated use {@link #createSignatureRemapper} instead.
+ */
+ @Deprecated
+ protected SignatureVisitor createRemappingSignatureAdapter(
+ final SignatureVisitor signatureVisitor) {
+ return createSignatureRemapper(signatureVisitor);
+ }
+
+ /**
+ * Constructs a new remapper for signatures. The default implementation of this method returns a
+ * new {@link SignatureRemapper}.
+ *
+ * @param signatureVisitor the SignatureVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected SignatureVisitor createSignatureRemapper(final SignatureVisitor signatureVisitor) {
+ return new SignatureRemapper(signatureVisitor, this);
+ }
+
+ /**
+ * Maps an inner class name to its new name. The default implementation of this method provides a
+ * strategy that will work for inner classes produced by Java, but not necessarily other
+ * languages. Subclasses can override.
+ *
+ * @param name the fully-qualified internal name of the inner class.
+ * @param ownerName the internal name of the owner class of the inner class.
+ * @param innerName the internal name of the inner class.
+ * @return the new inner name of the inner class.
+ */
+ public String mapInnerClassName(
+ final String name, final String ownerName, final String innerName) {
+ final String remappedInnerName = this.mapType(name);
+ if (remappedInnerName.contains("$")) {
+ return remappedInnerName.substring(remappedInnerName.lastIndexOf('$') + 1);
+ } else {
+ return innerName;
}
+ }
+
+ /**
+ * Maps a method name to its new name. The default implementation of this method returns the given
+ * name, unchanged. Subclasses can override.
+ *
+ * @param owner the internal name of the owner class of the method.
+ * @param name the name of the method.
+ * @param descriptor the descriptor of the method.
+ * @return the new name of the method.
+ */
+ public String mapMethodName(final String owner, final String name, final String descriptor) {
+ return name;
+ }
+
+ /**
+ * Maps an invokedynamic or a constant dynamic method name to its new name. The default
+ * implementation of this method returns the given name, unchanged. Subclasses can override.
+ *
+ * @param name the name of the method.
+ * @param descriptor the descriptor of the method.
+ * @return the new name of the method.
+ */
+ public String mapInvokeDynamicMethodName(final String name, final String descriptor) {
+ return name;
+ }
+
+ /**
+ * Maps a field name to its new name. The default implementation of this method returns the given
+ * name, unchanged. Subclasses can override.
+ *
+ * @param owner the internal name of the owner class of the field.
+ * @param name the name of the field.
+ * @param descriptor the descriptor of the field.
+ * @return the new name of the field.
+ */
+ public String mapFieldName(final String owner, final String name, final String descriptor) {
+ return name;
+ }
+
+ /**
+ * Maps a package name to its new name. The default implementation of this method returns the
+ * given name, unchanged. Subclasses can override.
+ *
+ * @param name the fully qualified name of the package (using dots).
+ * @return the new name of the package.
+ */
+ public String mapPackageName(final String name) {
+ return name;
+ }
+
+ /**
+ * Maps a module name to its new name. The default implementation of this method returns the given
+ * name, unchanged. Subclasses can override.
+ *
+ * @param name the fully qualified name (using dots) of a module.
+ * @return the new name of the module.
+ */
+ public String mapModuleName(final String name) {
+ return name;
+ }
+
+ /**
+ * Maps the internal name of a class to its new name. The default implementation of this method
+ * returns the given name, unchanged. Subclasses can override.
+ *
+ * @param internalName the internal name of a class.
+ * @return the new internal name.
+ */
+ public String map(final String internalName) {
+ return internalName;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
old mode 100644
new mode 100755
index ebb34b8..cf7ada2
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -35,47 +33,53 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* An {@link AnnotationVisitor} adapter for type remapping.
- *
+ *
* @deprecated use {@link AnnotationRemapper} instead.
* @author Eugene Kuleshov
*/
@Deprecated
public class RemappingAnnotationAdapter extends AnnotationVisitor {
- protected final Remapper remapper;
+ protected final Remapper remapper;
- public RemappingAnnotationAdapter(final AnnotationVisitor av,
- final Remapper remapper) {
- this(Opcodes.ASM6, av, remapper);
- }
+ public RemappingAnnotationAdapter(
+ final AnnotationVisitor annotationVisitor, final Remapper remapper) {
+ this(Opcodes.ASM6, annotationVisitor, remapper);
+ }
- protected RemappingAnnotationAdapter(final int api,
- final AnnotationVisitor av, final Remapper remapper) {
- super(api, av);
- this.remapper = remapper;
- }
+ protected RemappingAnnotationAdapter(
+ final int api, final AnnotationVisitor annotationVisitor, final Remapper remapper) {
+ super(api, annotationVisitor);
+ this.remapper = remapper;
+ }
- @Override
- public void visit(String name, Object value) {
- av.visit(name, remapper.mapValue(value));
- }
+ @Override
+ public void visit(final String name, final Object value) {
+ av.visit(name, remapper.mapValue(value));
+ }
- @Override
- public void visitEnum(String name, String desc, String value) {
- av.visitEnum(name, remapper.mapDesc(desc), value);
- }
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ av.visitEnum(name, remapper.mapDesc(descriptor), value);
+ }
- @Override
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
- return v == null ? null : (v == av ? this
- : new RemappingAnnotationAdapter(v, remapper));
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ AnnotationVisitor annotationVisitor = av.visitAnnotation(name, remapper.mapDesc(descriptor));
+ return annotationVisitor == null
+ ? null
+ : (annotationVisitor == av
+ ? this
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper));
+ }
- @Override
- public AnnotationVisitor visitArray(String name) {
- AnnotationVisitor v = av.visitArray(name);
- return v == null ? null : (v == av ? this
- : new RemappingAnnotationAdapter(v, remapper));
- }
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ AnnotationVisitor annotationVisitor = av.visitArray(name);
+ return annotationVisitor == null
+ ? null
+ : (annotationVisitor == av
+ ? this
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper));
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
old mode 100644
new mode 100755
index baf6a41..72b110c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -40,104 +38,130 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A {@link ClassVisitor} for type remapping.
- *
+ *
* @deprecated use {@link ClassRemapper} instead.
* @author Eugene Kuleshov
*/
@Deprecated
public class RemappingClassAdapter extends ClassVisitor {
- protected final Remapper remapper;
-
- protected String className;
-
- public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
- this(Opcodes.ASM6, cv, remapper);
- }
-
- protected RemappingClassAdapter(final int api, final ClassVisitor cv,
- final Remapper remapper) {
- super(api, cv);
- this.remapper = remapper;
- }
-
- @Override
- public void visit(int version, int access, String name, String signature,
- String superName, String[] interfaces) {
- this.className = name;
- super.visit(version, access, remapper.mapType(name), remapper
- .mapSignature(signature, false), remapper.mapType(superName),
- interfaces == null ? null : remapper.mapTypes(interfaces));
- }
-
- @Override
- public ModuleVisitor visitModule(String name, int flags, String version) {
- throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead");
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
- visible);
- return av == null ? null : createRemappingAnnotationAdapter(av);
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? null : createRemappingAnnotationAdapter(av);
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- FieldVisitor fv = super.visitField(access,
- remapper.mapFieldName(className, name, desc),
- remapper.mapDesc(desc), remapper.mapSignature(signature, true),
- remapper.mapValue(value));
- return fv == null ? null : createRemappingFieldAdapter(fv);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- String newDesc = remapper.mapMethodDesc(desc);
- MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
- className, name, desc), newDesc, remapper.mapSignature(
- signature, false),
- exceptions == null ? null : remapper.mapTypes(exceptions));
- return mv == null ? null : createRemappingMethodAdapter(access,
- newDesc, mv);
- }
-
- @Override
- public void visitInnerClass(String name, String outerName,
- String innerName, int access) {
- // TODO should innerName be changed?
- super.visitInnerClass(remapper.mapType(name), outerName == null ? null
- : remapper.mapType(outerName), innerName, access);
- }
-
- @Override
- public void visitOuterClass(String owner, String name, String desc) {
- super.visitOuterClass(remapper.mapType(owner), name == null ? null
- : remapper.mapMethodName(owner, name, desc),
- desc == null ? null : remapper.mapMethodDesc(desc));
- }
-
- protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
- return new RemappingFieldAdapter(fv, remapper);
- }
-
- protected MethodVisitor createRemappingMethodAdapter(int access,
- String newDesc, MethodVisitor mv) {
- return new RemappingMethodAdapter(access, newDesc, mv, remapper);
- }
-
- protected AnnotationVisitor createRemappingAnnotationAdapter(
- AnnotationVisitor av) {
- return new RemappingAnnotationAdapter(av, remapper);
- }
+ protected final Remapper remapper;
+
+ protected String className;
+
+ public RemappingClassAdapter(final ClassVisitor classVisitor, final Remapper remapper) {
+ this(Opcodes.ASM6, classVisitor, remapper);
+ }
+
+ protected RemappingClassAdapter(
+ final int api, final ClassVisitor classVisitor, final Remapper remapper) {
+ super(api, classVisitor);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ this.className = name;
+ super.visit(
+ version,
+ access,
+ remapper.mapType(name),
+ remapper.mapSignature(signature, false),
+ remapper.mapType(superName),
+ interfaces == null ? null : remapper.mapTypes(interfaces));
+ }
+
+ @Override
+ public ModuleVisitor visitModule(final String name, final int flags, final String version) {
+ throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead");
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitAnnotation(remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null ? null : createRemappingAnnotationAdapter(annotationVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null ? null : createRemappingAnnotationAdapter(annotationVisitor);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ FieldVisitor fieldVisitor =
+ super.visitField(
+ access,
+ remapper.mapFieldName(className, name, descriptor),
+ remapper.mapDesc(descriptor),
+ remapper.mapSignature(signature, true),
+ remapper.mapValue(value));
+ return fieldVisitor == null ? null : createRemappingFieldAdapter(fieldVisitor);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ String newDescriptor = remapper.mapMethodDesc(descriptor);
+ MethodVisitor methodVisitor =
+ super.visitMethod(
+ access,
+ remapper.mapMethodName(className, name, descriptor),
+ newDescriptor,
+ remapper.mapSignature(signature, false),
+ exceptions == null ? null : remapper.mapTypes(exceptions));
+ return methodVisitor == null
+ ? null
+ : createRemappingMethodAdapter(access, newDescriptor, methodVisitor);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ super.visitInnerClass(
+ remapper.mapType(name),
+ outerName == null ? null : remapper.mapType(outerName),
+ innerName,
+ access);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ super.visitOuterClass(
+ remapper.mapType(owner),
+ name == null ? null : remapper.mapMethodName(owner, name, descriptor),
+ descriptor == null ? null : remapper.mapMethodDesc(descriptor));
+ }
+
+ protected FieldVisitor createRemappingFieldAdapter(final FieldVisitor fieldVisitor) {
+ return new RemappingFieldAdapter(fieldVisitor, remapper);
+ }
+
+ protected MethodVisitor createRemappingMethodAdapter(
+ final int access, final String newDescriptor, final MethodVisitor methodVisitior) {
+ return new RemappingMethodAdapter(access, newDescriptor, methodVisitior, remapper);
+ }
+
+ protected AnnotationVisitor createRemappingAnnotationAdapter(final AnnotationVisitor av) {
+ return new RemappingAnnotationAdapter(av, remapper);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
old mode 100644
new mode 100755
index 4bb4d3f..e6ed262
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -37,37 +35,40 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A {@link FieldVisitor} adapter for type remapping.
- *
+ *
* @deprecated use {@link FieldRemapper} instead.
* @author Eugene Kuleshov
*/
@Deprecated
public class RemappingFieldAdapter extends FieldVisitor {
- private final Remapper remapper;
+ private final Remapper remapper;
- public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
- this(Opcodes.ASM6, fv, remapper);
- }
+ public RemappingFieldAdapter(final FieldVisitor fieldVisitor, final Remapper remapper) {
+ this(Opcodes.ASM6, fieldVisitor, remapper);
+ }
- protected RemappingFieldAdapter(final int api, final FieldVisitor fv,
- final Remapper remapper) {
- super(api, fv);
- this.remapper = remapper;
- }
+ protected RemappingFieldAdapter(
+ final int api, final FieldVisitor fieldVisitor, final Remapper remapper) {
+ super(api, fieldVisitor);
+ this.remapper = remapper;
+ }
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
- visible);
- return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor = fv.visitAnnotation(remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? null
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? null
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
old mode 100644
new mode 100755
index cd74921..90a719a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -39,190 +37,243 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A {@link LocalVariablesSorter} for type mapping.
- *
+ *
* @deprecated use {@link MethodRemapper} instead.
* @author Eugene Kuleshov
*/
@Deprecated
public class RemappingMethodAdapter extends LocalVariablesSorter {
- protected final Remapper remapper;
+ protected final Remapper remapper;
- public RemappingMethodAdapter(final int access, final String desc,
- final MethodVisitor mv, final Remapper remapper) {
- this(Opcodes.ASM6, access, desc, mv, remapper);
- }
+ public RemappingMethodAdapter(
+ final int access,
+ final String descriptor,
+ final MethodVisitor methodVisitor,
+ final Remapper remapper) {
+ this(Opcodes.ASM6, access, descriptor, methodVisitor, remapper);
+ }
- protected RemappingMethodAdapter(final int api, final int access,
- final String desc, final MethodVisitor mv, final Remapper remapper) {
- super(api, access, desc, mv);
- this.remapper = remapper;
- }
+ protected RemappingMethodAdapter(
+ final int api,
+ final int access,
+ final String descriptor,
+ final MethodVisitor methodVisitor,
+ final Remapper remapper) {
+ super(api, access, descriptor, methodVisitor);
+ this.remapper = remapper;
+ }
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- AnnotationVisitor av = super.visitAnnotationDefault();
- return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ AnnotationVisitor annotationVisitor = super.visitAnnotationDefault();
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
- visible);
- return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitAnnotation(remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
- @Override
- public AnnotationVisitor visitParameterAnnotation(int parameter,
- String desc, boolean visible) {
- AnnotationVisitor av = super.visitParameterAnnotation(parameter,
- remapper.mapDesc(desc), visible);
- return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitParameterAnnotation(parameter, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
- @Override
- public void visitFrame(int type, int nLocal, Object[] local, int nStack,
- Object[] stack) {
- super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
- remapEntries(nStack, stack));
- }
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ super.visitFrame(
+ type, numLocal, remapEntries(numLocal, local), numStack, remapEntries(numStack, stack));
+ }
- private Object[] remapEntries(int n, Object[] entries) {
- if (entries != null) {
- for (int i = 0; i < n; i++) {
- if (entries[i] instanceof String) {
- Object[] newEntries = new Object[n];
- if (i > 0) {
- System.arraycopy(entries, 0, newEntries, 0, i);
- }
- do {
- Object t = entries[i];
- newEntries[i++] = t instanceof String ? remapper
- .mapType((String) t) : t;
- } while (i < n);
- return newEntries;
- }
- }
+ private Object[] remapEntries(final int numTypes, final Object[] entries) {
+ if (entries == null) {
+ return entries;
+ }
+ Object[] remappedEntries = null;
+ for (int i = 0; i < numTypes; ++i) {
+ if (entries[i] instanceof String) {
+ if (remappedEntries == null) {
+ remappedEntries = new Object[numTypes];
+ System.arraycopy(entries, 0, remappedEntries, 0, numTypes);
}
- return entries;
+ remappedEntries[i] = remapper.mapType((String) entries[i]);
+ }
}
+ return remappedEntries == null ? entries : remappedEntries;
+ }
- @Override
- public void visitFieldInsn(int opcode, String owner, String name,
- String desc) {
- super.visitFieldInsn(opcode, remapper.mapType(owner),
- remapper.mapFieldName(owner, name, desc),
- remapper.mapDesc(desc));
- }
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ super.visitFieldInsn(
+ opcode,
+ remapper.mapType(owner),
+ remapper.mapFieldName(owner, name, descriptor),
+ remapper.mapDesc(descriptor));
+ }
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
}
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
}
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
- private void doVisitMethodInsn(int opcode, String owner, String name,
- String desc, boolean itf) {
- // Calling super.visitMethodInsn requires to call the correct version
- // depending on this.api (otherwise infinite loops can occur). To
- // simplify and to make it easier to automatically remove the backward
- // compatibility code, we inline the code of the overridden method here.
- // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
- // LocalVariableSorter.
- if (mv != null) {
- mv.visitMethodInsn(opcode, remapper.mapType(owner),
- remapper.mapMethodName(owner, name, desc),
- remapper.mapMethodDesc(desc), itf);
- }
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ // Calling super.visitMethodInsn requires to call the correct version
+ // depending on this.api (otherwise infinite loops can occur). To
+ // simplify and to make it easier to automatically remove the backward
+ // compatibility code, we inline the code of the overridden method here.
+ // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
+ // LocalVariableSorter.
+ if (mv != null) {
+ mv.visitMethodInsn(
+ opcode,
+ remapper.mapType(owner),
+ remapper.mapMethodName(owner, name, descriptor),
+ remapper.mapMethodDesc(descriptor),
+ isInterface);
}
+ }
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- for (int i = 0; i < bsmArgs.length; i++) {
- bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
- }
- super.visitInvokeDynamicInsn(
- remapper.mapInvokeDynamicMethodName(name, desc),
- remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
- bsmArgs);
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ for (int i = 0; i < bootstrapMethodArguments.length; i++) {
+ bootstrapMethodArguments[i] = remapper.mapValue(bootstrapMethodArguments[i]);
}
+ super.visitInvokeDynamicInsn(
+ remapper.mapInvokeDynamicMethodName(name, descriptor),
+ remapper.mapMethodDesc(descriptor),
+ (Handle) remapper.mapValue(bootstrapMethodHandle),
+ bootstrapMethodArguments);
+ }
- @Override
- public void visitTypeInsn(int opcode, String type) {
- super.visitTypeInsn(opcode, remapper.mapType(type));
- }
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ super.visitTypeInsn(opcode, remapper.mapType(type));
+ }
- @Override
- public void visitLdcInsn(Object cst) {
- super.visitLdcInsn(remapper.mapValue(cst));
- }
+ @Override
+ public void visitLdcInsn(final Object value) {
+ super.visitLdcInsn(remapper.mapValue(value));
+ }
- @Override
- public void visitMultiANewArrayInsn(String desc, int dims) {
- super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
- }
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ super.visitMultiANewArrayInsn(remapper.mapDesc(descriptor), numDimensions);
+ }
- @Override
- public AnnotationVisitor visitInsnAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitInsnAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler,
- String type) {
- super.visitTryCatchBlock(start, end, handler, type == null ? null
- : remapper.mapType(type));
- }
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ super.visitTryCatchBlock(start, end, handler, type == null ? null : remapper.mapType(type));
+ }
- @Override
- public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTryCatchAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
- @Override
- public void visitLocalVariable(String name, String desc, String signature,
- Label start, Label end, int index) {
- super.visitLocalVariable(name, remapper.mapDesc(desc),
- remapper.mapSignature(signature, true), start, end, index);
- }
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ super.visitLocalVariable(
+ name,
+ remapper.mapDesc(descriptor),
+ remapper.mapSignature(signature, true),
+ start,
+ end,
+ index);
+ }
- @Override
- public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
- TypePath typePath, Label[] start, Label[] end, int[] index,
- String desc, boolean visible) {
- AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
- typePath, start, end, index, remapper.mapDesc(desc), visible);
- return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, index, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? annotationVisitor
+ : new RemappingAnnotationAdapter(annotationVisitor, remapper);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
old mode 100644
new mode 100755
index 74276a8..0c60a91
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -35,123 +33,125 @@ import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
/**
* A {@link SignatureVisitor} adapter for type mapping.
- *
+ *
* @deprecated use {@link SignatureRemapper} instead.
* @author Eugene Kuleshov
*/
@Deprecated
public class RemappingSignatureAdapter extends SignatureVisitor {
- private final SignatureVisitor v;
-
- private final Remapper remapper;
-
- private String className;
-
- public RemappingSignatureAdapter(final SignatureVisitor v,
- final Remapper remapper) {
- this(Opcodes.ASM6, v, remapper);
- }
-
- protected RemappingSignatureAdapter(final int api,
- final SignatureVisitor v, final Remapper remapper) {
- super(api);
- this.v = v;
- this.remapper = remapper;
- }
-
- @Override
- public void visitClassType(String name) {
- className = name;
- v.visitClassType(remapper.mapType(name));
- }
-
- @Override
- public void visitInnerClassType(String name) {
- String remappedOuter = remapper.mapType(className) + '$';
- className = className + '$' + name;
- String remappedName = remapper.mapType(className);
- int index = remappedName.startsWith(remappedOuter) ? remappedOuter
- .length() : remappedName.lastIndexOf('$') + 1;
- v.visitInnerClassType(remappedName.substring(index));
- }
-
- @Override
- public void visitFormalTypeParameter(String name) {
- v.visitFormalTypeParameter(name);
- }
-
- @Override
- public void visitTypeVariable(String name) {
- v.visitTypeVariable(name);
- }
-
- @Override
- public SignatureVisitor visitArrayType() {
- v.visitArrayType();
- return this;
- }
-
- @Override
- public void visitBaseType(char descriptor) {
- v.visitBaseType(descriptor);
- }
-
- @Override
- public SignatureVisitor visitClassBound() {
- v.visitClassBound();
- return this;
- }
-
- @Override
- public SignatureVisitor visitExceptionType() {
- v.visitExceptionType();
- return this;
- }
-
- @Override
- public SignatureVisitor visitInterface() {
- v.visitInterface();
- return this;
- }
-
- @Override
- public SignatureVisitor visitInterfaceBound() {
- v.visitInterfaceBound();
- return this;
- }
-
- @Override
- public SignatureVisitor visitParameterType() {
- v.visitParameterType();
- return this;
- }
-
- @Override
- public SignatureVisitor visitReturnType() {
- v.visitReturnType();
- return this;
- }
-
- @Override
- public SignatureVisitor visitSuperclass() {
- v.visitSuperclass();
- return this;
- }
-
- @Override
- public void visitTypeArgument() {
- v.visitTypeArgument();
- }
-
- @Override
- public SignatureVisitor visitTypeArgument(char wildcard) {
- v.visitTypeArgument(wildcard);
- return this;
- }
-
- @Override
- public void visitEnd() {
- v.visitEnd();
- }
+ private final SignatureVisitor signatureVisitor;
+
+ private final Remapper remapper;
+
+ private String className;
+
+ public RemappingSignatureAdapter(
+ final SignatureVisitor signatureVisitor, final Remapper remapper) {
+ this(Opcodes.ASM6, signatureVisitor, remapper);
+ }
+
+ protected RemappingSignatureAdapter(
+ final int api, final SignatureVisitor signatureVisitor, final Remapper remapper) {
+ super(api);
+ this.signatureVisitor = signatureVisitor;
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ className = name;
+ signatureVisitor.visitClassType(remapper.mapType(name));
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ String remappedOuter = remapper.mapType(className) + '$';
+ className = className + '$' + name;
+ String remappedName = remapper.mapType(className);
+ int index =
+ remappedName.startsWith(remappedOuter)
+ ? remappedOuter.length()
+ : remappedName.lastIndexOf('$') + 1;
+ signatureVisitor.visitInnerClassType(remappedName.substring(index));
+ }
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ signatureVisitor.visitFormalTypeParameter(name);
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ signatureVisitor.visitTypeVariable(name);
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ signatureVisitor.visitArrayType();
+ return this;
+ }
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ signatureVisitor.visitBaseType(descriptor);
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ signatureVisitor.visitClassBound();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ signatureVisitor.visitExceptionType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ signatureVisitor.visitInterface();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ signatureVisitor.visitInterfaceBound();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ signatureVisitor.visitParameterType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ signatureVisitor.visitReturnType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ signatureVisitor.visitSuperclass();
+ return this;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ signatureVisitor.visitTypeArgument();
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ signatureVisitor.visitTypeArgument(wildcard);
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ signatureVisitor.visitEnd();
+ }
}
[27/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
old mode 100644
new mode 100755
index c483e81..dc43c0f
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
@@ -1,48 +1,43 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
import org.apache.tapestry5.internal.plastic.asm.tree.InsnNode;
@@ -55,698 +50,514 @@ import org.apache.tapestry5.internal.plastic.asm.tree.TableSwitchInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
/**
- * A {@link org.objectweb.asm.MethodVisitor} that removes JSR instructions and
- * inlines the referenced subroutines.
- *
- * <b>Explanation of how it works</b> TODO
- *
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} that removes JSR instructions and inlines the
+ * referenced subroutines.
+ *
* @author Niko Matsakis
*/
+// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public class JSRInlinerAdapter extends MethodNode implements Opcodes {
- private static final boolean LOGGING = false;
-
- /**
- * For each label that is jumped to by a JSR, we create a BitSet instance.
- */
- private final Map<LabelNode, BitSet> subroutineHeads = new HashMap<LabelNode, BitSet>();
-
- /**
- * This subroutine instance denotes the line of execution that is not
- * contained within any subroutine; i.e., the "subroutine" that is executing
- * when a method first begins.
- */
- private final BitSet mainSubroutine = new BitSet();
-
- /**
- * This BitSet contains the index of every instruction that belongs to more
- * than one subroutine. This should not happen often.
- */
- final BitSet dualCitizens = new BitSet();
-
- /**
- * Creates a new JSRInliner. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #JSRInlinerAdapter(int, MethodVisitor, int, String, String, String, String[])}
- * version.
- *
- * @param mv
- * the <code>MethodVisitor</code> to send the resulting inlined
- * method code to (use <code>null</code> for none).
- * @param access
- * the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt>.
- * @param exceptions
- * the internal names of the method's exception classes (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public JSRInlinerAdapter(final MethodVisitor mv, final int access,
- final String name, final String desc, final String signature,
- final String[] exceptions) {
- this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
- if (getClass() != JSRInlinerAdapter.class) {
- throw new IllegalStateException();
- }
+ /**
+ * The instructions that belong to the main "subroutine". Bit i is set iff instruction at index i
+ * belongs to this main "subroutine".
+ */
+ private final BitSet mainSubroutineInsns = new BitSet();
+
+ /**
+ * The instructions that belong to each subroutine. For each label which is the target of a JSR
+ * instruction, bit i of the corresponding BitSet in this map is set iff instruction at index i
+ * belongs to this subroutine.
+ */
+ private final Map<LabelNode, BitSet> subroutinesInsns = new HashMap<LabelNode, BitSet>();
+
+ /**
+ * The instructions that belong to more that one subroutine. Bit i is set iff instruction at index
+ * i belongs to more than one subroutine.
+ */
+ final BitSet sharedSubroutineInsns = new BitSet();
+
+ /**
+ * Constructs a new {@link JSRInlinerAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #JSRInlinerAdapter(int, MethodVisitor, int, String, String,
+ * String, String[])} version.
+ *
+ * @param methodVisitor the method visitor to send the resulting inlined method code to, or <code>
+ * null</code>.
+ * @param access the method's access flags.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor.
+ * @param signature the method's signature. May be {@literal null}.
+ * @param exceptions the internal names of the method's exception classes. May be {@literal null}.
+ * @throws IllegalStateException if a subclass calls this constructor.
+ */
+ public JSRInlinerAdapter(
+ final MethodVisitor methodVisitor,
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ this(Opcodes.ASM7, methodVisitor, access, name, descriptor, signature, exceptions);
+ if (getClass() != JSRInlinerAdapter.class) {
+ throw new IllegalStateException();
}
-
- /**
- * Creates a new JSRInliner.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param mv
- * the <code>MethodVisitor</code> to send the resulting inlined
- * method code to (use <code>null</code> for none).
- * @param access
- * the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt>.
- * @param exceptions
- * the internal names of the method's exception classes (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- */
- protected JSRInlinerAdapter(final int api, final MethodVisitor mv,
- final int access, final String name, final String desc,
- final String signature, final String[] exceptions) {
- super(api, access, name, desc, signature, exceptions);
- this.mv = mv;
+ }
+
+ /**
+ * Constructs a new {@link JSRInlinerAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param methodVisitor the method visitor to send the resulting inlined method code to, or <code>
+ * null</code>.
+ * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the method is synthetic and/or deprecated.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor.
+ * @param signature the method's signature. May be {@literal null}.
+ * @param exceptions the internal names of the method's exception classes. May be {@literal null}.
+ */
+ protected JSRInlinerAdapter(
+ final int api,
+ final MethodVisitor methodVisitor,
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ super(api, access, name, descriptor, signature, exceptions);
+ this.mv = methodVisitor;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ super.visitJumpInsn(opcode, label);
+ LabelNode labelNode = ((JumpInsnNode) instructions.getLast()).label;
+ if (opcode == JSR && !subroutinesInsns.containsKey(labelNode)) {
+ subroutinesInsns.put(labelNode, new BitSet());
}
-
- /**
- * Detects a JSR instruction and sets a flag to indicate we will need to do
- * inlining.
- */
- @Override
- public void visitJumpInsn(final int opcode, final Label lbl) {
- super.visitJumpInsn(opcode, lbl);
- LabelNode ln = ((JumpInsnNode) instructions.getLast()).label;
- if (opcode == JSR && !subroutineHeads.containsKey(ln)) {
- subroutineHeads.put(ln, new BitSet());
- }
+ }
+
+ @Override
+ public void visitEnd() {
+ if (!subroutinesInsns.isEmpty()) {
+ // If the code contains at least one JSR instruction, inline the subroutines.
+ findSubroutinesInsns();
+ emitCode();
}
-
- /**
- * If any JSRs were seen, triggers the inlining process. Otherwise, forwards
- * the byte codes untouched.
- */
- @Override
- public void visitEnd() {
- if (!subroutineHeads.isEmpty()) {
- markSubroutines();
- if (LOGGING) {
- log(mainSubroutine.toString());
- Iterator<BitSet> it = subroutineHeads.values().iterator();
- while (it.hasNext()) {
- BitSet sub = it.next();
- log(sub.toString());
- }
- }
- emitCode();
+ if (mv != null) {
+ accept(mv);
+ }
+ }
+
+ /** Determines, for each instruction, to which subroutine(s) it belongs. */
+ private void findSubroutinesInsns() {
+ // Find the instructions that belong to main subroutine.
+ BitSet visitedInsns = new BitSet();
+ findSubroutineInsns(0, mainSubroutineInsns, visitedInsns);
+ // For each subroutine, find the instructions that belong to this subroutine.
+ for (Map.Entry<LabelNode, BitSet> entry : subroutinesInsns.entrySet()) {
+ LabelNode jsrLabelNode = entry.getKey();
+ BitSet subroutineInsns = entry.getValue();
+ findSubroutineInsns(instructions.indexOf(jsrLabelNode), subroutineInsns, visitedInsns);
+ }
+ }
+
+ /**
+ * Finds the instructions that belong to the subroutine starting at the given instruction index.
+ * For this the control flow graph is visited with a depth first search (this includes the normal
+ * control flow and the exception handlers).
+ *
+ * @param startInsnIndex the index of the first instruction of the subroutine.
+ * @param subroutineInsns where the indices of the instructions of the subroutine must be stored.
+ * @param visitedInsns the indices of the instructions that have been visited so far (including in
+ * previous calls to this method). This bitset is updated by this method each time a new
+ * instruction is visited. It is used to make sure each instruction is visited at most once.
+ */
+ private void findSubroutineInsns(
+ final int startInsnIndex, final BitSet subroutineInsns, final BitSet visitedInsns) {
+ // First find the instructions reachable via normal execution.
+ findReachableInsns(startInsnIndex, subroutineInsns, visitedInsns);
+
+ // Then find the instructions reachable via the applicable exception handlers.
+ while (true) {
+ boolean applicableHandlerFound = false;
+ for (TryCatchBlockNode tryCatchBlockNode : tryCatchBlocks) {
+ // If the handler has already been processed, skip it.
+ int handlerIndex = instructions.indexOf(tryCatchBlockNode.handler);
+ if (subroutineInsns.get(handlerIndex)) {
+ continue;
}
- // Forward the translate opcodes on if appropriate:
- if (mv != null) {
- accept(mv);
+ // If an instruction in the exception handler range belongs to the subroutine, the handler
+ // can be reached from the routine, and its instructions must be added to the subroutine.
+ int startIndex = instructions.indexOf(tryCatchBlockNode.start);
+ int endIndex = instructions.indexOf(tryCatchBlockNode.end);
+ int firstSubroutineInsnAfterTryCatchStart = subroutineInsns.nextSetBit(startIndex);
+ if (firstSubroutineInsnAfterTryCatchStart >= startIndex
+ && firstSubroutineInsnAfterTryCatchStart < endIndex) {
+ findReachableInsns(handlerIndex, subroutineInsns, visitedInsns);
+ applicableHandlerFound = true;
}
+ }
+ // If an applicable exception handler has been found, other handlers may become applicable, so
+ // we must examine them again.
+ if (!applicableHandlerFound) {
+ return;
+ }
}
-
- /**
- * Walks the method and determines which internal subroutine(s), if any,
- * each instruction is a method of.
- */
- private void markSubroutines() {
- BitSet anyvisited = new BitSet();
-
- // First walk the main subroutine and find all those instructions which
- // can be reached without invoking any JSR at all
- markSubroutineWalk(mainSubroutine, 0, anyvisited);
-
- // Go through the head of each subroutine and find any nodes reachable
- // to that subroutine without following any JSR links.
- for (Iterator<Map.Entry<LabelNode, BitSet>> it = subroutineHeads
- .entrySet().iterator(); it.hasNext();) {
- Map.Entry<LabelNode, BitSet> entry = it.next();
- LabelNode lab = entry.getKey();
- BitSet sub = entry.getValue();
- int index = instructions.indexOf(lab);
- markSubroutineWalk(sub, index, anyvisited);
+ }
+
+ /**
+ * Finds the instructions that are reachable from the given instruction, without following any JSR
+ * instruction nor any exception handler. For this the control flow graph is visited with a depth
+ * first search.
+ *
+ * @param insnIndex the index of an instruction of the subroutine.
+ * @param subroutineInsns where the indices of the instructions of the subroutine must be stored.
+ * @param visitedInsns the indices of the instructions that have been visited so far (including in
+ * previous calls to this method). This bitset is updated by this method each time a new
+ * instruction is visited. It is used to make sure each instruction is visited at most once.
+ */
+ private void findReachableInsns(
+ final int insnIndex, final BitSet subroutineInsns, final BitSet visitedInsns) {
+ int currentInsnIndex = insnIndex;
+ // We implicitly assume below that execution can always fall through to the next instruction
+ // after a JSR. But a subroutine may never return, in which case the code after the JSR is
+ // unreachable and can be anything. In particular, it can seem to fall off the end of the
+ // method, so we must handle this case here (we could instead detect whether execution can
+ // return or not from a JSR, but this is more complicated).
+ while (currentInsnIndex < instructions.size()) {
+ // Visit each instruction at most once.
+ if (subroutineInsns.get(currentInsnIndex)) {
+ return;
+ }
+ subroutineInsns.set(currentInsnIndex);
+
+ // Check if this instruction has already been visited by another subroutine.
+ if (visitedInsns.get(currentInsnIndex)) {
+ sharedSubroutineInsns.set(currentInsnIndex);
+ }
+ visitedInsns.set(currentInsnIndex);
+
+ AbstractInsnNode currentInsnNode = instructions.get(currentInsnIndex);
+ if (currentInsnNode.getType() == AbstractInsnNode.JUMP_INSN
+ && currentInsnNode.getOpcode() != JSR) {
+ // Don't follow JSR instructions in the control flow graph.
+ JumpInsnNode jumpInsnNode = (JumpInsnNode) currentInsnNode;
+ findReachableInsns(instructions.indexOf(jumpInsnNode.label), subroutineInsns, visitedInsns);
+ } else if (currentInsnNode.getType() == AbstractInsnNode.TABLESWITCH_INSN) {
+ TableSwitchInsnNode tableSwitchInsnNode = (TableSwitchInsnNode) currentInsnNode;
+ findReachableInsns(
+ instructions.indexOf(tableSwitchInsnNode.dflt), subroutineInsns, visitedInsns);
+ for (LabelNode labelNode : tableSwitchInsnNode.labels) {
+ findReachableInsns(instructions.indexOf(labelNode), subroutineInsns, visitedInsns);
}
+ } else if (currentInsnNode.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) {
+ LookupSwitchInsnNode lookupSwitchInsnNode = (LookupSwitchInsnNode) currentInsnNode;
+ findReachableInsns(
+ instructions.indexOf(lookupSwitchInsnNode.dflt), subroutineInsns, visitedInsns);
+ for (LabelNode labelNode : lookupSwitchInsnNode.labels) {
+ findReachableInsns(instructions.indexOf(labelNode), subroutineInsns, visitedInsns);
+ }
+ }
+
+ // Check if this instruction falls through to the next instruction; if not, return.
+ switch (instructions.get(currentInsnIndex).getOpcode()) {
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ // Note: this either returns from this subroutine, or from a parent subroutine.
+ return;
+ default:
+ // Go to the next instruction.
+ currentInsnIndex++;
+ break;
+ }
}
-
- /**
- * Performs a depth first search walking the normal byte code path starting
- * at <code>index</code>, and adding each instruction encountered into the
- * subroutine <code>sub</code>. After this walk is complete, iterates over
- * the exception handlers to ensure that we also include those byte codes
- * which are reachable through an exception that may be thrown during the
- * execution of the subroutine. Invoked from <code>markSubroutines()</code>.
- *
- * @param sub
- * the subroutine whose instructions must be computed.
- * @param index
- * an instruction of this subroutine.
- * @param anyvisited
- * indexes of the already visited instructions, i.e. marked as
- * part of this subroutine or any previously computed subroutine.
- */
- private void markSubroutineWalk(final BitSet sub, final int index,
- final BitSet anyvisited) {
- if (LOGGING) {
- log("markSubroutineWalk: sub=" + sub + " index=" + index);
+ }
+
+ /**
+ * Creates the new instructions, inlining each instantiation of each subroutine until the code is
+ * fully elaborated.
+ */
+ private void emitCode() {
+ LinkedList<Instantiation> worklist = new LinkedList<Instantiation>();
+ // Create an instantiation of the main "subroutine", which is just the main routine.
+ worklist.add(new Instantiation(null, mainSubroutineInsns));
+
+ // Emit instantiations of each subroutine we encounter, including the main subroutine.
+ InsnList newInstructions = new InsnList();
+ List<TryCatchBlockNode> newTryCatchBlocks = new ArrayList<TryCatchBlockNode>();
+ List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>();
+ while (!worklist.isEmpty()) {
+ Instantiation instantiation = worklist.removeFirst();
+ emitInstantiation(
+ instantiation, worklist, newInstructions, newTryCatchBlocks, newLocalVariables);
+ }
+ instructions = newInstructions;
+ tryCatchBlocks = newTryCatchBlocks;
+ localVariables = newLocalVariables;
+ }
+
+ /**
+ * Emits an instantiation of a subroutine, specified by <code>instantiation</code>. May add new
+ * instantiations that are invoked by this one to the <code>worklist</code>, and new try/catch
+ * blocks to <code>newTryCatchBlocks</code>.
+ *
+ * @param instantiation the instantiation that must be performed.
+ * @param worklist list of the instantiations that remain to be done.
+ * @param newInstructions the instruction list to which the instantiated code must be appended.
+ * @param newTryCatchBlocks the exception handler list to which the instantiated handlers must be
+ * appended.
+ * @param newLocalVariables the local variables list to which the instantiated local variables
+ * must be appended.
+ */
+ private void emitInstantiation(
+ final Instantiation instantiation,
+ final List<Instantiation> worklist,
+ final InsnList newInstructions,
+ final List<TryCatchBlockNode> newTryCatchBlocks,
+ final List<LocalVariableNode> newLocalVariables) {
+ LabelNode previousLabelNode = null;
+ for (int i = 0; i < instructions.size(); ++i) {
+ AbstractInsnNode insnNode = instructions.get(i);
+ if (insnNode.getType() == AbstractInsnNode.LABEL) {
+ // Always clone all labels, while avoiding to add the same label more than once.
+ LabelNode labelNode = (LabelNode) insnNode;
+ LabelNode clonedLabelNode = instantiation.getClonedLabel(labelNode);
+ if (clonedLabelNode != previousLabelNode) {
+ newInstructions.add(clonedLabelNode);
+ previousLabelNode = clonedLabelNode;
}
-
- // First find those instructions reachable via normal execution
- markSubroutineWalkDFS(sub, index, anyvisited);
-
- // Now, make sure we also include any applicable exception handlers
- boolean loop = true;
- while (loop) {
- loop = false;
- for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
- .hasNext();) {
- TryCatchBlockNode trycatch = it.next();
-
- if (LOGGING) {
- // TODO use of default toString().
- log("Scanning try/catch " + trycatch);
- }
-
- // If the handler has already been processed, skip it.
- int handlerindex = instructions.indexOf(trycatch.handler);
- if (sub.get(handlerindex)) {
- continue;
- }
-
- int startindex = instructions.indexOf(trycatch.start);
- int endindex = instructions.indexOf(trycatch.end);
- int nextbit = sub.nextSetBit(startindex);
- if (nextbit != -1 && nextbit < endindex) {
- if (LOGGING) {
- log("Adding exception handler: " + startindex + '-'
- + endindex + " due to " + nextbit + " handler "
- + handlerindex);
- }
- markSubroutineWalkDFS(sub, handlerindex, anyvisited);
- loop = true;
- }
+ } else if (instantiation.findOwner(i) == instantiation) {
+ // Don't emit instructions that were already emitted by an ancestor subroutine. Note that it
+ // is still possible for a given instruction to be emitted twice because it may belong to
+ // two subroutines that do not invoke each other.
+
+ if (insnNode.getOpcode() == RET) {
+ // Translate RET instruction(s) to a jump to the return label for the appropriate
+ // instantiation. The problem is that the subroutine may "fall through" to the ret of a
+ // parent subroutine; therefore, to find the appropriate ret label we find the oldest
+ // instantiation that claims to own this instruction.
+ LabelNode retLabel = null;
+ for (Instantiation retLabelOwner = instantiation;
+ retLabelOwner != null;
+ retLabelOwner = retLabelOwner.parent) {
+ if (retLabelOwner.subroutineInsns.get(i)) {
+ retLabel = retLabelOwner.returnLabel;
}
+ }
+ if (retLabel == null) {
+ // This is only possible if the mainSubroutine owns a RET instruction, which should
+ // never happen for verifiable code.
+ throw new IllegalArgumentException(
+ "Instruction #" + i + " is a RET not owned by any subroutine");
+ }
+ newInstructions.add(new JumpInsnNode(GOTO, retLabel));
+ } else if (insnNode.getOpcode() == JSR) {
+ LabelNode jsrLabelNode = ((JumpInsnNode) insnNode).label;
+ BitSet subroutineInsns = subroutinesInsns.get(jsrLabelNode);
+ Instantiation newInstantiation = new Instantiation(instantiation, subroutineInsns);
+ LabelNode clonedJsrLabelNode = newInstantiation.getClonedLabelForJumpInsn(jsrLabelNode);
+ // Replace the JSR instruction with a GOTO to the instantiated subroutine, and push NULL
+ // for what was once the return address value. This hack allows us to avoid doing any sort
+ // of data flow analysis to figure out which instructions manipulate the old return
+ // address value pointer which is now known to be unneeded.
+ newInstructions.add(new InsnNode(ACONST_NULL));
+ newInstructions.add(new JumpInsnNode(GOTO, clonedJsrLabelNode));
+ newInstructions.add(newInstantiation.returnLabel);
+ // Insert this new instantiation into the queue to be emitted later.
+ worklist.add(newInstantiation);
+ } else {
+ newInstructions.add(insnNode.clone(instantiation));
}
+ }
}
- /**
- * Performs a simple DFS of the instructions, assigning each to the
- * subroutine <code>sub</code>. Starts from <code>index</code>. Invoked only
- * by <code>markSubroutineWalk()</code>.
- *
- * @param sub
- * the subroutine whose instructions must be computed.
- * @param index
- * an instruction of this subroutine.
- * @param anyvisited
- * indexes of the already visited instructions, i.e. marked as
- * part of this subroutine or any previously computed subroutine.
- */
- private void markSubroutineWalkDFS(final BitSet sub, int index,
- final BitSet anyvisited) {
- while (true) {
- AbstractInsnNode node = instructions.get(index);
-
- // don't visit a node twice
- if (sub.get(index)) {
- return;
- }
- sub.set(index);
-
- // check for those nodes already visited by another subroutine
- if (anyvisited.get(index)) {
- dualCitizens.set(index);
- if (LOGGING) {
- log("Instruction #" + index + " is dual citizen.");
- }
- }
- anyvisited.set(index);
-
- if (node.getType() == AbstractInsnNode.JUMP_INSN
- && node.getOpcode() != JSR) {
- // we do not follow recursively called subroutines here; but any
- // other sort of branch we do follow
- JumpInsnNode jnode = (JumpInsnNode) node;
- int destidx = instructions.indexOf(jnode.label);
- markSubroutineWalkDFS(sub, destidx, anyvisited);
- }
- if (node.getType() == AbstractInsnNode.TABLESWITCH_INSN) {
- TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
- int destidx = instructions.indexOf(tsnode.dflt);
- markSubroutineWalkDFS(sub, destidx, anyvisited);
- for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
- LabelNode l = tsnode.labels.get(i);
- destidx = instructions.indexOf(l);
- markSubroutineWalkDFS(sub, destidx, anyvisited);
- }
- }
- if (node.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) {
- LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
- int destidx = instructions.indexOf(lsnode.dflt);
- markSubroutineWalkDFS(sub, destidx, anyvisited);
- for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
- LabelNode l = lsnode.labels.get(i);
- destidx = instructions.indexOf(l);
- markSubroutineWalkDFS(sub, destidx, anyvisited);
- }
- }
-
- // check to see if this opcode falls through to the next instruction
- // or not; if not, return.
- switch (instructions.get(index).getOpcode()) {
- case GOTO:
- case RET:
- case TABLESWITCH:
- case LOOKUPSWITCH:
- case IRETURN:
- case LRETURN:
- case FRETURN:
- case DRETURN:
- case ARETURN:
- case RETURN:
- case ATHROW:
- /*
- * note: this either returns from this subroutine, or a parent
- * subroutine which invoked it
- */
- return;
- }
-
- // Use tail recursion here in the form of an outer while loop to
- // avoid our stack growing needlessly:
- index++;
-
- // We implicitly assumed above that execution can always fall
- // through to the next instruction after a JSR. But a subroutine may
- // never return, in which case the code after the JSR is unreachable
- // and can be anything. In particular, it can seem to fall off the
- // end of the method, so we must handle this case here (we could
- // instead detect whether execution can return or not from a JSR,
- // but this is more complicated).
- if (index >= instructions.size()) {
- return;
- }
+ // Emit the try/catch blocks that are relevant for this instantiation.
+ for (TryCatchBlockNode tryCatchBlockNode : tryCatchBlocks) {
+ final LabelNode start = instantiation.getClonedLabel(tryCatchBlockNode.start);
+ final LabelNode end = instantiation.getClonedLabel(tryCatchBlockNode.end);
+ if (start != end) {
+ final LabelNode handler =
+ instantiation.getClonedLabelForJumpInsn(tryCatchBlockNode.handler);
+ if (start == null || end == null || handler == null) {
+ throw new AssertionError("Internal error!");
}
+ newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler, tryCatchBlockNode.type));
+ }
}
- /**
- * Creates the new instructions, inlining each instantiation of each
- * subroutine until the code is fully elaborated.
- */
- private void emitCode() {
- LinkedList<Instantiation> worklist = new LinkedList<Instantiation>();
- // Create an instantiation of the "root" subroutine, which is just the
- // main routine
- worklist.add(new Instantiation(null, mainSubroutine));
-
- // Emit instantiations of each subroutine we encounter, including the
- // main subroutine
- InsnList newInstructions = new InsnList();
- List<TryCatchBlockNode> newTryCatchBlocks = new ArrayList<TryCatchBlockNode>();
- List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>();
- while (!worklist.isEmpty()) {
- Instantiation inst = worklist.removeFirst();
- emitSubroutine(inst, worklist, newInstructions, newTryCatchBlocks,
- newLocalVariables);
- }
- instructions = newInstructions;
- tryCatchBlocks = newTryCatchBlocks;
- localVariables = newLocalVariables;
+ // Emit the local variable nodes that are relevant for this instantiation.
+ for (LocalVariableNode localVariableNode : localVariables) {
+ final LabelNode start = instantiation.getClonedLabel(localVariableNode.start);
+ final LabelNode end = instantiation.getClonedLabel(localVariableNode.end);
+ if (start != end) {
+ newLocalVariables.add(
+ new LocalVariableNode(
+ localVariableNode.name,
+ localVariableNode.desc,
+ localVariableNode.signature,
+ start,
+ end,
+ localVariableNode.index));
+ }
}
+ }
+
+ /** An instantiation of a subroutine. */
+ private class Instantiation extends AbstractMap<LabelNode, LabelNode> {
/**
- * Emits one instantiation of one subroutine, specified by
- * <code>instant</code>. May add new instantiations that are invoked by this
- * one to the <code>worklist</code> parameter, and new try/catch blocks to
- * <code>newTryCatchBlocks</code>.
- *
- * @param instant
- * the instantiation that must be performed.
- * @param worklist
- * list of the instantiations that remain to be done.
- * @param newInstructions
- * the instruction list to which the instantiated code must be
- * appended.
- * @param newTryCatchBlocks
- * the exception handler list to which the instantiated handlers
- * must be appended.
+ * The instantiation from which this one was created (or {@literal null} for the instantiation
+ * of the main "subroutine").
*/
- private void emitSubroutine(final Instantiation instant,
- final List<Instantiation> worklist, final InsnList newInstructions,
- final List<TryCatchBlockNode> newTryCatchBlocks,
- final List<LocalVariableNode> newLocalVariables) {
- LabelNode duplbl = null;
-
- if (LOGGING) {
- log("--------------------------------------------------------");
- log("Emitting instantiation of subroutine " + instant.subroutine);
- }
+ final Instantiation parent;
- // Emit the relevant instructions for this instantiation, translating
- // labels and jump targets as we go:
- for (int i = 0, c = instructions.size(); i < c; i++) {
- AbstractInsnNode insn = instructions.get(i);
- Instantiation owner = instant.findOwner(i);
-
- // Always remap labels:
- if (insn.getType() == AbstractInsnNode.LABEL) {
- // Translate labels into their renamed equivalents.
- // Avoid adding the same label more than once. Note
- // that because we own this instruction the gotoTable
- // and the rangeTable will always agree.
- LabelNode ilbl = (LabelNode) insn;
- LabelNode remap = instant.rangeLabel(ilbl);
- if (LOGGING) {
- // TODO use of default toString().
- log("Translating lbl #" + i + ':' + ilbl + " to " + remap);
- }
- if (remap != duplbl) {
- newInstructions.add(remap);
- duplbl = remap;
- }
- continue;
- }
+ /**
+ * The original instructions that belong to the subroutine which is instantiated. Bit i is set
+ * iff instruction at index i belongs to this subroutine.
+ */
+ final BitSet subroutineInsns;
- // We don't want to emit instructions that were already
- // emitted by a subroutine higher on the stack. Note that
- // it is still possible for a given instruction to be
- // emitted twice because it may belong to two subroutines
- // that do not invoke each other.
- if (owner != instant) {
- continue;
- }
+ /**
+ * A map from labels from the original code to labels pointing at code specific to this
+ * instantiation, for use in remapping try/catch blocks, as well as jumps.
+ *
+ * <p>Note that in the presence of instructions belonging to several subroutines, we map the
+ * target label of a GOTO to the label used by the oldest instantiation (parent instantiations
+ * are older than their children). This avoids code duplication during inlining in most cases.
+ */
+ final Map<LabelNode, LabelNode> clonedLabels;
- if (LOGGING) {
- log("Emitting inst #" + i);
- }
+ /** The return label for this instantiation, to which all original returns will be mapped. */
+ final LabelNode returnLabel;
- if (insn.getOpcode() == RET) {
- // Translate RET instruction(s) to a jump to the return label
- // for the appropriate instantiation. The problem is that the
- // subroutine may "fall through" to the ret of a parent
- // subroutine; therefore, to find the appropriate ret label we
- // find the lowest subroutine on the stack that claims to own
- // this instruction. See the class javadoc comment for an
- // explanation on why this technique is safe (note: it is only
- // safe if the input is verifiable).
- LabelNode retlabel = null;
- for (Instantiation p = instant; p != null; p = p.previous) {
- if (p.subroutine.get(i)) {
- retlabel = p.returnLabel;
- }
- }
- if (retlabel == null) {
- // This is only possible if the mainSubroutine owns a RET
- // instruction, which should never happen for verifiable
- // code.
- throw new RuntimeException("Instruction #" + i
- + " is a RET not owned by any subroutine");
- }
- newInstructions.add(new JumpInsnNode(GOTO, retlabel));
- } else if (insn.getOpcode() == JSR) {
- LabelNode lbl = ((JumpInsnNode) insn).label;
- BitSet sub = subroutineHeads.get(lbl);
- Instantiation newinst = new Instantiation(instant, sub);
- LabelNode startlbl = newinst.gotoLabel(lbl);
-
- if (LOGGING) {
- log(" Creating instantiation of subr " + sub);
- }
-
- // Rather than JSRing, we will jump to the inline version and
- // push NULL for what was once the return value. This hack
- // allows us to avoid doing any sort of data flow analysis to
- // figure out which instructions manipulate the old return value
- // pointer which is now known to be unneeded.
- newInstructions.add(new InsnNode(ACONST_NULL));
- newInstructions.add(new JumpInsnNode(GOTO, startlbl));
- newInstructions.add(newinst.returnLabel);
-
- // Insert this new instantiation into the queue to be emitted
- // later.
- worklist.add(newinst);
- } else {
- newInstructions.add(insn.clone(instant));
- }
+ Instantiation(final Instantiation parent, final BitSet subroutineInsns) {
+ for (Instantiation instantiation = parent;
+ instantiation != null;
+ instantiation = instantiation.parent) {
+ if (instantiation.subroutineInsns == subroutineInsns) {
+ throw new IllegalArgumentException("Recursive invocation of " + subroutineInsns);
}
-
- // Emit try/catch blocks that are relevant to this method.
- for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
- .hasNext();) {
- TryCatchBlockNode trycatch = it.next();
-
- if (LOGGING) {
- // TODO use of default toString().
- log("try catch block original labels=" + trycatch.start + '-'
- + trycatch.end + "->" + trycatch.handler);
- }
-
- final LabelNode start = instant.rangeLabel(trycatch.start);
- final LabelNode end = instant.rangeLabel(trycatch.end);
-
- // Ignore empty try/catch regions
- if (start == end) {
- if (LOGGING) {
- log(" try catch block empty in this subroutine");
- }
- continue;
- }
-
- final LabelNode handler = instant.gotoLabel(trycatch.handler);
-
- if (LOGGING) {
- // TODO use of default toString().
- log(" try catch block new labels=" + start + '-' + end + "->"
- + handler);
- }
-
- if (start == null || end == null || handler == null) {
- throw new RuntimeException("Internal error!");
- }
-
- newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler,
- trycatch.type));
+ }
+
+ this.parent = parent;
+ this.subroutineInsns = subroutineInsns;
+ this.returnLabel = parent == null ? null : new LabelNode();
+ this.clonedLabels = new HashMap<LabelNode, LabelNode>();
+
+ // Create a clone of each label in the original code of the subroutine. Note that we collapse
+ // labels which point at the same instruction into one.
+ LabelNode clonedLabelNode = null;
+ for (int insnIndex = 0; insnIndex < instructions.size(); insnIndex++) {
+ AbstractInsnNode insnNode = instructions.get(insnIndex);
+ if (insnNode.getType() == AbstractInsnNode.LABEL) {
+ LabelNode labelNode = (LabelNode) insnNode;
+ // If we already have a label pointing at this spot, don't recreate it.
+ if (clonedLabelNode == null) {
+ clonedLabelNode = new LabelNode();
+ }
+ clonedLabels.put(labelNode, clonedLabelNode);
+ } else if (findOwner(insnIndex) == this) {
+ // We will emit this instruction, so clear the duplicateLabelNode flag since the next
+ // Label will refer to a distinct instruction.
+ clonedLabelNode = null;
}
+ }
+ }
- for (Iterator<LocalVariableNode> it = localVariables.iterator(); it
- .hasNext();) {
- LocalVariableNode lvnode = it.next();
- if (LOGGING) {
- log("local var " + lvnode.name);
- }
- final LabelNode start = instant.rangeLabel(lvnode.start);
- final LabelNode end = instant.rangeLabel(lvnode.end);
- if (start == end) {
- if (LOGGING) {
- log(" local variable empty in this sub");
- }
- continue;
- }
- newLocalVariables.add(new LocalVariableNode(lvnode.name,
- lvnode.desc, lvnode.signature, start, end, lvnode.index));
+ /**
+ * Returns the "owner" of a particular instruction relative to this instantiation: the owner
+ * refers to the Instantiation which will emit the version of this instruction that we will
+ * execute.
+ *
+ * <p>Typically, the return value is either <code>this</code> or <code>null</code>. <code>this
+ * </code> indicates that this instantiation will generate the version of this instruction that
+ * we will execute, and <code>null</code> indicates that this instantiation never executes the
+ * given instruction.
+ *
+ * <p>Sometimes, however, an instruction can belong to multiple subroutines; this is called a
+ * shared instruction, and occurs when multiple subroutines branch to common points of control.
+ * In this case, the owner is the oldest instantiation which owns the instruction in question
+ * (parent instantiations are older than their children).
+ *
+ * @param insnIndex the index of an instruction in the original code.
+ * @return the "owner" of a particular instruction relative to this instantiation.
+ */
+ Instantiation findOwner(final int insnIndex) {
+ if (!subroutineInsns.get(insnIndex)) {
+ return null;
+ }
+ if (!sharedSubroutineInsns.get(insnIndex)) {
+ return this;
+ }
+ Instantiation owner = this;
+ for (Instantiation instantiation = parent;
+ instantiation != null;
+ instantiation = instantiation.parent) {
+ if (instantiation.subroutineInsns.get(insnIndex)) {
+ owner = instantiation;
}
+ }
+ return owner;
}
- private static void log(final String str) {
- System.err.println(str);
+ /**
+ * Returns the clone of the given original label that is appropriate for use in a jump
+ * instruction.
+ *
+ * @param labelNode a label of the original code.
+ * @return a clone of the given label for use in a jump instruction in the inlined code.
+ */
+ LabelNode getClonedLabelForJumpInsn(final LabelNode labelNode) {
+ // findOwner should never return null, because owner is null only if an instruction cannot be
+ // reached from this subroutine.
+ return findOwner(instructions.indexOf(labelNode)).clonedLabels.get(labelNode);
}
/**
- * A class that represents an instantiation of a subroutine. Each
- * instantiation has an associate "stack" --- which is a listing of those
- * instantiations that were active when this particular instance of this
- * subroutine was invoked. Each instantiation also has a map from the
- * original labels of the program to the labels appropriate for this
- * instantiation, and finally a label to return to.
+ * Returns the clone of the given original label that is appropriate for use by a try/catch
+ * block or a variable annotation.
+ *
+ * @param labelNode a label of the original code.
+ * @return a clone of the given label for use by a try/catch block or a variable annotation in
+ * the inlined code.
*/
- private class Instantiation extends AbstractMap<LabelNode, LabelNode> {
-
- /**
- * Previous instantiations; the stack must be statically predictable to
- * be inlinable.
- */
- final Instantiation previous;
-
- /**
- * The subroutine this is an instantiation of.
- */
- public final BitSet subroutine;
-
- /**
- * This table maps Labels from the original source to Labels pointing at
- * code specific to this instantiation, for use in remapping try/catch
- * blocks,as well as gotos.
- *
- * Note that in the presence of dual citizens instructions, that is,
- * instructions which belong to more than one subroutine due to the
- * merging of control flow without a RET instruction, we will map the
- * target label of a GOTO to the label used by the instantiation lowest
- * on the stack. This avoids code duplication during inlining in most
- * cases.
- *
- * @see #findOwner(int)
- */
- public final Map<LabelNode, LabelNode> rangeTable = new HashMap<LabelNode, LabelNode>();
-
- /**
- * All returns for this instantiation will be mapped to this label
- */
- public final LabelNode returnLabel;
-
- Instantiation(final Instantiation prev, final BitSet sub) {
- previous = prev;
- subroutine = sub;
- for (Instantiation p = prev; p != null; p = p.previous) {
- if (p.subroutine == sub) {
- throw new RuntimeException("Recursive invocation of " + sub);
- }
- }
-
- // Determine the label to return to when this subroutine terminates
- // via RET: note that the main subroutine never terminates via RET.
- if (prev != null) {
- returnLabel = new LabelNode();
- } else {
- returnLabel = null;
- }
-
- // Each instantiation will remap the labels from the code above to
- // refer to its particular copy of its own instructions. Note that
- // we collapse labels which point at the same instruction into one:
- // this is fairly common as we are often ignoring large chunks of
- // instructions, so what were previously distinct labels become
- // duplicates.
- LabelNode duplbl = null;
- for (int i = 0, c = instructions.size(); i < c; i++) {
- AbstractInsnNode insn = instructions.get(i);
-
- if (insn.getType() == AbstractInsnNode.LABEL) {
- LabelNode ilbl = (LabelNode) insn;
-
- if (duplbl == null) {
- // if we already have a label pointing at this spot,
- // don't recreate it.
- duplbl = new LabelNode();
- }
-
- // Add an entry in the rangeTable for every label
- // in the original code which points at the next
- // instruction of our own to be emitted.
- rangeTable.put(ilbl, duplbl);
- } else if (findOwner(i) == this) {
- // We will emit this instruction, so clear the 'duplbl' flag
- // since the next Label will refer to a distinct
- // instruction.
- duplbl = null;
- }
- }
- }
-
- /**
- * Returns the "owner" of a particular instruction relative to this
- * instantiation: the owner referes to the Instantiation which will emit
- * the version of this instruction that we will execute.
- *
- * Typically, the return value is either <code>this</code> or
- * <code>null</code>. <code>this</code> indicates that this
- * instantiation will generate the version of this instruction that we
- * will execute, and <code>null</code> indicates that this instantiation
- * never executes the given instruction.
- *
- * Sometimes, however, an instruction can belong to multiple
- * subroutines; this is called a "dual citizen" instruction (though it
- * may belong to more than 2 subroutines), and occurs when multiple
- * subroutines branch to common points of control. In this case, the
- * owner is the subroutine that appears lowest on the stack, and which
- * also owns the instruction in question.
- *
- * @param i
- * the index of the instruction in the original code
- * @return the "owner" of a particular instruction relative to this
- * instantiation.
- */
- public Instantiation findOwner(final int i) {
- if (!subroutine.get(i)) {
- return null;
- }
- if (!dualCitizens.get(i)) {
- return this;
- }
- Instantiation own = this;
- for (Instantiation p = previous; p != null; p = p.previous) {
- if (p.subroutine.get(i)) {
- own = p;
- }
- }
- return own;
- }
+ LabelNode getClonedLabel(final LabelNode labelNode) {
+ return clonedLabels.get(labelNode);
+ }
- /**
- * Looks up the label <code>l</code> in the <code>gotoTable</code>, thus
- * translating it from a Label in the original code, to a Label in the
- * inlined code that is appropriate for use by an instruction that
- * branched to the original label.
- *
- * @param l
- * The label we will be translating
- * @return a label for use by a branch instruction in the inlined code
- * @see #rangeLabel
- */
- public LabelNode gotoLabel(final LabelNode l) {
- // owner should never be null, because owner is only null
- // if an instruction cannot be reached from this subroutine
- Instantiation owner = findOwner(instructions.indexOf(l));
- return owner.rangeTable.get(l);
- }
+ // AbstractMap implementation
- /**
- * Looks up the label <code>l</code> in the <code>rangeTable</code>,
- * thus translating it from a Label in the original code, to a Label in
- * the inlined code that is appropriate for use by an try/catch or
- * variable use annotation.
- *
- * @param l
- * The label we will be translating
- * @return a label for use by a try/catch or variable annotation in the
- * original code
- * @see #rangeTable
- */
- public LabelNode rangeLabel(final LabelNode l) {
- return rangeTable.get(l);
- }
+ @Override
+ public Set<Map.Entry<LabelNode, LabelNode>> entrySet() {
+ throw new UnsupportedOperationException();
+ }
- // AbstractMap implementation
+ @Override
+ public LabelNode get(final Object key) {
+ return getClonedLabelForJumpInsn((LabelNode) key);
+ }
- @Override
- public Set<Map.Entry<LabelNode, LabelNode>> entrySet() {
- return null;
- }
+ @Override
+ public boolean equals(final Object other) {
+ throw new UnsupportedOperationException();
+ }
- @Override
- public LabelNode get(final Object o) {
- return gotoLabel((LabelNode) o);
- }
+ @Override
+ public int hashCode() {
+ throw new UnsupportedOperationException();
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
old mode 100644
new mode 100755
index a7d2f1d..08657ee
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
@@ -37,331 +35,317 @@ import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link MethodVisitor} that renumbers local variables in their order of
- * appearance. This adapter allows one to easily add new local variables to a
- * method. It may be used by inheriting from this class, but the preferred way
- * of using it is via delegation: the next visitor in the chain can indeed add
- * new locals when needed by calling {@link #newLocal} on this adapter (this
- * requires a reference back to this {@link LocalVariablesSorter}).
- *
+ * A {@link MethodVisitor} that renumbers local variables in their order of appearance. This adapter
+ * allows one to easily add new local variables to a method. It may be used by inheriting from this
+ * class, but the preferred way of using it is via delegation: the next visitor in the chain can
+ * indeed add new locals when needed by calling {@link #newLocal} on this adapter (this requires a
+ * reference back to this {@link LocalVariablesSorter}).
+ *
* @author Chris Nokleberg
* @author Eugene Kuleshov
* @author Eric Bruneton
*/
public class LocalVariablesSorter extends MethodVisitor {
- private static final Type OBJECT_TYPE = Type
- .getObjectType("java/lang/Object");
-
- /**
- * Mapping from old to new local variable indexes. A local variable at index
- * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
- * index i of size 2 is remapped to 'mapping[2*i+1]'.
- */
- private int[] mapping = new int[40];
-
- /**
- * Array used to store stack map local variable types after remapping.
- */
- private Object[] newLocals = new Object[20];
-
- /**
- * Index of the first local variable, after formal parameters.
- */
- protected final int firstLocal;
-
- /**
- * Index of the next local variable to be created by {@link #newLocal}.
- */
- protected int nextLocal;
-
- /**
- * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
- * this constructor</i>. Instead, they must use the
- * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version.
- *
- * @param access
- * access flags of the adapted method.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public LocalVariablesSorter(final int access, final String desc,
- final MethodVisitor mv) {
- this(Opcodes.ASM6, access, desc, mv);
- if (getClass() != LocalVariablesSorter.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Creates a new {@link LocalVariablesSorter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param access
- * access flags of the adapted method.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls.
- */
- protected LocalVariablesSorter(final int api, final int access,
- final String desc, final MethodVisitor mv) {
- super(api, mv);
- Type[] args = Type.getArgumentTypes(desc);
- nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
- for (int i = 0; i < args.length; i++) {
- nextLocal += args[i].getSize();
- }
- firstLocal = nextLocal;
+ /** The type of the java.lang.Object class. */
+ private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object");
+
+ /**
+ * The mapping from old to new local variable indices. A local variable at index i of size 1 is
+ * remapped to 'mapping[2*i]', while a local variable at index i of size 2 is remapped to
+ * 'mapping[2*i+1]'.
+ */
+ private int[] remappedVariableIndices = new int[40];
+
+ /**
+ * The local variable types after remapping. The format of this array is the same as in {@link
+ * MethodVisitor#visitFrame}, except that long and double types use two slots.
+ */
+ private Object[] remappedLocalTypes = new Object[20];
+
+ /** The index of the first local variable, after formal parameters. */
+ protected final int firstLocal;
+
+ /** The index of the next local variable to be created by {@link #newLocal}. */
+ protected int nextLocal;
+
+ /**
+ * Constructs a new {@link LocalVariablesSorter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #LocalVariablesSorter(int, int, String, MethodVisitor)}
+ * version.
+ *
+ * @param access access flags of the adapted method.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param methodVisitor the method visitor to which this adapter delegates calls.
+ * @throws IllegalStateException if a subclass calls this constructor.
+ */
+ public LocalVariablesSorter(
+ final int access, final String descriptor, final MethodVisitor methodVisitor) {
+ this(Opcodes.ASM7, access, descriptor, methodVisitor);
+ if (getClass() != LocalVariablesSorter.class) {
+ throw new IllegalStateException();
}
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- Type type;
- switch (opcode) {
- case Opcodes.LLOAD:
- case Opcodes.LSTORE:
- type = Type.LONG_TYPE;
- break;
-
- case Opcodes.DLOAD:
- case Opcodes.DSTORE:
- type = Type.DOUBLE_TYPE;
- break;
-
- case Opcodes.FLOAD:
- case Opcodes.FSTORE:
- type = Type.FLOAT_TYPE;
- break;
-
- case Opcodes.ILOAD:
- case Opcodes.ISTORE:
- type = Type.INT_TYPE;
- break;
-
- default:
- // case Opcodes.ALOAD:
- // case Opcodes.ASTORE:
- // case RET:
- type = OBJECT_TYPE;
- break;
- }
- mv.visitVarInsn(opcode, remap(var, type));
+ }
+
+ /**
+ * Constructs a new {@link LocalVariablesSorter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param access access flags of the adapted method.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param methodVisitor the method visitor to which this adapter delegates calls.
+ */
+ protected LocalVariablesSorter(
+ final int api, final int access, final String descriptor, final MethodVisitor methodVisitor) {
+ super(api, methodVisitor);
+ nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
+ for (Type argumentType : Type.getArgumentTypes(descriptor)) {
+ nextLocal += argumentType.getSize();
}
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
+ firstLocal = nextLocal;
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ Type varType;
+ switch (opcode) {
+ case Opcodes.LLOAD:
+ case Opcodes.LSTORE:
+ varType = Type.LONG_TYPE;
+ break;
+ case Opcodes.DLOAD:
+ case Opcodes.DSTORE:
+ varType = Type.DOUBLE_TYPE;
+ break;
+ case Opcodes.FLOAD:
+ case Opcodes.FSTORE:
+ varType = Type.FLOAT_TYPE;
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.ISTORE:
+ varType = Type.INT_TYPE;
+ break;
+ case Opcodes.ALOAD:
+ case Opcodes.ASTORE:
+ case Opcodes.RET:
+ varType = OBJECT_TYPE;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid opcode " + opcode);
}
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- mv.visitMaxs(maxStack, nextLocal);
+ super.visitVarInsn(opcode, remap(var, varType));
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ super.visitIincInsn(remap(var, Type.INT_TYPE), increment);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ super.visitMaxs(maxStack, nextLocal);
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ int remappedIndex = remap(index, Type.getType(descriptor));
+ super.visitLocalVariable(name, descriptor, signature, start, end, remappedIndex);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ Type type = Type.getType(descriptor);
+ int[] remappedIndex = new int[index.length];
+ for (int i = 0; i < remappedIndex.length; ++i) {
+ remappedIndex[i] = remap(index[i], type);
}
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- int newIndex = remap(index, Type.getType(desc));
- mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
+ return super.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, remappedIndex, descriptor, visible);
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ if (type != Opcodes.F_NEW) { // Uncompressed frame.
+ throw new IllegalArgumentException(
+ "LocalVariablesSorter only accepts expanded frames (see ClassReader.EXPAND_FRAMES)");
}
- @Override
- public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
- TypePath typePath, Label[] start, Label[] end, int[] index,
- String desc, boolean visible) {
- Type t = Type.getType(desc);
- int[] newIndex = new int[index.length];
- for (int i = 0; i < newIndex.length; ++i) {
- newIndex[i] = remap(index[i], t);
+ // Create a copy of remappedLocals.
+ Object[] oldRemappedLocals = new Object[remappedLocalTypes.length];
+ System.arraycopy(remappedLocalTypes, 0, oldRemappedLocals, 0, oldRemappedLocals.length);
+
+ updateNewLocals(remappedLocalTypes);
+
+ // Copy the types from 'local' to 'remappedLocals'. 'remappedLocals' already contains the
+ // variables added with 'newLocal'.
+ int oldVar = 0; // Old local variable index.
+ for (int i = 0; i < numLocal; ++i) {
+ Object localType = local[i];
+ if (localType != Opcodes.TOP) {
+ Type varType = OBJECT_TYPE;
+ if (localType == Opcodes.INTEGER) {
+ varType = Type.INT_TYPE;
+ } else if (localType == Opcodes.FLOAT) {
+ varType = Type.FLOAT_TYPE;
+ } else if (localType == Opcodes.LONG) {
+ varType = Type.LONG_TYPE;
+ } else if (localType == Opcodes.DOUBLE) {
+ varType = Type.DOUBLE_TYPE;
+ } else if (localType instanceof String) {
+ varType = Type.getObjectType((String) localType);
}
- return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
- newIndex, desc, visible);
+ setFrameLocal(remap(oldVar, varType), localType);
+ }
+ oldVar += localType == Opcodes.LONG || localType == Opcodes.DOUBLE ? 2 : 1;
}
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- if (type != Opcodes.F_NEW) { // uncompressed frame
- throw new IllegalStateException(
- "ClassReader.accept() should be called with EXPAND_FRAMES flag");
- }
-
- // creates a copy of newLocals
- Object[] oldLocals = new Object[newLocals.length];
- System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
-
- updateNewLocals(newLocals);
-
- // copies types from 'local' to 'newLocals'
- // 'newLocals' already contains the variables added with 'newLocal'
-
- int index = 0; // old local variable index
- int number = 0; // old local variable number
- for (; number < nLocal; ++number) {
- Object t = local[number];
- int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
- if (t != Opcodes.TOP) {
- Type typ = OBJECT_TYPE;
- if (t == Opcodes.INTEGER) {
- typ = Type.INT_TYPE;
- } else if (t == Opcodes.FLOAT) {
- typ = Type.FLOAT_TYPE;
- } else if (t == Opcodes.LONG) {
- typ = Type.LONG_TYPE;
- } else if (t == Opcodes.DOUBLE) {
- typ = Type.DOUBLE_TYPE;
- } else if (t instanceof String) {
- typ = Type.getObjectType((String) t);
- }
- setFrameLocal(remap(index, typ), t);
- }
- index += size;
- }
-
- // removes TOP after long and double types as well as trailing TOPs
-
- index = 0;
- number = 0;
- for (int i = 0; index < newLocals.length; ++i) {
- Object t = newLocals[index++];
- if (t != null && t != Opcodes.TOP) {
- newLocals[i] = t;
- number = i + 1;
- if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
- index += 1;
- }
- } else {
- newLocals[i] = Opcodes.TOP;
- }
- }
-
- // visits remapped frame
- mv.visitFrame(type, number, newLocals, nStack, stack);
-
- // restores original value of 'newLocals'
- newLocals = oldLocals;
+ // Remove TOP after long and double types as well as trailing TOPs.
+ oldVar = 0;
+ int newVar = 0;
+ int remappedNumLocal = 0;
+ while (oldVar < remappedLocalTypes.length) {
+ Object localType = remappedLocalTypes[oldVar];
+ oldVar += localType == Opcodes.LONG || localType == Opcodes.DOUBLE ? 2 : 1;
+ if (localType != null && localType != Opcodes.TOP) {
+ remappedLocalTypes[newVar++] = localType;
+ remappedNumLocal = newVar;
+ } else {
+ remappedLocalTypes[newVar++] = Opcodes.TOP;
+ }
}
- // -------------
-
- /**
- * Creates a new local variable of the given type.
- *
- * @param type
- * the type of the local variable to be created.
- * @return the identifier of the newly created local variable.
- */
- public int newLocal(final Type type) {
- Object t;
- switch (type.getSort()) {
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- case Type.INT:
- t = Opcodes.INTEGER;
- break;
- case Type.FLOAT:
- t = Opcodes.FLOAT;
- break;
- case Type.LONG:
- t = Opcodes.LONG;
- break;
- case Type.DOUBLE:
- t = Opcodes.DOUBLE;
- break;
- case Type.ARRAY:
- t = type.getDescriptor();
- break;
- // case Type.OBJECT:
- default:
- t = type.getInternalName();
- break;
- }
- int local = newLocalMapping(type);
- setLocalType(local, type);
- setFrameLocal(local, t);
- return local;
+ // Visit the remapped frame.
+ super.visitFrame(type, remappedNumLocal, remappedLocalTypes, numStack, stack);
+
+ // Restore the original value of 'remappedLocals'.
+ remappedLocalTypes = oldRemappedLocals;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new local variable of the given type.
+ *
+ * @param type the type of the local variable to be created.
+ * @return the identifier of the newly created local variable.
+ */
+ public int newLocal(final Type type) {
+ Object localType;
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ localType = Opcodes.INTEGER;
+ break;
+ case Type.FLOAT:
+ localType = Opcodes.FLOAT;
+ break;
+ case Type.LONG:
+ localType = Opcodes.LONG;
+ break;
+ case Type.DOUBLE:
+ localType = Opcodes.DOUBLE;
+ break;
+ case Type.ARRAY:
+ localType = type.getDescriptor();
+ break;
+ case Type.OBJECT:
+ localType = type.getInternalName();
+ break;
+ default:
+ throw new AssertionError();
}
-
- /**
- * Notifies subclasses that a new stack map frame is being visited. The
- * array argument contains the stack map frame types corresponding to the
- * local variables added with {@link #newLocal}. This method can update
- * these types in place for the stack map frame being visited. The default
- * implementation of this method does nothing, i.e. a local variable added
- * with {@link #newLocal} will have the same type in all stack map frames.
- * But this behavior is not always the desired one, for instance if a local
- * variable is added in the middle of a try/catch block: the frame for the
- * exception handler should have a TOP type for this new local.
- *
- * @param newLocals
- * the stack map frame types corresponding to the local variables
- * added with {@link #newLocal} (and null for the others). The
- * format of this array is the same as in
- * {@link MethodVisitor#visitFrame}, except that long and double
- * types use two slots. The types for the current stack map frame
- * must be updated in place in this array.
- */
- protected void updateNewLocals(Object[] newLocals) {
- }
-
- /**
- * Notifies subclasses that a local variable has been added or remapped. The
- * default implementation of this method does nothing.
- *
- * @param local
- * a local variable identifier, as returned by {@link #newLocal
- * newLocal()}.
- * @param type
- * the type of the value being stored in the local variable.
- */
- protected void setLocalType(final int local, final Type type) {
+ int local = newLocalMapping(type);
+ setLocalType(local, type);
+ setFrameLocal(local, localType);
+ return local;
+ }
+
+ /**
+ * Notifies subclasses that a new stack map frame is being visited. The array argument contains
+ * the stack map frame types corresponding to the local variables added with {@link #newLocal}.
+ * This method can update these types in place for the stack map frame being visited. The default
+ * implementation of this method does nothing, i.e. a local variable added with {@link #newLocal}
+ * will have the same type in all stack map frames. But this behavior is not always the desired
+ * one, for instance if a local variable is added in the middle of a try/catch block: the frame
+ * for the exception handler should have a TOP type for this new local.
+ *
+ * @param newLocals the stack map frame types corresponding to the local variables added with
+ * {@link #newLocal} (and null for the others). The format of this array is the same as in
+ * {@link MethodVisitor#visitFrame}, except that long and double types use two slots. The
+ * types for the current stack map frame must be updated in place in this array.
+ */
+ protected void updateNewLocals(final Object[] newLocals) {
+ // The default implementation does nothing.
+ }
+
+ /**
+ * Notifies subclasses that a local variable has been added or remapped. The default
+ * implementation of this method does nothing.
+ *
+ * @param local a local variable identifier, as returned by {@link #newLocal}.
+ * @param type the type of the value being stored in the local variable.
+ */
+ protected void setLocalType(final int local, final Type type) {
+ // The default implementation does nothing.
+ }
+
+ private void setFrameLocal(final int local, final Object type) {
+ int numLocals = remappedLocalTypes.length;
+ if (local >= numLocals) {
+ Object[] newRemappedLocalTypes = new Object[Math.max(2 * numLocals, local + 1)];
+ System.arraycopy(remappedLocalTypes, 0, newRemappedLocalTypes, 0, numLocals);
+ remappedLocalTypes = newRemappedLocalTypes;
}
+ remappedLocalTypes[local] = type;
+ }
- private void setFrameLocal(final int local, final Object type) {
- int l = newLocals.length;
- if (local >= l) {
- Object[] a = new Object[Math.max(2 * l, local + 1)];
- System.arraycopy(newLocals, 0, a, 0, l);
- newLocals = a;
- }
- newLocals[local] = type;
+ private int remap(final int var, final Type type) {
+ if (var + type.getSize() <= firstLocal) {
+ return var;
}
-
- private int remap(final int var, final Type type) {
- if (var + type.getSize() <= firstLocal) {
- return var;
- }
- int key = 2 * var + type.getSize() - 1;
- int size = mapping.length;
- if (key >= size) {
- int[] newMapping = new int[Math.max(2 * size, key + 1)];
- System.arraycopy(mapping, 0, newMapping, 0, size);
- mapping = newMapping;
- }
- int value = mapping[key];
- if (value == 0) {
- value = newLocalMapping(type);
- setLocalType(value, type);
- mapping[key] = value + 1;
- } else {
- value--;
- }
- return value;
+ int key = 2 * var + type.getSize() - 1;
+ int size = remappedVariableIndices.length;
+ if (key >= size) {
+ int[] newRemappedVariableIndices = new int[Math.max(2 * size, key + 1)];
+ System.arraycopy(remappedVariableIndices, 0, newRemappedVariableIndices, 0, size);
+ remappedVariableIndices = newRemappedVariableIndices;
}
-
- protected int newLocalMapping(final Type type) {
- int local = nextLocal;
- nextLocal += type.getSize();
- return local;
+ int value = remappedVariableIndices[key];
+ if (value == 0) {
+ value = newLocalMapping(type);
+ setLocalType(value, type);
+ remappedVariableIndices[key] = value + 1;
+ } else {
+ value--;
}
+ return value;
+ }
+
+ protected int newLocalMapping(final Type type) {
+ int local = nextLocal;
+ nextLocal += type.getSize();
+ return local;
+ }
}
[34/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/SymbolTable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/SymbolTable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/SymbolTable.java
new file mode 100755
index 0000000..e6574bb
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/SymbolTable.java
@@ -0,0 +1,1318 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * The constant pool entries, the BootstrapMethods attribute entries and the (ASM specific) type
+ * table entries of a class.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4">JVMS
+ * 4.4</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
+ * 4.7.23</a>
+ * @author Eric Bruneton
+ */
+final class SymbolTable {
+
+ /**
+ * The ClassWriter to which this SymbolTable belongs. This is only used to get access to {@link
+ * ClassWriter#getCommonSuperClass} and to serialize custom attributes with {@link
+ * Attribute#write}.
+ */
+ final ClassWriter classWriter;
+
+ /**
+ * The ClassReader from which this SymbolTable was constructed, or {@literal null} if it was
+ * constructed from scratch.
+ */
+ private final ClassReader sourceClassReader;
+
+ /** The major version number of the class to which this symbol table belongs. */
+ private int majorVersion;
+
+ /** The internal name of the class to which this symbol table belongs. */
+ private String className;
+
+ /**
+ * The total number of {@link Entry} instances in {@link #entries}. This includes entries that are
+ * accessible (recursively) via {@link Entry#next}.
+ */
+ private int entryCount;
+
+ /**
+ * A hash set of all the entries in this SymbolTable (this includes the constant pool entries, the
+ * bootstrap method entries and the type table entries). Each {@link Entry} instance is stored at
+ * the array index given by its hash code modulo the array size. If several entries must be stored
+ * at the same array index, they are linked together via their {@link Entry#next} field. The
+ * factory methods of this class make sure that this table does not contain duplicated entries.
+ */
+ private Entry[] entries;
+
+ /**
+ * The number of constant pool items in {@link #constantPool}, plus 1. The first constant pool
+ * item has index 1, and long and double items count for two items.
+ */
+ private int constantPoolCount;
+
+ /**
+ * The content of the ClassFile's constant_pool JVMS structure corresponding to this SymbolTable.
+ * The ClassFile's constant_pool_count field is <i>not</i> included.
+ */
+ private ByteVector constantPool;
+
+ /**
+ * The number of bootstrap methods in {@link #bootstrapMethods}. Corresponds to the
+ * BootstrapMethods_attribute's num_bootstrap_methods field value.
+ */
+ private int bootstrapMethodCount;
+
+ /**
+ * The content of the BootstrapMethods attribute 'bootstrap_methods' array corresponding to this
+ * SymbolTable. Note that the first 6 bytes of the BootstrapMethods_attribute, and its
+ * num_bootstrap_methods field, are <i>not</i> included.
+ */
+ private ByteVector bootstrapMethods;
+
+ /**
+ * The actual number of elements in {@link #typeTable}. These elements are stored from index 0 to
+ * typeCount (excluded). The other array entries are empty.
+ */
+ private int typeCount;
+
+ /**
+ * An ASM specific type table used to temporarily store internal names that will not necessarily
+ * be stored in the constant pool. This type table is used by the control flow and data flow
+ * analysis algorithm used to compute stack map frames from scratch. This array stores {@link
+ * Symbol#TYPE_TAG} and {@link Symbol#UNINITIALIZED_TYPE_TAG}) Symbol. The type symbol at index
+ * {@code i} has its {@link Symbol#index} equal to {@code i} (and vice versa).
+ */
+ private Entry[] typeTable;
+
+ /**
+ * Constructs a new, empty SymbolTable for the given ClassWriter.
+ *
+ * @param classWriter a ClassWriter.
+ */
+ SymbolTable(final ClassWriter classWriter) {
+ this.classWriter = classWriter;
+ this.sourceClassReader = null;
+ this.entries = new Entry[256];
+ this.constantPoolCount = 1;
+ this.constantPool = new ByteVector();
+ }
+
+ /**
+ * Constructs a new SymbolTable for the given ClassWriter, initialized with the constant pool and
+ * bootstrap methods of the given ClassReader.
+ *
+ * @param classWriter a ClassWriter.
+ * @param classReader the ClassReader whose constant pool and bootstrap methods must be copied to
+ * initialize the SymbolTable.
+ */
+ SymbolTable(final ClassWriter classWriter, final ClassReader classReader) {
+ this.classWriter = classWriter;
+ this.sourceClassReader = classReader;
+
+ // Copy the constant pool binary content.
+ byte[] inputBytes = classReader.b;
+ int constantPoolOffset = classReader.getItem(1) - 1;
+ int constantPoolLength = classReader.header - constantPoolOffset;
+ constantPoolCount = classReader.getItemCount();
+ constantPool = new ByteVector(constantPoolLength);
+ constantPool.putByteArray(inputBytes, constantPoolOffset, constantPoolLength);
+
+ // Add the constant pool items in the symbol table entries. Reserve enough space in 'entries' to
+ // avoid too many hash set collisions (entries is not dynamically resized by the addConstant*
+ // method calls below), and to account for bootstrap method entries.
+ entries = new Entry[constantPoolCount * 2];
+ char[] charBuffer = new char[classReader.getMaxStringLength()];
+ boolean hasBootstrapMethods = false;
+ int itemIndex = 1;
+ while (itemIndex < constantPoolCount) {
+ int itemOffset = classReader.getItem(itemIndex);
+ int itemTag = inputBytes[itemOffset - 1];
+ int nameAndTypeItemOffset;
+ switch (itemTag) {
+ case Symbol.CONSTANT_FIELDREF_TAG:
+ case Symbol.CONSTANT_METHODREF_TAG:
+ case Symbol.CONSTANT_INTERFACE_METHODREF_TAG:
+ nameAndTypeItemOffset =
+ classReader.getItem(classReader.readUnsignedShort(itemOffset + 2));
+ addConstantMemberReference(
+ itemIndex,
+ itemTag,
+ classReader.readClass(itemOffset, charBuffer),
+ classReader.readUTF8(nameAndTypeItemOffset, charBuffer),
+ classReader.readUTF8(nameAndTypeItemOffset + 2, charBuffer));
+ break;
+ case Symbol.CONSTANT_INTEGER_TAG:
+ case Symbol.CONSTANT_FLOAT_TAG:
+ addConstantIntegerOrFloat(itemIndex, itemTag, classReader.readInt(itemOffset));
+ break;
+ case Symbol.CONSTANT_NAME_AND_TYPE_TAG:
+ addConstantNameAndType(
+ itemIndex,
+ classReader.readUTF8(itemOffset, charBuffer),
+ classReader.readUTF8(itemOffset + 2, charBuffer));
+ break;
+ case Symbol.CONSTANT_LONG_TAG:
+ case Symbol.CONSTANT_DOUBLE_TAG:
+ addConstantLongOrDouble(itemIndex, itemTag, classReader.readLong(itemOffset));
+ break;
+ case Symbol.CONSTANT_UTF8_TAG:
+ addConstantUtf8(itemIndex, classReader.readUtf(itemIndex, charBuffer));
+ break;
+ case Symbol.CONSTANT_METHOD_HANDLE_TAG:
+ int memberRefItemOffset =
+ classReader.getItem(classReader.readUnsignedShort(itemOffset + 1));
+ nameAndTypeItemOffset =
+ classReader.getItem(classReader.readUnsignedShort(memberRefItemOffset + 2));
+ addConstantMethodHandle(
+ itemIndex,
+ classReader.readByte(itemOffset),
+ classReader.readClass(memberRefItemOffset, charBuffer),
+ classReader.readUTF8(nameAndTypeItemOffset, charBuffer),
+ classReader.readUTF8(nameAndTypeItemOffset + 2, charBuffer));
+ break;
+ case Symbol.CONSTANT_DYNAMIC_TAG:
+ case Symbol.CONSTANT_INVOKE_DYNAMIC_TAG:
+ hasBootstrapMethods = true;
+ nameAndTypeItemOffset =
+ classReader.getItem(classReader.readUnsignedShort(itemOffset + 2));
+ addConstantDynamicOrInvokeDynamicReference(
+ itemTag,
+ itemIndex,
+ classReader.readUTF8(nameAndTypeItemOffset, charBuffer),
+ classReader.readUTF8(nameAndTypeItemOffset + 2, charBuffer),
+ classReader.readUnsignedShort(itemOffset));
+ break;
+ case Symbol.CONSTANT_STRING_TAG:
+ case Symbol.CONSTANT_CLASS_TAG:
+ case Symbol.CONSTANT_METHOD_TYPE_TAG:
+ case Symbol.CONSTANT_MODULE_TAG:
+ case Symbol.CONSTANT_PACKAGE_TAG:
+ addConstantUtf8Reference(
+ itemIndex, itemTag, classReader.readUTF8(itemOffset, charBuffer));
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ itemIndex +=
+ (itemTag == Symbol.CONSTANT_LONG_TAG || itemTag == Symbol.CONSTANT_DOUBLE_TAG) ? 2 : 1;
+ }
+
+ // Copy the BootstrapMethods, if any.
+ if (hasBootstrapMethods) {
+ copyBootstrapMethods(classReader, charBuffer);
+ }
+ }
+
+ /**
+ * Read the BootstrapMethods 'bootstrap_methods' array binary content and add them as entries of
+ * the SymbolTable.
+ *
+ * @param classReader the ClassReader whose bootstrap methods must be copied to initialize the
+ * SymbolTable.
+ * @param charBuffer a buffer used to read strings in the constant pool.
+ */
+ private void copyBootstrapMethods(final ClassReader classReader, final char[] charBuffer) {
+ // Find attributOffset of the 'bootstrap_methods' array.
+ byte[] inputBytes = classReader.b;
+ int currentAttributeOffset = classReader.getFirstAttributeOffset();
+ for (int i = classReader.readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) {
+ String attributeName = classReader.readUTF8(currentAttributeOffset, charBuffer);
+ if (Constants.BOOTSTRAP_METHODS.equals(attributeName)) {
+ bootstrapMethodCount = classReader.readUnsignedShort(currentAttributeOffset + 6);
+ break;
+ }
+ currentAttributeOffset += 6 + classReader.readInt(currentAttributeOffset + 2);
+ }
+ if (bootstrapMethodCount > 0) {
+ // Compute the offset and the length of the BootstrapMethods 'bootstrap_methods' array.
+ int bootstrapMethodsOffset = currentAttributeOffset + 8;
+ int bootstrapMethodsLength = classReader.readInt(currentAttributeOffset + 2) - 2;
+ bootstrapMethods = new ByteVector(bootstrapMethodsLength);
+ bootstrapMethods.putByteArray(inputBytes, bootstrapMethodsOffset, bootstrapMethodsLength);
+
+ // Add each bootstrap method in the symbol table entries.
+ int currentOffset = bootstrapMethodsOffset;
+ for (int i = 0; i < bootstrapMethodCount; i++) {
+ int offset = currentOffset - bootstrapMethodsOffset;
+ int bootstrapMethodRef = classReader.readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ int numBootstrapArguments = classReader.readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ int hashCode = classReader.readConst(bootstrapMethodRef, charBuffer).hashCode();
+ while (numBootstrapArguments-- > 0) {
+ int bootstrapArgument = classReader.readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ hashCode ^= classReader.readConst(bootstrapArgument, charBuffer).hashCode();
+ }
+ add(new Entry(i, Symbol.BOOTSTRAP_METHOD_TAG, offset, hashCode & 0x7FFFFFFF));
+ }
+ }
+ }
+
+ /**
+ * Returns the ClassReader from which this SymbolTable was constructed.
+ *
+ * @return the ClassReader from which this SymbolTable was constructed, or {@literal null} if it
+ * was constructed from scratch.
+ */
+ ClassReader getSource() {
+ return sourceClassReader;
+ }
+
+ /**
+ * Returns the major version of the class to which this symbol table belongs.
+ *
+ * @return the major version of the class to which this symbol table belongs.
+ */
+ int getMajorVersion() {
+ return majorVersion;
+ }
+
+ /**
+ * Returns the internal name of the class to which this symbol table belongs.
+ *
+ * @return the internal name of the class to which this symbol table belongs.
+ */
+ String getClassName() {
+ return className;
+ }
+
+ /**
+ * Sets the major version and the name of the class to which this symbol table belongs. Also adds
+ * the class name to the constant pool.
+ *
+ * @param majorVersion a major ClassFile version number.
+ * @param className an internal class name.
+ * @return the constant pool index of a new or already existing Symbol with the given class name.
+ */
+ int setMajorVersionAndClassName(final int majorVersion, final String className) {
+ this.majorVersion = majorVersion;
+ this.className = className;
+ return addConstantClass(className).index;
+ }
+
+ /**
+ * Returns the number of items in this symbol table's constant_pool array (plus 1).
+ *
+ * @return the number of items in this symbol table's constant_pool array (plus 1).
+ */
+ int getConstantPoolCount() {
+ return constantPoolCount;
+ }
+
+ /**
+ * Returns the length in bytes of this symbol table's constant_pool array.
+ *
+ * @return the length in bytes of this symbol table's constant_pool array.
+ */
+ int getConstantPoolLength() {
+ return constantPool.length;
+ }
+
+ /**
+ * Puts this symbol table's constant_pool array in the given ByteVector, preceded by the
+ * constant_pool_count value.
+ *
+ * @param output where the JVMS ClassFile's constant_pool array must be put.
+ */
+ void putConstantPool(final ByteVector output) {
+ output.putShort(constantPoolCount).putByteArray(constantPool.data, 0, constantPool.length);
+ }
+
+ /**
+ * Returns the size in bytes of this symbol table's BootstrapMethods attribute. Also adds the
+ * attribute name in the constant pool.
+ *
+ * @return the size in bytes of this symbol table's BootstrapMethods attribute.
+ */
+ int computeBootstrapMethodsSize() {
+ if (bootstrapMethods != null) {
+ addConstantUtf8(Constants.BOOTSTRAP_METHODS);
+ return 8 + bootstrapMethods.length;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Puts this symbol table's BootstrapMethods attribute in the given ByteVector. This includes the
+ * 6 attribute header bytes and the num_bootstrap_methods value.
+ *
+ * @param output where the JVMS BootstrapMethods attribute must be put.
+ */
+ void putBootstrapMethods(final ByteVector output) {
+ if (bootstrapMethods != null) {
+ output
+ .putShort(addConstantUtf8(Constants.BOOTSTRAP_METHODS))
+ .putInt(bootstrapMethods.length + 2)
+ .putShort(bootstrapMethodCount)
+ .putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Generic symbol table entries management.
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the list of entries which can potentially have the given hash code.
+ *
+ * @param hashCode a {@link Entry#hashCode} value.
+ * @return the list of entries which can potentially have the given hash code. The list is stored
+ * via the {@link Entry#next} field.
+ */
+ private Entry get(final int hashCode) {
+ return entries[hashCode % entries.length];
+ }
+
+ /**
+ * Puts the given entry in the {@link #entries} hash set. This method does <i>not</i> check
+ * whether {@link #entries} already contains a similar entry or not. {@link #entries} is resized
+ * if necessary to avoid hash collisions (multiple entries needing to be stored at the same {@link
+ * #entries} array index) as much as possible, with reasonable memory usage.
+ *
+ * @param entry an Entry (which must not already be contained in {@link #entries}).
+ * @return the given entry
+ */
+ private Entry put(final Entry entry) {
+ if (entryCount > (entries.length * 3) / 4) {
+ int currentCapacity = entries.length;
+ int newCapacity = currentCapacity * 2 + 1;
+ Entry[] newEntries = new Entry[newCapacity];
+ for (int i = currentCapacity - 1; i >= 0; --i) {
+ Entry currentEntry = entries[i];
+ while (currentEntry != null) {
+ int newCurrentEntryIndex = currentEntry.hashCode % newCapacity;
+ Entry nextEntry = currentEntry.next;
+ currentEntry.next = newEntries[newCurrentEntryIndex];
+ newEntries[newCurrentEntryIndex] = currentEntry;
+ currentEntry = nextEntry;
+ }
+ }
+ entries = newEntries;
+ }
+ entryCount++;
+ int index = entry.hashCode % entries.length;
+ entry.next = entries[index];
+ return entries[index] = entry;
+ }
+
+ /**
+ * Adds the given entry in the {@link #entries} hash set. This method does <i>not</i> check
+ * whether {@link #entries} already contains a similar entry or not, and does <i>not</i> resize
+ * {@link #entries} if necessary.
+ *
+ * @param entry an Entry (which must not already be contained in {@link #entries}).
+ */
+ private void add(final Entry entry) {
+ entryCount++;
+ int index = entry.hashCode % entries.length;
+ entry.next = entries[index];
+ entries[index] = entry;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Constant pool entries management.
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Adds a number or string constant to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param value the value of the constant to be added to the constant pool. This parameter must be
+ * an {@link Integer}, {@link Byte}, {@link Character}, {@link Short}, {@link Boolean}, {@link
+ * Float}, {@link Long}, {@link Double}, {@link String}, {@link Type} or {@link Handle}.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstant(final Object value) {
+ if (value instanceof Integer) {
+ return addConstantInteger(((Integer) value).intValue());
+ } else if (value instanceof Byte) {
+ return addConstantInteger(((Byte) value).intValue());
+ } else if (value instanceof Character) {
+ return addConstantInteger(((Character) value).charValue());
+ } else if (value instanceof Short) {
+ return addConstantInteger(((Short) value).intValue());
+ } else if (value instanceof Boolean) {
+ return addConstantInteger(((Boolean) value).booleanValue() ? 1 : 0);
+ } else if (value instanceof Float) {
+ return addConstantFloat(((Float) value).floatValue());
+ } else if (value instanceof Long) {
+ return addConstantLong(((Long) value).longValue());
+ } else if (value instanceof Double) {
+ return addConstantDouble(((Double) value).doubleValue());
+ } else if (value instanceof String) {
+ return addConstantString((String) value);
+ } else if (value instanceof Type) {
+ Type type = (Type) value;
+ int typeSort = type.getSort();
+ if (typeSort == Type.OBJECT) {
+ return addConstantClass(type.getInternalName());
+ } else if (typeSort == Type.METHOD) {
+ return addConstantMethodType(type.getDescriptor());
+ } else { // type is a primitive or array type.
+ return addConstantClass(type.getDescriptor());
+ }
+ } else if (value instanceof Handle) {
+ Handle handle = (Handle) value;
+ return addConstantMethodHandle(
+ handle.getTag(),
+ handle.getOwner(),
+ handle.getName(),
+ handle.getDesc(),
+ handle.isInterface());
+ } else if (value instanceof ConstantDynamic) {
+ ConstantDynamic constantDynamic = (ConstantDynamic) value;
+ return addConstantDynamic(
+ constantDynamic.getName(),
+ constantDynamic.getDescriptor(),
+ constantDynamic.getBootstrapMethod(),
+ constantDynamic.getBootstrapMethodArgumentsUnsafe());
+ } else {
+ throw new IllegalArgumentException("value " + value);
+ }
+ }
+
+ /**
+ * Adds a CONSTANT_Class_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param value the internal name of a class.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantClass(final String value) {
+ return addConstantUtf8Reference(Symbol.CONSTANT_CLASS_TAG, value);
+ }
+
+ /**
+ * Adds a CONSTANT_Fieldref_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param owner the internal name of a class.
+ * @param name a field name.
+ * @param descriptor a field descriptor.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantFieldref(final String owner, final String name, final String descriptor) {
+ return addConstantMemberReference(Symbol.CONSTANT_FIELDREF_TAG, owner, name, descriptor);
+ }
+
+ /**
+ * Adds a CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info to the constant pool of this
+ * symbol table. Does nothing if the constant pool already contains a similar item.
+ *
+ * @param owner the internal name of a class.
+ * @param name a method name.
+ * @param descriptor a method descriptor.
+ * @param isInterface whether owner is an interface or not.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantMethodref(
+ final String owner, final String name, final String descriptor, final boolean isInterface) {
+ int tag = isInterface ? Symbol.CONSTANT_INTERFACE_METHODREF_TAG : Symbol.CONSTANT_METHODREF_TAG;
+ return addConstantMemberReference(tag, owner, name, descriptor);
+ }
+
+ /**
+ * Adds a CONSTANT_Fieldref_info, CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info to
+ * the constant pool of this symbol table. Does nothing if the constant pool already contains a
+ * similar item.
+ *
+ * @param tag one of {@link Symbol#CONSTANT_FIELDREF_TAG}, {@link Symbol#CONSTANT_METHODREF_TAG}
+ * or {@link Symbol#CONSTANT_INTERFACE_METHODREF_TAG}.
+ * @param owner the internal name of a class.
+ * @param name a field or method name.
+ * @param descriptor a field or method descriptor.
+ * @return a new or already existing Symbol with the given value.
+ */
+ private Entry addConstantMemberReference(
+ final int tag, final String owner, final String name, final String descriptor) {
+ int hashCode = hash(tag, owner, name, descriptor);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == tag
+ && entry.hashCode == hashCode
+ && entry.owner.equals(owner)
+ && entry.name.equals(name)
+ && entry.value.equals(descriptor)) {
+ return entry;
+ }
+ entry = entry.next;
+ }
+ constantPool.put122(
+ tag, addConstantClass(owner).index, addConstantNameAndType(name, descriptor));
+ return put(new Entry(constantPoolCount++, tag, owner, name, descriptor, 0, hashCode));
+ }
+
+ /**
+ * Adds a new CONSTANT_Fieldref_info, CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info
+ * to the constant pool of this symbol table.
+ *
+ * @param index the constant pool index of the new Symbol.
+ * @param tag one of {@link Symbol#CONSTANT_FIELDREF_TAG}, {@link Symbol#CONSTANT_METHODREF_TAG}
+ * or {@link Symbol#CONSTANT_INTERFACE_METHODREF_TAG}.
+ * @param owner the internal name of a class.
+ * @param name a field or method name.
+ * @param descriptor a field or method descriptor.
+ */
+ private void addConstantMemberReference(
+ final int index,
+ final int tag,
+ final String owner,
+ final String name,
+ final String descriptor) {
+ add(new Entry(index, tag, owner, name, descriptor, 0, hash(tag, owner, name, descriptor)));
+ }
+
+ /**
+ * Adds a CONSTANT_String_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param value a string.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantString(final String value) {
+ return addConstantUtf8Reference(Symbol.CONSTANT_STRING_TAG, value);
+ }
+
+ /**
+ * Adds a CONSTANT_Integer_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param value an int.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantInteger(final int value) {
+ return addConstantIntegerOrFloat(Symbol.CONSTANT_INTEGER_TAG, value);
+ }
+
+ /**
+ * Adds a CONSTANT_Float_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param value a float.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantFloat(final float value) {
+ return addConstantIntegerOrFloat(Symbol.CONSTANT_FLOAT_TAG, Float.floatToRawIntBits(value));
+ }
+
+ /**
+ * Adds a CONSTANT_Integer_info or CONSTANT_Float_info to the constant pool of this symbol table.
+ * Does nothing if the constant pool already contains a similar item.
+ *
+ * @param tag one of {@link Symbol#CONSTANT_INTEGER_TAG} or {@link Symbol#CONSTANT_FLOAT_TAG}.
+ * @param value an int or float.
+ * @return a constant pool constant with the given tag and primitive values.
+ */
+ private Symbol addConstantIntegerOrFloat(final int tag, final int value) {
+ int hashCode = hash(tag, value);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == tag && entry.hashCode == hashCode && entry.data == value) {
+ return entry;
+ }
+ entry = entry.next;
+ }
+ constantPool.putByte(tag).putInt(value);
+ return put(new Entry(constantPoolCount++, tag, value, hashCode));
+ }
+
+ /**
+ * Adds a new CONSTANT_Integer_info or CONSTANT_Float_info to the constant pool of this symbol
+ * table.
+ *
+ * @param index the constant pool index of the new Symbol.
+ * @param tag one of {@link Symbol#CONSTANT_INTEGER_TAG} or {@link Symbol#CONSTANT_FLOAT_TAG}.
+ * @param value an int or float.
+ */
+ private void addConstantIntegerOrFloat(final int index, final int tag, final int value) {
+ add(new Entry(index, tag, value, hash(tag, value)));
+ }
+
+ /**
+ * Adds a CONSTANT_Long_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param value a long.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantLong(final long value) {
+ return addConstantLongOrDouble(Symbol.CONSTANT_LONG_TAG, value);
+ }
+
+ /**
+ * Adds a CONSTANT_Double_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param value a double.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantDouble(final double value) {
+ return addConstantLongOrDouble(Symbol.CONSTANT_DOUBLE_TAG, Double.doubleToRawLongBits(value));
+ }
+
+ /**
+ * Adds a CONSTANT_Long_info or CONSTANT_Double_info to the constant pool of this symbol table.
+ * Does nothing if the constant pool already contains a similar item.
+ *
+ * @param tag one of {@link Symbol#CONSTANT_LONG_TAG} or {@link Symbol#CONSTANT_DOUBLE_TAG}.
+ * @param value a long or double.
+ * @return a constant pool constant with the given tag and primitive values.
+ */
+ private Symbol addConstantLongOrDouble(final int tag, final long value) {
+ int hashCode = hash(tag, value);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == tag && entry.hashCode == hashCode && entry.data == value) {
+ return entry;
+ }
+ entry = entry.next;
+ }
+ int index = constantPoolCount;
+ constantPool.putByte(tag).putLong(value);
+ constantPoolCount += 2;
+ return put(new Entry(index, tag, value, hashCode));
+ }
+
+ /**
+ * Adds a new CONSTANT_Long_info or CONSTANT_Double_info to the constant pool of this symbol
+ * table.
+ *
+ * @param index the constant pool index of the new Symbol.
+ * @param tag one of {@link Symbol#CONSTANT_LONG_TAG} or {@link Symbol#CONSTANT_DOUBLE_TAG}.
+ * @param value a long or double.
+ */
+ private void addConstantLongOrDouble(final int index, final int tag, final long value) {
+ add(new Entry(index, tag, value, hash(tag, value)));
+ }
+
+ /**
+ * Adds a CONSTANT_NameAndType_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param name a field or method name.
+ * @param descriptor a field or method descriptor.
+ * @return a new or already existing Symbol with the given value.
+ */
+ int addConstantNameAndType(final String name, final String descriptor) {
+ final int tag = Symbol.CONSTANT_NAME_AND_TYPE_TAG;
+ int hashCode = hash(tag, name, descriptor);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == tag
+ && entry.hashCode == hashCode
+ && entry.name.equals(name)
+ && entry.value.equals(descriptor)) {
+ return entry.index;
+ }
+ entry = entry.next;
+ }
+ constantPool.put122(tag, addConstantUtf8(name), addConstantUtf8(descriptor));
+ return put(new Entry(constantPoolCount++, tag, name, descriptor, hashCode)).index;
+ }
+
+ /**
+ * Adds a new CONSTANT_NameAndType_info to the constant pool of this symbol table.
+ *
+ * @param index the constant pool index of the new Symbol.
+ * @param name a field or method name.
+ * @param descriptor a field or method descriptor.
+ */
+ private void addConstantNameAndType(final int index, final String name, final String descriptor) {
+ final int tag = Symbol.CONSTANT_NAME_AND_TYPE_TAG;
+ add(new Entry(index, tag, name, descriptor, hash(tag, name, descriptor)));
+ }
+
+ /**
+ * Adds a CONSTANT_Utf8_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param value a string.
+ * @return a new or already existing Symbol with the given value.
+ */
+ int addConstantUtf8(final String value) {
+ int hashCode = hash(Symbol.CONSTANT_UTF8_TAG, value);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == Symbol.CONSTANT_UTF8_TAG
+ && entry.hashCode == hashCode
+ && entry.value.equals(value)) {
+ return entry.index;
+ }
+ entry = entry.next;
+ }
+ constantPool.putByte(Symbol.CONSTANT_UTF8_TAG).putUTF8(value);
+ return put(new Entry(constantPoolCount++, Symbol.CONSTANT_UTF8_TAG, value, hashCode)).index;
+ }
+
+ /**
+ * Adds a new CONSTANT_String_info to the constant pool of this symbol table.
+ *
+ * @param index the constant pool index of the new Symbol.
+ * @param value a string.
+ */
+ private void addConstantUtf8(final int index, final String value) {
+ add(new Entry(index, Symbol.CONSTANT_UTF8_TAG, value, hash(Symbol.CONSTANT_UTF8_TAG, value)));
+ }
+
+ /**
+ * Adds a CONSTANT_MethodHandle_info to the constant pool of this symbol table. Does nothing if
+ * the constant pool already contains a similar item.
+ *
+ * @param referenceKind one of {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link
+ * Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link
+ * Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, {@link
+ * Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner the internal name of a class of interface.
+ * @param name a field or method name.
+ * @param descriptor a field or method descriptor.
+ * @param isInterface whether owner is an interface or not.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantMethodHandle(
+ final int referenceKind,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ final int tag = Symbol.CONSTANT_METHOD_HANDLE_TAG;
+ // Note that we don't need to include isInterface in the hash computation, because it is
+ // redundant with owner (we can't have the same owner with different isInterface values).
+ int hashCode = hash(tag, owner, name, descriptor, referenceKind);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == tag
+ && entry.hashCode == hashCode
+ && entry.data == referenceKind
+ && entry.owner.equals(owner)
+ && entry.name.equals(name)
+ && entry.value.equals(descriptor)) {
+ return entry;
+ }
+ entry = entry.next;
+ }
+ if (referenceKind <= Opcodes.H_PUTSTATIC) {
+ constantPool.put112(tag, referenceKind, addConstantFieldref(owner, name, descriptor).index);
+ } else {
+ constantPool.put112(
+ tag, referenceKind, addConstantMethodref(owner, name, descriptor, isInterface).index);
+ }
+ return put(
+ new Entry(constantPoolCount++, tag, owner, name, descriptor, referenceKind, hashCode));
+ }
+
+ /**
+ * Adds a new CONSTANT_MethodHandle_info to the constant pool of this symbol table.
+ *
+ * @param index the constant pool index of the new Symbol.
+ * @param referenceKind one of {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link
+ * Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link
+ * Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, {@link
+ * Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner the internal name of a class of interface.
+ * @param name a field or method name.
+ * @param descriptor a field or method descriptor.
+ */
+ private void addConstantMethodHandle(
+ final int index,
+ final int referenceKind,
+ final String owner,
+ final String name,
+ final String descriptor) {
+ final int tag = Symbol.CONSTANT_METHOD_HANDLE_TAG;
+ int hashCode = hash(tag, owner, name, descriptor, referenceKind);
+ add(new Entry(index, tag, owner, name, descriptor, referenceKind, hashCode));
+ }
+
+ /**
+ * Adds a CONSTANT_MethodType_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantMethodType(final String methodDescriptor) {
+ return addConstantUtf8Reference(Symbol.CONSTANT_METHOD_TYPE_TAG, methodDescriptor);
+ }
+
+ /**
+ * Adds a CONSTANT_Dynamic_info to the constant pool of this symbol table. Also adds the related
+ * bootstrap method to the BootstrapMethods of this symbol table. Does nothing if the constant
+ * pool already contains a similar item.
+ *
+ * @param name a method name.
+ * @param descriptor a field descriptor.
+ * @param bootstrapMethodHandle a bootstrap method handle.
+ * @param bootstrapMethodArguments the bootstrap method arguments.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantDynamic(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ Symbol bootstrapMethod = addBootstrapMethod(bootstrapMethodHandle, bootstrapMethodArguments);
+ return addConstantDynamicOrInvokeDynamicReference(
+ Symbol.CONSTANT_DYNAMIC_TAG, name, descriptor, bootstrapMethod.index);
+ }
+
+ /**
+ * Adds a CONSTANT_InvokeDynamic_info to the constant pool of this symbol table. Also adds the
+ * related bootstrap method to the BootstrapMethods of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param name a method name.
+ * @param descriptor a method descriptor.
+ * @param bootstrapMethodHandle a bootstrap method handle.
+ * @param bootstrapMethodArguments the bootstrap method arguments.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantInvokeDynamic(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ Symbol bootstrapMethod = addBootstrapMethod(bootstrapMethodHandle, bootstrapMethodArguments);
+ return addConstantDynamicOrInvokeDynamicReference(
+ Symbol.CONSTANT_INVOKE_DYNAMIC_TAG, name, descriptor, bootstrapMethod.index);
+ }
+
+ /**
+ * Adds a CONSTANT_Dynamic or a CONSTANT_InvokeDynamic_info to the constant pool of this symbol
+ * table. Does nothing if the constant pool already contains a similar item.
+ *
+ * @param tag one of {@link Symbol#CONSTANT_DYNAMIC_TAG} or {@link
+ * Symbol#CONSTANT_INVOKE_DYNAMIC_TAG}.
+ * @param name a method name.
+ * @param descriptor a field descriptor for CONSTANT_DYNAMIC_TAG) or a method descriptor for
+ * CONSTANT_INVOKE_DYNAMIC_TAG.
+ * @param bootstrapMethodIndex the index of a bootstrap method in the BootstrapMethods attribute.
+ * @return a new or already existing Symbol with the given value.
+ */
+ private Symbol addConstantDynamicOrInvokeDynamicReference(
+ final int tag, final String name, final String descriptor, final int bootstrapMethodIndex) {
+ int hashCode = hash(tag, name, descriptor, bootstrapMethodIndex);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == tag
+ && entry.hashCode == hashCode
+ && entry.data == bootstrapMethodIndex
+ && entry.name.equals(name)
+ && entry.value.equals(descriptor)) {
+ return entry;
+ }
+ entry = entry.next;
+ }
+ constantPool.put122(tag, bootstrapMethodIndex, addConstantNameAndType(name, descriptor));
+ return put(
+ new Entry(
+ constantPoolCount++, tag, null, name, descriptor, bootstrapMethodIndex, hashCode));
+ }
+
+ /**
+ * Adds a new CONSTANT_Dynamic_info or CONSTANT_InvokeDynamic_info to the constant pool of this
+ * symbol table.
+ *
+ * @param tag one of {@link Symbol#CONSTANT_DYNAMIC_TAG} or {@link
+ * Symbol#CONSTANT_INVOKE_DYNAMIC_TAG}.
+ * @param index the constant pool index of the new Symbol.
+ * @param name a method name.
+ * @param descriptor a field descriptor for CONSTANT_DYNAMIC_TAG or a method descriptor for
+ * CONSTANT_INVOKE_DYNAMIC_TAG.
+ * @param bootstrapMethodIndex the index of a bootstrap method in the BootstrapMethods attribute.
+ */
+ private void addConstantDynamicOrInvokeDynamicReference(
+ final int tag,
+ final int index,
+ final String name,
+ final String descriptor,
+ final int bootstrapMethodIndex) {
+ int hashCode = hash(tag, name, descriptor, bootstrapMethodIndex);
+ add(new Entry(index, tag, null, name, descriptor, bootstrapMethodIndex, hashCode));
+ }
+
+ /**
+ * Adds a CONSTANT_Module_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param moduleName a fully qualified name (using dots) of a module.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantModule(final String moduleName) {
+ return addConstantUtf8Reference(Symbol.CONSTANT_MODULE_TAG, moduleName);
+ }
+
+ /**
+ * Adds a CONSTANT_Package_info to the constant pool of this symbol table. Does nothing if the
+ * constant pool already contains a similar item.
+ *
+ * @param packageName the internal name of a package.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addConstantPackage(final String packageName) {
+ return addConstantUtf8Reference(Symbol.CONSTANT_PACKAGE_TAG, packageName);
+ }
+
+ /**
+ * Adds a CONSTANT_Class_info, CONSTANT_String_info, CONSTANT_MethodType_info,
+ * CONSTANT_Module_info or CONSTANT_Package_info to the constant pool of this symbol table. Does
+ * nothing if the constant pool already contains a similar item.
+ *
+ * @param tag one of {@link Symbol#CONSTANT_CLASS_TAG}, {@link Symbol#CONSTANT_STRING_TAG}, {@link
+ * Symbol#CONSTANT_METHOD_TYPE_TAG}, {@link Symbol#CONSTANT_MODULE_TAG} or {@link
+ * Symbol#CONSTANT_PACKAGE_TAG}.
+ * @param value an internal class name, an arbitrary string, a method descriptor, a module or a
+ * package name, depending on tag.
+ * @return a new or already existing Symbol with the given value.
+ */
+ private Symbol addConstantUtf8Reference(final int tag, final String value) {
+ int hashCode = hash(tag, value);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == tag && entry.hashCode == hashCode && entry.value.equals(value)) {
+ return entry;
+ }
+ entry = entry.next;
+ }
+ constantPool.put12(tag, addConstantUtf8(value));
+ return put(new Entry(constantPoolCount++, tag, value, hashCode));
+ }
+
+ /**
+ * Adds a new CONSTANT_Class_info, CONSTANT_String_info, CONSTANT_MethodType_info,
+ * CONSTANT_Module_info or CONSTANT_Package_info to the constant pool of this symbol table.
+ *
+ * @param index the constant pool index of the new Symbol.
+ * @param tag one of {@link Symbol#CONSTANT_CLASS_TAG}, {@link Symbol#CONSTANT_STRING_TAG}, {@link
+ * Symbol#CONSTANT_METHOD_TYPE_TAG}, {@link Symbol#CONSTANT_MODULE_TAG} or {@link
+ * Symbol#CONSTANT_PACKAGE_TAG}.
+ * @param value an internal class name, an arbitrary string, a method descriptor, a module or a
+ * package name, depending on tag.
+ */
+ private void addConstantUtf8Reference(final int index, final int tag, final String value) {
+ add(new Entry(index, tag, value, hash(tag, value)));
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Bootstrap method entries management.
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Adds a bootstrap method to the BootstrapMethods attribute of this symbol table. Does nothing if
+ * the BootstrapMethods already contains a similar bootstrap method.
+ *
+ * @param bootstrapMethodHandle a bootstrap method handle.
+ * @param bootstrapMethodArguments the bootstrap method arguments.
+ * @return a new or already existing Symbol with the given value.
+ */
+ Symbol addBootstrapMethod(
+ final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments) {
+ ByteVector bootstrapMethodsAttribute = bootstrapMethods;
+ if (bootstrapMethodsAttribute == null) {
+ bootstrapMethodsAttribute = bootstrapMethods = new ByteVector();
+ }
+
+ // The bootstrap method arguments can be Constant_Dynamic values, which reference other
+ // bootstrap methods. We must therefore add the bootstrap method arguments to the constant pool
+ // and BootstrapMethods attribute first, so that the BootstrapMethods attribute is not modified
+ // while adding the given bootstrap method to it, in the rest of this method.
+ for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
+ addConstant(bootstrapMethodArgument);
+ }
+
+ // Write the bootstrap method in the BootstrapMethods table. This is necessary to be able to
+ // compare it with existing ones, and will be reverted below if there is already a similar
+ // bootstrap method.
+ int bootstrapMethodOffset = bootstrapMethodsAttribute.length;
+ bootstrapMethodsAttribute.putShort(
+ addConstantMethodHandle(
+ bootstrapMethodHandle.getTag(),
+ bootstrapMethodHandle.getOwner(),
+ bootstrapMethodHandle.getName(),
+ bootstrapMethodHandle.getDesc(),
+ bootstrapMethodHandle.isInterface())
+ .index);
+ int numBootstrapArguments = bootstrapMethodArguments.length;
+ bootstrapMethodsAttribute.putShort(numBootstrapArguments);
+ for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
+ bootstrapMethodsAttribute.putShort(addConstant(bootstrapMethodArgument).index);
+ }
+
+ // Compute the length and the hash code of the bootstrap method.
+ int bootstrapMethodlength = bootstrapMethodsAttribute.length - bootstrapMethodOffset;
+ int hashCode = bootstrapMethodHandle.hashCode();
+ for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
+ hashCode ^= bootstrapMethodArgument.hashCode();
+ }
+ hashCode &= 0x7FFFFFFF;
+
+ // Add the bootstrap method to the symbol table or revert the above changes.
+ return addBootstrapMethod(bootstrapMethodOffset, bootstrapMethodlength, hashCode);
+ }
+
+ /**
+ * Adds a bootstrap method to the BootstrapMethods attribute of this symbol table. Does nothing if
+ * the BootstrapMethods already contains a similar bootstrap method (more precisely, reverts the
+ * content of {@link #bootstrapMethods} to remove the last, duplicate bootstrap method).
+ *
+ * @param offset the offset of the last bootstrap method in {@link #bootstrapMethods}, in bytes.
+ * @param length the length of this bootstrap method in {@link #bootstrapMethods}, in bytes.
+ * @param hashCode the hash code of this bootstrap method.
+ * @return a new or already existing Symbol with the given value.
+ */
+ private Symbol addBootstrapMethod(final int offset, final int length, final int hashCode) {
+ final byte[] bootstrapMethodsData = bootstrapMethods.data;
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == Symbol.BOOTSTRAP_METHOD_TAG && entry.hashCode == hashCode) {
+ int otherOffset = (int) entry.data;
+ boolean isSameBootstrapMethod = true;
+ for (int i = 0; i < length; ++i) {
+ if (bootstrapMethodsData[offset + i] != bootstrapMethodsData[otherOffset + i]) {
+ isSameBootstrapMethod = false;
+ break;
+ }
+ }
+ if (isSameBootstrapMethod) {
+ bootstrapMethods.length = offset; // Revert to old position.
+ return entry;
+ }
+ }
+ entry = entry.next;
+ }
+ return put(new Entry(bootstrapMethodCount++, Symbol.BOOTSTRAP_METHOD_TAG, offset, hashCode));
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Type table entries management.
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the type table element whose index is given.
+ *
+ * @param typeIndex a type table index.
+ * @return the type table element whose index is given.
+ */
+ Symbol getType(final int typeIndex) {
+ return typeTable[typeIndex];
+ }
+
+ /**
+ * Adds a type in the type table of this symbol table. Does nothing if the type table already
+ * contains a similar type.
+ *
+ * @param value an internal class name.
+ * @return the index of a new or already existing type Symbol with the given value.
+ */
+ int addType(final String value) {
+ int hashCode = hash(Symbol.TYPE_TAG, value);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == Symbol.TYPE_TAG && entry.hashCode == hashCode && entry.value.equals(value)) {
+ return entry.index;
+ }
+ entry = entry.next;
+ }
+ return addTypeInternal(new Entry(typeCount, Symbol.TYPE_TAG, value, hashCode));
+ }
+
+ /**
+ * Adds an {@link Frame#ITEM_UNINITIALIZED} type in the type table of this symbol table. Does
+ * nothing if the type table already contains a similar type.
+ *
+ * @param value an internal class name.
+ * @param bytecodeOffset the bytecode offset of the NEW instruction that created this {@link
+ * Frame#ITEM_UNINITIALIZED} type value.
+ * @return the index of a new or already existing type Symbol with the given value.
+ */
+ int addUninitializedType(final String value, final int bytecodeOffset) {
+ int hashCode = hash(Symbol.UNINITIALIZED_TYPE_TAG, value, bytecodeOffset);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == Symbol.UNINITIALIZED_TYPE_TAG
+ && entry.hashCode == hashCode
+ && entry.data == bytecodeOffset
+ && entry.value.equals(value)) {
+ return entry.index;
+ }
+ entry = entry.next;
+ }
+ return addTypeInternal(
+ new Entry(typeCount, Symbol.UNINITIALIZED_TYPE_TAG, value, bytecodeOffset, hashCode));
+ }
+
+ /**
+ * Adds a merged type in the type table of this symbol table. Does nothing if the type table
+ * already contains a similar type.
+ *
+ * @param typeTableIndex1 a {@link Symbol#TYPE_TAG} type, specified by its index in the type
+ * table.
+ * @param typeTableIndex2 another {@link Symbol#TYPE_TAG} type, specified by its index in the type
+ * table.
+ * @return the index of a new or already existing {@link Symbol#TYPE_TAG} type Symbol,
+ * corresponding to the common super class of the given types.
+ */
+ int addMergedType(final int typeTableIndex1, final int typeTableIndex2) {
+ // TODO sort the arguments? The merge result should be independent of their order.
+ long data = typeTableIndex1 | (((long) typeTableIndex2) << 32);
+ int hashCode = hash(Symbol.MERGED_TYPE_TAG, typeTableIndex1 + typeTableIndex2);
+ Entry entry = get(hashCode);
+ while (entry != null) {
+ if (entry.tag == Symbol.MERGED_TYPE_TAG && entry.hashCode == hashCode && entry.data == data) {
+ return entry.info;
+ }
+ entry = entry.next;
+ }
+ String type1 = typeTable[typeTableIndex1].value;
+ String type2 = typeTable[typeTableIndex2].value;
+ int commonSuperTypeIndex = addType(classWriter.getCommonSuperClass(type1, type2));
+ put(new Entry(typeCount, Symbol.MERGED_TYPE_TAG, data, hashCode)).info = commonSuperTypeIndex;
+ return commonSuperTypeIndex;
+ }
+
+ /**
+ * Adds the given type Symbol to {@link #typeTable}.
+ *
+ * @param entry a {@link Symbol#TYPE_TAG} or {@link Symbol#UNINITIALIZED_TYPE_TAG} type symbol.
+ * The index of this Symbol must be equal to the current value of {@link #typeCount}.
+ * @return the index in {@link #typeTable} where the given type was added, which is also equal to
+ * entry's index by hypothesis.
+ */
+ private int addTypeInternal(final Entry entry) {
+ if (typeTable == null) {
+ typeTable = new Entry[16];
+ }
+ if (typeCount == typeTable.length) {
+ Entry[] newTypeTable = new Entry[2 * typeTable.length];
+ System.arraycopy(typeTable, 0, newTypeTable, 0, typeTable.length);
+ typeTable = newTypeTable;
+ }
+ typeTable[typeCount++] = entry;
+ return put(entry).index;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Static helper methods to compute hash codes.
+ // -----------------------------------------------------------------------------------------------
+
+ private static int hash(final int tag, final int value) {
+ return 0x7FFFFFFF & (tag + value);
+ }
+
+ private static int hash(final int tag, final long value) {
+ return 0x7FFFFFFF & (tag + (int) value + (int) (value >>> 32));
+ }
+
+ private static int hash(final int tag, final String value) {
+ return 0x7FFFFFFF & (tag + value.hashCode());
+ }
+
+ private static int hash(final int tag, final String value1, final int value2) {
+ return 0x7FFFFFFF & (tag + value1.hashCode() + value2);
+ }
+
+ private static int hash(final int tag, final String value1, final String value2) {
+ return 0x7FFFFFFF & (tag + value1.hashCode() * value2.hashCode());
+ }
+
+ private static int hash(
+ final int tag, final String value1, final String value2, final int value3) {
+ return 0x7FFFFFFF & (tag + value1.hashCode() * value2.hashCode() * (value3 + 1));
+ }
+
+ private static int hash(
+ final int tag, final String value1, final String value2, final String value3) {
+ return 0x7FFFFFFF & (tag + value1.hashCode() * value2.hashCode() * value3.hashCode());
+ }
+
+ private static int hash(
+ final int tag,
+ final String value1,
+ final String value2,
+ final String value3,
+ final int value4) {
+ return 0x7FFFFFFF & (tag + value1.hashCode() * value2.hashCode() * value3.hashCode() * value4);
+ }
+
+ /**
+ * An entry of a SymbolTable. This concrete and private subclass of {@link Symbol} adds two fields
+ * which are only used inside SymbolTable, to implement hash sets of symbols (in order to avoid
+ * duplicate symbols). See {@link #entries}.
+ *
+ * @author Eric Bruneton
+ */
+ private static class Entry extends Symbol {
+
+ /** The hash code of this entry. */
+ final int hashCode;
+
+ /**
+ * Another entry (and so on recursively) having the same hash code (modulo the size of {@link
+ * #entries}) as this one.
+ */
+ Entry next;
+
+ Entry(
+ final int index,
+ final int tag,
+ final String owner,
+ final String name,
+ final String value,
+ final long data,
+ final int hashCode) {
+ super(index, tag, owner, name, value, data);
+ this.hashCode = hashCode;
+ }
+
+ Entry(final int index, final int tag, final String value, final int hashCode) {
+ super(index, tag, /* owner = */ null, /* name = */ null, value, /* data = */ 0);
+ this.hashCode = hashCode;
+ }
+
+ Entry(final int index, final int tag, final String value, final long data, final int hashCode) {
+ super(index, tag, /* owner = */ null, /* name = */ null, value, data);
+ this.hashCode = hashCode;
+ }
+
+ Entry(
+ final int index, final int tag, final String name, final String value, final int hashCode) {
+ super(index, tag, /* owner = */ null, name, value, /* data = */ 0);
+ this.hashCode = hashCode;
+ }
+
+ Entry(final int index, final int tag, final long data, final int hashCode) {
+ super(index, tag, /* owner = */ null, /* name = */ null, /* value = */ null, data);
+ this.hashCode = hashCode;
+ }
+ }
+}
[20/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
old mode 100644
new mode 100755
index 21fb269..c604cb4
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
@@ -1,102 +1,92 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A node that represents an invokedynamic instruction.
- *
+ *
* @author Remi Forax
*/
public class InvokeDynamicInsnNode extends AbstractInsnNode {
- /**
- * Invokedynamic name.
- */
- public String name;
+ /** The method's name. */
+ public String name;
- /**
- * Invokedynamic descriptor.
- */
- public String desc;
+ /** The method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}). */
+ public String desc;
- /**
- * Bootstrap method
- */
- public Handle bsm;
+ /** The bootstrap method. */
+ public Handle bsm;
- /**
- * Bootstrap constant arguments
- */
- public Object[] bsmArgs;
+ /** The bootstrap method constant arguments. */
+ public Object[] bsmArgs;
- /**
- * Constructs a new {@link InvokeDynamicInsnNode}.
- *
- * @param name
- * invokedynamic name.
- * @param desc
- * invokedynamic descriptor (see {@link org.objectweb.asm.Type}).
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the boostrap constant arguments.
- */
- public InvokeDynamicInsnNode(final String name, final String desc,
- final Handle bsm, final Object... bsmArgs) {
- super(Opcodes.INVOKEDYNAMIC);
- this.name = name;
- this.desc = desc;
- this.bsm = bsm;
- this.bsmArgs = bsmArgs;
- }
+ /**
+ * Constructs a new {@link InvokeDynamicInsnNode}.
+ *
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param bootstrapMethodHandle the bootstrap method.
+ * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type} or {@link Handle} value. This method is allowed to modify the
+ * content of the array so a caller should expect that this array may change.
+ */
+ public InvokeDynamicInsnNode(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) { // NOPMD(ArrayIsStoredDirectly): public field.
+ super(Opcodes.INVOKEDYNAMIC);
+ this.name = name;
+ this.desc = descriptor;
+ this.bsm = bootstrapMethodHandle;
+ this.bsmArgs = bootstrapMethodArguments;
+ }
- @Override
- public int getType() {
- return INVOKE_DYNAMIC_INSN;
- }
+ @Override
+ public int getType() {
+ return INVOKE_DYNAMIC_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)
- .cloneAnnotations(this);
- }
-}
\ No newline at end of file
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs).cloneAnnotations(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
old mode 100644
new mode 100755
index 386c900..e033874
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
@@ -1,97 +1,87 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
- * A node that represents a jump instruction. A jump instruction is an
- * instruction that may jump to another instruction.
- *
+ * A node that represents a jump instruction. A jump instruction is an instruction that may jump to
+ * another instruction.
+ *
* @author Eric Bruneton
*/
public class JumpInsnNode extends AbstractInsnNode {
- /**
- * The operand of this instruction. This operand is a label that designates
- * the instruction to which this instruction may jump.
- */
- public LabelNode label;
+ /**
+ * The operand of this instruction. This operand is a label that designates the instruction to
+ * which this instruction may jump.
+ */
+ public LabelNode label;
- /**
- * Constructs a new {@link JumpInsnNode}.
- *
- * @param opcode
- * the opcode of the type instruction to be constructed. This
- * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
- * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
- * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
- * @param label
- * the operand of the instruction to be constructed. This operand
- * is a label that designates the instruction to which the jump
- * instruction may jump.
- */
- public JumpInsnNode(final int opcode, final LabelNode label) {
- super(opcode);
- this.label = label;
- }
+ /**
+ * Constructs a new {@link JumpInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This opcode must be IFEQ,
+ * IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT,
+ * IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label the operand of the instruction to be constructed. This operand is a label that
+ * designates the instruction to which the jump instruction may jump.
+ */
+ public JumpInsnNode(final int opcode, final LabelNode label) {
+ super(opcode);
+ this.label = label;
+ }
- /**
- * Sets the opcode of this instruction.
- *
- * @param opcode
- * the new instruction opcode. This opcode must be IFEQ, IFNE,
- * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
- * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO,
- * JSR, IFNULL or IFNONNULL.
- */
- public void setOpcode(final int opcode) {
- this.opcode = opcode;
- }
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT,
+ * IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
+ * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
- @Override
- public int getType() {
- return JUMP_INSN;
- }
+ @Override
+ public int getType() {
+ return JUMP_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitJumpInsn(opcode, label.getLabel());
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitJumpInsn(opcode, label.getLabel());
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new JumpInsnNode(opcode, clone(label, labels))
- .cloneAnnotations(this);
- }
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new JumpInsnNode(opcode, clone(label, clonedLabels)).cloneAnnotations(this);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
old mode 100644
new mode 100755
index 39c08ef..5711525
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
@@ -1,78 +1,79 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-/**
- * An {@link AbstractInsnNode} that encapsulates a {@link Label}.
- */
+/** An {@link AbstractInsnNode} that encapsulates a {@link Label}. */
public class LabelNode extends AbstractInsnNode {
- private Label label;
+ private Label value;
- public LabelNode() {
- super(-1);
- }
+ public LabelNode() {
+ super(-1);
+ }
- public LabelNode(final Label label) {
- super(-1);
- this.label = label;
- }
+ public LabelNode(final Label label) {
+ super(-1);
+ this.value = label;
+ }
- @Override
- public int getType() {
- return LABEL;
- }
+ @Override
+ public int getType() {
+ return LABEL;
+ }
- public Label getLabel() {
- if (label == null) {
- label = new Label();
- }
- return label;
+ /**
+ * Returns the label encapsulated by this node. A new label is created and associated with this
+ * node if it was created without an encapsulated label.
+ *
+ * @return the label encapsulated by this node.
+ */
+ public Label getLabel() {
+ if (value == null) {
+ value = new Label();
}
+ return value;
+ }
- @Override
- public void accept(final MethodVisitor cv) {
- cv.visitLabel(getLabel());
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitLabel(getLabel());
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return labels.get(this);
- }
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return clonedLabels.get(this);
+ }
- public void resetLabel() {
- label = null;
- }
-}
\ No newline at end of file
+ public void resetLabel() {
+ value = null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
old mode 100644
new mode 100755
index 458086d..06ef516
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
@@ -1,79 +1,74 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A node that represents an LDC instruction.
- *
+ *
* @author Eric Bruneton
*/
public class LdcInsnNode extends AbstractInsnNode {
- /**
- * The constant to be loaded on the stack. This parameter must be a non null
- * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a
- * {@link String} or a {@link org.objectweb.asm.Type}.
- */
- public Object cst;
+ /**
+ * The constant to be loaded on the stack. This parameter must be a non null {@link Integer}, a
+ * {@link Float}, a {@link Long}, a {@link Double}, a {@link String} or a {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type}.
+ */
+ public Object cst;
- /**
- * Constructs a new {@link LdcInsnNode}.
- *
- * @param cst
- * the constant to be loaded on the stack. This parameter must be
- * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
- */
- public LdcInsnNode(final Object cst) {
- super(Opcodes.LDC);
- this.cst = cst;
- }
+ /**
+ * Constructs a new {@link LdcInsnNode}.
+ *
+ * @param value the constant to be loaded on the stack. This parameter must be a non null {@link
+ * Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
+ */
+ public LdcInsnNode(final Object value) {
+ super(Opcodes.LDC);
+ this.cst = value;
+ }
- @Override
- public int getType() {
- return LDC_INSN;
- }
+ @Override
+ public int getType() {
+ return LDC_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitLdcInsn(cst);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitLdcInsn(cst);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new LdcInsnNode(cst).cloneAnnotations(this);
- }
-}
\ No newline at end of file
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new LdcInsnNode(cst).cloneAnnotations(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
old mode 100644
new mode 100755
index c475ee8..e02faac
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
@@ -1,84 +1,74 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
- * A node that represents a line number declaration. These nodes are pseudo
- * instruction nodes in order to be inserted in an instruction list.
- *
+ * A node that represents a line number declaration. These nodes are pseudo instruction nodes in
+ * order to be inserted in an instruction list.
+ *
* @author Eric Bruneton
*/
public class LineNumberNode extends AbstractInsnNode {
- /**
- * A line number. This number refers to the source file from which the class
- * was compiled.
- */
- public int line;
+ /** A line number. This number refers to the source file from which the class was compiled. */
+ public int line;
- /**
- * The first instruction corresponding to this line number.
- */
- public LabelNode start;
+ /** The first instruction corresponding to this line number. */
+ public LabelNode start;
- /**
- * Constructs a new {@link LineNumberNode}.
- *
- * @param line
- * a line number. This number refers to the source file from
- * which the class was compiled.
- * @param start
- * the first instruction corresponding to this line number.
- */
- public LineNumberNode(final int line, final LabelNode start) {
- super(-1);
- this.line = line;
- this.start = start;
- }
+ /**
+ * Constructs a new {@link LineNumberNode}.
+ *
+ * @param line a line number. This number refers to the source file from which the class was
+ * compiled.
+ * @param start the first instruction corresponding to this line number.
+ */
+ public LineNumberNode(final int line, final LabelNode start) {
+ super(-1);
+ this.line = line;
+ this.start = start;
+ }
- @Override
- public int getType() {
- return LINE;
- }
+ @Override
+ public int getType() {
+ return LINE;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitLineNumber(line, start.getLabel());
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitLineNumber(line, start.getLabel());
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new LineNumberNode(line, clone(start, labels));
- }
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new LineNumberNode(line, clone(start, clonedLabels));
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
old mode 100644
new mode 100755
index 8da8627..ac1bc9c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
@@ -1,157 +1,140 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.apache.tapestry5.internal.plastic.asm.tree;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.TypePath;
-import org.apache.tapestry5.internal.plastic.asm.TypeReference;
-
-/**
- * A node that represents a type annotation on a local or resource variable.
- *
- * @author Eric Bruneton
- */
-public class LocalVariableAnnotationNode extends TypeAnnotationNode {
-
- /**
- * The fist instructions corresponding to the continuous ranges that make
- * the scope of this local variable (inclusive). Must not be <tt>null</tt>.
- */
- public List<LabelNode> start;
-
- /**
- * The last instructions corresponding to the continuous ranges that make
- * the scope of this local variable (exclusive). This list must have the
- * same size as the 'start' list. Must not be <tt>null</tt>.
- */
- public List<LabelNode> end;
-
- /**
- * The local variable's index in each range. This list must have the same
- * size as the 'start' list. Must not be <tt>null</tt>.
- */
- public List<Integer> index;
-
- /**
- * Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must
- * not use this constructor</i>. Instead, they must use the
- * {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], String)}
- * version.
- *
- * @param typeRef
- * a reference to the annotated type. See {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param start
- * the fist instructions corresponding to the continuous ranges
- * that make the scope of this local variable (inclusive).
- * @param end
- * the last instructions corresponding to the continuous ranges
- * that make the scope of this local variable (exclusive). This
- * array must have the same size as the 'start' array.
- * @param index
- * the local variable's index in each range. This array must have
- * the same size as the 'start' array.
- * @param desc
- * the class descriptor of the annotation class.
- */
- public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
- LabelNode[] start, LabelNode[] end, int[] index, String desc) {
- this(Opcodes.ASM6, typeRef, typePath, start, end, index, desc);
- }
-
- /**
- * Constructs a new {@link LocalVariableAnnotationNode}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param typeRef
- * a reference to the annotated type. See {@link TypeReference}.
- * @param start
- * the fist instructions corresponding to the continuous ranges
- * that make the scope of this local variable (inclusive).
- * @param end
- * the last instructions corresponding to the continuous ranges
- * that make the scope of this local variable (exclusive). This
- * array must have the same size as the 'start' array.
- * @param index
- * the local variable's index in each range. This array must have
- * the same size as the 'start' array.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- */
- public LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath,
- LabelNode[] start, LabelNode[] end, int[] index, String desc) {
- super(api, typeRef, typePath, desc);
- this.start = new ArrayList<LabelNode>(start.length);
- this.start.addAll(Arrays.asList(start));
- this.end = new ArrayList<LabelNode>(end.length);
- this.end.addAll(Arrays.asList(end));
- this.index = new ArrayList<Integer>(index.length);
- for (int i : index) {
- this.index.add(i);
- }
- }
-
- /**
- * Makes the given visitor visit this type annotation.
- *
- * @param mv
- * the visitor that must visit this annotation.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- */
- public void accept(final MethodVisitor mv, boolean visible) {
- Label[] start = new Label[this.start.size()];
- Label[] end = new Label[this.end.size()];
- int[] index = new int[this.index.size()];
- for (int i = 0; i < start.length; ++i) {
- start[i] = this.start.get(i).getLabel();
- end[i] = this.end.get(i).getLabel();
- index[i] = this.index.get(i);
- }
- accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
- index, desc, visible));
- }
-}
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.apache.tapestry5.internal.plastic.asm.tree;
+
+import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A node that represents a type annotation on a local or resource variable.
+ *
+ * @author Eric Bruneton
+ */
+public class LocalVariableAnnotationNode extends TypeAnnotationNode {
+
+ /**
+ * The fist instructions corresponding to the continuous ranges that make the scope of this local
+ * variable (inclusive). Must not be {@literal null}.
+ */
+ public List<LabelNode> start;
+
+ /**
+ * The last instructions corresponding to the continuous ranges that make the scope of this local
+ * variable (exclusive). This list must have the same size as the 'start' list. Must not be
+ * {@literal null}.
+ */
+ public List<LabelNode> end;
+
+ /**
+ * The local variable's index in each range. This list must have the same size as the 'start'
+ * list. Must not be {@literal null}.
+ */
+ public List<Integer> index;
+
+ /**
+ * Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the {@link #LocalVariableAnnotationNode(int, TypePath,
+ * LabelNode[], LabelNode[], int[], String)} version.
+ *
+ * @param typeRef a reference to the annotated type. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param start the fist instructions corresponding to the continuous ranges that make the scope
+ * of this local variable (inclusive).
+ * @param end the last instructions corresponding to the continuous ranges that make the scope of
+ * this local variable (exclusive). This array must have the same size as the 'start' array.
+ * @param index the local variable's index in each range. This array must have the same size as
+ * the 'start' array.
+ * @param descriptor the class descriptor of the annotation class.
+ */
+ public LocalVariableAnnotationNode(
+ final int typeRef,
+ final TypePath typePath,
+ final LabelNode[] start,
+ final LabelNode[] end,
+ final int[] index,
+ final String descriptor) {
+ this(Opcodes.ASM7, typeRef, typePath, start, end, index, descriptor);
+ }
+
+ /**
+ * Constructs a new {@link LocalVariableAnnotationNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param typeRef a reference to the annotated type. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param start the fist instructions corresponding to the continuous ranges that make the scope
+ * of this local variable (inclusive).
+ * @param end the last instructions corresponding to the continuous ranges that make the scope of
+ * this local variable (exclusive). This array must have the same size as the 'start' array.
+ * @param index the local variable's index in each range. This array must have the same size as
+ * the 'start' array.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ */
+ public LocalVariableAnnotationNode(
+ final int api,
+ final int typeRef,
+ final TypePath typePath,
+ final LabelNode[] start,
+ final LabelNode[] end,
+ final int[] index,
+ final String descriptor) {
+ super(api, typeRef, typePath, descriptor);
+ this.start = Util.asArrayList(start);
+ this.end = Util.asArrayList(end);
+ this.index = Util.asArrayList(index);
+ }
+
+ /**
+ * Makes the given visitor visit this type annotation.
+ *
+ * @param methodVisitor the visitor that must visit this annotation.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ */
+ public void accept(final MethodVisitor methodVisitor, final boolean visible) {
+ Label[] startLabels = new Label[this.start.size()];
+ Label[] endLabels = new Label[this.end.size()];
+ int[] indices = new int[this.index.size()];
+ for (int i = 0, n = startLabels.length; i < n; ++i) {
+ startLabels[i] = this.start.get(i).getLabel();
+ endLabels[i] = this.end.get(i).getLabel();
+ indices[i] = this.index.get(i);
+ }
+ accept(
+ methodVisitor.visitLocalVariableAnnotation(
+ typeRef, typePath, startLabels, endLabels, indices, desc, visible));
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
old mode 100644
new mode 100755
index 775a6e8..e00438b
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
@@ -1,112 +1,92 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents a local variable declaration.
- *
+ *
* @author Eric Bruneton
*/
public class LocalVariableNode {
- /**
- * The name of a local variable.
- */
- public String name;
+ /** The name of a local variable. */
+ public String name;
- /**
- * The type descriptor of this local variable.
- */
- public String desc;
+ /** The type descriptor of this local variable. */
+ public String desc;
- /**
- * The signature of this local variable. May be <tt>null</tt>.
- */
- public String signature;
+ /** The signature of this local variable. May be {@literal null}. */
+ public String signature;
- /**
- * The first instruction corresponding to the scope of this local variable
- * (inclusive).
- */
- public LabelNode start;
+ /** The first instruction corresponding to the scope of this local variable (inclusive). */
+ public LabelNode start;
- /**
- * The last instruction corresponding to the scope of this local variable
- * (exclusive).
- */
- public LabelNode end;
+ /** The last instruction corresponding to the scope of this local variable (exclusive). */
+ public LabelNode end;
- /**
- * The local variable's index.
- */
- public int index;
+ /** The local variable's index. */
+ public int index;
- /**
- * Constructs a new {@link LocalVariableNode}.
- *
- * @param name
- * the name of a local variable.
- * @param desc
- * the type descriptor of this local variable.
- * @param signature
- * the signature of this local variable. May be <tt>null</tt>.
- * @param start
- * the first instruction corresponding to the scope of this local
- * variable (inclusive).
- * @param end
- * the last instruction corresponding to the scope of this local
- * variable (exclusive).
- * @param index
- * the local variable's index.
- */
- public LocalVariableNode(final String name, final String desc,
- final String signature, final LabelNode start, final LabelNode end,
- final int index) {
- this.name = name;
- this.desc = desc;
- this.signature = signature;
- this.start = start;
- this.end = end;
- this.index = index;
- }
+ /**
+ * Constructs a new {@link LocalVariableNode}.
+ *
+ * @param name the name of a local variable.
+ * @param descriptor the type descriptor of this local variable.
+ * @param signature the signature of this local variable. May be {@literal null}.
+ * @param start the first instruction corresponding to the scope of this local variable
+ * (inclusive).
+ * @param end the last instruction corresponding to the scope of this local variable (exclusive).
+ * @param index the local variable's index.
+ */
+ public LocalVariableNode(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final LabelNode start,
+ final LabelNode end,
+ final int index) {
+ this.name = name;
+ this.desc = descriptor;
+ this.signature = signature;
+ this.start = start;
+ this.end = end;
+ this.index = index;
+ }
- /**
- * Makes the given visitor visit this local variable declaration.
- *
- * @param mv
- * a method visitor.
- */
- public void accept(final MethodVisitor mv) {
- mv.visitLocalVariable(name, desc, signature, start.getLabel(),
- end.getLabel(), index);
- }
+ /**
+ * Makes the given visitor visit this local variable declaration.
+ *
+ * @param methodVisitor a method visitor.
+ */
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitLocalVariable(
+ name, desc, signature, start.getLabel(), end.getLabel(), index);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
old mode 100644
new mode 100755
index 0ecad60..f339b17
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
@@ -1,118 +1,93 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A node that represents a LOOKUPSWITCH instruction.
- *
+ *
* @author Eric Bruneton
*/
public class LookupSwitchInsnNode extends AbstractInsnNode {
- /**
- * Beginning of the default handler block.
- */
- public LabelNode dflt;
+ /** Beginning of the default handler block. */
+ public LabelNode dflt;
- /**
- * The values of the keys. This list is a list of {@link Integer} objects.
- */
- public List<Integer> keys;
+ /** The values of the keys. */
+ public List<Integer> keys;
- /**
- * Beginnings of the handler blocks. This list is a list of
- * {@link LabelNode} objects.
- */
- public List<LabelNode> labels;
+ /** Beginnings of the handler blocks. */
+ public List<LabelNode> labels;
- /**
- * Constructs a new {@link LookupSwitchInsnNode}.
- *
- * @param dflt
- * beginning of the default handler block.
- * @param keys
- * the values of the keys.
- * @param labels
- * beginnings of the handler blocks. <tt>labels[i]</tt> is the
- * beginning of the handler block for the <tt>keys[i]</tt> key.
- */
- public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys,
- final LabelNode[] labels) {
- super(Opcodes.LOOKUPSWITCH);
- this.dflt = dflt;
- this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length);
- this.labels = new ArrayList<LabelNode>(labels == null ? 0
- : labels.length);
- if (keys != null) {
- for (int i = 0; i < keys.length; ++i) {
- this.keys.add(keys[i]);
- }
- }
- if (labels != null) {
- this.labels.addAll(Arrays.asList(labels));
- }
- }
+ /**
+ * Constructs a new {@link LookupSwitchInsnNode}.
+ *
+ * @param dflt beginning of the default handler block.
+ * @param keys the values of the keys.
+ * @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the
+ * handler block for the {@code keys[i]} key.
+ */
+ public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys, final LabelNode[] labels) {
+ super(Opcodes.LOOKUPSWITCH);
+ this.dflt = dflt;
+ this.keys = Util.asArrayList(keys);
+ this.labels = Util.asArrayList(labels);
+ }
- @Override
- public int getType() {
- return LOOKUPSWITCH_INSN;
- }
+ @Override
+ public int getType() {
+ return LOOKUPSWITCH_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- int[] keys = new int[this.keys.size()];
- for (int i = 0; i < keys.length; ++i) {
- keys[i] = this.keys.get(i).intValue();
- }
- Label[] labels = new Label[this.labels.size()];
- for (int i = 0; i < labels.length; ++i) {
- labels[i] = this.labels.get(i).getLabel();
- }
- mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
- acceptAnnotations(mv);
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ int[] keysArray = new int[this.keys.size()];
+ for (int i = 0, n = keysArray.length; i < n; ++i) {
+ keysArray[i] = this.keys.get(i).intValue();
}
-
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
- labels), null, clone(this.labels, labels));
- clone.keys.addAll(keys);
- return clone.cloneAnnotations(this);
+ Label[] labelsArray = new Label[this.labels.size()];
+ for (int i = 0, n = labelsArray.length; i < n; ++i) {
+ labelsArray[i] = this.labels.get(i).getLabel();
}
+ methodVisitor.visitLookupSwitchInsn(dflt.getLabel(), keysArray, labelsArray);
+ acceptAnnotations(methodVisitor);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ LookupSwitchInsnNode clone =
+ new LookupSwitchInsnNode(clone(dflt, clonedLabels), null, clone(labels, clonedLabels));
+ clone.keys.addAll(keys);
+ return clone.cloneAnnotations(this);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
old mode 100644
new mode 100755
index 8d86df7..530ea1d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
@@ -1,141 +1,126 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
-import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import java.util.Map;
+
/**
- * A node that represents a method instruction. A method instruction is an
- * instruction that invokes a method.
- *
+ * A node that represents a method instruction. A method instruction is an instruction that invokes
+ * a method.
+ *
* @author Eric Bruneton
*/
public class MethodInsnNode extends AbstractInsnNode {
- /**
- * The internal name of the method's owner class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- */
- public String owner;
+ /**
+ * The internal name of the method's owner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ *
+ * <p>For methods of arrays, e.g., {@code clone()}, the array type descriptor.
+ */
+ public String owner;
- /**
- * The method's name.
- */
- public String name;
+ /** The method's name. */
+ public String name;
- /**
- * The method's descriptor (see {@link org.objectweb.asm.Type}).
- */
- public String desc;
+ /** The method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}). */
+ public String desc;
- /**
- * If the method's owner class if an interface.
- */
- public boolean itf;
+ /** Whether the method's owner class if an interface. */
+ public boolean itf;
- /**
- * Constructs a new {@link MethodInsnNode}.
- *
- * @param opcode
- * the opcode of the type instruction to be constructed. This
- * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner
- * the internal name of the method's owner class (see
- * {@link org.objectweb.asm.Type#getInternalName()
- * getInternalName}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link org.objectweb.asm.Type}).
- */
- @Deprecated
- public MethodInsnNode(final int opcode, final String owner,
- final String name, final String desc) {
- this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE);
- }
+ /**
+ * Constructs a new {@link MethodInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This opcode must be
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @deprecated use {@link #MethodInsnNode(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ public MethodInsnNode(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ this(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
- /**
- * Constructs a new {@link MethodInsnNode}.
- *
- * @param opcode
- * the opcode of the type instruction to be constructed. This
- * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner
- * the internal name of the method's owner class (see
- * {@link org.objectweb.asm.Type#getInternalName()
- * getInternalName}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link org.objectweb.asm.Type}).
- * @param itf
- * if the method's owner class is an interface.
- */
- public MethodInsnNode(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- super(opcode);
- this.owner = owner;
- this.name = name;
- this.desc = desc;
- this.itf = itf;
- }
+ /**
+ * Constructs a new {@link MethodInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This opcode must be
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param isInterface if the method's owner class is an interface.
+ */
+ public MethodInsnNode(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ super(opcode);
+ this.owner = owner;
+ this.name = name;
+ this.desc = descriptor;
+ this.itf = isInterface;
+ }
- /**
- * Sets the opcode of this instruction.
- *
- * @param opcode
- * the new instruction opcode. This opcode must be INVOKEVIRTUAL,
- * INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
- */
- public void setOpcode(final int opcode) {
- this.opcode = opcode;
- }
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be INVOKEVIRTUAL, INVOKESPECIAL,
+ * INVOKESTATIC or INVOKEINTERFACE.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
- @Override
- public int getType() {
- return METHOD_INSN;
- }
+ @Override
+ public int getType() {
+ return METHOD_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitMethodInsn(opcode, owner, name, desc, itf);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitMethodInsn(opcode, owner, name, desc, itf);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new MethodInsnNode(opcode, owner, name, desc, itf);
- }
-}
\ No newline at end of file
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new MethodInsnNode(opcode, owner, name, desc, itf).cloneAnnotations(this);
+ }
+}
[19/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
old mode 100644
new mode 100755
index 68b4e31..39114ac
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
@@ -1,41 +1,38 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
@@ -45,796 +42,774 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A node that represents a method.
- *
+ *
* @author Eric Bruneton
*/
public class MethodNode extends MethodVisitor {
- /**
- * The method's access flags (see {@link Opcodes}). This field also
- * indicates if the method is synthetic and/or deprecated.
- */
- public int access;
-
- /**
- * The method's name.
- */
- public String name;
-
- /**
- * The method's descriptor (see {@link Type}).
- */
- public String desc;
-
- /**
- * The method's signature. May be <tt>null</tt>.
- */
- public String signature;
-
- /**
- * The internal names of the method's exception classes (see
- * {@link Type#getInternalName() getInternalName}). This list is a list of
- * {@link String} objects.
- */
- public List<String> exceptions;
-
- /**
- * The method parameter info (access flags and name)
- */
- public List<ParameterNode> parameters;
-
- /**
- * The runtime visible annotations of this method. This list is a list of
- * {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.AnnotationNode
- * @label visible
- */
- public List<AnnotationNode> visibleAnnotations;
-
- /**
- * The runtime invisible annotations of this method. This list is a list of
- * {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.AnnotationNode
- * @label invisible
- */
- public List<AnnotationNode> invisibleAnnotations;
-
- /**
- * The runtime visible type annotations of this method. This list is a list
- * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label visible
- */
- public List<TypeAnnotationNode> visibleTypeAnnotations;
-
- /**
- * The runtime invisible type annotations of this method. This list is a
- * list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label invisible
- */
- public List<TypeAnnotationNode> invisibleTypeAnnotations;
-
- /**
- * The non standard attributes of this method. This list is a list of
- * {@link Attribute} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.Attribute
- */
- public List<Attribute> attrs;
-
- /**
- * The default value of this annotation interface method. This field must be
- * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
- * {@link Integer}, {@link Long}, {@link Float}, {@link Double},
- * {@link String} or {@link Type}, or an two elements String array (for
- * enumeration values), a {@link AnnotationNode}, or a {@link List} of
- * values of one of the preceding types. May be <tt>null</tt>.
- */
- public Object annotationDefault;
-
- /**
- * The runtime visible parameter annotations of this method. These lists are
- * lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.AnnotationNode
- * @label invisible parameters
- */
- public List<AnnotationNode>[] visibleParameterAnnotations;
-
- /**
- * The runtime invisible parameter annotations of this method. These lists
- * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.AnnotationNode
- * @label visible parameters
- */
- public List<AnnotationNode>[] invisibleParameterAnnotations;
-
- /**
- * The instructions of this method. This list is a list of
- * {@link AbstractInsnNode} objects.
- *
- * @associates org.objectweb.asm.tree.AbstractInsnNode
- * @label instructions
- */
- public InsnList instructions;
-
- /**
- * The try catch blocks of this method. This list is a list of
- * {@link TryCatchBlockNode} objects.
- *
- * @associates org.objectweb.asm.tree.TryCatchBlockNode
- */
- public List<TryCatchBlockNode> tryCatchBlocks;
-
- /**
- * The maximum stack size of this method.
- */
- public int maxStack;
-
- /**
- * The maximum number of local variables of this method.
- */
- public int maxLocals;
-
- /**
- * The local variables of this method. This list is a list of
- * {@link LocalVariableNode} objects. May be <tt>null</tt>
- *
- * @associates org.objectweb.asm.tree.LocalVariableNode
- */
- public List<LocalVariableNode> localVariables;
-
- /**
- * The visible local variable annotations of this method. This list is a
- * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
- *
- * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
- */
- public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations;
-
- /**
- * The invisible local variable annotations of this method. This list is a
- * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
- *
- * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
- */
- public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations;
-
- /**
- * If the accept method has been called on this object.
- */
- private boolean visited;
-
- /**
- * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not
- * use this constructor</i>. Instead, they must use the
- * {@link #MethodNode(int)} version.
- *
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public MethodNode() {
- this(Opcodes.ASM6);
- if (getClass() != MethodNode.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Constructs an uninitialized {@link MethodNode}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public MethodNode(final int api) {
- super(api);
- this.instructions = new InsnList();
- }
-
- /**
- * Constructs a new {@link MethodNode}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #MethodNode(int, int, String, String, String, String[])} version.
- *
- * @param access
- * the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt>.
- * @param exceptions
- * the internal names of the method's exception classes (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public MethodNode(final int access, final String name, final String desc,
- final String signature, final String[] exceptions) {
- this(Opcodes.ASM6, access, name, desc, signature, exceptions);
- if (getClass() != MethodNode.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Constructs a new {@link MethodNode}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param access
- * the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt>.
- * @param exceptions
- * the internal names of the method's exception classes (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- */
- public MethodNode(final int api, final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- super(api);
- this.access = access;
- this.name = name;
- this.desc = desc;
- this.signature = signature;
- this.exceptions = new ArrayList<String>(exceptions == null ? 0
- : exceptions.length);
- boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
- if (!isAbstract) {
- this.localVariables = new ArrayList<LocalVariableNode>(5);
- }
- this.tryCatchBlocks = new ArrayList<TryCatchBlockNode>();
- if (exceptions != null) {
- this.exceptions.addAll(Arrays.asList(exceptions));
- }
- this.instructions = new InsnList();
- }
-
- // ------------------------------------------------------------------------
- // Implementation of the MethodVisitor abstract class
- // ------------------------------------------------------------------------
-
- @Override
- public void visitParameter(String name, int access) {
- if (parameters == null) {
- parameters = new ArrayList<ParameterNode>(5);
- }
- parameters.add(new ParameterNode(name, access));
- }
-
- @Override
- @SuppressWarnings("serial")
- public AnnotationVisitor visitAnnotationDefault() {
- return new AnnotationNode(new ArrayList<Object>(0) {
- @Override
- public boolean add(final Object o) {
- annotationDefault = o;
- return super.add(o);
- }
+ /**
+ * The method's access flags (see {@link Opcodes}). This field also indicates if the method is
+ * synthetic and/or deprecated.
+ */
+ public int access;
+
+ /** The method's name. */
+ public String name;
+
+ /** The method's descriptor (see {@link Type}). */
+ public String desc;
+
+ /** The method's signature. May be {@literal null}. */
+ public String signature;
+
+ /** The internal names of the method's exception classes (see {@link Type#getInternalName()}). */
+ public List<String> exceptions;
+
+ /** The method parameter info (access flags and name). */
+ public List<ParameterNode> parameters;
+
+ /** The runtime visible annotations of this method. May be {@literal null}. */
+ public List<AnnotationNode> visibleAnnotations;
+
+ /** The runtime invisible annotations of this method. May be {@literal null}. */
+ public List<AnnotationNode> invisibleAnnotations;
+
+ /** The runtime visible type annotations of this method. May be {@literal null}. */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /** The runtime invisible type annotations of this method. May be {@literal null}. */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /** The non standard attributes of this method. May be {@literal null}. */
+ public List<Attribute> attrs;
+
+ /**
+ * The default value of this annotation interface method. This field must be a {@link Byte},
+ * {@link Boolean}, {@link Character}, {@link Short}, {@link Integer}, {@link Long}, {@link
+ * Float}, {@link Double}, {@link String} or {@link Type}, or an two elements String array (for
+ * enumeration values), a {@link AnnotationNode}, or a {@link List} of values of one of the
+ * preceding types. May be {@literal null}.
+ */
+ public Object annotationDefault;
+
+ /**
+ * The number of method parameters than can have runtime visible annotations. This number must be
+ * less or equal than the number of parameter types in the method descriptor (the default value 0
+ * indicates that all the parameters described in the method descriptor can have annotations). It
+ * can be strictly less when a method has synthetic parameters and when these parameters are
+ * ignored when computing parameter indices for the purpose of parameter annotations (see
+ * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18).
+ */
+ public int visibleAnnotableParameterCount;
+
+ /**
+ * The runtime visible parameter annotations of this method. These lists are lists of {@link
+ * AnnotationNode} objects. May be {@literal null}.
+ */
+ public List<AnnotationNode>[] visibleParameterAnnotations;
+
+ /**
+ * The number of method parameters than can have runtime invisible annotations. This number must
+ * be less or equal than the number of parameter types in the method descriptor (the default value
+ * 0 indicates that all the parameters described in the method descriptor can have annotations).
+ * It can be strictly less when a method has synthetic parameters and when these parameters are
+ * ignored when computing parameter indices for the purpose of parameter annotations (see
+ * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18).
+ */
+ public int invisibleAnnotableParameterCount;
+
+ /**
+ * The runtime invisible parameter annotations of this method. These lists are lists of {@link
+ * AnnotationNode} objects. May be {@literal null}.
+ */
+ public List<AnnotationNode>[] invisibleParameterAnnotations;
+
+ /** The instructions of this method. */
+ public InsnList instructions;
+
+ /** The try catch blocks of this method. */
+ public List<TryCatchBlockNode> tryCatchBlocks;
+
+ /** The maximum stack size of this method. */
+ public int maxStack;
+
+ /** The maximum number of local variables of this method. */
+ public int maxLocals;
+
+ /** The local variables of this method. May be {@literal null} */
+ public List<LocalVariableNode> localVariables;
+
+ /** The visible local variable annotations of this method. May be {@literal null} */
+ public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations;
+
+ /** The invisible local variable annotations of this method. May be {@literal null} */
+ public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations;
+
+ /** Whether the accept method has been called on this object. */
+ private boolean visited;
+
+ /**
+ * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the {@link #MethodNode(int)} version.
+ *
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public MethodNode() {
+ this(Opcodes.ASM7);
+ if (getClass() != MethodNode.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs an uninitialized {@link MethodNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public MethodNode(final int api) {
+ super(api);
+ this.instructions = new InsnList();
+ }
+
+ /**
+ * Constructs a new {@link MethodNode}. <i>Subclasses must not use this constructor</i>. Instead,
+ * they must use the {@link #MethodNode(int, int, String, String, String, String[])} version.
+ *
+ * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the method is synthetic and/or deprecated.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be {@literal null}.
+ * @param exceptions the internal names of the method's exception classes (see {@link
+ * Type#getInternalName()}). May be {@literal null}.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public MethodNode(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ this(Opcodes.ASM7, access, name, descriptor, signature, exceptions);
+ if (getClass() != MethodNode.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link MethodNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the method is synthetic and/or deprecated.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be {@literal null}.
+ * @param exceptions the internal names of the method's exception classes (see {@link
+ * Type#getInternalName()}). May be {@literal null}.
+ */
+ public MethodNode(
+ final int api,
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ super(api);
+ this.access = access;
+ this.name = name;
+ this.desc = descriptor;
+ this.signature = signature;
+ this.exceptions = Util.asArrayList(exceptions);
+ if ((access & Opcodes.ACC_ABSTRACT) == 0) {
+ this.localVariables = new ArrayList<LocalVariableNode>(5);
+ }
+ this.tryCatchBlocks = new ArrayList<TryCatchBlockNode>();
+ this.instructions = new InsnList();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the MethodVisitor abstract class
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visitParameter(final String name, final int access) {
+ if (parameters == null) {
+ parameters = new ArrayList<ParameterNode>(5);
+ }
+ parameters.add(new ParameterNode(name, access));
+ }
+
+ @Override
+ @SuppressWarnings("serial")
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new AnnotationNode(
+ new ArrayList<Object>(0) {
+ @Override
+ public boolean add(final Object o) {
+ annotationDefault = o;
+ return super.add(o);
+ }
});
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- AnnotationNode an = new AnnotationNode(desc);
- if (visible) {
- if (visibleAnnotations == null) {
- visibleAnnotations = new ArrayList<AnnotationNode>(1);
- }
- visibleAnnotations.add(an);
- } else {
- if (invisibleAnnotations == null) {
- invisibleAnnotations = new ArrayList<AnnotationNode>(1);
- }
- invisibleAnnotations.add(an);
- }
- return an;
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
- if (visible) {
- if (visibleTypeAnnotations == null) {
- visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
- }
- visibleTypeAnnotations.add(an);
- } else {
- if (invisibleTypeAnnotations == null) {
- invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
- }
- invisibleTypeAnnotations.add(an);
- }
- return an;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public AnnotationVisitor visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- AnnotationNode an = new AnnotationNode(desc);
- if (visible) {
- if (visibleParameterAnnotations == null) {
- int params = Type.getArgumentTypes(this.desc).length;
- visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
- }
- if (visibleParameterAnnotations[parameter] == null) {
- visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
- 1);
- }
- visibleParameterAnnotations[parameter].add(an);
- } else {
- if (invisibleParameterAnnotations == null) {
- int params = Type.getArgumentTypes(this.desc).length;
- invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
- }
- if (invisibleParameterAnnotations[parameter] == null) {
- invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
- 1);
- }
- invisibleParameterAnnotations[parameter].add(an);
- }
- return an;
- }
-
- @Override
- public void visitAttribute(final Attribute attr) {
- if (attrs == null) {
- attrs = new ArrayList<Attribute>(1);
- }
- attrs.add(attr);
- }
-
- @Override
- public void visitCode() {
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- instructions.add(new FrameNode(type, nLocal, local == null ? null
- : getLabelNodes(local), nStack, stack == null ? null
- : getLabelNodes(stack)));
- }
-
- @Override
- public void visitInsn(final int opcode) {
- instructions.add(new InsnNode(opcode));
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- instructions.add(new IntInsnNode(opcode, operand));
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- instructions.add(new VarInsnNode(opcode, var));
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- instructions.add(new TypeInsnNode(opcode, type));
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- instructions.add(new FieldInsnNode(opcode, owner, name, desc));
- }
-
- @Deprecated
- @Override
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- instructions.add(new MethodInsnNode(opcode, owner, name, desc));
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc, boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf));
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- instructions.add(new JumpInsnNode(opcode, getLabelNode(label)));
- }
-
- @Override
- public void visitLabel(final Label label) {
- instructions.add(getLabelNode(label));
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- instructions.add(new LdcInsnNode(cst));
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- instructions.add(new IincInsnNode(var, increment));
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt),
- getLabelNodes(labels)));
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys,
- getLabelNodes(labels)));
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- instructions.add(new MultiANewArrayInsnNode(desc, dims));
- }
-
- @Override
- public AnnotationVisitor visitInsnAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- // Finds the last real instruction, i.e. the instruction targeted by
- // this annotation.
- AbstractInsnNode insn = instructions.getLast();
- while (insn.getOpcode() == -1) {
- insn = insn.getPrevious();
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationNode annotation = new AnnotationNode(descriptor);
+ if (visible) {
+ if (visibleAnnotations == null) {
+ visibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ visibleAnnotations.add(annotation);
+ } else {
+ if (invisibleAnnotations == null) {
+ invisibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ invisibleAnnotations.add(annotation);
+ }
+ return annotation;
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(typeAnnotation);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(typeAnnotation);
+ }
+ return typeAnnotation;
+ }
+
+ @Override
+ public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ if (visible) {
+ visibleAnnotableParameterCount = parameterCount;
+ } else {
+ invisibleAnnotableParameterCount = parameterCount;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ AnnotationNode annotation = new AnnotationNode(descriptor);
+ if (visible) {
+ if (visibleParameterAnnotations == null) {
+ int params = Type.getArgumentTypes(desc).length;
+ visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
+ }
+ if (visibleParameterAnnotations[parameter] == null) {
+ visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ }
+ visibleParameterAnnotations[parameter].add(annotation);
+ } else {
+ if (invisibleParameterAnnotations == null) {
+ int params = Type.getArgumentTypes(desc).length;
+ invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
+ }
+ if (invisibleParameterAnnotations[parameter] == null) {
+ invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ }
+ invisibleParameterAnnotations[parameter].add(annotation);
+ }
+ return annotation;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ if (attrs == null) {
+ attrs = new ArrayList<Attribute>(1);
+ }
+ attrs.add(attribute);
+ }
+
+ @Override
+ public void visitCode() {
+ // Nothing to do.
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ instructions.add(
+ new FrameNode(
+ type,
+ numLocal,
+ local == null ? null : getLabelNodes(local),
+ numStack,
+ stack == null ? null : getLabelNodes(stack)));
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ instructions.add(new InsnNode(opcode));
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ instructions.add(new IntInsnNode(opcode, operand));
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ instructions.add(new VarInsnNode(opcode, var));
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ instructions.add(new TypeInsnNode(opcode, type));
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ instructions.add(new FieldInsnNode(opcode, owner, name, descriptor));
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
+ }
+ instructions.add(new MethodInsnNode(opcode, owner, name, descriptor));
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
+ }
+ instructions.add(new MethodInsnNode(opcode, owner, name, descriptor, isInterface));
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ instructions.add(
+ new InvokeDynamicInsnNode(
+ name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments));
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ instructions.add(new JumpInsnNode(opcode, getLabelNode(label)));
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ instructions.add(getLabelNode(label));
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ instructions.add(new LdcInsnNode(value));
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ instructions.add(new IincInsnNode(var, increment));
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt), getLabelNodes(labels)));
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys, getLabelNodes(labels)));
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ instructions.add(new MultiANewArrayInsnNode(descriptor, numDimensions));
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ // Find the last real instruction, i.e. the instruction targeted by this annotation.
+ AbstractInsnNode currentInsn = instructions.getLast();
+ while (currentInsn.getOpcode() == -1) {
+ currentInsn = currentInsn.getPrevious();
+ }
+ // Add the annotation to this instruction.
+ TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
+ if (visible) {
+ if (currentInsn.visibleTypeAnnotations == null) {
+ currentInsn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ currentInsn.visibleTypeAnnotations.add(typeAnnotation);
+ } else {
+ if (currentInsn.invisibleTypeAnnotations == null) {
+ currentInsn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ currentInsn.invisibleTypeAnnotations.add(typeAnnotation);
+ }
+ return typeAnnotation;
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ tryCatchBlocks.add(
+ new TryCatchBlockNode(getLabelNode(start), getLabelNode(end), getLabelNode(handler), type));
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ TryCatchBlockNode tryCatchBlock = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
+ TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
+ if (visible) {
+ if (tryCatchBlock.visibleTypeAnnotations == null) {
+ tryCatchBlock.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ tryCatchBlock.visibleTypeAnnotations.add(typeAnnotation);
+ } else {
+ if (tryCatchBlock.invisibleTypeAnnotations == null) {
+ tryCatchBlock.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ tryCatchBlock.invisibleTypeAnnotations.add(typeAnnotation);
+ }
+ return typeAnnotation;
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ localVariables.add(
+ new LocalVariableNode(
+ name, descriptor, signature, getLabelNode(start), getLabelNode(end), index));
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ LocalVariableAnnotationNode localVariableAnnotation =
+ new LocalVariableAnnotationNode(
+ typeRef, typePath, getLabelNodes(start), getLabelNodes(end), index, descriptor);
+ if (visible) {
+ if (visibleLocalVariableAnnotations == null) {
+ visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(1);
+ }
+ visibleLocalVariableAnnotations.add(localVariableAnnotation);
+ } else {
+ if (invisibleLocalVariableAnnotations == null) {
+ invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(1);
+ }
+ invisibleLocalVariableAnnotations.add(localVariableAnnotation);
+ }
+ return localVariableAnnotation;
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ instructions.add(new LineNumberNode(line, getLabelNode(start)));
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ this.maxStack = maxStack;
+ this.maxLocals = maxLocals;
+ }
+
+ @Override
+ public void visitEnd() {
+ // Nothing to do.
+ }
+
+ /**
+ * Returns the LabelNode corresponding to the given Label. Creates a new LabelNode if necessary.
+ * The default implementation of this method uses the {@link Label#info} field to store
+ * associations between labels and label nodes.
+ *
+ * @param label a Label.
+ * @return the LabelNode corresponding to label.
+ */
+ protected LabelNode getLabelNode(final Label label) {
+ if (!(label.info instanceof LabelNode)) {
+ label.info = new LabelNode();
+ }
+ return (LabelNode) label.info;
+ }
+
+ private LabelNode[] getLabelNodes(final Label[] labels) {
+ LabelNode[] labelNodes = new LabelNode[labels.length];
+ for (int i = 0, n = labels.length; i < n; ++i) {
+ labelNodes[i] = getLabelNode(labels[i]);
+ }
+ return labelNodes;
+ }
+
+ private Object[] getLabelNodes(final Object[] objects) {
+ Object[] labelNodes = new Object[objects.length];
+ for (int i = 0, n = objects.length; i < n; ++i) {
+ Object o = objects[i];
+ if (o instanceof Label) {
+ o = getLabelNode((Label) o);
+ }
+ labelNodes[i] = o;
+ }
+ return labelNodes;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Accept method
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Checks that this method node is compatible with the given ASM API version. This method checks
+ * that this node, and all its children recursively, do not contain elements that were introduced
+ * in more recent versions of the ASM API than the given version.
+ *
+ * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5},
+ * {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public void check(final int api) {
+ if (api == Opcodes.ASM4) {
+ if (parameters != null && !parameters.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
+ if (visibleTypeAnnotations != null && !visibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
+ if (invisibleTypeAnnotations != null && !invisibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
+ if (tryCatchBlocks != null) {
+ for (int i = tryCatchBlocks.size() - 1; i >= 0; --i) {
+ TryCatchBlockNode tryCatchBlock = tryCatchBlocks.get(i);
+ if (tryCatchBlock.visibleTypeAnnotations != null
+ && !tryCatchBlock.visibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
+ if (tryCatchBlock.invisibleTypeAnnotations != null
+ && !tryCatchBlock.invisibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
}
- // Adds the annotation to this instruction.
- TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
- if (visible) {
- if (insn.visibleTypeAnnotations == null) {
- insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
- 1);
- }
- insn.visibleTypeAnnotations.add(an);
- } else {
- if (insn.invisibleTypeAnnotations == null) {
- insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
- 1);
- }
- insn.invisibleTypeAnnotations.add(an);
+ }
+ for (int i = instructions.size() - 1; i >= 0; --i) {
+ AbstractInsnNode insn = instructions.get(i);
+ if (insn.visibleTypeAnnotations != null && !insn.visibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
}
- return an;
- }
-
- @Override
- public void visitTryCatchBlock(final Label start, final Label end,
- final Label handler, final String type) {
- tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
- getLabelNode(end), getLabelNode(handler), type));
- }
-
- @Override
- public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
- TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
- if (visible) {
- if (tcb.visibleTypeAnnotations == null) {
- tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
- 1);
- }
- tcb.visibleTypeAnnotations.add(an);
- } else {
- if (tcb.invisibleTypeAnnotations == null) {
- tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
- 1);
- }
- tcb.invisibleTypeAnnotations.add(an);
+ if (insn.invisibleTypeAnnotations != null && !insn.invisibleTypeAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
}
- return an;
- }
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- localVariables.add(new LocalVariableNode(name, desc, signature,
- getLabelNode(start), getLabelNode(end), index));
- }
-
- @Override
- public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
- TypePath typePath, Label[] start, Label[] end, int[] index,
- String desc, boolean visible) {
- LocalVariableAnnotationNode an = new LocalVariableAnnotationNode(
- typeRef, typePath, getLabelNodes(start), getLabelNodes(end),
- index, desc);
- if (visible) {
- if (visibleLocalVariableAnnotations == null) {
- visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
- 1);
- }
- visibleLocalVariableAnnotations.add(an);
- } else {
- if (invisibleLocalVariableAnnotations == null) {
- invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
- 1);
- }
- invisibleLocalVariableAnnotations.add(an);
+ if (insn instanceof MethodInsnNode) {
+ boolean isInterface = ((MethodInsnNode) insn).itf;
+ if (isInterface != (insn.opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new UnsupportedClassVersionException();
+ }
+ } else if (insn instanceof LdcInsnNode) {
+ Object value = ((LdcInsnNode) insn).cst;
+ if (value instanceof Handle
+ || (value instanceof Type && ((Type) value).getSort() == Type.METHOD)) {
+ throw new UnsupportedClassVersionException();
+ }
}
- return an;
- }
-
- @Override
- public void visitLineNumber(final int line, final Label start) {
- instructions.add(new LineNumberNode(line, getLabelNode(start)));
- }
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- this.maxStack = maxStack;
- this.maxLocals = maxLocals;
- }
-
- @Override
- public void visitEnd() {
- }
-
- /**
- * Returns the LabelNode corresponding to the given Label. Creates a new
- * LabelNode if necessary. The default implementation of this method uses
- * the {@link Label#info} field to store associations between labels and
- * label nodes.
- *
- * @param l
- * a Label.
- * @return the LabelNode corresponding to l.
- */
- protected LabelNode getLabelNode(final Label l) {
- if (!(l.info instanceof LabelNode)) {
- l.info = new LabelNode();
+ }
+ if (visibleLocalVariableAnnotations != null && !visibleLocalVariableAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
+ if (invisibleLocalVariableAnnotations != null
+ && !invisibleLocalVariableAnnotations.isEmpty()) {
+ throw new UnsupportedClassVersionException();
+ }
+ }
+ if (api != Opcodes.ASM7) {
+ for (int i = instructions.size() - 1; i >= 0; --i) {
+ AbstractInsnNode insn = instructions.get(i);
+ if (insn instanceof LdcInsnNode) {
+ Object value = ((LdcInsnNode) insn).cst;
+ if (value instanceof ConstantDynamic) {
+ throw new UnsupportedClassVersionException();
+ }
}
- return (LabelNode) l.info;
- }
-
- private LabelNode[] getLabelNodes(final Label[] l) {
- LabelNode[] nodes = new LabelNode[l.length];
- for (int i = 0; i < l.length; ++i) {
- nodes[i] = getLabelNode(l[i]);
+ }
+ }
+ }
+
+ /**
+ * Makes the given class visitor visit this method.
+ *
+ * @param classVisitor a class visitor.
+ */
+ public void accept(final ClassVisitor classVisitor) {
+ String[] exceptionsArray = new String[this.exceptions.size()];
+ this.exceptions.toArray(exceptionsArray);
+ MethodVisitor methodVisitor =
+ classVisitor.visitMethod(access, name, desc, signature, exceptionsArray);
+ if (methodVisitor != null) {
+ accept(methodVisitor);
+ }
+ }
+
+ /**
+ * Makes the given method visitor visit this method.
+ *
+ * @param methodVisitor a method visitor.
+ */
+ public void accept(final MethodVisitor methodVisitor) {
+ // Visit the parameters.
+ if (parameters != null) {
+ for (int i = 0, n = parameters.size(); i < n; i++) {
+ parameters.get(i).accept(methodVisitor);
+ }
+ }
+ // Visit the annotations.
+ if (annotationDefault != null) {
+ AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotationDefault();
+ AnnotationNode.accept(annotationVisitor, null, annotationDefault);
+ if (annotationVisitor != null) {
+ annotationVisitor.visitEnd();
+ }
+ }
+ if (visibleAnnotations != null) {
+ for (int i = 0, n = visibleAnnotations.size(); i < n; ++i) {
+ AnnotationNode annotation = visibleAnnotations.get(i);
+ annotation.accept(methodVisitor.visitAnnotation(annotation.desc, true));
+ }
+ }
+ if (invisibleAnnotations != null) {
+ for (int i = 0, n = invisibleAnnotations.size(); i < n; ++i) {
+ AnnotationNode annotation = invisibleAnnotations.get(i);
+ annotation.accept(methodVisitor.visitAnnotation(annotation.desc, false));
+ }
+ }
+ if (visibleTypeAnnotations != null) {
+ for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ methodVisitor.visitTypeAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
+ }
+ }
+ if (invisibleTypeAnnotations != null) {
+ for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ methodVisitor.visitTypeAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
+ }
+ }
+ if (visibleAnnotableParameterCount > 0) {
+ methodVisitor.visitAnnotableParameterCount(visibleAnnotableParameterCount, true);
+ }
+ if (visibleParameterAnnotations != null) {
+ for (int i = 0, n = visibleParameterAnnotations.length; i < n; ++i) {
+ List<AnnotationNode> parameterAnnotations = visibleParameterAnnotations[i];
+ if (parameterAnnotations == null) {
+ continue;
}
- return nodes;
- }
-
- private Object[] getLabelNodes(final Object[] objs) {
- Object[] nodes = new Object[objs.length];
- for (int i = 0; i < objs.length; ++i) {
- Object o = objs[i];
- if (o instanceof Label) {
- o = getLabelNode((Label) o);
- }
- nodes[i] = o;
- }
- return nodes;
- }
-
- // ------------------------------------------------------------------------
- // Accept method
- // ------------------------------------------------------------------------
-
- /**
- * Checks that this method node is compatible with the given ASM API
- * version. This methods checks that this node, and all its nodes
- * recursively, do not contain elements that were introduced in more recent
- * versions of the ASM API than the given version.
- *
- * @param api
- * an ASM API version. Must be one of {@link Opcodes#ASM4},
- * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public void check(final int api) {
- if (api == Opcodes.ASM4) {
- if (visibleTypeAnnotations != null
- && visibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- if (invisibleTypeAnnotations != null
- && invisibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
- for (int i = 0; i < n; ++i) {
- TryCatchBlockNode tcb = tryCatchBlocks.get(i);
- if (tcb.visibleTypeAnnotations != null
- && tcb.visibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- if (tcb.invisibleTypeAnnotations != null
- && tcb.invisibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- }
- for (int i = 0; i < instructions.size(); ++i) {
- AbstractInsnNode insn = instructions.get(i);
- if (insn.visibleTypeAnnotations != null
- && insn.visibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- if (insn.invisibleTypeAnnotations != null
- && insn.invisibleTypeAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- if (insn instanceof MethodInsnNode) {
- boolean itf = ((MethodInsnNode) insn).itf;
- if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) {
- throw new RuntimeException();
- }
- }
- }
- if (visibleLocalVariableAnnotations != null
- && visibleLocalVariableAnnotations.size() > 0) {
- throw new RuntimeException();
- }
- if (invisibleLocalVariableAnnotations != null
- && invisibleLocalVariableAnnotations.size() > 0) {
- throw new RuntimeException();
- }
+ for (int j = 0, m = parameterAnnotations.size(); j < m; ++j) {
+ AnnotationNode annotation = parameterAnnotations.get(j);
+ annotation.accept(methodVisitor.visitParameterAnnotation(i, annotation.desc, true));
}
+ }
}
-
- /**
- * Makes the given class visitor visit this method.
- *
- * @param cv
- * a class visitor.
- */
- public void accept(final ClassVisitor cv) {
- String[] exceptions = new String[this.exceptions.size()];
- this.exceptions.toArray(exceptions);
- MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
- exceptions);
- if (mv != null) {
- accept(mv);
- }
+ if (invisibleAnnotableParameterCount > 0) {
+ methodVisitor.visitAnnotableParameterCount(invisibleAnnotableParameterCount, false);
}
-
- /**
- * Makes the given method visitor visit this method.
- *
- * @param mv
- * a method visitor.
- */
- public void accept(final MethodVisitor mv) {
- // visits the method parameters
- int i, j, n;
- n = parameters == null ? 0 : parameters.size();
- for (i = 0; i < n; i++) {
- ParameterNode parameter = parameters.get(i);
- mv.visitParameter(parameter.name, parameter.access);
- }
- // visits the method attributes
- if (annotationDefault != null) {
- AnnotationVisitor av = mv.visitAnnotationDefault();
- AnnotationNode.accept(av, null, annotationDefault);
- if (av != null) {
- av.visitEnd();
- }
- }
- n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
- for (i = 0; i < n; ++i) {
- AnnotationNode an = visibleAnnotations.get(i);
- an.accept(mv.visitAnnotation(an.desc, true));
- }
- n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
- for (i = 0; i < n; ++i) {
- AnnotationNode an = invisibleAnnotations.get(i);
- an.accept(mv.visitAnnotation(an.desc, false));
- }
- n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
- for (i = 0; i < n; ++i) {
- TypeAnnotationNode an = visibleTypeAnnotations.get(i);
- an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
- true));
- }
- n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
- .size();
- for (i = 0; i < n; ++i) {
- TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
- an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
- false));
+ if (invisibleParameterAnnotations != null) {
+ for (int i = 0, n = invisibleParameterAnnotations.length; i < n; ++i) {
+ List<AnnotationNode> parameterAnnotations = invisibleParameterAnnotations[i];
+ if (parameterAnnotations == null) {
+ continue;
}
- n = visibleParameterAnnotations == null ? 0
- : visibleParameterAnnotations.length;
- for (i = 0; i < n; ++i) {
- List<?> l = visibleParameterAnnotations[i];
- if (l == null) {
- continue;
- }
- for (j = 0; j < l.size(); ++j) {
- AnnotationNode an = (AnnotationNode) l.get(j);
- an.accept(mv.visitParameterAnnotation(i, an.desc, true));
- }
+ for (int j = 0, m = parameterAnnotations.size(); j < m; ++j) {
+ AnnotationNode annotation = parameterAnnotations.get(j);
+ annotation.accept(methodVisitor.visitParameterAnnotation(i, annotation.desc, false));
}
- n = invisibleParameterAnnotations == null ? 0
- : invisibleParameterAnnotations.length;
- for (i = 0; i < n; ++i) {
- List<?> l = invisibleParameterAnnotations[i];
- if (l == null) {
- continue;
- }
- for (j = 0; j < l.size(); ++j) {
- AnnotationNode an = (AnnotationNode) l.get(j);
- an.accept(mv.visitParameterAnnotation(i, an.desc, false));
- }
+ }
+ }
+ // Visit the non standard attributes.
+ if (visited) {
+ instructions.resetLabels();
+ }
+ if (attrs != null) {
+ for (int i = 0, n = attrs.size(); i < n; ++i) {
+ methodVisitor.visitAttribute(attrs.get(i));
+ }
+ }
+ // Visit the code.
+ if (instructions.size() > 0) {
+ methodVisitor.visitCode();
+ // Visits the try catch blocks.
+ if (tryCatchBlocks != null) {
+ for (int i = 0, n = tryCatchBlocks.size(); i < n; ++i) {
+ tryCatchBlocks.get(i).updateIndex(i);
+ tryCatchBlocks.get(i).accept(methodVisitor);
}
- if (visited) {
- instructions.resetLabels();
+ }
+ // Visit the instructions.
+ instructions.accept(methodVisitor);
+ // Visits the local variables.
+ if (localVariables != null) {
+ for (int i = 0, n = localVariables.size(); i < n; ++i) {
+ localVariables.get(i).accept(methodVisitor);
}
- n = attrs == null ? 0 : attrs.size();
- for (i = 0; i < n; ++i) {
- mv.visitAttribute(attrs.get(i));
+ }
+ // Visits the local variable annotations.
+ if (visibleLocalVariableAnnotations != null) {
+ for (int i = 0, n = visibleLocalVariableAnnotations.size(); i < n; ++i) {
+ visibleLocalVariableAnnotations.get(i).accept(methodVisitor, true);
}
- // visits the method's code
- if (instructions.size() > 0) {
- mv.visitCode();
- // visits try catch blocks
- n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
- for (i = 0; i < n; ++i) {
- tryCatchBlocks.get(i).updateIndex(i);
- tryCatchBlocks.get(i).accept(mv);
- }
- // visits instructions
- instructions.accept(mv);
- // visits local variables
- n = localVariables == null ? 0 : localVariables.size();
- for (i = 0; i < n; ++i) {
- localVariables.get(i).accept(mv);
- }
- // visits local variable annotations
- n = visibleLocalVariableAnnotations == null ? 0
- : visibleLocalVariableAnnotations.size();
- for (i = 0; i < n; ++i) {
- visibleLocalVariableAnnotations.get(i).accept(mv, true);
- }
- n = invisibleLocalVariableAnnotations == null ? 0
- : invisibleLocalVariableAnnotations.size();
- for (i = 0; i < n; ++i) {
- invisibleLocalVariableAnnotations.get(i).accept(mv, false);
- }
- // visits maxs
- mv.visitMaxs(maxStack, maxLocals);
- visited = true;
+ }
+ if (invisibleLocalVariableAnnotations != null) {
+ for (int i = 0, n = invisibleLocalVariableAnnotations.size(); i < n; ++i) {
+ invisibleLocalVariableAnnotations.get(i).accept(methodVisitor, false);
}
- mv.visitEnd();
+ }
+ methodVisitor.visitMaxs(maxStack, maxLocals);
+ visited = true;
}
+ methodVisitor.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleExportNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleExportNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleExportNode.java
old mode 100644
new mode 100755
index 946872d..c4f6503
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleExportNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleExportNode.java
@@ -1,82 +1,79 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
/**
* A node that represents an exported package with its name and the module that can access to it.
- *
+ *
* @author Remi Forax
*/
public class ModuleExportNode {
- /**
- * The package name.
- */
- public String packaze;
-
- /**
- * The access flags (see {@link org.objectweb.asm.Opcodes}).
- * Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
- */
- public int access;
- /**
- * A list of modules that can access to this exported package.
- * May be <tt>null</tt>.
- */
- public List<String> modules;
+ /** The internal name of the exported package. */
+ public String packaze;
+
+ /**
+ * The access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). Valid values are {@code
+ * ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ */
+ public int access;
+
+ /**
+ * The list of modules that can access this exported package, specified with fully qualified names
+ * (using dots). May be {@literal null}.
+ */
+ public List<String> modules;
- /**
- * Constructs a new {@link ModuleExportNode}.
- *
- * @param packaze
- * the parameter's name.
- * @param modules
- * a list of modules that can access to this exported package.
- */
- public ModuleExportNode(final String packaze, final int access, final List<String> modules) {
- this.packaze = packaze;
- this.access = access;
- this.modules = modules;
- }
+ /**
+ * Constructs a new {@link ModuleExportNode}.
+ *
+ * @param packaze the internal name of the exported package.
+ * @param access the package access flags, one or more of {@code ACC_SYNTHETIC} and {@code
+ * ACC_MANDATED}.
+ * @param modules a list of modules that can access this exported package, specified with fully
+ * qualified names (using dots).
+ */
+ public ModuleExportNode(final String packaze, final int access, final List<String> modules) {
+ this.packaze = packaze;
+ this.access = access;
+ this.modules = modules;
+ }
- /**
- * Makes the given module visitor visit this export declaration.
- *
- * @param mv
- * a module visitor.
- */
- public void accept(final ModuleVisitor mv) {
- mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0]));
- }
+ /**
+ * Makes the given module visitor visit this export declaration.
+ *
+ * @param moduleVisitor a module visitor.
+ */
+ public void accept(final ModuleVisitor moduleVisitor) {
+ moduleVisitor.visitExport(
+ packaze, access, modules == null ? null : modules.toArray(new String[0]));
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleNode.java
old mode 100644
new mode 100755
index e76dbf1..fe05259
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ModuleNode.java
@@ -1,115 +1,116 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.ArrayList;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A node that represents a module declaration.
- *
+ *
* @author Remi Forax
*/
public class ModuleNode extends ModuleVisitor {
- /**
- * Module name
- */
- public String name;
-
- /**
- * Module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
- * and {@code ACC_MANDATED}.
- */
- public int access;
-
- /**
- * Version of the module.
- * May be <tt>null</tt>.
- */
- public String version;
-
- /**
- * Name of the main class in internal form
- * May be <tt>null</tt>.
- */
- public String mainClass;
-
- /**
- * A list of packages that are declared by the current module.
- * May be <tt>null</tt>.
- */
- public List<String> packages;
-
- /**
- * A list of modules can are required by the current module.
- * May be <tt>null</tt>.
- */
- public List<ModuleRequireNode> requires;
-
- /**
- * A list of packages that are exported by the current module.
- * May be <tt>null</tt>.
- */
- public List<ModuleExportNode> exports;
-
- /**
- * A list of packages that are opened by the current module.
- * May be <tt>null</tt>.
- */
- public List<ModuleOpenNode> opens;
-
- /**
- * A list of classes in their internal forms that are used
- * as a service by the current module. May be <tt>null</tt>.
- */
- public List<String> uses;
-
- /**
- * A list of services along with their implementations provided
- * by the current module. May be <tt>null</tt>.
- */
- public List<ModuleProvideNode> provides;
-
- public ModuleNode(final String name, final int access,
- final String version) {
- super(Opcodes.ASM6);
- this.name = name;
- this.access = access;
- this.version = version;
+
+ /** The fully qualified name (using dots) of this module. */
+ public String name;
+
+ /**
+ * The module's access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
+ * ACC_MANDATED}.
+ */
+ public int access;
+
+ /** The version of this module. May be {@literal null}. */
+ public String version;
+
+ /** The internal name of the main class of this module. May be {@literal null}. */
+ public String mainClass;
+
+ /** The internal name of the packages declared by this module. May be {@literal null}. */
+ public List<String> packages;
+
+ /** The dependencies of this module. May be {@literal null}. */
+ public List<ModuleRequireNode> requires;
+
+ /** The packages exported by this module. May be {@literal null}. */
+ public List<ModuleExportNode> exports;
+
+ /** The packages opened by this module. May be {@literal null}. */
+ public List<ModuleOpenNode> opens;
+
+ /** The internal names of the services used by this module. May be {@literal null}. */
+ public List<String> uses;
+
+ /** The services provided by this module. May be {@literal null}. */
+ public List<ModuleProvideNode> provides;
+
+ /**
+ * Constructs a {@link ModuleNode}. <i>Subclasses must not use this constructor</i>. Instead, they
+ * must use the {@link #ModuleNode(int,String,int,String,List,List,List,List,List)} version.
+ *
+ * @param name the fully qualified name (using dots) of the module.
+ * @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
+ * ACC_MANDATED}.
+ * @param version the module version, or {@literal null}.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public ModuleNode(final String name, final int access, final String version) {
+ super(Opcodes.ASM7);
+ if (getClass() != ModuleNode.class) {
+ throw new IllegalStateException();
}
-
- public ModuleNode(final int api,
+ this.name = name;
+ this.access = access;
+ this.version = version;
+ }
+
+ // TODO(forax): why is there no 'mainClass' and 'packages' parameters in this constructor?
+ /**
+ * Constructs a {@link ModuleNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM6}
+ * or {@link Opcodes#ASM7}.
+ * @param name the fully qualified name (using dots) of the module.
+ * @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
+ * ACC_MANDATED}.
+ * @param version the module version, or {@literal null}.
+ * @param requires The dependencies of this module. May be {@literal null}.
+ * @param exports The packages exported by this module. May be {@literal null}.
+ * @param opens The packages opened by this module. May be {@literal null}.
+ * @param uses The internal names of the services used by this module. May be {@literal null}.
+ * @param provides The services provided by this module. May be {@literal null}.
+ */
+ public ModuleNode(
+ final int api,
final String name,
final int access,
final String version,
@@ -118,134 +119,117 @@ public class ModuleNode extends ModuleVisitor {
final List<ModuleOpenNode> opens,
final List<String> uses,
final List<ModuleProvideNode> provides) {
- super(api);
- this.name = name;
- this.access = access;
- this.version = version;
- this.requires = requires;
- this.exports = exports;
- this.opens = opens;
- this.uses = uses;
- this.provides = provides;
- if (getClass() != ModuleNode.class) {
- throw new IllegalStateException();
- }
+ super(api);
+ this.name = name;
+ this.access = access;
+ this.version = version;
+ this.requires = requires;
+ this.exports = exports;
+ this.opens = opens;
+ this.uses = uses;
+ this.provides = provides;
+ }
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ this.mainClass = mainClass;
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ if (packages == null) {
+ packages = new ArrayList<String>(5);
}
-
- @Override
- public void visitMainClass(String mainClass) {
- this.mainClass = mainClass;
+ packages.add(packaze);
+ }
+
+ @Override
+ public void visitRequire(final String module, final int access, final String version) {
+ if (requires == null) {
+ requires = new ArrayList<ModuleRequireNode>(5);
+ }
+ requires.add(new ModuleRequireNode(module, access, version));
+ }
+
+ @Override
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ if (exports == null) {
+ exports = new ArrayList<ModuleExportNode>(5);
}
-
- @Override
- public void visitPackage(String packaze) {
- if (packages == null) {
- packages = new ArrayList<String>(5);
- }
- packages.add(packaze);
+ exports.add(new ModuleExportNode(packaze, access, Util.asArrayList(modules)));
+ }
+
+ @Override
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ if (opens == null) {
+ opens = new ArrayList<ModuleOpenNode>(5);
+ }
+ opens.add(new ModuleOpenNode(packaze, access, Util.asArrayList(modules)));
+ }
+
+ @Override
+ public void visitUse(final String service) {
+ if (uses == null) {
+ uses = new ArrayList<String>(5);
+ }
+ uses.add(service);
+ }
+
+ @Override
+ public void visitProvide(final String service, final String... providers) {
+ if (provides == null) {
+ provides = new ArrayList<ModuleProvideNode>(5);
+ }
+ provides.add(new ModuleProvideNode(service, Util.asArrayList(providers)));
+ }
+
+ @Override
+ public void visitEnd() {
+ // Nothing to do.
+ }
+
+ /**
+ * Makes the given class visitor visit this module.
+ *
+ * @param classVisitor a class visitor.
+ */
+ public void accept(final ClassVisitor classVisitor) {
+ ModuleVisitor moduleVisitor = classVisitor.visitModule(name, access, version);
+ if (moduleVisitor == null) {
+ return;
}
-
- @Override
- public void visitRequire(String module, int access, String version) {
- if (requires == null) {
- requires = new ArrayList<ModuleRequireNode>(5);
- }
- requires.add(new ModuleRequireNode(module, access, version));
+ if (mainClass != null) {
+ moduleVisitor.visitMainClass(mainClass);
}
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- if (exports == null) {
- exports = new ArrayList<ModuleExportNode>(5);
- }
- List<String> moduleList = null;
- if (modules != null) {
- moduleList = new ArrayList<String>(modules.length);
- for (int i = 0; i < modules.length; i++) {
- moduleList.add(modules[i]);
- }
- }
- exports.add(new ModuleExportNode(packaze, access, moduleList));
+ if (packages != null) {
+ for (int i = 0, n = packages.size(); i < n; i++) {
+ moduleVisitor.visitPackage(packages.get(i));
+ }
}
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- if (opens == null) {
- opens = new ArrayList<ModuleOpenNode>(5);
- }
- List<String> moduleList = null;
- if (modules != null) {
- moduleList = new ArrayList<String>(modules.length);
- for (int i = 0; i < modules.length; i++) {
- moduleList.add(modules[i]);
- }
- }
- opens.add(new ModuleOpenNode(packaze, access, moduleList));
+ if (requires != null) {
+ for (int i = 0, n = requires.size(); i < n; i++) {
+ requires.get(i).accept(moduleVisitor);
+ }
}
-
- @Override
- public void visitUse(String service) {
- if (uses == null) {
- uses = new ArrayList<String>(5);
- }
- uses.add(service);
+ if (exports != null) {
+ for (int i = 0, n = exports.size(); i < n; i++) {
+ exports.get(i).accept(moduleVisitor);
+ }
}
-
- @Override
- public void visitProvide(String service, String... providers) {
- if (provides == null) {
- provides = new ArrayList<ModuleProvideNode>(5);
- }
- ArrayList<String> providerList =
- new ArrayList<String>(providers.length);
- for (int i = 0; i < providers.length; i++) {
- providerList.add(providers[i]);
- }
- provides.add(new ModuleProvideNode(service, providerList));
+ if (opens != null) {
+ for (int i = 0, n = opens.size(); i < n; i++) {
+ opens.get(i).accept(moduleVisitor);
+ }
}
-
- @Override
- public void visitEnd() {
+ if (uses != null) {
+ for (int i = 0, n = uses.size(); i < n; i++) {
+ moduleVisitor.visitUse(uses.get(i));
+ }
}
-
- public void accept(final ClassVisitor cv) {
- ModuleVisitor mv = cv.visitModule(name, access, version);
- if (mv == null) {
- return;
- }
- if (mainClass != null) {
- mv.visitMainClass(mainClass);
- }
- if (packages != null) {
- for (int i = 0; i < packages.size(); i++) {
- mv.visitPackage(packages.get(i));
- }
- }
-
- if (requires != null) {
- for (int i = 0; i < requires.size(); i++) {
- requires.get(i).accept(mv);
- }
- }
- if (exports != null) {
- for (int i = 0; i < exports.size(); i++) {
- exports.get(i).accept(mv);
- }
- }
- if (opens != null) {
- for (int i = 0; i < opens.size(); i++) {
- opens.get(i).accept(mv);
- }
- }
- if (uses != null) {
- for (int i = 0; i < uses.size(); i++) {
- mv.visitUse(uses.get(i));
- }
- }
- if (provides != null) {
- for (int i = 0; i < provides.size(); i++) {
- provides.get(i).accept(mv);
- }
- }
+ if (provides != null) {
+ for (int i = 0, n = provides.size(); i < n; i++) {
+ provides.get(i).accept(moduleVisitor);
+ }
}
+ }
}
[12/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
old mode 100644
new mode 100755
index 029c464..e3bcae4
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
@@ -35,102 +33,103 @@ import org.apache.tapestry5.internal.plastic.asm.Type;
/**
* An {@link AnnotationVisitor} that checks that its methods are properly used.
- *
+ *
* @author Eric Bruneton
*/
public class CheckAnnotationAdapter extends AnnotationVisitor {
- private final boolean named;
+ /**
+ * Whether the values of the visited annotation are named. AnnotationVisitor instances used for
+ * annotation default and annotation arrays use unnamed values.
+ */
+ private final boolean useNamedValue;
- private boolean end;
+ /** Whether the {@link #visitEnd} method has been called. */
+ private boolean visitEndCalled;
- public CheckAnnotationAdapter(final AnnotationVisitor av) {
- this(av, true);
- }
+ public CheckAnnotationAdapter(final AnnotationVisitor annotationVisitor) {
+ this(annotationVisitor, true);
+ }
- CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) {
- super(Opcodes.ASM6, av);
- this.named = named;
- }
+ CheckAnnotationAdapter(final AnnotationVisitor annotationVisitor, final boolean useNamedValues) {
+ super(Opcodes.ASM7, annotationVisitor);
+ this.useNamedValue = useNamedValues;
+ }
- @Override
- public void visit(final String name, final Object value) {
- checkEnd();
- checkName(name);
- if (!(value instanceof Byte || value instanceof Boolean
- || value instanceof Character || value instanceof Short
- || value instanceof Integer || value instanceof Long
- || value instanceof Float || value instanceof Double
- || value instanceof String || value instanceof Type
- || value instanceof byte[] || value instanceof boolean[]
- || value instanceof char[] || value instanceof short[]
- || value instanceof int[] || value instanceof long[]
- || value instanceof float[] || value instanceof double[])) {
- throw new IllegalArgumentException("Invalid annotation value");
- }
- if (value instanceof Type) {
- int sort = ((Type) value).getSort();
- if (sort == Type.METHOD) {
- throw new IllegalArgumentException("Invalid annotation value");
- }
- }
- if (av != null) {
- av.visit(name, value);
- }
+ @Override
+ public void visit(final String name, final Object value) {
+ checkVisitEndNotCalled();
+ checkName(name);
+ if (!(value instanceof Byte
+ || value instanceof Boolean
+ || value instanceof Character
+ || value instanceof Short
+ || value instanceof Integer
+ || value instanceof Long
+ || value instanceof Float
+ || value instanceof Double
+ || value instanceof String
+ || value instanceof Type
+ || value instanceof byte[]
+ || value instanceof boolean[]
+ || value instanceof char[]
+ || value instanceof short[]
+ || value instanceof int[]
+ || value instanceof long[]
+ || value instanceof float[]
+ || value instanceof double[])) {
+ throw new IllegalArgumentException("Invalid annotation value");
}
-
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- checkEnd();
- checkName(name);
- CheckMethodAdapter.checkDesc(desc, false);
- if (value == null) {
- throw new IllegalArgumentException("Invalid enum value");
- }
- if (av != null) {
- av.visitEnum(name, desc, value);
- }
+ if (value instanceof Type && ((Type) value).getSort() == Type.METHOD) {
+ throw new IllegalArgumentException("Invalid annotation value");
}
+ super.visit(name, value);
+ }
- @Override
- public AnnotationVisitor visitAnnotation(final String name,
- final String desc) {
- checkEnd();
- checkName(name);
- CheckMethodAdapter.checkDesc(desc, false);
- return new CheckAnnotationAdapter(av == null ? null
- : av.visitAnnotation(name, desc));
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ checkVisitEndNotCalled();
+ checkName(name);
+ // Annotations can only appear in V1_5 or more classes.
+ CheckMethodAdapter.checkDescriptor(Opcodes.V1_5, descriptor, false);
+ if (value == null) {
+ throw new IllegalArgumentException("Invalid enum value");
}
+ super.visitEnum(name, descriptor, value);
+ }
- @Override
- public AnnotationVisitor visitArray(final String name) {
- checkEnd();
- checkName(name);
- return new CheckAnnotationAdapter(av == null ? null
- : av.visitArray(name), false);
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ checkVisitEndNotCalled();
+ checkName(name);
+ // Annotations can only appear in V1_5 or more classes.
+ CheckMethodAdapter.checkDescriptor(Opcodes.V1_5, descriptor, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(name, descriptor));
+ }
- @Override
- public void visitEnd() {
- checkEnd();
- end = true;
- if (av != null) {
- av.visitEnd();
- }
- }
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ checkVisitEndNotCalled();
+ checkName(name);
+ return new CheckAnnotationAdapter(super.visitArray(name), false);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkVisitEndNotCalled();
+ visitEndCalled = true;
+ super.visitEnd();
+ }
- private void checkEnd() {
- if (end) {
- throw new IllegalStateException(
- "Cannot call a visit method after visitEnd has been called");
- }
+ private void checkName(final String name) {
+ if (useNamedValue && name == null) {
+ throw new IllegalArgumentException("Annotation value name must not be null");
}
+ }
- private void checkName(final String name) {
- if (named && name == null) {
- throw new IllegalArgumentException(
- "Annotation value name must not be null");
- }
+ private void checkVisitEndNotCalled() {
+ if (visitEndCalled) {
+ throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");
}
+ }
}
[31/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
old mode 100644
new mode 100755
index 5ff7100..b541ecd
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
@@ -1,39 +1,37 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
@@ -41,909 +39,899 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
/**
- * A {@link MethodVisitor} that keeps track of stack map frame changes between
- * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This
- * adapter must be used with the
- * {@link org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each
- * visit<i>X</i> instruction delegates to the next visitor in the chain, if any,
- * and then simulates the effect of this instruction on the stack map frame,
- * represented by {@link #locals} and {@link #stack}. The next visitor in the
- * chain can get the state of the stack map frame <i>before</i> each instruction
- * by reading the value of these fields in its visit<i>X</i> methods (this
- * requires a reference to the AnalyzerAdapter that is before it in the chain).
- * If this adapter is used with a class that does not contain stack map table
- * attributes (i.e., pre Java 6 classes) then this adapter may not be able to
- * compute the stack map frame for each instruction. In this case no exception
- * is thrown but the {@link #locals} and {@link #stack} fields will be null for
- * these instructions.
- *
+ * A {@link MethodVisitor} that keeps track of stack map frame changes between {@link
+ * #visitFrame(int, int, Object[], int, Object[])} calls. This adapter must be used with the {@link
+ * org.apache.tapestry5.internal.plastic.asm.ClassReader#EXPAND_FRAMES} option. Each visit<i>X</i> instruction delegates to
+ * the next visitor in the chain, if any, and then simulates the effect of this instruction on the
+ * stack map frame, represented by {@link #locals} and {@link #stack}. The next visitor in the chain
+ * can get the state of the stack map frame <i>before</i> each instruction by reading the value of
+ * these fields in its visit<i>X</i> methods (this requires a reference to the AnalyzerAdapter that
+ * is before it in the chain). If this adapter is used with a class that does not contain stack map
+ * table attributes (i.e., pre Java 6 classes) then this adapter may not be able to compute the
+ * stack map frame for each instruction. In this case no exception is thrown but the {@link #locals}
+ * and {@link #stack} fields will be null for these instructions.
+ *
* @author Eric Bruneton
*/
public class AnalyzerAdapter extends MethodVisitor {
- /**
- * <code>List</code> of the local variable slots for current execution
- * frame. Primitive types are represented by {@link Opcodes#TOP},
- * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
- * two elements, the second one being TOP). Reference types are represented
- * by String objects (representing internal names), and uninitialized types
- * by Label objects (this label designates the NEW instruction that created
- * this uninitialized value). This field is <tt>null</tt> for unreachable
- * instructions.
- */
- public List<Object> locals;
-
- /**
- * <code>List</code> of the operand stack slots for current execution frame.
- * Primitive types are represented by {@link Opcodes#TOP},
- * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
- * two elements, the second one being TOP). Reference types are represented
- * by String objects (representing internal names), and uninitialized types
- * by Label objects (this label designates the NEW instruction that created
- * this uninitialized value). This field is <tt>null</tt> for unreachable
- * instructions.
- */
- public List<Object> stack;
-
- /**
- * The labels that designate the next instruction to be visited. May be
- * <tt>null</tt>.
- */
- private List<Label> labels;
-
- /**
- * Information about uninitialized types in the current execution frame.
- * This map associates internal names to Label objects. Each label
- * designates a NEW instruction that created the currently uninitialized
- * types, and the associated internal name represents the NEW operand, i.e.
- * the final, initialized type value.
- */
- public Map<Object, Object> uninitializedTypes;
-
- /**
- * The maximum stack size of this method.
- */
- private int maxStack;
-
- /**
- * The maximum number of local variables of this method.
- */
- private int maxLocals;
-
- /**
- * The owner's class name.
- */
- private String owner;
-
- /**
- * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)}
- * version.
- *
- * @param owner
- * the owner's class name.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls. May
- * be <tt>null</tt>.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public AnalyzerAdapter(final String owner, final int access,
- final String name, final String desc, final MethodVisitor mv) {
- this(Opcodes.ASM6, owner, access, name, desc, mv);
- if (getClass() != AnalyzerAdapter.class) {
- throw new IllegalStateException();
- }
+ /**
+ * The local variable slots for the current execution frame. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or {@link Opcodes#UNINITIALIZED_THIS} (long and
+ * double are represented by two elements, the second one being TOP). Reference types are
+ * represented by String objects (representing internal names), and uninitialized types by Label
+ * objects (this label designates the NEW instruction that created this uninitialized value). This
+ * field is {@literal null} for unreachable instructions.
+ */
+ public List<Object> locals;
+
+ /**
+ * The operand stack slots for the current execution frame. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or {@link Opcodes#UNINITIALIZED_THIS} (long and
+ * double are represented by two elements, the second one being TOP). Reference types are
+ * represented by String objects (representing internal names), and uninitialized types by Label
+ * objects (this label designates the NEW instruction that created this uninitialized value). This
+ * field is {@literal null} for unreachable instructions.
+ */
+ public List<Object> stack;
+
+ /** The labels that designate the next instruction to be visited. May be {@literal null}. */
+ private List<Label> labels;
+
+ /**
+ * The uninitialized types in the current execution frame. This map associates internal names to
+ * Label objects. Each label designates a NEW instruction that created the currently uninitialized
+ * types, and the associated internal name represents the NEW operand, i.e. the final, initialized
+ * type value.
+ */
+ public Map<Object, Object> uninitializedTypes;
+
+ /** The maximum stack size of this method. */
+ private int maxStack;
+
+ /** The maximum number of local variables of this method. */
+ private int maxLocals;
+
+ /** The owner's class name. */
+ private String owner;
+
+ /**
+ * Constructs a new {@link AnalyzerAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #AnalyzerAdapter(int, String, int, String, String,
+ * MethodVisitor)} version.
+ *
+ * @param owner the owner's class name.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param methodVisitor the method visitor to which this adapter delegates calls. May be {@literal
+ * null}.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public AnalyzerAdapter(
+ final String owner,
+ final int access,
+ final String name,
+ final String descriptor,
+ final MethodVisitor methodVisitor) {
+ this(Opcodes.ASM7, owner, access, name, descriptor, methodVisitor);
+ if (getClass() != AnalyzerAdapter.class) {
+ throw new IllegalStateException();
}
-
- /**
- * Creates a new {@link AnalyzerAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param owner
- * the owner's class name.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param mv
- * the method visitor to which this adapter delegates calls. May
- * be <tt>null</tt>.
- */
- protected AnalyzerAdapter(final int api, final String owner,
- final int access, final String name, final String desc,
- final MethodVisitor mv) {
- super(api, mv);
- this.owner = owner;
- locals = new ArrayList<Object>();
- stack = new ArrayList<Object>();
- uninitializedTypes = new HashMap<Object, Object>();
-
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ("<init>".equals(name)) {
- locals.add(Opcodes.UNINITIALIZED_THIS);
- } else {
- locals.add(owner);
- }
- }
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; ++i) {
- Type type = types[i];
- switch (type.getSort()) {
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- case Type.INT:
- locals.add(Opcodes.INTEGER);
- break;
- case Type.FLOAT:
- locals.add(Opcodes.FLOAT);
- break;
- case Type.LONG:
- locals.add(Opcodes.LONG);
- locals.add(Opcodes.TOP);
- break;
- case Type.DOUBLE:
- locals.add(Opcodes.DOUBLE);
- locals.add(Opcodes.TOP);
- break;
- case Type.ARRAY:
- locals.add(types[i].getDescriptor());
- break;
- // case Type.OBJECT:
- default:
- locals.add(types[i].getInternalName());
- }
- }
- maxLocals = locals.size();
+ }
+
+ /**
+ * Constructs a new {@link AnalyzerAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param owner the owner's class name.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param methodVisitor the method visitor to which this adapter delegates calls. May be {@literal
+ * null}.
+ */
+ protected AnalyzerAdapter(
+ final int api,
+ final String owner,
+ final int access,
+ final String name,
+ final String descriptor,
+ final MethodVisitor methodVisitor) {
+ super(api, methodVisitor);
+ this.owner = owner;
+ locals = new ArrayList<Object>();
+ stack = new ArrayList<Object>();
+ uninitializedTypes = new HashMap<Object, Object>();
+
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ("<init>".equals(name)) {
+ locals.add(Opcodes.UNINITIALIZED_THIS);
+ } else {
+ locals.add(owner);
+ }
}
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- if (type != Opcodes.F_NEW) { // uncompressed frame
- throw new IllegalStateException(
- "ClassReader.accept() should be called with EXPAND_FRAMES flag");
- }
-
- if (mv != null) {
- mv.visitFrame(type, nLocal, local, nStack, stack);
- }
-
- if (this.locals != null) {
- this.locals.clear();
- this.stack.clear();
- } else {
- this.locals = new ArrayList<Object>();
- this.stack = new ArrayList<Object>();
- }
- visitFrameTypes(nLocal, local, this.locals);
- visitFrameTypes(nStack, stack, this.stack);
- maxStack = Math.max(maxStack, this.stack.size());
+ for (Type argumentType : Type.getArgumentTypes(descriptor)) {
+ switch (argumentType.getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ locals.add(Opcodes.INTEGER);
+ break;
+ case Type.FLOAT:
+ locals.add(Opcodes.FLOAT);
+ break;
+ case Type.LONG:
+ locals.add(Opcodes.LONG);
+ locals.add(Opcodes.TOP);
+ break;
+ case Type.DOUBLE:
+ locals.add(Opcodes.DOUBLE);
+ locals.add(Opcodes.TOP);
+ break;
+ case Type.ARRAY:
+ locals.add(argumentType.getDescriptor());
+ break;
+ case Type.OBJECT:
+ locals.add(argumentType.getInternalName());
+ break;
+ default:
+ throw new AssertionError();
+ }
}
-
- private static void visitFrameTypes(final int n, final Object[] types,
- final List<Object> result) {
- for (int i = 0; i < n; ++i) {
- Object type = types[i];
- result.add(type);
- if (type == Opcodes.LONG || type == Opcodes.DOUBLE) {
- result.add(Opcodes.TOP);
- }
- }
+ maxLocals = locals.size();
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ if (type != Opcodes.F_NEW) { // Uncompressed frame.
+ throw new IllegalArgumentException(
+ "AnalyzerAdapter only accepts expanded frames (see ClassReader.EXPAND_FRAMES)");
}
- @Override
- public void visitInsn(final int opcode) {
- if (mv != null) {
- mv.visitInsn(opcode);
- }
- execute(opcode, 0, null);
- if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
- || opcode == Opcodes.ATHROW) {
- this.locals = null;
- this.stack = null;
- }
- }
+ super.visitFrame(type, numLocal, local, numStack, stack);
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- if (mv != null) {
- mv.visitIntInsn(opcode, operand);
- }
- execute(opcode, operand, null);
+ if (this.locals != null) {
+ this.locals.clear();
+ this.stack.clear();
+ } else {
+ this.locals = new ArrayList<Object>();
+ this.stack = new ArrayList<Object>();
}
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- if (mv != null) {
- mv.visitVarInsn(opcode, var);
- }
- execute(opcode, var, null);
+ visitFrameTypes(numLocal, local, this.locals);
+ visitFrameTypes(numStack, stack, this.stack);
+ maxLocals = Math.max(maxLocals, this.locals.size());
+ maxStack = Math.max(maxStack, this.stack.size());
+ }
+
+ private static void visitFrameTypes(
+ final int numTypes, final Object[] frameTypes, final List<Object> result) {
+ for (int i = 0; i < numTypes; ++i) {
+ Object frameType = frameTypes[i];
+ result.add(frameType);
+ if (frameType == Opcodes.LONG || frameType == Opcodes.DOUBLE) {
+ result.add(Opcodes.TOP);
+ }
}
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- if (opcode == Opcodes.NEW) {
- if (labels == null) {
- Label l = new Label();
- labels = new ArrayList<Label>(3);
- labels.add(l);
- if (mv != null) {
- mv.visitLabel(l);
- }
- }
- for (int i = 0; i < labels.size(); ++i) {
- uninitializedTypes.put(labels.get(i), type);
- }
- }
- if (mv != null) {
- mv.visitTypeInsn(opcode, type);
- }
- execute(opcode, 0, type);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ super.visitInsn(opcode);
+ execute(opcode, 0, null);
+ if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
+ this.locals = null;
+ this.stack = null;
}
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ super.visitIntInsn(opcode, operand);
+ execute(opcode, operand, null);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ super.visitVarInsn(opcode, var);
+ boolean isLongOrDouble =
+ opcode == Opcodes.LLOAD
+ || opcode == Opcodes.DLOAD
+ || opcode == Opcodes.LSTORE
+ || opcode == Opcodes.DSTORE;
+ maxLocals = Math.max(maxLocals, var + (isLongOrDouble ? 2 : 1));
+ execute(opcode, var, null);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ if (opcode == Opcodes.NEW) {
+ if (labels == null) {
+ Label label = new Label();
+ labels = new ArrayList<Label>(3);
+ labels.add(label);
if (mv != null) {
- mv.visitFieldInsn(opcode, owner, name, desc);
+ mv.visitLabel(label);
}
- execute(opcode, 0, desc);
+ }
+ for (Label label : labels) {
+ uninitializedTypes.put(label, type);
+ }
}
-
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
+ super.visitTypeInsn(opcode, type);
+ execute(opcode, 0, type);
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ super.visitFieldInsn(opcode, owner, name, descriptor);
+ execute(opcode, 0, descriptor);
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
}
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
}
-
- private void doVisitMethodInsn(int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- pop(desc);
- if (opcode != Opcodes.INVOKESTATIC) {
- Object t = pop();
- if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') {
- Object u;
- if (t == Opcodes.UNINITIALIZED_THIS) {
- u = this.owner;
- } else {
- u = uninitializedTypes.get(t);
- }
- for (int i = 0; i < locals.size(); ++i) {
- if (locals.get(i) == t) {
- locals.set(i, u);
- }
- }
- for (int i = 0; i < stack.size(); ++i) {
- if (stack.get(i) == t) {
- stack.set(i, u);
- }
- }
- }
- }
- pushDesc(desc);
- labels = null;
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- if (mv != null) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- pop(desc);
- pushDesc(desc);
- labels = null;
+ if (this.locals == null) {
+ labels = null;
+ return;
}
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- if (mv != null) {
- mv.visitJumpInsn(opcode, label);
+ pop(descriptor);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ Object value = pop();
+ if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
+ Object initializedValue;
+ if (value == Opcodes.UNINITIALIZED_THIS) {
+ initializedValue = this.owner;
+ } else {
+ initializedValue = uninitializedTypes.get(value);
}
- execute(opcode, 0, null);
- if (opcode == Opcodes.GOTO) {
- this.locals = null;
- this.stack = null;
+ for (int i = 0; i < locals.size(); ++i) {
+ if (locals.get(i) == value) {
+ locals.set(i, initializedValue);
+ }
}
- }
-
- @Override
- public void visitLabel(final Label label) {
- if (mv != null) {
- mv.visitLabel(label);
- }
- if (labels == null) {
- labels = new ArrayList<Label>(3);
+ for (int i = 0; i < stack.size(); ++i) {
+ if (stack.get(i) == value) {
+ stack.set(i, initializedValue);
+ }
}
- labels.add(label);
+ }
}
-
- @Override
- public void visitLdcInsn(final Object cst) {
- if (mv != null) {
- mv.visitLdcInsn(cst);
- }
- if (this.locals == null) {
- labels = null;
- return;
- }
- if (cst instanceof Integer) {
- push(Opcodes.INTEGER);
- } else if (cst instanceof Long) {
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- } else if (cst instanceof Float) {
- push(Opcodes.FLOAT);
- } else if (cst instanceof Double) {
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- } else if (cst instanceof String) {
- push("java/lang/String");
- } else if (cst instanceof Type) {
- int sort = ((Type) cst).getSort();
- if (sort == Type.OBJECT || sort == Type.ARRAY) {
- push("java/lang/Class");
- } else if (sort == Type.METHOD) {
- push("java/lang/invoke/MethodType");
- } else {
- throw new IllegalArgumentException();
- }
- } else if (cst instanceof Handle) {
- push("java/lang/invoke/MethodHandle");
- } else {
- throw new IllegalArgumentException();
- }
- labels = null;
+ pushDescriptor(descriptor);
+ labels = null;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ if (this.locals == null) {
+ labels = null;
+ return;
}
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- if (mv != null) {
- mv.visitIincInsn(var, increment);
- }
- execute(Opcodes.IINC, var, null);
+ pop(descriptor);
+ pushDescriptor(descriptor);
+ labels = null;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ super.visitJumpInsn(opcode, label);
+ execute(opcode, 0, null);
+ if (opcode == Opcodes.GOTO) {
+ this.locals = null;
+ this.stack = null;
}
+ }
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- if (mv != null) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
- execute(Opcodes.TABLESWITCH, 0, null);
- this.locals = null;
- this.stack = null;
+ @Override
+ public void visitLabel(final Label label) {
+ super.visitLabel(label);
+ if (labels == null) {
+ labels = new ArrayList<Label>(3);
}
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- if (mv != null) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
- execute(Opcodes.LOOKUPSWITCH, 0, null);
- this.locals = null;
- this.stack = null;
+ labels.add(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ super.visitLdcInsn(value);
+ if (this.locals == null) {
+ labels = null;
+ return;
}
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- if (mv != null) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
- execute(Opcodes.MULTIANEWARRAY, dims, desc);
+ if (value instanceof Integer) {
+ push(Opcodes.INTEGER);
+ } else if (value instanceof Long) {
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ } else if (value instanceof Float) {
+ push(Opcodes.FLOAT);
+ } else if (value instanceof Double) {
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ } else if (value instanceof String) {
+ push("java/lang/String");
+ } else if (value instanceof Type) {
+ int sort = ((Type) value).getSort();
+ if (sort == Type.OBJECT || sort == Type.ARRAY) {
+ push("java/lang/Class");
+ } else if (sort == Type.METHOD) {
+ push("java/lang/invoke/MethodType");
+ } else {
+ throw new IllegalArgumentException();
+ }
+ } else if (value instanceof Handle) {
+ push("java/lang/invoke/MethodHandle");
+ } else if (value instanceof ConstantDynamic) {
+ pushDescriptor(((ConstantDynamic) value).getDescriptor());
+ } else {
+ throw new IllegalArgumentException();
}
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- if (mv != null) {
- this.maxStack = Math.max(this.maxStack, maxStack);
- this.maxLocals = Math.max(this.maxLocals, maxLocals);
- mv.visitMaxs(this.maxStack, this.maxLocals);
- }
+ labels = null;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ super.visitIincInsn(var, increment);
+ maxLocals = Math.max(maxLocals, var + 1);
+ execute(Opcodes.IINC, var, null);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ execute(Opcodes.TABLESWITCH, 0, null);
+ this.locals = null;
+ this.stack = null;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ execute(Opcodes.LOOKUPSWITCH, 0, null);
+ this.locals = null;
+ this.stack = null;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ super.visitMultiANewArrayInsn(descriptor, numDimensions);
+ execute(Opcodes.MULTIANEWARRAY, numDimensions, descriptor);
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ char firstDescriptorChar = descriptor.charAt(0);
+ maxLocals =
+ Math.max(
+ maxLocals, index + (firstDescriptorChar == 'J' || firstDescriptorChar == 'D' ? 2 : 1));
+ super.visitLocalVariable(name, descriptor, signature, start, end, index);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (mv != null) {
+ this.maxStack = Math.max(this.maxStack, maxStack);
+ this.maxLocals = Math.max(this.maxLocals, maxLocals);
+ mv.visitMaxs(this.maxStack, this.maxLocals);
}
+ }
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
- private Object get(final int local) {
- maxLocals = Math.max(maxLocals, local + 1);
- return local < locals.size() ? locals.get(local) : Opcodes.TOP;
- }
+ private Object get(final int local) {
+ maxLocals = Math.max(maxLocals, local + 1);
+ return local < locals.size() ? locals.get(local) : Opcodes.TOP;
+ }
- private void set(final int local, final Object type) {
- maxLocals = Math.max(maxLocals, local + 1);
- while (local >= locals.size()) {
- locals.add(Opcodes.TOP);
+ private void set(final int local, final Object type) {
+ maxLocals = Math.max(maxLocals, local + 1);
+ while (local >= locals.size()) {
+ locals.add(Opcodes.TOP);
+ }
+ locals.set(local, type);
+ }
+
+ private void push(final Object type) {
+ stack.add(type);
+ maxStack = Math.max(maxStack, stack.size());
+ }
+
+ private void pushDescriptor(final String descriptor) {
+ int index = descriptor.charAt(0) == '(' ? descriptor.indexOf(')') + 1 : 0;
+ switch (descriptor.charAt(index)) {
+ case 'V':
+ return;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ push(Opcodes.INTEGER);
+ return;
+ case 'F':
+ push(Opcodes.FLOAT);
+ return;
+ case 'J':
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ return;
+ case 'D':
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ return;
+ case '[':
+ if (index == 0) {
+ push(descriptor);
+ } else {
+ push(descriptor.substring(index, descriptor.length()));
}
- locals.set(local, type);
+ break;
+ case 'L':
+ if (index == 0) {
+ push(descriptor.substring(1, descriptor.length() - 1));
+ } else {
+ push(descriptor.substring(index + 1, descriptor.length() - 1));
+ }
+ break;
+ default:
+ throw new AssertionError();
}
+ }
- private void push(final Object type) {
- stack.add(type);
- maxStack = Math.max(maxStack, stack.size());
- }
+ private Object pop() {
+ return stack.remove(stack.size() - 1);
+ }
- private void pushDesc(final String desc) {
- int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
- switch (desc.charAt(index)) {
- case 'V':
- return;
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- push(Opcodes.INTEGER);
- return;
- case 'F':
- push(Opcodes.FLOAT);
- return;
- case 'J':
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- return;
- case 'D':
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- return;
- case '[':
- if (index == 0) {
- push(desc);
- } else {
- push(desc.substring(index, desc.length()));
- }
- break;
- // case 'L':
- default:
- if (index == 0) {
- push(desc.substring(1, desc.length() - 1));
- } else {
- push(desc.substring(index + 1, desc.length() - 1));
- }
- }
+ private void pop(final int numSlots) {
+ int size = stack.size();
+ int end = size - numSlots;
+ for (int i = size - 1; i >= end; --i) {
+ stack.remove(i);
}
-
- private Object pop() {
- return stack.remove(stack.size() - 1);
+ }
+
+ private void pop(final String descriptor) {
+ char firstDescriptorChar = descriptor.charAt(0);
+ if (firstDescriptorChar == '(') {
+ int numSlots = 0;
+ Type[] types = Type.getArgumentTypes(descriptor);
+ for (Type type : types) {
+ numSlots += type.getSize();
+ }
+ pop(numSlots);
+ } else if (firstDescriptorChar == 'J' || firstDescriptorChar == 'D') {
+ pop(2);
+ } else {
+ pop(1);
}
+ }
- private void pop(final int n) {
- int size = stack.size();
- int end = size - n;
- for (int i = size - 1; i >= end; --i) {
- stack.remove(i);
- }
+ private void execute(final int opcode, final int intArg, final String stringArg) {
+ if (this.locals == null) {
+ labels = null;
+ return;
}
-
- private void pop(final String desc) {
- char c = desc.charAt(0);
- if (c == '(') {
- int n = 0;
- Type[] types = Type.getArgumentTypes(desc);
- for (int i = 0; i < types.length; ++i) {
- n += types[i].getSize();
- }
- pop(n);
- } else if (c == 'J' || c == 'D') {
- pop(2);
+ Object value1;
+ Object value2;
+ Object value3;
+ Object t4;
+ switch (opcode) {
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(Opcodes.NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.ALOAD:
+ push(get(intArg));
+ break;
+ case Opcodes.LLOAD:
+ case Opcodes.DLOAD:
+ push(get(intArg));
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ value1 = pop();
+ if (value1 instanceof String) {
+ pushDescriptor(((String) value1).substring(1));
+ } else if (value1 == Opcodes.NULL) {
+ push(value1);
} else {
- pop(1);
- }
- }
-
- private void execute(final int opcode, final int iarg, final String sarg) {
- if (this.locals == null) {
- labels = null;
- return;
- }
- Object t1, t2, t3, t4;
- switch (opcode) {
- case Opcodes.NOP:
- case Opcodes.INEG:
- case Opcodes.LNEG:
- case Opcodes.FNEG:
- case Opcodes.DNEG:
- case Opcodes.I2B:
- case Opcodes.I2C:
- case Opcodes.I2S:
- case Opcodes.GOTO:
- case Opcodes.RETURN:
- break;
- case Opcodes.ACONST_NULL:
- push(Opcodes.NULL);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- case Opcodes.BIPUSH:
- case Opcodes.SIPUSH:
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.ILOAD:
- case Opcodes.FLOAD:
- case Opcodes.ALOAD:
- push(get(iarg));
- break;
- case Opcodes.LLOAD:
- case Opcodes.DLOAD:
- push(get(iarg));
- push(Opcodes.TOP);
- break;
- case Opcodes.IALOAD:
- case Opcodes.BALOAD:
- case Opcodes.CALOAD:
- case Opcodes.SALOAD:
- pop(2);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LALOAD:
- case Opcodes.D2L:
- pop(2);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FALOAD:
- pop(2);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DALOAD:
- case Opcodes.L2D:
- pop(2);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.AALOAD:
- pop(1);
- t1 = pop();
- if (t1 instanceof String) {
- pushDesc(((String) t1).substring(1));
- } else if (t1 == Opcodes.NULL) {
- push(t1);
- } else {
- push("java/lang/Object");
- }
- break;
- case Opcodes.ISTORE:
- case Opcodes.FSTORE:
- case Opcodes.ASTORE:
- t1 = pop();
- set(iarg, t1);
- if (iarg > 0) {
- t2 = get(iarg - 1);
- if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
- set(iarg - 1, Opcodes.TOP);
- }
- }
- break;
- case Opcodes.LSTORE:
- case Opcodes.DSTORE:
- pop(1);
- t1 = pop();
- set(iarg, t1);
- set(iarg + 1, Opcodes.TOP);
- if (iarg > 0) {
- t2 = get(iarg - 1);
- if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
- set(iarg - 1, Opcodes.TOP);
- }
- }
- break;
- case Opcodes.IASTORE:
- case Opcodes.BASTORE:
- case Opcodes.CASTORE:
- case Opcodes.SASTORE:
- case Opcodes.FASTORE:
- case Opcodes.AASTORE:
- pop(3);
- break;
- case Opcodes.LASTORE:
- case Opcodes.DASTORE:
- pop(4);
- break;
- case Opcodes.POP:
- case Opcodes.IFEQ:
- case Opcodes.IFNE:
- case Opcodes.IFLT:
- case Opcodes.IFGE:
- case Opcodes.IFGT:
- case Opcodes.IFLE:
- case Opcodes.IRETURN:
- case Opcodes.FRETURN:
- case Opcodes.ARETURN:
- case Opcodes.TABLESWITCH:
- case Opcodes.LOOKUPSWITCH:
- case Opcodes.ATHROW:
- case Opcodes.MONITORENTER:
- case Opcodes.MONITOREXIT:
- case Opcodes.IFNULL:
- case Opcodes.IFNONNULL:
- pop(1);
- break;
- case Opcodes.POP2:
- case Opcodes.IF_ICMPEQ:
- case Opcodes.IF_ICMPNE:
- case Opcodes.IF_ICMPLT:
- case Opcodes.IF_ICMPGE:
- case Opcodes.IF_ICMPGT:
- case Opcodes.IF_ICMPLE:
- case Opcodes.IF_ACMPEQ:
- case Opcodes.IF_ACMPNE:
- case Opcodes.LRETURN:
- case Opcodes.DRETURN:
- pop(2);
- break;
- case Opcodes.DUP:
- t1 = pop();
- push(t1);
- push(t1);
- break;
- case Opcodes.DUP_X1:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2:
- t1 = pop();
- t2 = pop();
- push(t2);
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X1:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t2);
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- t4 = pop();
- push(t2);
- push(t1);
- push(t4);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.SWAP:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- break;
- case Opcodes.IADD:
- case Opcodes.ISUB:
- case Opcodes.IMUL:
- case Opcodes.IDIV:
- case Opcodes.IREM:
- case Opcodes.IAND:
- case Opcodes.IOR:
- case Opcodes.IXOR:
- case Opcodes.ISHL:
- case Opcodes.ISHR:
- case Opcodes.IUSHR:
- case Opcodes.L2I:
- case Opcodes.D2I:
- case Opcodes.FCMPL:
- case Opcodes.FCMPG:
- pop(2);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LADD:
- case Opcodes.LSUB:
- case Opcodes.LMUL:
- case Opcodes.LDIV:
- case Opcodes.LREM:
- case Opcodes.LAND:
- case Opcodes.LOR:
- case Opcodes.LXOR:
- pop(4);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.FADD:
- case Opcodes.FSUB:
- case Opcodes.FMUL:
- case Opcodes.FDIV:
- case Opcodes.FREM:
- case Opcodes.L2F:
- case Opcodes.D2F:
- pop(2);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.DADD:
- case Opcodes.DSUB:
- case Opcodes.DMUL:
- case Opcodes.DDIV:
- case Opcodes.DREM:
- pop(4);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.LSHL:
- case Opcodes.LSHR:
- case Opcodes.LUSHR:
- pop(3);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.IINC:
- set(iarg, Opcodes.INTEGER);
- break;
- case Opcodes.I2L:
- case Opcodes.F2L:
- pop(1);
- push(Opcodes.LONG);
- push(Opcodes.TOP);
- break;
- case Opcodes.I2F:
- pop(1);
- push(Opcodes.FLOAT);
- break;
- case Opcodes.I2D:
- case Opcodes.F2D:
- pop(1);
- push(Opcodes.DOUBLE);
- push(Opcodes.TOP);
- break;
- case Opcodes.F2I:
- case Opcodes.ARRAYLENGTH:
- case Opcodes.INSTANCEOF:
- pop(1);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.LCMP:
- case Opcodes.DCMPL:
- case Opcodes.DCMPG:
- pop(4);
- push(Opcodes.INTEGER);
- break;
- case Opcodes.JSR:
- case Opcodes.RET:
- throw new RuntimeException("JSR/RET are not supported");
- case Opcodes.GETSTATIC:
- pushDesc(sarg);
- break;
- case Opcodes.PUTSTATIC:
- pop(sarg);
- break;
- case Opcodes.GETFIELD:
- pop(1);
- pushDesc(sarg);
- break;
- case Opcodes.PUTFIELD:
- pop(sarg);
- pop();
- break;
- case Opcodes.NEW:
- push(labels.get(0));
- break;
- case Opcodes.NEWARRAY:
- pop();
- switch (iarg) {
- case Opcodes.T_BOOLEAN:
- pushDesc("[Z");
- break;
- case Opcodes.T_CHAR:
- pushDesc("[C");
- break;
- case Opcodes.T_BYTE:
- pushDesc("[B");
- break;
- case Opcodes.T_SHORT:
- pushDesc("[S");
- break;
- case Opcodes.T_INT:
- pushDesc("[I");
- break;
- case Opcodes.T_FLOAT:
- pushDesc("[F");
- break;
- case Opcodes.T_DOUBLE:
- pushDesc("[D");
- break;
- // case Opcodes.T_LONG:
- default:
- pushDesc("[J");
- break;
- }
- break;
- case Opcodes.ANEWARRAY:
- pop();
- pushDesc("[" + Type.getObjectType(sarg));
- break;
- case Opcodes.CHECKCAST:
- pop();
- pushDesc(Type.getObjectType(sarg).getDescriptor());
- break;
- // case Opcodes.MULTIANEWARRAY:
- default:
- pop(iarg);
- pushDesc(sarg);
- break;
- }
- labels = null;
+ push("java/lang/Object");
+ }
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ value1 = pop();
+ set(intArg, value1);
+ if (intArg > 0) {
+ value2 = get(intArg - 1);
+ if (value2 == Opcodes.LONG || value2 == Opcodes.DOUBLE) {
+ set(intArg - 1, Opcodes.TOP);
+ }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ value1 = pop();
+ set(intArg, value1);
+ set(intArg + 1, Opcodes.TOP);
+ if (intArg > 0) {
+ value2 = get(intArg - 1);
+ if (value2 == Opcodes.LONG || value2 == Opcodes.DOUBLE) {
+ set(intArg - 1, Opcodes.TOP);
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ value1 = pop();
+ push(value1);
+ push(value1);
+ break;
+ case Opcodes.DUP_X1:
+ value1 = pop();
+ value2 = pop();
+ push(value1);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP_X2:
+ value1 = pop();
+ value2 = pop();
+ value3 = pop();
+ push(value1);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP2:
+ value1 = pop();
+ value2 = pop();
+ push(value2);
+ push(value1);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP2_X1:
+ value1 = pop();
+ value2 = pop();
+ value3 = pop();
+ push(value2);
+ push(value1);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP2_X2:
+ value1 = pop();
+ value2 = pop();
+ value3 = pop();
+ t4 = pop();
+ push(value2);
+ push(value1);
+ push(t4);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.SWAP:
+ value1 = pop();
+ value2 = pop();
+ push(value1);
+ push(value2);
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FALOAD:
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.IINC:
+ set(intArg, Opcodes.INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new IllegalArgumentException("JSR/RET are not supported");
+ case Opcodes.GETSTATIC:
+ pushDescriptor(stringArg);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(stringArg);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ pushDescriptor(stringArg);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(stringArg);
+ pop();
+ break;
+ case Opcodes.NEW:
+ push(labels.get(0));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (intArg) {
+ case Opcodes.T_BOOLEAN:
+ pushDescriptor("[Z");
+ break;
+ case Opcodes.T_CHAR:
+ pushDescriptor("[C");
+ break;
+ case Opcodes.T_BYTE:
+ pushDescriptor("[B");
+ break;
+ case Opcodes.T_SHORT:
+ pushDescriptor("[S");
+ break;
+ case Opcodes.T_INT:
+ pushDescriptor("[I");
+ break;
+ case Opcodes.T_FLOAT:
+ pushDescriptor("[F");
+ break;
+ case Opcodes.T_DOUBLE:
+ pushDescriptor("[D");
+ break;
+ case Opcodes.T_LONG:
+ pushDescriptor("[J");
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid array type " + intArg);
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ pop();
+ pushDescriptor("[" + Type.getObjectType(stringArg));
+ break;
+ case Opcodes.CHECKCAST:
+ pop();
+ pushDescriptor(Type.getObjectType(stringArg).getDescriptor());
+ break;
+ case Opcodes.MULTIANEWARRAY:
+ pop(intArg);
+ pushDescriptor(stringArg);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid opcode " + opcode);
}
+ labels = null;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java
old mode 100644
new mode 100755
index 74dded8..24a2de5
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnnotationRemapper.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -34,46 +32,72 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * An {@link AnnotationVisitor} adapter for type remapping.
- *
+ * An {@link AnnotationVisitor} that remaps types with a {@link Remapper}.
+ *
* @author Eugene Kuleshov
*/
public class AnnotationRemapper extends AnnotationVisitor {
- protected final Remapper remapper;
+ /** The remapper used to remap the types in the visited annotation. */
+ protected final Remapper remapper;
- public AnnotationRemapper(final AnnotationVisitor av,
- final Remapper remapper) {
- this(Opcodes.ASM6, av, remapper);
- }
+ /**
+ * Constructs a new {@link AnnotationRemapper}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #AnnotationRemapper(int,AnnotationVisitor,Remapper)} version.
+ *
+ * @param annotationVisitor the annotation visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited annotation.
+ */
+ public AnnotationRemapper(final AnnotationVisitor annotationVisitor, final Remapper remapper) {
+ this(Opcodes.ASM7, annotationVisitor, remapper);
+ }
- protected AnnotationRemapper(final int api, final AnnotationVisitor av,
- final Remapper remapper) {
- super(api, av);
- this.remapper = remapper;
- }
+ /**
+ * Constructs a new {@link AnnotationRemapper}.
+ *
+ * @param api the ASM API version supported by this remapper. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6}.
+ * @param annotationVisitor the annotation visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited annotation.
+ */
+ protected AnnotationRemapper(
+ final int api, final AnnotationVisitor annotationVisitor, final Remapper remapper) {
+ super(api, annotationVisitor);
+ this.remapper = remapper;
+ }
- @Override
- public void visit(String name, Object value) {
- av.visit(name, remapper.mapValue(value));
- }
+ @Override
+ public void visit(final String name, final Object value) {
+ super.visit(name, remapper.mapValue(value));
+ }
- @Override
- public void visitEnum(String name, String desc, String value) {
- av.visitEnum(name, remapper.mapDesc(desc), value);
- }
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ super.visitEnum(name, remapper.mapDesc(descriptor), value);
+ }
- @Override
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
- return v == null ? null : (v == av ? this : new AnnotationRemapper(v,
- remapper));
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, remapper.mapDesc(descriptor));
+ if (annotationVisitor == null) {
+ return null;
+ } else {
+ return annotationVisitor == av
+ ? this
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
}
+ }
- @Override
- public AnnotationVisitor visitArray(String name) {
- AnnotationVisitor v = av.visitArray(name);
- return v == null ? null : (v == av ? this : new AnnotationRemapper(v,
- remapper));
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
+ if (annotationVisitor == null) {
+ return null;
+ } else {
+ return annotationVisitor == av
+ ? this
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java
old mode 100644
new mode 100755
index 8090c0d..f837457
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/ClassRemapper.java
@@ -1,37 +1,34 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
@@ -42,117 +39,198 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link ClassVisitor} for type remapping.
- *
+ * A {@link ClassVisitor} that remaps types with a {@link Remapper}.
+ *
* @author Eugene Kuleshov
*/
public class ClassRemapper extends ClassVisitor {
- protected final Remapper remapper;
-
- protected String className;
-
- public ClassRemapper(final ClassVisitor cv, final Remapper remapper) {
- this(Opcodes.ASM6, cv, remapper);
- }
-
- protected ClassRemapper(final int api, final ClassVisitor cv,
- final Remapper remapper) {
- super(api, cv);
- this.remapper = remapper;
- }
-
- @Override
- public void visit(int version, int access, String name, String signature,
- String superName, String[] interfaces) {
- this.className = name;
- super.visit(version, access, remapper.mapType(name), remapper
- .mapSignature(signature, false), remapper.mapType(superName),
- interfaces == null ? null : remapper.mapTypes(interfaces));
- }
-
- @Override
- public ModuleVisitor visitModule(String name, int flags, String version) {
- ModuleVisitor mv = super.visitModule(remapper.mapModuleName(name), flags, version);
- return mv == null ? null : createModuleRemapper(mv);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
- visible);
- return av == null ? null : createAnnotationRemapper(av);
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? null : createAnnotationRemapper(av);
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- if (attr instanceof ModuleHashesAttribute) {
- ModuleHashesAttribute hashesAttr = new ModuleHashesAttribute();
- List<String> modules = hashesAttr.modules;
- for(int i = 0; i < modules.size(); i++) {
- modules.set(i, remapper.mapModuleName(modules.get(i)));
- }
- }
- super.visitAttribute(attr);
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- FieldVisitor fv = super.visitField(access,
- remapper.mapFieldName(className, name, desc),
- remapper.mapDesc(desc), remapper.mapSignature(signature, true),
- remapper.mapValue(value));
- return fv == null ? null : createFieldRemapper(fv);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- String newDesc = remapper.mapMethodDesc(desc);
- MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
- className, name, desc), newDesc, remapper.mapSignature(
- signature, false),
- exceptions == null ? null : remapper.mapTypes(exceptions));
- return mv == null ? null : createMethodRemapper(mv);
- }
-
- @Override
- public void visitInnerClass(String name, String outerName,
- String innerName, int access) {
- // TODO should innerName be changed?
- super.visitInnerClass(remapper.mapType(name), outerName == null ? null
- : remapper.mapType(outerName), innerName, access);
- }
-
- @Override
- public void visitOuterClass(String owner, String name, String desc) {
- super.visitOuterClass(remapper.mapType(owner), name == null ? null
- : remapper.mapMethodName(owner, name, desc),
- desc == null ? null : remapper.mapMethodDesc(desc));
- }
-
- protected FieldVisitor createFieldRemapper(FieldVisitor fv) {
- return new FieldRemapper(fv, remapper);
- }
-
- protected MethodVisitor createMethodRemapper(MethodVisitor mv) {
- return new MethodRemapper(mv, remapper);
- }
-
- protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) {
- return new AnnotationRemapper(av, remapper);
- }
-
- protected ModuleVisitor createModuleRemapper(ModuleVisitor mv) {
- return new ModuleRemapper(mv, remapper);
+ /** The remapper used to remap the types in the visited class. */
+ protected final Remapper remapper;
+
+ /** The internal name of the visited class. */
+ protected String className;
+
+ /**
+ * Constructs a new {@link ClassRemapper}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #ClassRemapper(int,ClassVisitor,Remapper)} version.
+ *
+ * @param classVisitor the class visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited class.
+ */
+ public ClassRemapper(final ClassVisitor classVisitor, final Remapper remapper) {
+ this(Opcodes.ASM7, classVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new {@link ClassRemapper}.
+ *
+ * @param api the ASM API version supported by this remapper. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+ * @param classVisitor the class visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited class.
+ */
+ protected ClassRemapper(final int api, final ClassVisitor classVisitor, final Remapper remapper) {
+ super(api, classVisitor);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ this.className = name;
+ super.visit(
+ version,
+ access,
+ remapper.mapType(name),
+ remapper.mapSignature(signature, false),
+ remapper.mapType(superName),
+ interfaces == null ? null : remapper.mapTypes(interfaces));
+ }
+
+ @Override
+ public ModuleVisitor visitModule(final String name, final int flags, final String version) {
+ ModuleVisitor moduleVisitor = super.visitModule(remapper.mapModuleName(name), flags, version);
+ return moduleVisitor == null ? null : createModuleRemapper(moduleVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitAnnotation(remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ if (attribute instanceof ModuleHashesAttribute) {
+ ModuleHashesAttribute moduleHashesAttribute = (ModuleHashesAttribute) attribute;
+ List<String> modules = moduleHashesAttribute.modules;
+ for (int i = 0; i < modules.size(); ++i) {
+ modules.set(i, remapper.mapModuleName(modules.get(i)));
+ }
}
+ super.visitAttribute(attribute);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ FieldVisitor fieldVisitor =
+ super.visitField(
+ access,
+ remapper.mapFieldName(className, name, descriptor),
+ remapper.mapDesc(descriptor),
+ remapper.mapSignature(signature, true),
+ (value == null) ? null : remapper.mapValue(value));
+ return fieldVisitor == null ? null : createFieldRemapper(fieldVisitor);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ String remappedDescriptor = remapper.mapMethodDesc(descriptor);
+ MethodVisitor methodVisitor =
+ super.visitMethod(
+ access,
+ remapper.mapMethodName(className, name, descriptor),
+ remappedDescriptor,
+ remapper.mapSignature(signature, false),
+ exceptions == null ? null : remapper.mapTypes(exceptions));
+ return methodVisitor == null ? null : createMethodRemapper(methodVisitor);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ super.visitInnerClass(
+ remapper.mapType(name),
+ outerName == null ? null : remapper.mapType(outerName),
+ innerName == null ? null : remapper.mapInnerClassName(name, outerName, innerName),
+ access);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ super.visitOuterClass(
+ remapper.mapType(owner),
+ name == null ? null : remapper.mapMethodName(owner, name, descriptor),
+ descriptor == null ? null : remapper.mapMethodDesc(descriptor));
+ }
+
+ @Override
+ public void visitNestHost(final String nestHost) {
+ super.visitNestHost(remapper.mapType(nestHost));
+ }
+
+ @Override
+ public void visitNestMember(final String nestMember) {
+ super.visitNestMember(remapper.mapType(nestMember));
+ }
+
+ /**
+ * Constructs a new remapper for fields. The default implementation of this method returns a new
+ * {@link FieldRemapper}.
+ *
+ * @param fieldVisitor the FieldVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected FieldVisitor createFieldRemapper(final FieldVisitor fieldVisitor) {
+ return new FieldRemapper(api, fieldVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new remapper for methods. The default implementation of this method returns a new
+ * {@link MethodRemapper}.
+ *
+ * @param methodVisitor the MethodVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected MethodVisitor createMethodRemapper(final MethodVisitor methodVisitor) {
+ return new MethodRemapper(api, methodVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new remapper for annotations. The default implementation of this method returns a
+ * new {@link AnnotationRemapper}.
+ *
+ * @param annotationVisitor the AnnotationVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) {
+ return new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
+
+ /**
+ * Constructs a new remapper for modules. The default implementation of this method returns a new
+ * {@link ModuleRemapper}.
+ *
+ * @param moduleVisitor the ModuleVisitor the remapper must delegate to.
+ * @return the newly created remapper.
+ */
+ protected ModuleVisitor createModuleRemapper(final ModuleVisitor moduleVisitor) {
+ return new ModuleRemapper(api, moduleVisitor, remapper);
+ }
}
[33/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
old mode 100644
new mode 100755
index 3455196..2174939
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
@@ -1,905 +1,891 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
- * A Java field or method type. This class can be used to make it easier to
- * manipulate type and method descriptors.
- *
+ * A Java field or method type. This class can be used to make it easier to manipulate type and
+ * method descriptors.
+ *
* @author Eric Bruneton
* @author Chris Nokleberg
*/
-public class Type {
-
- /**
- * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
- */
- public static final int VOID = 0;
-
- /**
- * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
- */
- public static final int BOOLEAN = 1;
-
- /**
- * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
- */
- public static final int CHAR = 2;
-
- /**
- * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
- */
- public static final int BYTE = 3;
-
- /**
- * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
- */
- public static final int SHORT = 4;
-
- /**
- * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
- */
- public static final int INT = 5;
-
- /**
- * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
- */
- public static final int FLOAT = 6;
-
- /**
- * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
- */
- public static final int LONG = 7;
-
- /**
- * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
- */
- public static final int DOUBLE = 8;
-
- /**
- * The sort of array reference types. See {@link #getSort getSort}.
- */
- public static final int ARRAY = 9;
-
- /**
- * The sort of object reference types. See {@link #getSort getSort}.
- */
- public static final int OBJECT = 10;
-
- /**
- * The sort of method types. See {@link #getSort getSort}.
- */
- public static final int METHOD = 11;
-
- /**
- * The <tt>void</tt> type.
- */
- public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24)
- | (5 << 16) | (0 << 8) | 0, 1);
-
- /**
- * The <tt>boolean</tt> type.
- */
- public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24)
- | (0 << 16) | (5 << 8) | 1, 1);
-
- /**
- * The <tt>char</tt> type.
- */
- public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24)
- | (0 << 16) | (6 << 8) | 1, 1);
-
- /**
- * The <tt>byte</tt> type.
- */
- public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24)
- | (0 << 16) | (5 << 8) | 1, 1);
-
- /**
- * The <tt>short</tt> type.
- */
- public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24)
- | (0 << 16) | (7 << 8) | 1, 1);
-
- /**
- * The <tt>int</tt> type.
- */
- public static final Type INT_TYPE = new Type(INT, null, ('I' << 24)
- | (0 << 16) | (0 << 8) | 1, 1);
-
- /**
- * The <tt>float</tt> type.
- */
- public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24)
- | (2 << 16) | (2 << 8) | 1, 1);
-
- /**
- * The <tt>long</tt> type.
- */
- public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24)
- | (1 << 16) | (1 << 8) | 2, 1);
-
- /**
- * The <tt>double</tt> type.
- */
- public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24)
- | (3 << 16) | (3 << 8) | 2, 1);
-
- // ------------------------------------------------------------------------
- // Fields
- // ------------------------------------------------------------------------
-
- /**
- * The sort of this Java type.
- */
- private final int sort;
-
- /**
- * A buffer containing the internal name of this Java type. This field is
- * only used for reference types.
- */
- private final char[] buf;
-
- /**
- * The offset of the internal name of this Java type in {@link #buf buf} or,
- * for primitive types, the size, descriptor and getOpcode offsets for this
- * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset
- * for IALOAD or IASTORE, byte 3 the offset for all other instructions).
- */
- private final int off;
-
- /**
- * The length of the internal name of this Java type.
- */
- private final int len;
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a reference type.
- *
- * @param sort
- * the sort of the reference type to be constructed.
- * @param buf
- * a buffer containing the descriptor of the previous type.
- * @param off
- * the offset of this descriptor in the previous buffer.
- * @param len
- * the length of this descriptor.
- */
- private Type(final int sort, final char[] buf, final int off, final int len) {
- this.sort = sort;
- this.buf = buf;
- this.off = off;
- this.len = len;
- }
+public final class Type {
- /**
- * Returns the Java type corresponding to the given type descriptor.
- *
- * @param typeDescriptor
- * a field or method type descriptor.
- * @return the Java type corresponding to the given type descriptor.
- */
- public static Type getType(final String typeDescriptor) {
- return getType(typeDescriptor.toCharArray(), 0);
- }
+ /** The sort of the {@code void} type. See {@link #getSort}. */
+ public static final int VOID = 0;
- /**
- * Returns the Java type corresponding to the given internal name.
- *
- * @param internalName
- * an internal name.
- * @return the Java type corresponding to the given internal name.
- */
- public static Type getObjectType(final String internalName) {
- char[] buf = internalName.toCharArray();
- return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
- }
+ /** The sort of the {@code boolean} type. See {@link #getSort}. */
+ public static final int BOOLEAN = 1;
- /**
- * Returns the Java type corresponding to the given method descriptor.
- * Equivalent to <code>Type.getType(methodDescriptor)</code>.
- *
- * @param methodDescriptor
- * a method descriptor.
- * @return the Java type corresponding to the given method descriptor.
- */
- public static Type getMethodType(final String methodDescriptor) {
- return getType(methodDescriptor.toCharArray(), 0);
- }
-
- /**
- * Returns the Java method type corresponding to the given argument and
- * return types.
- *
- * @param returnType
- * the return type of the method.
- * @param argumentTypes
- * the argument types of the method.
- * @return the Java type corresponding to the given argument and return
- * types.
- */
- public static Type getMethodType(final Type returnType,
- final Type... argumentTypes) {
- return getType(getMethodDescriptor(returnType, argumentTypes));
- }
+ /** The sort of the {@code char} type. See {@link #getSort}. */
+ public static final int CHAR = 2;
- /**
- * Returns the Java type corresponding to the given class.
- *
- * @param c
- * a class.
- * @return the Java type corresponding to the given class.
- */
- public static Type getType(final Class<?> c) {
- if (c.isPrimitive()) {
- if (c == Integer.TYPE) {
- return INT_TYPE;
- } else if (c == Void.TYPE) {
- return VOID_TYPE;
- } else if (c == Boolean.TYPE) {
- return BOOLEAN_TYPE;
- } else if (c == Byte.TYPE) {
- return BYTE_TYPE;
- } else if (c == Character.TYPE) {
- return CHAR_TYPE;
- } else if (c == Short.TYPE) {
- return SHORT_TYPE;
- } else if (c == Double.TYPE) {
- return DOUBLE_TYPE;
- } else if (c == Float.TYPE) {
- return FLOAT_TYPE;
- } else /* if (c == Long.TYPE) */{
- return LONG_TYPE;
- }
- } else {
- return getType(getDescriptor(c));
- }
- }
+ /** The sort of the {@code byte} type. See {@link #getSort}. */
+ public static final int BYTE = 3;
- /**
- * Returns the Java method type corresponding to the given constructor.
- *
- * @param c
- * a {@link Constructor Constructor} object.
- * @return the Java method type corresponding to the given constructor.
- */
- public static Type getType(final Constructor<?> c) {
- return getType(getConstructorDescriptor(c));
- }
+ /** The sort of the {@code short} type. See {@link #getSort}. */
+ public static final int SHORT = 4;
- /**
- * Returns the Java method type corresponding to the given method.
- *
- * @param m
- * a {@link Method Method} object.
- * @return the Java method type corresponding to the given method.
- */
- public static Type getType(final Method m) {
- return getType(getMethodDescriptor(m));
- }
-
- /**
- * Returns the Java types corresponding to the argument types of the given
- * method descriptor.
- *
- * @param methodDescriptor
- * a method descriptor.
- * @return the Java types corresponding to the argument types of the given
- * method descriptor.
- */
- public static Type[] getArgumentTypes(final String methodDescriptor) {
- char[] buf = methodDescriptor.toCharArray();
- int off = 1;
- int size = 0;
- while (true) {
- char car = buf[off++];
- if (car == ')') {
- break;
- } else if (car == 'L') {
- while (buf[off++] != ';') {
- }
- ++size;
- } else if (car != '[') {
- ++size;
- }
- }
- Type[] args = new Type[size];
- off = 1;
- size = 0;
- while (buf[off] != ')') {
- args[size] = getType(buf, off);
- off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);
- size += 1;
- }
- return args;
- }
-
- /**
- * Returns the Java types corresponding to the argument types of the given
- * method.
- *
- * @param method
- * a method.
- * @return the Java types corresponding to the argument types of the given
- * method.
- */
- public static Type[] getArgumentTypes(final Method method) {
- Class<?>[] classes = method.getParameterTypes();
- Type[] types = new Type[classes.length];
- for (int i = classes.length - 1; i >= 0; --i) {
- types[i] = getType(classes[i]);
+ /** The sort of the {@code int} type. See {@link #getSort}. */
+ public static final int INT = 5;
+
+ /** The sort of the {@code float} type. See {@link #getSort}. */
+ public static final int FLOAT = 6;
+
+ /** The sort of the {@code long} type. See {@link #getSort}. */
+ public static final int LONG = 7;
+
+ /** The sort of the {@code double} type. See {@link #getSort}. */
+ public static final int DOUBLE = 8;
+
+ /** The sort of array reference types. See {@link #getSort}. */
+ public static final int ARRAY = 9;
+
+ /** The sort of object reference types. See {@link #getSort}. */
+ public static final int OBJECT = 10;
+
+ /** The sort of method types. See {@link #getSort}. */
+ public static final int METHOD = 11;
+
+ /** The (private) sort of object reference types represented with an internal name. */
+ private static final int INTERNAL = 12;
+
+ /** The descriptors of the primitive types. */
+ private static final String PRIMITIVE_DESCRIPTORS = "VZCBSIFJD";
+
+ /** The {@code void} type. */
+ public static final Type VOID_TYPE = new Type(VOID, PRIMITIVE_DESCRIPTORS, VOID, VOID + 1);
+
+ /** The {@code boolean} type. */
+ public static final Type BOOLEAN_TYPE =
+ new Type(BOOLEAN, PRIMITIVE_DESCRIPTORS, BOOLEAN, BOOLEAN + 1);
+
+ /** The {@code char} type. */
+ public static final Type CHAR_TYPE = new Type(CHAR, PRIMITIVE_DESCRIPTORS, CHAR, CHAR + 1);
+
+ /** The {@code byte} type. */
+ public static final Type BYTE_TYPE = new Type(BYTE, PRIMITIVE_DESCRIPTORS, BYTE, BYTE + 1);
+
+ /** The {@code short} type. */
+ public static final Type SHORT_TYPE = new Type(SHORT, PRIMITIVE_DESCRIPTORS, SHORT, SHORT + 1);
+
+ /** The {@code int} type. */
+ public static final Type INT_TYPE = new Type(INT, PRIMITIVE_DESCRIPTORS, INT, INT + 1);
+
+ /** The {@code float} type. */
+ public static final Type FLOAT_TYPE = new Type(FLOAT, PRIMITIVE_DESCRIPTORS, FLOAT, FLOAT + 1);
+
+ /** The {@code long} type. */
+ public static final Type LONG_TYPE = new Type(LONG, PRIMITIVE_DESCRIPTORS, LONG, LONG + 1);
+
+ /** The {@code double} type. */
+ public static final Type DOUBLE_TYPE =
+ new Type(DOUBLE, PRIMITIVE_DESCRIPTORS, DOUBLE, DOUBLE + 1);
+
+ // -----------------------------------------------------------------------------------------------
+ // Fields
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * The sort of this type. Either {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE},
+ * {@link #SHORT}, {@link #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY},
+ * {@link #OBJECT}, {@link #METHOD} or {@link #INTERNAL}.
+ */
+ private final int sort;
+
+ /**
+ * A buffer containing the value of this field or method type. This value is an internal name for
+ * {@link #OBJECT} and {@link #INTERNAL} types, and a field or method descriptor in the other
+ * cases.
+ *
+ * <p>For {@link #OBJECT} types, this field also contains the descriptor: the characters in
+ * [{@link #valueBegin},{@link #valueEnd}) contain the internal name, and those in [{@link
+ * #valueBegin} - 1, {@link #valueEnd} + 1) contain the descriptor.
+ */
+ private final String valueBuffer;
+
+ /**
+ * The beginning index, inclusive, of the value of this Java field or method type in {@link
+ * #valueBuffer}. This value is an internal name for {@link #OBJECT} and {@link #INTERNAL} types,
+ * and a field or method descriptor in the other cases.
+ */
+ private final int valueBegin;
+
+ /**
+ * The end index, exclusive, of the value of this Java field or method type in {@link
+ * #valueBuffer}. This value is an internal name for {@link #OBJECT} and {@link #INTERNAL} types,
+ * and a field or method descriptor in the other cases.
+ */
+ private final int valueEnd;
+
+ /**
+ * Constructs a reference type.
+ *
+ * @param sort the sort of this type, see {@link #sort}.
+ * @param valueBuffer a buffer containing the value of this field or method type.
+ * @param valueBegin the beginning index, inclusive, of the value of this field or method type in
+ * valueBuffer.
+ * @param valueEnd the end index, exclusive, of the value of this field or method type in
+ * valueBuffer.
+ */
+ private Type(final int sort, final String valueBuffer, final int valueBegin, final int valueEnd) {
+ this.sort = sort;
+ this.valueBuffer = valueBuffer;
+ this.valueBegin = valueBegin;
+ this.valueEnd = valueEnd;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods to get Type(s) from a descriptor, a reflected Method or Constructor, other types, etc.
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the {@link Type} corresponding to the given type descriptor.
+ *
+ * @param typeDescriptor a field or method type descriptor.
+ * @return the {@link Type} corresponding to the given type descriptor.
+ */
+ public static Type getType(final String typeDescriptor) {
+ return getTypeInternal(typeDescriptor, 0, typeDescriptor.length());
+ }
+
+ /**
+ * Returns the {@link Type} corresponding to the given class.
+ *
+ * @param clazz a class.
+ * @return the {@link Type} corresponding to the given class.
+ */
+ public static Type getType(final Class<?> clazz) {
+ if (clazz.isPrimitive()) {
+ if (clazz == Integer.TYPE) {
+ return INT_TYPE;
+ } else if (clazz == Void.TYPE) {
+ return VOID_TYPE;
+ } else if (clazz == Boolean.TYPE) {
+ return BOOLEAN_TYPE;
+ } else if (clazz == Byte.TYPE) {
+ return BYTE_TYPE;
+ } else if (clazz == Character.TYPE) {
+ return CHAR_TYPE;
+ } else if (clazz == Short.TYPE) {
+ return SHORT_TYPE;
+ } else if (clazz == Double.TYPE) {
+ return DOUBLE_TYPE;
+ } else if (clazz == Float.TYPE) {
+ return FLOAT_TYPE;
+ } else if (clazz == Long.TYPE) {
+ return LONG_TYPE;
+ } else {
+ throw new AssertionError();
+ }
+ } else {
+ return getType(getDescriptor(clazz));
+ }
+ }
+
+ /**
+ * Returns the method {@link Type} corresponding to the given constructor.
+ *
+ * @param constructor a {@link Constructor} object.
+ * @return the method {@link Type} corresponding to the given constructor.
+ */
+ public static Type getType(final Constructor<?> constructor) {
+ return getType(getConstructorDescriptor(constructor));
+ }
+
+ /**
+ * Returns the method {@link Type} corresponding to the given method.
+ *
+ * @param method a {@link Method} object.
+ * @return the method {@link Type} corresponding to the given method.
+ */
+ public static Type getType(final Method method) {
+ return getType(getMethodDescriptor(method));
+ }
+
+ /**
+ * Returns the type of the elements of this array type. This method should only be used for an
+ * array type.
+ *
+ * @return Returns the type of the elements of this array type.
+ */
+ public Type getElementType() {
+ final int numDimensions = getDimensions();
+ return getTypeInternal(valueBuffer, valueBegin + numDimensions, valueEnd);
+ }
+
+ /**
+ * Returns the {@link Type} corresponding to the given internal name.
+ *
+ * @param internalName an internal name.
+ * @return the {@link Type} corresponding to the given internal name.
+ */
+ public static Type getObjectType(final String internalName) {
+ return new Type(
+ internalName.charAt(0) == '[' ? ARRAY : INTERNAL, internalName, 0, internalName.length());
+ }
+
+ /**
+ * Returns the {@link Type} corresponding to the given method descriptor. Equivalent to <code>
+ * Type.getType(methodDescriptor)</code>.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the {@link Type} corresponding to the given method descriptor.
+ */
+ public static Type getMethodType(final String methodDescriptor) {
+ return new Type(METHOD, methodDescriptor, 0, methodDescriptor.length());
+ }
+
+ /**
+ * Returns the method {@link Type} corresponding to the given argument and return types.
+ *
+ * @param returnType the return type of the method.
+ * @param argumentTypes the argument types of the method.
+ * @return the method {@link Type} corresponding to the given argument and return types.
+ */
+ public static Type getMethodType(final Type returnType, final Type... argumentTypes) {
+ return getType(getMethodDescriptor(returnType, argumentTypes));
+ }
+
+ /**
+ * Returns the argument types of methods of this type. This method should only be used for method
+ * types.
+ *
+ * @return the argument types of methods of this type.
+ */
+ public Type[] getArgumentTypes() {
+ return getArgumentTypes(getDescriptor());
+ }
+
+ /**
+ * Returns the {@link Type} values corresponding to the argument types of the given method
+ * descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the {@link Type} values corresponding to the argument types of the given method
+ * descriptor.
+ */
+ public static Type[] getArgumentTypes(final String methodDescriptor) {
+ // First step: compute the number of argument types in methodDescriptor.
+ int numArgumentTypes = 0;
+ // Skip the first character, which is always a '('.
+ int currentOffset = 1;
+ // Parse the argument types, one at a each loop iteration.
+ while (methodDescriptor.charAt(currentOffset) != ')') {
+ while (methodDescriptor.charAt(currentOffset) == '[') {
+ currentOffset++;
+ }
+ if (methodDescriptor.charAt(currentOffset++) == 'L') {
+ // Skip the argument descriptor content.
+ currentOffset = methodDescriptor.indexOf(';', currentOffset) + 1;
+ }
+ ++numArgumentTypes;
+ }
+
+ // Second step: create a Type instance for each argument type.
+ Type[] argumentTypes = new Type[numArgumentTypes];
+ // Skip the first character, which is always a '('.
+ currentOffset = 1;
+ // Parse and create the argument types, one at each loop iteration.
+ int currentArgumentTypeIndex = 0;
+ while (methodDescriptor.charAt(currentOffset) != ')') {
+ final int currentArgumentTypeOffset = currentOffset;
+ while (methodDescriptor.charAt(currentOffset) == '[') {
+ currentOffset++;
+ }
+ if (methodDescriptor.charAt(currentOffset++) == 'L') {
+ // Skip the argument descriptor content.
+ currentOffset = methodDescriptor.indexOf(';', currentOffset) + 1;
+ }
+ argumentTypes[currentArgumentTypeIndex++] =
+ getTypeInternal(methodDescriptor, currentArgumentTypeOffset, currentOffset);
+ }
+ return argumentTypes;
+ }
+
+ /**
+ * Returns the {@link Type} values corresponding to the argument types of the given method.
+ *
+ * @param method a method.
+ * @return the {@link Type} values corresponding to the argument types of the given method.
+ */
+ public static Type[] getArgumentTypes(final Method method) {
+ Class<?>[] classes = method.getParameterTypes();
+ Type[] types = new Type[classes.length];
+ for (int i = classes.length - 1; i >= 0; --i) {
+ types[i] = getType(classes[i]);
+ }
+ return types;
+ }
+
+ /**
+ * Returns the return type of methods of this type. This method should only be used for method
+ * types.
+ *
+ * @return the return type of methods of this type.
+ */
+ public Type getReturnType() {
+ return getReturnType(getDescriptor());
+ }
+
+ /**
+ * Returns the {@link Type} corresponding to the return type of the given method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the {@link Type} corresponding to the return type of the given method descriptor.
+ */
+ public static Type getReturnType(final String methodDescriptor) {
+ // Skip the first character, which is always a '('.
+ int currentOffset = 1;
+ // Skip the argument types, one at a each loop iteration.
+ while (methodDescriptor.charAt(currentOffset) != ')') {
+ while (methodDescriptor.charAt(currentOffset) == '[') {
+ currentOffset++;
+ }
+ if (methodDescriptor.charAt(currentOffset++) == 'L') {
+ // Skip the argument descriptor content.
+ currentOffset = methodDescriptor.indexOf(';', currentOffset) + 1;
+ }
+ }
+ return getTypeInternal(methodDescriptor, currentOffset + 1, methodDescriptor.length());
+ }
+
+ /**
+ * Returns the {@link Type} corresponding to the return type of the given method.
+ *
+ * @param method a method.
+ * @return the {@link Type} corresponding to the return type of the given method.
+ */
+ public static Type getReturnType(final Method method) {
+ return getType(method.getReturnType());
+ }
+
+ /**
+ * Returns the {@link Type} corresponding to the given field or method descriptor.
+ *
+ * @param descriptorBuffer a buffer containing the field or method descriptor.
+ * @param descriptorBegin the beginning index, inclusive, of the field or method descriptor in
+ * descriptorBuffer.
+ * @param descriptorEnd the end index, exclusive, of the field or method descriptor in
+ * descriptorBuffer.
+ * @return the {@link Type} corresponding to the given type descriptor.
+ */
+ private static Type getTypeInternal(
+ final String descriptorBuffer, final int descriptorBegin, final int descriptorEnd) {
+ switch (descriptorBuffer.charAt(descriptorBegin)) {
+ case 'V':
+ return VOID_TYPE;
+ case 'Z':
+ return BOOLEAN_TYPE;
+ case 'C':
+ return CHAR_TYPE;
+ case 'B':
+ return BYTE_TYPE;
+ case 'S':
+ return SHORT_TYPE;
+ case 'I':
+ return INT_TYPE;
+ case 'F':
+ return FLOAT_TYPE;
+ case 'J':
+ return LONG_TYPE;
+ case 'D':
+ return DOUBLE_TYPE;
+ case '[':
+ return new Type(ARRAY, descriptorBuffer, descriptorBegin, descriptorEnd);
+ case 'L':
+ return new Type(OBJECT, descriptorBuffer, descriptorBegin + 1, descriptorEnd - 1);
+ case '(':
+ return new Type(METHOD, descriptorBuffer, descriptorBegin, descriptorEnd);
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods to get class names, internal names or descriptors.
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the binary name of the class corresponding to this type. This method must not be used
+ * on method types.
+ *
+ * @return the binary name of the class corresponding to this type.
+ */
+ public String getClassName() {
+ switch (sort) {
+ case VOID:
+ return "void";
+ case BOOLEAN:
+ return "boolean";
+ case CHAR:
+ return "char";
+ case BYTE:
+ return "byte";
+ case SHORT:
+ return "short";
+ case INT:
+ return "int";
+ case FLOAT:
+ return "float";
+ case LONG:
+ return "long";
+ case DOUBLE:
+ return "double";
+ case ARRAY:
+ StringBuilder stringBuilder = new StringBuilder(getElementType().getClassName());
+ for (int i = getDimensions(); i > 0; --i) {
+ stringBuilder.append("[]");
}
- return types;
- }
-
- /**
- * Returns the Java type corresponding to the return type of the given
- * method descriptor.
- *
- * @param methodDescriptor
- * a method descriptor.
- * @return the Java type corresponding to the return type of the given
- * method descriptor.
- */
- public static Type getReturnType(final String methodDescriptor) {
- char[] buf = methodDescriptor.toCharArray();
- int off = 1;
- while (true) {
- char car = buf[off++];
- if (car == ')') {
- return getType(buf, off);
- } else if (car == 'L') {
- while (buf[off++] != ';') {
- }
- }
+ return stringBuilder.toString();
+ case OBJECT:
+ case INTERNAL:
+ return valueBuffer.substring(valueBegin, valueEnd).replace('/', '.');
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Returns the internal name of the class corresponding to this object or array type. The internal
+ * name of a class is its fully qualified name (as returned by Class.getName(), where '.' are
+ * replaced by '/'). This method should only be used for an object or array type.
+ *
+ * @return the internal name of the class corresponding to this object type.
+ */
+ public String getInternalName() {
+ return valueBuffer.substring(valueBegin, valueEnd);
+ }
+
+ /**
+ * Returns the internal name of the given class. The internal name of a class is its fully
+ * qualified name, as returned by Class.getName(), where '.' are replaced by '/'.
+ *
+ * @param clazz an object or array class.
+ * @return the internal name of the given class.
+ */
+ public static String getInternalName(final Class<?> clazz) {
+ return clazz.getName().replace('.', '/');
+ }
+
+ /**
+ * Returns the descriptor corresponding to this type.
+ *
+ * @return the descriptor corresponding to this type.
+ */
+ public String getDescriptor() {
+ if (sort == OBJECT) {
+ return valueBuffer.substring(valueBegin - 1, valueEnd + 1);
+ } else if (sort == INTERNAL) {
+ return new StringBuilder()
+ .append('L')
+ .append(valueBuffer, valueBegin, valueEnd)
+ .append(';')
+ .toString();
+ } else {
+ return valueBuffer.substring(valueBegin, valueEnd);
+ }
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given class.
+ *
+ * @param clazz an object class, a primitive class or an array class.
+ * @return the descriptor corresponding to the given class.
+ */
+ public static String getDescriptor(final Class<?> clazz) {
+ StringBuilder stringBuilder = new StringBuilder();
+ appendDescriptor(clazz, stringBuilder);
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given constructor.
+ *
+ * @param constructor a {@link Constructor} object.
+ * @return the descriptor of the given constructor.
+ */
+ public static String getConstructorDescriptor(final Constructor<?> constructor) {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append('(');
+ Class<?>[] parameters = constructor.getParameterTypes();
+ for (Class<?> parameter : parameters) {
+ appendDescriptor(parameter, stringBuilder);
+ }
+ return stringBuilder.append(")V").toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given argument and return types.
+ *
+ * @param returnType the return type of the method.
+ * @param argumentTypes the argument types of the method.
+ * @return the descriptor corresponding to the given argument and return types.
+ */
+ public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append('(');
+ for (Type argumentType : argumentTypes) {
+ argumentType.appendDescriptor(stringBuilder);
+ }
+ stringBuilder.append(')');
+ returnType.appendDescriptor(stringBuilder);
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given method.
+ *
+ * @param method a {@link Method} object.
+ * @return the descriptor of the given method.
+ */
+ public static String getMethodDescriptor(final Method method) {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append('(');
+ Class<?>[] parameters = method.getParameterTypes();
+ for (Class<?> parameter : parameters) {
+ appendDescriptor(parameter, stringBuilder);
+ }
+ stringBuilder.append(')');
+ appendDescriptor(method.getReturnType(), stringBuilder);
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Appends the descriptor corresponding to this type to the given string buffer.
+ *
+ * @param stringBuilder the string builder to which the descriptor must be appended.
+ */
+ private void appendDescriptor(final StringBuilder stringBuilder) {
+ if (sort == OBJECT) {
+ stringBuilder.append(valueBuffer, valueBegin - 1, valueEnd + 1);
+ } else if (sort == INTERNAL) {
+ stringBuilder.append('L').append(valueBuffer, valueBegin, valueEnd).append(';');
+ } else {
+ stringBuilder.append(valueBuffer, valueBegin, valueEnd);
+ }
+ }
+
+ /**
+ * Appends the descriptor of the given class to the given string builder.
+ *
+ * @param clazz the class whose descriptor must be computed.
+ * @param stringBuilder the string builder to which the descriptor must be appended.
+ */
+ private static void appendDescriptor(final Class<?> clazz, final StringBuilder stringBuilder) {
+ Class<?> currentClass = clazz;
+ while (currentClass.isArray()) {
+ stringBuilder.append('[');
+ currentClass = currentClass.getComponentType();
+ }
+ if (currentClass.isPrimitive()) {
+ char descriptor;
+ if (currentClass == Integer.TYPE) {
+ descriptor = 'I';
+ } else if (currentClass == Void.TYPE) {
+ descriptor = 'V';
+ } else if (currentClass == Boolean.TYPE) {
+ descriptor = 'Z';
+ } else if (currentClass == Byte.TYPE) {
+ descriptor = 'B';
+ } else if (currentClass == Character.TYPE) {
+ descriptor = 'C';
+ } else if (currentClass == Short.TYPE) {
+ descriptor = 'S';
+ } else if (currentClass == Double.TYPE) {
+ descriptor = 'D';
+ } else if (currentClass == Float.TYPE) {
+ descriptor = 'F';
+ } else if (currentClass == Long.TYPE) {
+ descriptor = 'J';
+ } else {
+ throw new AssertionError();
+ }
+ stringBuilder.append(descriptor);
+ } else {
+ stringBuilder.append('L');
+ String name = currentClass.getName();
+ int nameLength = name.length();
+ for (int i = 0; i < nameLength; ++i) {
+ char car = name.charAt(i);
+ stringBuilder.append(car == '.' ? '/' : car);
+ }
+ stringBuilder.append(';');
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods to get the sort, dimension, size, and opcodes corresponding to a Type or descriptor.
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the sort of this type.
+ *
+ * @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link
+ * #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or
+ * {@link #METHOD}.
+ */
+ public int getSort() {
+ return sort == INTERNAL ? OBJECT : sort;
+ }
+
+ /**
+ * Returns the number of dimensions of this array type. This method should only be used for an
+ * array type.
+ *
+ * @return the number of dimensions of this array type.
+ */
+ public int getDimensions() {
+ int numDimensions = 1;
+ while (valueBuffer.charAt(valueBegin + numDimensions) == '[') {
+ numDimensions++;
+ }
+ return numDimensions;
+ }
+
+ /**
+ * Returns the size of values of this type. This method must not be used for method types.
+ *
+ * @return the size of values of this type, i.e., 2 for {@code long} and {@code double}, 0 for
+ * {@code void} and 1 otherwise.
+ */
+ public int getSize() {
+ switch (sort) {
+ case VOID:
+ return 0;
+ case BOOLEAN:
+ case CHAR:
+ case BYTE:
+ case SHORT:
+ case INT:
+ case FLOAT:
+ case ARRAY:
+ case OBJECT:
+ case INTERNAL:
+ return 1;
+ case LONG:
+ case DOUBLE:
+ return 2;
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Returns the size of the arguments and of the return value of methods of this type. This method
+ * should only be used for method types.
+ *
+ * @return the size of the arguments of the method (plus one for the implicit this argument),
+ * argumentsSize, and the size of its return value, returnSize, packed into a single int i =
+ * {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code
+ * i >> 2}, and returnSize to {@code i & 0x03}).
+ */
+ public int getArgumentsAndReturnSizes() {
+ return getArgumentsAndReturnSizes(getDescriptor());
+ }
+
+ /**
+ * Computes the size of the arguments and of the return value of a method.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the size of the arguments of the method (plus one for the implicit this argument),
+ * argumentsSize, and the size of its return value, returnSize, packed into a single int i =
+ * {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code
+ * i >> 2}, and returnSize to {@code i & 0x03}).
+ */
+ public static int getArgumentsAndReturnSizes(final String methodDescriptor) {
+ int argumentsSize = 1;
+ // Skip the first character, which is always a '('.
+ int currentOffset = 1;
+ int currentChar = methodDescriptor.charAt(currentOffset);
+ // Parse the argument types and compute their size, one at a each loop iteration.
+ while (currentChar != ')') {
+ if (currentChar == 'J' || currentChar == 'D') {
+ currentOffset++;
+ argumentsSize += 2;
+ } else {
+ while (methodDescriptor.charAt(currentOffset) == '[') {
+ currentOffset++;
}
- }
-
- /**
- * Returns the Java type corresponding to the return type of the given
- * method.
- *
- * @param method
- * a method.
- * @return the Java type corresponding to the return type of the given
- * method.
- */
- public static Type getReturnType(final Method method) {
- return getType(method.getReturnType());
- }
-
- /**
- * Computes the size of the arguments and of the return value of a method.
- *
- * @param desc
- * the descriptor of a method.
- * @return the size of the arguments of the method (plus one for the
- * implicit this argument), argSize, and the size of its return
- * value, retSize, packed into a single int i =
- * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
- * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
- */
- public static int getArgumentsAndReturnSizes(final String desc) {
- int n = 1;
- int c = 1;
- while (true) {
- char car = desc.charAt(c++);
- if (car == ')') {
- car = desc.charAt(c);
- return n << 2
- | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
- } else if (car == 'L') {
- while (desc.charAt(c++) != ';') {
- }
- n += 1;
- } else if (car == '[') {
- while ((car = desc.charAt(c)) == '[') {
- ++c;
- }
- if (car == 'D' || car == 'J') {
- n -= 1;
- }
- } else if (car == 'D' || car == 'J') {
- n += 2;
- } else {
- n += 1;
- }
+ if (methodDescriptor.charAt(currentOffset++) == 'L') {
+ // Skip the argument descriptor content.
+ currentOffset = methodDescriptor.indexOf(';', currentOffset) + 1;
}
- }
-
- /**
- * Returns the Java type corresponding to the given type descriptor. For
- * method descriptors, buf is supposed to contain nothing more than the
- * descriptor itself.
- *
- * @param buf
- * a buffer containing a type descriptor.
- * @param off
- * the offset of this descriptor in the previous buffer.
- * @return the Java type corresponding to the given type descriptor.
- */
- private static Type getType(final char[] buf, final int off) {
- int len;
- switch (buf[off]) {
- case 'V':
- return VOID_TYPE;
- case 'Z':
- return BOOLEAN_TYPE;
- case 'C':
- return CHAR_TYPE;
- case 'B':
- return BYTE_TYPE;
- case 'S':
- return SHORT_TYPE;
- case 'I':
- return INT_TYPE;
- case 'F':
- return FLOAT_TYPE;
- case 'J':
- return LONG_TYPE;
- case 'D':
- return DOUBLE_TYPE;
- case '[':
- len = 1;
- while (buf[off + len] == '[') {
- ++len;
- }
- if (buf[off + len] == 'L') {
- ++len;
- while (buf[off + len] != ';') {
- ++len;
- }
- }
- return new Type(ARRAY, buf, off, len + 1);
- case 'L':
- len = 1;
- while (buf[off + len] != ';') {
- ++len;
- }
- return new Type(OBJECT, buf, off + 1, len - 1);
- // case '(':
+ argumentsSize += 1;
+ }
+ currentChar = methodDescriptor.charAt(currentOffset);
+ }
+ currentChar = methodDescriptor.charAt(currentOffset + 1);
+ if (currentChar == 'V') {
+ return argumentsSize << 2;
+ } else {
+ int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1;
+ return argumentsSize << 2 | returnSize;
+ }
+ }
+
+ /**
+ * Returns a JVM instruction opcode adapted to this {@link Type}. This method must not be used for
+ * method types.
+ *
+ * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD, ISTORE, IALOAD,
+ * IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL, ISHR, IUSHR, IAND, IOR, IXOR and
+ * IRETURN.
+ * @return an opcode that is similar to the given opcode, but adapted to this {@link Type}. For
+ * example, if this type is {@code float} and {@code opcode} is IRETURN, this method returns
+ * FRETURN.
+ */
+ public int getOpcode(final int opcode) {
+ if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
+ switch (sort) {
+ case BOOLEAN:
+ case BYTE:
+ return opcode + (Opcodes.BALOAD - Opcodes.IALOAD);
+ case CHAR:
+ return opcode + (Opcodes.CALOAD - Opcodes.IALOAD);
+ case SHORT:
+ return opcode + (Opcodes.SALOAD - Opcodes.IALOAD);
+ case INT:
+ return opcode;
+ case FLOAT:
+ return opcode + (Opcodes.FALOAD - Opcodes.IALOAD);
+ case LONG:
+ return opcode + (Opcodes.LALOAD - Opcodes.IALOAD);
+ case DOUBLE:
+ return opcode + (Opcodes.DALOAD - Opcodes.IALOAD);
+ case ARRAY:
+ case OBJECT:
+ case INTERNAL:
+ return opcode + (Opcodes.AALOAD - Opcodes.IALOAD);
+ case METHOD:
+ case VOID:
+ throw new UnsupportedOperationException();
default:
- return new Type(METHOD, buf, off, buf.length - off);
- }
- }
-
- // ------------------------------------------------------------------------
- // Accessors
- // ------------------------------------------------------------------------
-
- /**
- * Returns the sort of this Java type.
- *
- * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
- * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT},
- * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE},
- * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD
- * METHOD}.
- */
- public int getSort() {
- return sort;
- }
-
- /**
- * Returns the number of dimensions of this array type. This method should
- * only be used for an array type.
- *
- * @return the number of dimensions of this array type.
- */
- public int getDimensions() {
- int i = 1;
- while (buf[off + i] == '[') {
- ++i;
- }
- return i;
- }
-
- /**
- * Returns the type of the elements of this array type. This method should
- * only be used for an array type.
- *
- * @return Returns the type of the elements of this array type.
- */
- public Type getElementType() {
- return getType(buf, off + getDimensions());
- }
-
- /**
- * Returns the binary name of the class corresponding to this type. This
- * method must not be used on method types.
- *
- * @return the binary name of the class corresponding to this type.
- */
- public String getClassName() {
- switch (sort) {
+ throw new AssertionError();
+ }
+ } else {
+ switch (sort) {
case VOID:
- return "void";
+ if (opcode != Opcodes.IRETURN) {
+ throw new UnsupportedOperationException();
+ }
+ return Opcodes.RETURN;
case BOOLEAN:
- return "boolean";
- case CHAR:
- return "char";
case BYTE:
- return "byte";
+ case CHAR:
case SHORT:
- return "short";
case INT:
- return "int";
+ return opcode;
case FLOAT:
- return "float";
+ return opcode + (Opcodes.FRETURN - Opcodes.IRETURN);
case LONG:
- return "long";
+ return opcode + (Opcodes.LRETURN - Opcodes.IRETURN);
case DOUBLE:
- return "double";
+ return opcode + (Opcodes.DRETURN - Opcodes.IRETURN);
case ARRAY:
- StringBuilder sb = new StringBuilder(getElementType().getClassName());
- for (int i = getDimensions(); i > 0; --i) {
- sb.append("[]");
- }
- return sb.toString();
case OBJECT:
- return new String(buf, off, len).replace('/', '.');
+ case INTERNAL:
+ if (opcode != Opcodes.ILOAD && opcode != Opcodes.ISTORE && opcode != Opcodes.IRETURN) {
+ throw new UnsupportedOperationException();
+ }
+ return opcode + (Opcodes.ARETURN - Opcodes.IRETURN);
+ case METHOD:
+ throw new UnsupportedOperationException();
default:
- return null;
- }
- }
-
- /**
- * Returns the internal name of the class corresponding to this object or
- * array type. The internal name of a class is its fully qualified name (as
- * returned by Class.getName(), where '.' are replaced by '/'. This method
- * should only be used for an object or array type.
- *
- * @return the internal name of the class corresponding to this object type.
- */
- public String getInternalName() {
- return new String(buf, off, len);
- }
-
- /**
- * Returns the argument types of methods of this type. This method should
- * only be used for method types.
- *
- * @return the argument types of methods of this type.
- */
- public Type[] getArgumentTypes() {
- return getArgumentTypes(getDescriptor());
- }
-
- /**
- * Returns the return type of methods of this type. This method should only
- * be used for method types.
- *
- * @return the return type of methods of this type.
- */
- public Type getReturnType() {
- return getReturnType(getDescriptor());
- }
-
- /**
- * Returns the size of the arguments and of the return value of methods of
- * this type. This method should only be used for method types.
- *
- * @return the size of the arguments (plus one for the implicit this
- * argument), argSize, and the size of the return value, retSize,
- * packed into a single
- * int i = <tt>(argSize << 2) | retSize</tt>
- * (argSize is therefore equal to <tt>i >> 2</tt>,
- * and retSize to <tt>i & 0x03</tt>).
- */
- public int getArgumentsAndReturnSizes() {
- return getArgumentsAndReturnSizes(getDescriptor());
- }
-
- // ------------------------------------------------------------------------
- // Conversion to type descriptors
- // ------------------------------------------------------------------------
-
- /**
- * Returns the descriptor corresponding to this Java type.
- *
- * @return the descriptor corresponding to this Java type.
- */
- public String getDescriptor() {
- StringBuilder buf = new StringBuilder();
- getDescriptor(buf);
- return buf.toString();
- }
-
- /**
- * Returns the descriptor corresponding to the given argument and return
- * types.
- *
- * @param returnType
- * the return type of the method.
- * @param argumentTypes
- * the argument types of the method.
- * @return the descriptor corresponding to the given argument and return
- * types.
- */
- public static String getMethodDescriptor(final Type returnType,
- final Type... argumentTypes) {
- StringBuilder buf = new StringBuilder();
- buf.append('(');
- for (int i = 0; i < argumentTypes.length; ++i) {
- argumentTypes[i].getDescriptor(buf);
- }
- buf.append(')');
- returnType.getDescriptor(buf);
- return buf.toString();
- }
-
- /**
- * Appends the descriptor corresponding to this Java type to the given
- * string buffer.
- *
- * @param buf
- * the string buffer to which the descriptor must be appended.
- */
- private void getDescriptor(final StringBuilder buf) {
- if (this.buf == null) {
- // descriptor is in byte 3 of 'off' for primitive types (buf ==
- // null)
- buf.append((char) ((off & 0xFF000000) >>> 24));
- } else if (sort == OBJECT) {
- buf.append('L');
- buf.append(this.buf, off, len);
- buf.append(';');
- } else { // sort == ARRAY || sort == METHOD
- buf.append(this.buf, off, len);
- }
- }
-
- // ------------------------------------------------------------------------
- // Direct conversion from classes to type descriptors,
- // without intermediate Type objects
- // ------------------------------------------------------------------------
-
- /**
- * Returns the internal name of the given class. The internal name of a
- * class is its fully qualified name, as returned by Class.getName(), where
- * '.' are replaced by '/'.
- *
- * @param c
- * an object or array class.
- * @return the internal name of the given class.
- */
- public static String getInternalName(final Class<?> c) {
- return c.getName().replace('.', '/');
- }
-
- /**
- * Returns the descriptor corresponding to the given Java type.
- *
- * @param c
- * an object class, a primitive class or an array class.
- * @return the descriptor corresponding to the given class.
- */
- public static String getDescriptor(final Class<?> c) {
- StringBuilder buf = new StringBuilder();
- getDescriptor(buf, c);
- return buf.toString();
- }
-
- /**
- * Returns the descriptor corresponding to the given constructor.
- *
- * @param c
- * a {@link Constructor Constructor} object.
- * @return the descriptor of the given constructor.
- */
- public static String getConstructorDescriptor(final Constructor<?> c) {
- Class<?>[] parameters = c.getParameterTypes();
- StringBuilder buf = new StringBuilder();
- buf.append('(');
- for (int i = 0; i < parameters.length; ++i) {
- getDescriptor(buf, parameters[i]);
- }
- return buf.append(")V").toString();
- }
-
- /**
- * Returns the descriptor corresponding to the given method.
- *
- * @param m
- * a {@link Method Method} object.
- * @return the descriptor of the given method.
- */
- public static String getMethodDescriptor(final Method m) {
- Class<?>[] parameters = m.getParameterTypes();
- StringBuilder buf = new StringBuilder();
- buf.append('(');
- for (int i = 0; i < parameters.length; ++i) {
- getDescriptor(buf, parameters[i]);
- }
- buf.append(')');
- getDescriptor(buf, m.getReturnType());
- return buf.toString();
- }
-
- /**
- * Appends the descriptor of the given class to the given string buffer.
- *
- * @param buf
- * the string buffer to which the descriptor must be appended.
- * @param c
- * the class whose descriptor must be computed.
- */
- private static void getDescriptor(final StringBuilder buf, final Class<?> c) {
- Class<?> d = c;
- while (true) {
- if (d.isPrimitive()) {
- char car;
- if (d == Integer.TYPE) {
- car = 'I';
- } else if (d == Void.TYPE) {
- car = 'V';
- } else if (d == Boolean.TYPE) {
- car = 'Z';
- } else if (d == Byte.TYPE) {
- car = 'B';
- } else if (d == Character.TYPE) {
- car = 'C';
- } else if (d == Short.TYPE) {
- car = 'S';
- } else if (d == Double.TYPE) {
- car = 'D';
- } else if (d == Float.TYPE) {
- car = 'F';
- } else /* if (d == Long.TYPE) */{
- car = 'J';
- }
- buf.append(car);
- return;
- } else if (d.isArray()) {
- buf.append('[');
- d = d.getComponentType();
- } else {
- buf.append('L');
- String name = d.getName();
- int len = name.length();
- for (int i = 0; i < len; ++i) {
- char car = name.charAt(i);
- buf.append(car == '.' ? '/' : car);
- }
- buf.append(';');
- return;
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Corresponding size and opcodes
- // ------------------------------------------------------------------------
-
- /**
- * Returns the size of values of this type. This method must not be used for
- * method types.
- *
- * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
- * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
- */
- public int getSize() {
- // the size is in byte 0 of 'off' for primitive types (buf == null)
- return buf == null ? (off & 0xFF) : 1;
- }
-
- /**
- * Returns a JVM instruction opcode adapted to this Java type. This method
- * must not be used for method types.
- *
- * @param opcode
- * a JVM instruction opcode. This opcode must be one of ILOAD,
- * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG,
- * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
- * @return an opcode that is similar to the given opcode, but adapted to
- * this Java type. For example, if this type is <tt>float</tt> and
- * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
- */
- public int getOpcode(final int opcode) {
- if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
- // the offset for IALOAD or IASTORE is in byte 1 of 'off' for
- // primitive types (buf == null)
- return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4);
- } else {
- // the offset for other instructions is in byte 2 of 'off' for
- // primitive types (buf == null)
- return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4);
- }
- }
-
- // ------------------------------------------------------------------------
- // Equals, hashCode and toString
- // ------------------------------------------------------------------------
-
- /**
- * Tests if the given object is equal to this type.
- *
- * @param o
- * the object to be compared to this type.
- * @return <tt>true</tt> if the given object is equal to this type.
- */
- @Override
- public boolean equals(final Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof Type)) {
- return false;
- }
- Type t = (Type) o;
- if (sort != t.sort) {
- return false;
- }
- if (sort >= ARRAY) {
- if (len != t.len) {
- return false;
- }
- for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
- if (buf[i] != t.buf[j]) {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Returns a hash code value for this type.
- *
- * @return a hash code value for this type.
- */
- @Override
- public int hashCode() {
- int hc = 13 * sort;
- if (sort >= ARRAY) {
- for (int i = off, end = i + len; i < end; i++) {
- hc = 17 * (hc + buf[i]);
- }
- }
- return hc;
- }
-
- /**
- * Returns a string representation of this type.
- *
- * @return the descriptor of this type.
- */
- @Override
- public String toString() {
- return getDescriptor();
- }
+ throw new AssertionError();
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Equals, hashCode and toString.
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Tests if the given object is equal to this type.
+ *
+ * @param object the object to be compared to this type.
+ * @return {@literal true} if the given object is equal to this type.
+ */
+ @Override
+ public boolean equals(final Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (!(object instanceof Type)) {
+ return false;
+ }
+ Type other = (Type) object;
+ if ((sort == INTERNAL ? OBJECT : sort) != (other.sort == INTERNAL ? OBJECT : other.sort)) {
+ return false;
+ }
+ int begin = valueBegin;
+ int end = valueEnd;
+ int otherBegin = other.valueBegin;
+ int otherEnd = other.valueEnd;
+ // Compare the values.
+ if (end - begin != otherEnd - otherBegin) {
+ return false;
+ }
+ for (int i = begin, j = otherBegin; i < end; i++, j++) {
+ if (valueBuffer.charAt(i) != other.valueBuffer.charAt(j)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns a hash code value for this type.
+ *
+ * @return a hash code value for this type.
+ */
+ @Override
+ public int hashCode() {
+ int hashCode = 13 * (sort == INTERNAL ? OBJECT : sort);
+ if (sort >= ARRAY) {
+ for (int i = valueBegin, end = valueEnd; i < end; i++) {
+ hashCode = 17 * (hashCode + valueBuffer.charAt(i));
+ }
+ }
+ return hashCode;
+ }
+
+ /**
+ * Returns a string representation of this type.
+ *
+ * @return the descriptor of this type.
+ */
+ @Override
+ public String toString() {
+ return getDescriptor();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
old mode 100644
new mode 100755
index d86420d..06dd679
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
@@ -1,196 +1,201 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2013 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.apache.tapestry5.internal.plastic.asm;
-
-/**
- * The path to a type argument, wildcard bound, array element type, or static
- * inner type within an enclosing type.
- *
- * @author Eric Bruneton
- */
-public class TypePath {
-
- /**
- * A type path step that steps into the element type of an array type. See
- * {@link #getStep getStep}.
- */
- public final static int ARRAY_ELEMENT = 0;
-
- /**
- * A type path step that steps into the nested type of a class type. See
- * {@link #getStep getStep}.
- */
- public final static int INNER_TYPE = 1;
-
- /**
- * A type path step that steps into the bound of a wildcard type. See
- * {@link #getStep getStep}.
- */
- public final static int WILDCARD_BOUND = 2;
-
- /**
- * A type path step that steps into a type argument of a generic type. See
- * {@link #getStep getStep}.
- */
- public final static int TYPE_ARGUMENT = 3;
-
- /**
- * The byte array where the path is stored, in Java class file format.
- */
- byte[] b;
-
- /**
- * The offset of the first byte of the type path in 'b'.
- */
- int offset;
-
- /**
- * Creates a new type path.
- *
- * @param b
- * the byte array containing the type path in Java class file
- * format.
- * @param offset
- * the offset of the first byte of the type path in 'b'.
- */
- TypePath(byte[] b, int offset) {
- this.b = b;
- this.offset = offset;
- }
-
- /**
- * Returns the length of this path.
- *
- * @return the length of this path.
- */
- public int getLength() {
- return b[offset];
- }
-
- /**
- * Returns the value of the given step of this path.
- *
- * @param index
- * an index between 0 and {@link #getLength()}, exclusive.
- * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
- * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
- * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
- */
- public int getStep(int index) {
- return b[offset + 2 * index + 1];
- }
-
- /**
- * Returns the index of the type argument that the given step is stepping
- * into. This method should only be used for steps whose value is
- * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
- *
- * @param index
- * an index between 0 and {@link #getLength()}, exclusive.
- * @return the index of the type argument that the given step is stepping
- * into.
- */
- public int getStepArgument(int index) {
- return b[offset + 2 * index + 2];
- }
-
- /**
- * Converts a type path in string form, in the format used by
- * {@link #toString()}, into a TypePath object.
- *
- * @param typePath
- * a type path in string form, in the format used by
- * {@link #toString()}. May be null or empty.
- * @return the corresponding TypePath object, or null if the path is empty.
- */
- public static TypePath fromString(final String typePath) {
- if (typePath == null || typePath.length() == 0) {
- return null;
- }
- int n = typePath.length();
- ByteVector out = new ByteVector(n);
- out.putByte(0);
- for (int i = 0; i < n;) {
- char c = typePath.charAt(i++);
- if (c == '[') {
- out.put11(ARRAY_ELEMENT, 0);
- } else if (c == '.') {
- out.put11(INNER_TYPE, 0);
- } else if (c == '*') {
- out.put11(WILDCARD_BOUND, 0);
- } else if (c >= '0' && c <= '9') {
- int typeArg = c - '0';
- while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
- typeArg = typeArg * 10 + c - '0';
- i += 1;
- }
- if (i < n && typePath.charAt(i) == ';') {
- i += 1;
- }
- out.put11(TYPE_ARGUMENT, typeArg);
- }
- }
- out.data[0] = (byte) (out.length / 2);
- return new TypePath(out.data, 0);
- }
-
- /**
- * Returns a string representation of this type path. {@link #ARRAY_ELEMENT
- * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
- * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
- * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
- * argument index in decimal form followed by ';'.
- */
- @Override
- public String toString() {
- int length = getLength();
- StringBuilder result = new StringBuilder(length * 2);
- for (int i = 0; i < length; ++i) {
- switch (getStep(i)) {
- case ARRAY_ELEMENT:
- result.append('[');
- break;
- case INNER_TYPE:
- result.append('.');
- break;
- case WILDCARD_BOUND:
- result.append('*');
- break;
- case TYPE_ARGUMENT:
- result.append(getStepArgument(i)).append(';');
- break;
- default:
- result.append('_');
- }
- }
- return result.toString();
- }
-}
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * The path to a type argument, wildcard bound, array element type, or static inner type within an
+ * enclosing type.
+ *
+ * @author Eric Bruneton
+ */
+public final class TypePath {
+
+ /** A type path step that steps into the element type of an array type. See {@link #getStep}. */
+ public static final int ARRAY_ELEMENT = 0;
+
+ /** A type path step that steps into the nested type of a class type. See {@link #getStep}. */
+ public static final int INNER_TYPE = 1;
+
+ /** A type path step that steps into the bound of a wildcard type. See {@link #getStep}. */
+ public static final int WILDCARD_BOUND = 2;
+
+ /** A type path step that steps into a type argument of a generic type. See {@link #getStep}. */
+ public static final int TYPE_ARGUMENT = 3;
+
+ /**
+ * The byte array where the 'type_path' structure - as defined in the Java Virtual Machine
+ * Specification (JVMS) - corresponding to this TypePath is stored. The first byte of the
+ * structure in this array is given by {@link #typePathOffset}.
+ *
+ * @see <a
+ * href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.2">JVMS
+ * 4.7.20.2</a>
+ */
+ private final byte[] typePathContainer;
+
+ /** The offset of the first byte of the type_path JVMS structure in {@link #typePathContainer}. */
+ private final int typePathOffset;
+
+ /**
+ * Constructs a new TypePath.
+ *
+ * @param typePathContainer a byte array containing a type_path JVMS structure.
+ * @param typePathOffset the offset of the first byte of the type_path structure in
+ * typePathContainer.
+ */
+ TypePath(final byte[] typePathContainer, final int typePathOffset) {
+ this.typePathContainer = typePathContainer;
+ this.typePathOffset = typePathOffset;
+ }
+
+ /**
+ * Returns the length of this path, i.e. its number of steps.
+ *
+ * @return the length of this path.
+ */
+ public int getLength() {
+ // path_length is stored in the first byte of a type_path.
+ return typePathContainer[typePathOffset];
+ }
+
+ /**
+ * Returns the value of the given step of this path.
+ *
+ * @param index an index between 0 and {@link #getLength()}, exclusive.
+ * @return one of {@link #ARRAY_ELEMENT}, {@link #INNER_TYPE}, {@link #WILDCARD_BOUND}, or {@link
+ * #TYPE_ARGUMENT}.
+ */
+ public int getStep(final int index) {
+ // Returns the type_path_kind of the path element of the given index.
+ return typePathContainer[typePathOffset + 2 * index + 1];
+ }
+
+ /**
+ * Returns the index of the type argument that the given step is stepping into. This method should
+ * only be used for steps whose value is {@link #TYPE_ARGUMENT}.
+ *
+ * @param index an index between 0 and {@link #getLength()}, exclusive.
+ * @return the index of the type argument that the given step is stepping into.
+ */
+ public int getStepArgument(final int index) {
+ // Returns the type_argument_index of the path element of the given index.
+ return typePathContainer[typePathOffset + 2 * index + 2];
+ }
+
+ /**
+ * Converts a type path in string form, in the format used by {@link #toString()}, into a TypePath
+ * object.
+ *
+ * @param typePath a type path in string form, in the format used by {@link #toString()}. May be
+ * {@literal null} or empty.
+ * @return the corresponding TypePath object, or {@literal null} if the path is empty.
+ */
+ public static TypePath fromString(final String typePath) {
+ if (typePath == null || typePath.length() == 0) {
+ return null;
+ }
+ int typePathLength = typePath.length();
+ ByteVector output = new ByteVector(typePathLength);
+ output.putByte(0);
+ int typePathIndex = 0;
+ while (typePathIndex < typePathLength) {
+ char c = typePath.charAt(typePathIndex++);
+ if (c == '[') {
+ output.put11(ARRAY_ELEMENT, 0);
+ } else if (c == '.') {
+ output.put11(INNER_TYPE, 0);
+ } else if (c == '*') {
+ output.put11(WILDCARD_BOUND, 0);
+ } else if (c >= '0' && c <= '9') {
+ int typeArg = c - '0';
+ while (typePathIndex < typePathLength) {
+ c = typePath.charAt(typePathIndex++);
+ if (c >= '0' && c <= '9') {
+ typeArg = typeArg * 10 + c - '0';
+ } else if (c == ';') {
+ break;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+ output.put11(TYPE_ARGUMENT, typeArg);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+ output.data[0] = (byte) (output.length / 2);
+ return new TypePath(output.data, 0);
+ }
+
+ /**
+ * Returns a string representation of this type path. {@link #ARRAY_ELEMENT} steps are represented
+ * with '[', {@link #INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND} steps with '*' and {@link
+ * #TYPE_ARGUMENT} steps with their type argument index in decimal form followed by ';'.
+ */
+ @Override
+ public String toString() {
+ int length = getLength();
+ StringBuilder result = new StringBuilder(length * 2);
+ for (int i = 0; i < length; ++i) {
+ switch (getStep(i)) {
+ case ARRAY_ELEMENT:
+ result.append('[');
+ break;
+ case INNER_TYPE:
+ result.append('.');
+ break;
+ case WILDCARD_BOUND:
+ result.append('*');
+ break;
+ case TYPE_ARGUMENT:
+ result.append(getStepArgument(i)).append(';');
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Puts the type_path JVMS structure corresponding to the given TypePath into the given
+ * ByteVector.
+ *
+ * @param typePath a TypePath instance, or {@literal null} for empty paths.
+ * @param output where the type path must be put.
+ */
+ static void put(final TypePath typePath, final ByteVector output) {
+ if (typePath == null) {
+ output.putByte(0);
+ } else {
+ int length = typePath.typePathContainer[typePath.typePathOffset] * 2 + 1;
+ output.putByteArray(typePath.typePathContainer, typePath.typePathOffset, length);
+ }
+ }
+}
[43/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassTooLargeException.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassTooLargeException.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassTooLargeException.java
new file mode 100755
index 0000000..b3257ee
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassTooLargeException.java
@@ -0,0 +1,71 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * Exception thrown when the constant pool of a class produced by a {@link ClassWriter} is too
+ * large.
+ *
+ * @author Jason Zaugg
+ */
+public final class ClassTooLargeException extends IndexOutOfBoundsException {
+ private static final long serialVersionUID = 160715609518896765L;
+
+ private final String className;
+ private final int constantPoolCount;
+
+ /**
+ * Constructs a new {@link ClassTooLargeException}.
+ *
+ * @param className the internal name of the class.
+ * @param constantPoolCount the number of constant pool items of the class.
+ */
+ public ClassTooLargeException(final String className, final int constantPoolCount) {
+ super("Class too large: " + className);
+ this.className = className;
+ this.constantPoolCount = constantPoolCount;
+ }
+
+ /**
+ * Returns the internal name of the class.
+ *
+ * @return the internal name of the class.
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Returns the number of constant pool items of the class.
+ *
+ * @return the number of constant pool items of the class.
+ */
+ public int getConstantPoolCount() {
+ return constantPoolCount;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
old mode 100644
new mode 100755
index b5751d4..8631280f
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
@@ -1,342 +1,329 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java class. The methods of this class must be called in
- * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
- * <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
- * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
- * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
- * <tt>visitEnd</tt>.
- *
+ * A visitor to visit a Java class. The methods of this class must be called in the following order:
+ * {@code visit} [ {@code visitSource} ] [ {@code visitModule} ][ {@code visitNestHost} ][ {@code
+ * visitOuterClass} ] ( {@code visitAnnotation} | {@code visitTypeAnnotation} | {@code
+ * visitAttribute} )* ( {@code visitNestMember} | {@code visitInnerClass} | {@code visitField} |
+ * {@code visitMethod} )* {@code visitEnd}.
+ *
* @author Eric Bruneton
*/
public abstract class ClassVisitor {
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- protected final int api;
+ /**
+ * The ASM API version implemented by this visitor. The value of this field must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected final int api;
+
+ /** The class visitor to which this visitor must delegate method calls. May be null. */
+ protected ClassVisitor cv;
+
+ /**
+ * Constructs a new {@link ClassVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public ClassVisitor(final int api) {
+ this(api, null);
+ }
- /**
- * The class visitor to which this visitor must delegate method calls. May
- * be null.
- */
- protected ClassVisitor cv;
+ /**
+ * Constructs a new {@link ClassVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param classVisitor the class visitor to which this visitor must delegate method calls. May be
+ * null.
+ */
+ public ClassVisitor(final int api, final ClassVisitor classVisitor) {
+ if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
+ throw new IllegalArgumentException();
+ }
+ this.api = api;
+ this.cv = classVisitor;
+ }
- /**
- * Constructs a new {@link ClassVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public ClassVisitor(final int api) {
- this(api, null);
+ /**
+ * Visits the header of the class.
+ *
+ * @param version the class version. The minor version is stored in the 16 most significant bits,
+ * and the major version in the 16 least significant bits.
+ * @param access the class's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the class is deprecated.
+ * @param name the internal name of the class (see {@link Type#getInternalName()}).
+ * @param signature the signature of this class. May be {@literal null} if the class is not a
+ * generic one, and does not extend or implement generic classes or interfaces.
+ * @param superName the internal of name of the super class (see {@link Type#getInternalName()}).
+ * For interfaces, the super class is {@link Object}. May be {@literal null}, but only for the
+ * {@link Object} class.
+ * @param interfaces the internal names of the class's interfaces (see {@link
+ * Type#getInternalName()}). May be {@literal null}.
+ */
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ if (cv != null) {
+ cv.visit(version, access, name, signature, superName, interfaces);
}
+ }
- /**
- * Constructs a new {@link ClassVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param cv
- * the class visitor to which this visitor must delegate method
- * calls. May be null.
- */
- public ClassVisitor(final int api, final ClassVisitor cv) {
- if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.cv = cv;
+ /**
+ * Visits the source of the class.
+ *
+ * @param source the name of the source file from which the class was compiled. May be {@literal
+ * null}.
+ * @param debug additional debug information to compute the correspondence between source and
+ * compiled elements of the class. May be {@literal null}.
+ */
+ public void visitSource(final String source, final String debug) {
+ if (cv != null) {
+ cv.visitSource(source, debug);
}
+ }
- /**
- * Visits the header of the class.
- *
- * @param version
- * the class version.
- * @param access
- * the class's access flags (see {@link Opcodes}). This parameter
- * also indicates if the class is deprecated.
- * @param name
- * the internal name of the class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param signature
- * the signature of this class. May be <tt>null</tt> if the class
- * is not a generic one, and does not extend or implement generic
- * classes or interfaces.
- * @param superName
- * the internal of name of the super class (see
- * {@link Type#getInternalName() getInternalName}). For
- * interfaces, the super class is {@link Object}. May be
- * <tt>null</tt>, but only for the {@link Object} class.
- * @param interfaces
- * the internal names of the class's interfaces (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- */
- public void visit(int version, int access, String name, String signature,
- String superName, String[] interfaces) {
- if (cv != null) {
- cv.visit(version, access, name, signature, superName, interfaces);
- }
+ /**
+ * Visit the module corresponding to the class.
+ *
+ * @param name the fully qualified name (using dots) of the module.
+ * @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
+ * ACC_MANDATED}.
+ * @param version the module version, or {@literal null}.
+ * @return a visitor to visit the module values, or {@literal null} if this visitor is not
+ * interested in visiting this module.
+ */
+ public ModuleVisitor visitModule(final String name, final int access, final String version) {
+ if (api < Opcodes.ASM6) {
+ throw new UnsupportedOperationException("This feature requires ASM6");
+ }
+ if (cv != null) {
+ return cv.visitModule(name, access, version);
}
+ return null;
+ }
- /**
- * Visits the source of the class.
- *
- * @param source
- * the name of the source file from which the class was compiled.
- * May be <tt>null</tt>.
- * @param debug
- * additional debug information to compute the correspondance
- * between source and compiled elements of the class. May be
- * <tt>null</tt>.
- */
- public void visitSource(String source, String debug) {
- if (cv != null) {
- cv.visitSource(source, debug);
- }
+ /**
+ * Visits the nest host class of the class. A nest is a set of classes of the same package that
+ * share access to their private members. One of these classes, called the host, lists the other
+ * members of the nest, which in turn should link to the host of their nest. This method must be
+ * called only once and only if the visited class is a non-host member of a nest. A class is
+ * implicitly its own nest, so it's invalid to call this method with the visited class name as
+ * argument.
+ *
+ * @param nestHost the internal name of the host class of the nest.
+ */
+ public void visitNestHost(final String nestHost) {
+ if (api < Opcodes.ASM7) {
+ throw new UnsupportedOperationException("This feature requires ASM7");
+ }
+ if (cv != null) {
+ cv.visitNestHost(nestHost);
}
-
- /**
- * Visit the module corresponding to the class.
- * @param name
- * module name
- * @param access
- * module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
- * and {@code ACC_MANDATED}.
- * @param version
- * module version or null.
- * @return a visitor to visit the module values, or <tt>null</tt> if
- * this visitor is not interested in visiting this module.
- */
- public ModuleVisitor visitModule(String name, int access, String version) {
- if (api < Opcodes.ASM6) {
- throw new RuntimeException();
- }
- if (cv != null) {
- return cv.visitModule(name, access, version);
- }
- return null;
+ }
+
+ /**
+ * Visits the enclosing class of the class. This method must be called only if the class has an
+ * enclosing class.
+ *
+ * @param owner internal name of the enclosing class of the class.
+ * @param name the name of the method that contains the class, or {@literal null} if the class is
+ * not enclosed in a method of its enclosing class.
+ * @param descriptor the descriptor of the method that contains the class, or {@literal null} if
+ * the class is not enclosed in a method of its enclosing class.
+ */
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ if (cv != null) {
+ cv.visitOuterClass(owner, name, descriptor);
}
+ }
- /**
- * Visits the enclosing class of the class. This method must be called only
- * if the class has an enclosing class.
- *
- * @param owner
- * internal name of the enclosing class of the class.
- * @param name
- * the name of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
- * @param desc
- * the descriptor of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
- */
- public void visitOuterClass(String owner, String name, String desc) {
- if (cv != null) {
- cv.visitOuterClass(owner, name, desc);
- }
+ /**
+ * Visits an annotation of the class.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ if (cv != null) {
+ return cv.visitAnnotation(descriptor, visible);
}
+ return null;
+ }
- /**
- * Visits an annotation of the class.
- *
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (cv != null) {
- return cv.visitAnnotation(desc, visible);
- }
- return null;
+ /**
+ * Visits an annotation on a type in the class signature.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link
+ * TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See
+ * {@link TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+ * interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new UnsupportedOperationException("This feature requires ASM5");
+ }
+ if (cv != null) {
+ return cv.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
}
+ return null;
+ }
- /**
- * Visits an annotation on a type in the class signature.
- *
- * @param typeRef
- * a reference to the annotated type. The sort of this type
- * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
- * CLASS_TYPE_PARAMETER},
- * {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
- * CLASS_TYPE_PARAMETER_BOUND} or
- * {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See
- * {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param desc
- * the class descriptor of the annotation class.
- * @param visible
- * <tt>true</tt> if the annotation is visible at runtime.
- * @return a visitor to visit the annotation values, or <tt>null</tt> if
- * this visitor is not interested in visiting this annotation.
- */
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- if (api < Opcodes.ASM5) {
- throw new RuntimeException();
- }
- if (cv != null) {
- return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
- return null;
+ /**
+ * Visits a non standard attribute of the class.
+ *
+ * @param attribute an attribute.
+ */
+ public void visitAttribute(final Attribute attribute) {
+ if (cv != null) {
+ cv.visitAttribute(attribute);
}
+ }
- /**
- * Visits a non standard attribute of the class.
- *
- * @param attr
- * an attribute.
- */
- public void visitAttribute(Attribute attr) {
- if (cv != null) {
- cv.visitAttribute(attr);
- }
+ /**
+ * Visits a member of the nest. A nest is a set of classes of the same package that share access
+ * to their private members. One of these classes, called the host, lists the other members of the
+ * nest, which in turn should link to the host of their nest. This method must be called only if
+ * the visited class is the host of a nest. A nest host is implicitly a member of its own nest, so
+ * it's invalid to call this method with the visited class name as argument.
+ *
+ * @param nestMember the internal name of a nest member.
+ */
+ public void visitNestMember(final String nestMember) {
+ if (api < Opcodes.ASM7) {
+ throw new UnsupportedOperationException("This feature requires ASM7");
+ }
+ if (cv != null) {
+ cv.visitNestMember(nestMember);
}
+ }
- /**
- * Visits information about an inner class. This inner class is not
- * necessarily a member of the class being visited.
- *
- * @param name
- * the internal name of an inner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param outerName
- * the internal name of the class to which the inner class
- * belongs (see {@link Type#getInternalName() getInternalName}).
- * May be <tt>null</tt> for not member classes.
- * @param innerName
- * the (simple) name of the inner class inside its enclosing
- * class. May be <tt>null</tt> for anonymous inner classes.
- * @param access
- * the access flags of the inner class as originally declared in
- * the enclosing class.
- */
- public void visitInnerClass(String name, String outerName,
- String innerName, int access) {
- if (cv != null) {
- cv.visitInnerClass(name, outerName, innerName, access);
- }
+ /**
+ * Visits information about an inner class. This inner class is not necessarily a member of the
+ * class being visited.
+ *
+ * @param name the internal name of an inner class (see {@link Type#getInternalName()}).
+ * @param outerName the internal name of the class to which the inner class belongs (see {@link
+ * Type#getInternalName()}). May be {@literal null} for not member classes.
+ * @param innerName the (simple) name of the inner class inside its enclosing class. May be
+ * {@literal null} for anonymous inner classes.
+ * @param access the access flags of the inner class as originally declared in the enclosing
+ * class.
+ */
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ if (cv != null) {
+ cv.visitInnerClass(name, outerName, innerName, access);
}
+ }
- /**
- * Visits a field of the class.
- *
- * @param access
- * the field's access flags (see {@link Opcodes}). This parameter
- * also indicates if the field is synthetic and/or deprecated.
- * @param name
- * the field's name.
- * @param desc
- * the field's descriptor (see {@link Type Type}).
- * @param signature
- * the field's signature. May be <tt>null</tt> if the field's
- * type does not use generic types.
- * @param value
- * the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value,
- * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String} (for <tt>int</tt>,
- * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
- * respectively). <i>This parameter is only used for static
- * fields</i>. Its value is ignored for non static fields, which
- * must be initialized through bytecode instructions in
- * constructors or methods.
- * @return a visitor to visit field annotations and attributes, or
- * <tt>null</tt> if this class visitor is not interested in visiting
- * these annotations and attributes.
- */
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- if (cv != null) {
- return cv.visitField(access, name, desc, signature, value);
- }
- return null;
+ /**
+ * Visits a field of the class.
+ *
+ * @param access the field's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the field is synthetic and/or deprecated.
+ * @param name the field's name.
+ * @param descriptor the field's descriptor (see {@link Type}).
+ * @param signature the field's signature. May be {@literal null} if the field's type does not use
+ * generic types.
+ * @param value the field's initial value. This parameter, which may be {@literal null} if the
+ * field does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link
+ * Long}, a {@link Double} or a {@link String} (for {@code int}, {@code float}, {@code long}
+ * or {@code String} fields respectively). <i>This parameter is only used for static
+ * fields</i>. Its value is ignored for non static fields, which must be initialized through
+ * bytecode instructions in constructors or methods.
+ * @return a visitor to visit field annotations and attributes, or {@literal null} if this class
+ * visitor is not interested in visiting these annotations and attributes.
+ */
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ if (cv != null) {
+ return cv.visitField(access, name, descriptor, signature, value);
}
+ return null;
+ }
- /**
- * Visits a method of the class. This method <i>must</i> return a new
- * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,
- * i.e., it should not return a previously returned visitor.
- *
- * @param access
- * the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt> if the method
- * parameters, return type and exceptions do not use generic
- * types.
- * @param exceptions
- * the internal names of the method's exception classes (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- * @return an object to visit the byte code of the method, or <tt>null</tt>
- * if this class visitor is not interested in visiting the code of
- * this method.
- */
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- if (cv != null) {
- return cv.visitMethod(access, name, desc, signature, exceptions);
- }
- return null;
+ /**
+ * Visits a method of the class. This method <i>must</i> return a new {@link MethodVisitor}
+ * instance (or {@literal null}) each time it is called, i.e., it should not return a previously
+ * returned visitor.
+ *
+ * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
+ * the method is synthetic and/or deprecated.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be {@literal null} if the method parameters,
+ * return type and exceptions do not use generic types.
+ * @param exceptions the internal names of the method's exception classes (see {@link
+ * Type#getInternalName()}). May be {@literal null}.
+ * @return an object to visit the byte code of the method, or {@literal null} if this class
+ * visitor is not interested in visiting the code of this method.
+ */
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ if (cv != null) {
+ return cv.visitMethod(access, name, descriptor, signature, exceptions);
}
+ return null;
+ }
- /**
- * Visits the end of the class. This method, which is the last one to be
- * called, is used to inform the visitor that all the fields and methods of
- * the class have been visited.
- */
- public void visitEnd() {
- if (cv != null) {
- cv.visitEnd();
- }
+ /**
+ * Visits the end of the class. This method, which is the last one to be called, is used to inform
+ * the visitor that all the fields and methods of the class have been visited.
+ */
+ public void visitEnd() {
+ if (cv != null) {
+ cv.visitEnd();
}
+ }
}
[03/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
deleted file mode 100644
index 3ebe653..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
+++ /dev/null
@@ -1,1569 +0,0 @@
-/***
- * ASM XML Adapter
- * Copyright (c) 2004-2011, Eugene Kuleshov
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.xml;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
-import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Handle;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.Type;
-import org.apache.tapestry5.internal.plastic.asm.TypePath;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-/**
- * A {@link org.xml.sax.ContentHandler ContentHandler} that transforms XML
- * document into Java class file. This class can be feeded by any kind of SAX
- * 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code.
- *
- * @see org.objectweb.asm.xml.SAXClassAdapter
- * @see org.objectweb.asm.xml.Processor
- *
- * @author Eugene Kuleshov
- */
-public class ASMContentHandler extends DefaultHandler implements Opcodes {
-
- /**
- * Stack of the intermediate processing contexts.
- */
- private final ArrayList<Object> stack = new ArrayList<Object>();
-
- /**
- * Complete name of the current element.
- */
- String match = "";
-
- /**
- * Current instance of the {@link ClassVisitor ClassVisitor} used to visit
- * classfile bytecode.
- */
- protected ClassVisitor cv;
-
- /**
- * Map of the active {@link Label Label} instances for current method.
- */
- protected Map<Object, Label> labels;
-
- private static final String BASE = "class";
-
- private final RuleSet RULES = new RuleSet();
- {
- RULES.add(BASE, new ClassRule());
- RULES.add(BASE + "/interfaces/interface", new InterfaceRule());
- RULES.add(BASE + "/interfaces", new InterfacesRule());
- RULES.add(BASE + "/outerclass", new OuterClassRule());
- RULES.add(BASE + "/innerclass", new InnerClassRule());
- RULES.add(BASE + "/source", new SourceRule());
-
- ModuleRule moduleRule = new ModuleRule();
- RULES.add(BASE + "/module", moduleRule);
- RULES.add(BASE + "/module/main-class", moduleRule);
- RULES.add(BASE + "/module/target", moduleRule);
- RULES.add(BASE + "/module/packages", moduleRule);
- RULES.add(BASE + "/module/requires", moduleRule);
- RULES.add(BASE + "/module/exports", moduleRule);
- RULES.add(BASE + "/module/exports/to", moduleRule);
- RULES.add(BASE + "/module/uses", moduleRule);
- RULES.add(BASE + "/module/provides", moduleRule);
-
- RULES.add(BASE + "/field", new FieldRule());
-
- RULES.add(BASE + "/method", new MethodRule());
- RULES.add(BASE + "/method/exceptions/exception", new ExceptionRule());
- RULES.add(BASE + "/method/exceptions", new ExceptionsRule());
-
- RULES.add(BASE + "/method/parameter", new MethodParameterRule());
- RULES.add(BASE + "/method/annotationDefault",
- new AnnotationDefaultRule());
-
- RULES.add(BASE + "/method/code/*", new OpcodesRule()); // opcodes
-
- RULES.add(BASE + "/method/code/frame", new FrameRule());
- RULES.add(BASE + "/method/code/frame/local", new FrameTypeRule());
- RULES.add(BASE + "/method/code/frame/stack", new FrameTypeRule());
-
- RULES.add(BASE + "/method/code/TABLESWITCH", new TableSwitchRule());
- RULES.add(BASE + "/method/code/TABLESWITCH/label",
- new TableSwitchLabelRule());
- RULES.add(BASE + "/method/code/LOOKUPSWITCH", new LookupSwitchRule());
- RULES.add(BASE + "/method/code/LOOKUPSWITCH/label",
- new LookupSwitchLabelRule());
-
- RULES.add(BASE + "/method/code/INVOKEDYNAMIC", new InvokeDynamicRule());
- RULES.add(BASE + "/method/code/INVOKEDYNAMIC/bsmArg",
- new InvokeDynamicBsmArgumentsRule());
-
- RULES.add(BASE + "/method/code/Label", new LabelRule());
- RULES.add(BASE + "/method/code/TryCatch", new TryCatchRule());
- RULES.add(BASE + "/method/code/LineNumber", new LineNumberRule());
- RULES.add(BASE + "/method/code/LocalVar", new LocalVarRule());
- RULES.add(BASE + "/method/code/Max", new MaxRule());
-
- RULES.add("*/annotation", new AnnotationRule());
- RULES.add("*/typeAnnotation", new TypeAnnotationRule());
- RULES.add("*/parameterAnnotation", new AnnotationParameterRule());
- RULES.add("*/insnAnnotation", new InsnAnnotationRule());
- RULES.add("*/tryCatchAnnotation", new TryCatchAnnotationRule());
- RULES.add("*/localVariableAnnotation",
- new LocalVariableAnnotationRule());
- RULES.add("*/annotationValue", new AnnotationValueRule());
- RULES.add("*/annotationValueAnnotation",
- new AnnotationValueAnnotationRule());
- RULES.add("*/annotationValueEnum", new AnnotationValueEnumRule());
- RULES.add("*/annotationValueArray", new AnnotationValueArrayRule());
- }
-
- private static interface OpcodeGroup {
- public static final int INSN = 0;
- public static final int INSN_INT = 1;
- public static final int INSN_VAR = 2;
- public static final int INSN_TYPE = 3;
- public static final int INSN_FIELD = 4;
- public static final int INSN_METHOD = 5;
- public static final int INSN_JUMP = 6;
- public static final int INSN_LDC = 7;
- public static final int INSN_IINC = 8;
- public static final int INSN_MULTIANEWARRAY = 9;
- }
-
- /**
- * Map of the opcode names to opcode and opcode group
- */
- static final HashMap<String, Opcode> OPCODES = new HashMap<String, Opcode>();
- static {
- addOpcode("NOP", NOP, OpcodeGroup.INSN);
- addOpcode("ACONST_NULL", ACONST_NULL, OpcodeGroup.INSN);
- addOpcode("ICONST_M1", ICONST_M1, OpcodeGroup.INSN);
- addOpcode("ICONST_0", ICONST_0, OpcodeGroup.INSN);
- addOpcode("ICONST_1", ICONST_1, OpcodeGroup.INSN);
- addOpcode("ICONST_2", ICONST_2, OpcodeGroup.INSN);
- addOpcode("ICONST_3", ICONST_3, OpcodeGroup.INSN);
- addOpcode("ICONST_4", ICONST_4, OpcodeGroup.INSN);
- addOpcode("ICONST_5", ICONST_5, OpcodeGroup.INSN);
- addOpcode("LCONST_0", LCONST_0, OpcodeGroup.INSN);
- addOpcode("LCONST_1", LCONST_1, OpcodeGroup.INSN);
- addOpcode("FCONST_0", FCONST_0, OpcodeGroup.INSN);
- addOpcode("FCONST_1", FCONST_1, OpcodeGroup.INSN);
- addOpcode("FCONST_2", FCONST_2, OpcodeGroup.INSN);
- addOpcode("DCONST_0", DCONST_0, OpcodeGroup.INSN);
- addOpcode("DCONST_1", DCONST_1, OpcodeGroup.INSN);
- addOpcode("BIPUSH", BIPUSH, OpcodeGroup.INSN_INT);
- addOpcode("SIPUSH", SIPUSH, OpcodeGroup.INSN_INT);
- addOpcode("LDC", LDC, OpcodeGroup.INSN_LDC);
- addOpcode("ILOAD", ILOAD, OpcodeGroup.INSN_VAR);
- addOpcode("LLOAD", LLOAD, OpcodeGroup.INSN_VAR);
- addOpcode("FLOAD", FLOAD, OpcodeGroup.INSN_VAR);
- addOpcode("DLOAD", DLOAD, OpcodeGroup.INSN_VAR);
- addOpcode("ALOAD", ALOAD, OpcodeGroup.INSN_VAR);
- addOpcode("IALOAD", IALOAD, OpcodeGroup.INSN);
- addOpcode("LALOAD", LALOAD, OpcodeGroup.INSN);
- addOpcode("FALOAD", FALOAD, OpcodeGroup.INSN);
- addOpcode("DALOAD", DALOAD, OpcodeGroup.INSN);
- addOpcode("AALOAD", AALOAD, OpcodeGroup.INSN);
- addOpcode("BALOAD", BALOAD, OpcodeGroup.INSN);
- addOpcode("CALOAD", CALOAD, OpcodeGroup.INSN);
- addOpcode("SALOAD", SALOAD, OpcodeGroup.INSN);
- addOpcode("ISTORE", ISTORE, OpcodeGroup.INSN_VAR);
- addOpcode("LSTORE", LSTORE, OpcodeGroup.INSN_VAR);
- addOpcode("FSTORE", FSTORE, OpcodeGroup.INSN_VAR);
- addOpcode("DSTORE", DSTORE, OpcodeGroup.INSN_VAR);
- addOpcode("ASTORE", ASTORE, OpcodeGroup.INSN_VAR);
- addOpcode("IASTORE", IASTORE, OpcodeGroup.INSN);
- addOpcode("LASTORE", LASTORE, OpcodeGroup.INSN);
- addOpcode("FASTORE", FASTORE, OpcodeGroup.INSN);
- addOpcode("DASTORE", DASTORE, OpcodeGroup.INSN);
- addOpcode("AASTORE", AASTORE, OpcodeGroup.INSN);
- addOpcode("BASTORE", BASTORE, OpcodeGroup.INSN);
- addOpcode("CASTORE", CASTORE, OpcodeGroup.INSN);
- addOpcode("SASTORE", SASTORE, OpcodeGroup.INSN);
- addOpcode("POP", POP, OpcodeGroup.INSN);
- addOpcode("POP2", POP2, OpcodeGroup.INSN);
- addOpcode("DUP", DUP, OpcodeGroup.INSN);
- addOpcode("DUP_X1", DUP_X1, OpcodeGroup.INSN);
- addOpcode("DUP_X2", DUP_X2, OpcodeGroup.INSN);
- addOpcode("DUP2", DUP2, OpcodeGroup.INSN);
- addOpcode("DUP2_X1", DUP2_X1, OpcodeGroup.INSN);
- addOpcode("DUP2_X2", DUP2_X2, OpcodeGroup.INSN);
- addOpcode("SWAP", SWAP, OpcodeGroup.INSN);
- addOpcode("IADD", IADD, OpcodeGroup.INSN);
- addOpcode("LADD", LADD, OpcodeGroup.INSN);
- addOpcode("FADD", FADD, OpcodeGroup.INSN);
- addOpcode("DADD", DADD, OpcodeGroup.INSN);
- addOpcode("ISUB", ISUB, OpcodeGroup.INSN);
- addOpcode("LSUB", LSUB, OpcodeGroup.INSN);
- addOpcode("FSUB", FSUB, OpcodeGroup.INSN);
- addOpcode("DSUB", DSUB, OpcodeGroup.INSN);
- addOpcode("IMUL", IMUL, OpcodeGroup.INSN);
- addOpcode("LMUL", LMUL, OpcodeGroup.INSN);
- addOpcode("FMUL", FMUL, OpcodeGroup.INSN);
- addOpcode("DMUL", DMUL, OpcodeGroup.INSN);
- addOpcode("IDIV", IDIV, OpcodeGroup.INSN);
- addOpcode("LDIV", LDIV, OpcodeGroup.INSN);
- addOpcode("FDIV", FDIV, OpcodeGroup.INSN);
- addOpcode("DDIV", DDIV, OpcodeGroup.INSN);
- addOpcode("IREM", IREM, OpcodeGroup.INSN);
- addOpcode("LREM", LREM, OpcodeGroup.INSN);
- addOpcode("FREM", FREM, OpcodeGroup.INSN);
- addOpcode("DREM", DREM, OpcodeGroup.INSN);
- addOpcode("INEG", INEG, OpcodeGroup.INSN);
- addOpcode("LNEG", LNEG, OpcodeGroup.INSN);
- addOpcode("FNEG", FNEG, OpcodeGroup.INSN);
- addOpcode("DNEG", DNEG, OpcodeGroup.INSN);
- addOpcode("ISHL", ISHL, OpcodeGroup.INSN);
- addOpcode("LSHL", LSHL, OpcodeGroup.INSN);
- addOpcode("ISHR", ISHR, OpcodeGroup.INSN);
- addOpcode("LSHR", LSHR, OpcodeGroup.INSN);
- addOpcode("IUSHR", IUSHR, OpcodeGroup.INSN);
- addOpcode("LUSHR", LUSHR, OpcodeGroup.INSN);
- addOpcode("IAND", IAND, OpcodeGroup.INSN);
- addOpcode("LAND", LAND, OpcodeGroup.INSN);
- addOpcode("IOR", IOR, OpcodeGroup.INSN);
- addOpcode("LOR", LOR, OpcodeGroup.INSN);
- addOpcode("IXOR", IXOR, OpcodeGroup.INSN);
- addOpcode("LXOR", LXOR, OpcodeGroup.INSN);
- addOpcode("IINC", IINC, OpcodeGroup.INSN_IINC);
- addOpcode("I2L", I2L, OpcodeGroup.INSN);
- addOpcode("I2F", I2F, OpcodeGroup.INSN);
- addOpcode("I2D", I2D, OpcodeGroup.INSN);
- addOpcode("L2I", L2I, OpcodeGroup.INSN);
- addOpcode("L2F", L2F, OpcodeGroup.INSN);
- addOpcode("L2D", L2D, OpcodeGroup.INSN);
- addOpcode("F2I", F2I, OpcodeGroup.INSN);
- addOpcode("F2L", F2L, OpcodeGroup.INSN);
- addOpcode("F2D", F2D, OpcodeGroup.INSN);
- addOpcode("D2I", D2I, OpcodeGroup.INSN);
- addOpcode("D2L", D2L, OpcodeGroup.INSN);
- addOpcode("D2F", D2F, OpcodeGroup.INSN);
- addOpcode("I2B", I2B, OpcodeGroup.INSN);
- addOpcode("I2C", I2C, OpcodeGroup.INSN);
- addOpcode("I2S", I2S, OpcodeGroup.INSN);
- addOpcode("LCMP", LCMP, OpcodeGroup.INSN);
- addOpcode("FCMPL", FCMPL, OpcodeGroup.INSN);
- addOpcode("FCMPG", FCMPG, OpcodeGroup.INSN);
- addOpcode("DCMPL", DCMPL, OpcodeGroup.INSN);
- addOpcode("DCMPG", DCMPG, OpcodeGroup.INSN);
- addOpcode("IFEQ", IFEQ, OpcodeGroup.INSN_JUMP);
- addOpcode("IFNE", IFNE, OpcodeGroup.INSN_JUMP);
- addOpcode("IFLT", IFLT, OpcodeGroup.INSN_JUMP);
- addOpcode("IFGE", IFGE, OpcodeGroup.INSN_JUMP);
- addOpcode("IFGT", IFGT, OpcodeGroup.INSN_JUMP);
- addOpcode("IFLE", IFLE, OpcodeGroup.INSN_JUMP);
- addOpcode("IF_ICMPEQ", IF_ICMPEQ, OpcodeGroup.INSN_JUMP);
- addOpcode("IF_ICMPNE", IF_ICMPNE, OpcodeGroup.INSN_JUMP);
- addOpcode("IF_ICMPLT", IF_ICMPLT, OpcodeGroup.INSN_JUMP);
- addOpcode("IF_ICMPGE", IF_ICMPGE, OpcodeGroup.INSN_JUMP);
- addOpcode("IF_ICMPGT", IF_ICMPGT, OpcodeGroup.INSN_JUMP);
- addOpcode("IF_ICMPLE", IF_ICMPLE, OpcodeGroup.INSN_JUMP);
- addOpcode("IF_ACMPEQ", IF_ACMPEQ, OpcodeGroup.INSN_JUMP);
- addOpcode("IF_ACMPNE", IF_ACMPNE, OpcodeGroup.INSN_JUMP);
- addOpcode("GOTO", GOTO, OpcodeGroup.INSN_JUMP);
- addOpcode("JSR", JSR, OpcodeGroup.INSN_JUMP);
- addOpcode("RET", RET, OpcodeGroup.INSN_VAR);
- addOpcode("IRETURN", IRETURN, OpcodeGroup.INSN);
- addOpcode("LRETURN", LRETURN, OpcodeGroup.INSN);
- addOpcode("FRETURN", FRETURN, OpcodeGroup.INSN);
- addOpcode("DRETURN", DRETURN, OpcodeGroup.INSN);
- addOpcode("ARETURN", ARETURN, OpcodeGroup.INSN);
- addOpcode("RETURN", RETURN, OpcodeGroup.INSN);
- addOpcode("GETSTATIC", GETSTATIC, OpcodeGroup.INSN_FIELD);
- addOpcode("PUTSTATIC", PUTSTATIC, OpcodeGroup.INSN_FIELD);
- addOpcode("GETFIELD", GETFIELD, OpcodeGroup.INSN_FIELD);
- addOpcode("PUTFIELD", PUTFIELD, OpcodeGroup.INSN_FIELD);
- addOpcode("INVOKEVIRTUAL", INVOKEVIRTUAL, OpcodeGroup.INSN_METHOD);
- addOpcode("INVOKESPECIAL", INVOKESPECIAL, OpcodeGroup.INSN_METHOD);
- addOpcode("INVOKESTATIC", INVOKESTATIC, OpcodeGroup.INSN_METHOD);
- addOpcode("INVOKEINTERFACE", INVOKEINTERFACE, OpcodeGroup.INSN_METHOD);
- addOpcode("NEW", NEW, OpcodeGroup.INSN_TYPE);
- addOpcode("NEWARRAY", NEWARRAY, OpcodeGroup.INSN_INT);
- addOpcode("ANEWARRAY", ANEWARRAY, OpcodeGroup.INSN_TYPE);
- addOpcode("ARRAYLENGTH", ARRAYLENGTH, OpcodeGroup.INSN);
- addOpcode("ATHROW", ATHROW, OpcodeGroup.INSN);
- addOpcode("CHECKCAST", CHECKCAST, OpcodeGroup.INSN_TYPE);
- addOpcode("INSTANCEOF", INSTANCEOF, OpcodeGroup.INSN_TYPE);
- addOpcode("MONITORENTER", MONITORENTER, OpcodeGroup.INSN);
- addOpcode("MONITOREXIT", MONITOREXIT, OpcodeGroup.INSN);
- addOpcode("MULTIANEWARRAY", MULTIANEWARRAY,
- OpcodeGroup.INSN_MULTIANEWARRAY);
- addOpcode("IFNULL", IFNULL, OpcodeGroup.INSN_JUMP);
- addOpcode("IFNONNULL", IFNONNULL, OpcodeGroup.INSN_JUMP);
- }
-
- private static void addOpcode(String operStr, int oper, int group) {
- OPCODES.put(operStr, new Opcode(oper, group));
- }
-
- static final HashMap<String, Integer> TYPES = new HashMap<String, Integer>();
- static {
- String[] types = SAXCodeAdapter.TYPES;
- for (int i = 0; i < types.length; i++) {
- TYPES.put(types[i], i);
- }
- }
-
- /**
- * Constructs a new {@link ASMContentHandler ASMContentHandler} object.
- *
- * @param cv
- * class visitor that will be called to reconstruct the classfile
- * using the XML stream.
- */
- public ASMContentHandler(final ClassVisitor cv) {
- this.cv = cv;
- }
-
- /**
- * Process notification of the start of an XML element being reached.
- *
- * @param ns
- * - The Namespace URI, or the empty string if the element has no
- * Namespace URI or if Namespace processing is not being
- * performed.
- * @param lName
- * - The local name (without prefix), or the empty string if
- * Namespace processing is not being performed.
- * @param qName
- * - The qualified name (with prefix), or the empty string if
- * qualified names are not available.
- * @param list
- * - The attributes attached to the element. If there are no
- * attributes, it shall be an empty Attributes object.
- * @exception SAXException
- * if a parsing error is to be reported
- */
- @Override
- public final void startElement(final String ns, final String lName,
- final String qName, final Attributes list) throws SAXException {
- // the actual element name is either in lName or qName, depending
- // on whether the parser is namespace aware
- String name = lName == null || lName.length() == 0 ? qName : lName;
-
- // Compute the current matching rule
- StringBuilder sb = new StringBuilder(match);
- if (match.length() > 0) {
- sb.append('/');
- }
- sb.append(name);
- match = sb.toString();
-
- // Fire "begin" events for all relevant rules
- Rule r = (Rule) RULES.match(match);
- if (r != null) {
- r.begin(name, list);
- }
- }
-
- /**
- * Process notification of the end of an XML element being reached.
- *
- * @param ns
- * - The Namespace URI, or the empty string if the element has no
- * Namespace URI or if Namespace processing is not being
- * performed.
- * @param lName
- * - The local name (without prefix), or the empty string if
- * Namespace processing is not being performed.
- * @param qName
- * - The qualified XML 1.0 name (with prefix), or the empty
- * string if qualified names are not available.
- *
- * @exception SAXException
- * if a parsing error is to be reported
- */
- @Override
- public final void endElement(final String ns, final String lName,
- final String qName) throws SAXException {
- // the actual element name is either in lName or qName, depending
- // on whether the parser is namespace aware
- String name = lName == null || lName.length() == 0 ? qName : lName;
-
- // Fire "end" events for all relevant rules in reverse order
- Rule r = (Rule) RULES.match(match);
- if (r != null) {
- r.end(name);
- }
-
- // Recover the previous match expression
- int slash = match.lastIndexOf('/');
- if (slash >= 0) {
- match = match.substring(0, slash);
- } else {
- match = "";
- }
- }
-
- /**
- * Return the top object on the stack without removing it. If there are no
- * objects on the stack, return <code>null</code>.
- *
- * @return the top object on the stack without removing it.
- */
- final Object peek() {
- int size = stack.size();
- return size == 0 ? null : stack.get(size - 1);
- }
-
- /**
- * Pop the top object off of the stack, and return it. If there are no
- * objects on the stack, return <code>null</code>.
- *
- * @return the top object off of the stack.
- */
- final Object pop() {
- int size = stack.size();
- return size == 0 ? null : stack.remove(size - 1);
- }
-
- /**
- * Push a new object onto the top of the object stack.
- *
- * @param object
- * The new object
- */
- final void push(final Object object) {
- stack.add(object);
- }
-
- static final class RuleSet {
-
- private final HashMap<String, Object> rules = new HashMap<String, Object>();
-
- private final ArrayList<String> lpatterns = new ArrayList<String>();
-
- private final ArrayList<String> rpatterns = new ArrayList<String>();
-
- public void add(final String path, final Object rule) {
- String pattern = path;
- if (path.startsWith("*/")) {
- pattern = path.substring(1);
- lpatterns.add(pattern);
- } else if (path.endsWith("/*")) {
- pattern = path.substring(0, path.length() - 1);
- rpatterns.add(pattern);
- }
- rules.put(pattern, rule);
- }
-
- public Object match(final String path) {
- if (rules.containsKey(path)) {
- return rules.get(path);
- }
-
- int n = path.lastIndexOf('/');
- for (Iterator<String> it = lpatterns.iterator(); it.hasNext();) {
- String pattern = it.next();
- if (path.substring(n).endsWith(pattern)) {
- return rules.get(pattern);
- }
- }
-
- for (Iterator<String> it = rpatterns.iterator(); it.hasNext();) {
- String pattern = it.next();
- if (path.startsWith(pattern)) {
- return rules.get(pattern);
- }
- }
-
- return null;
- }
- }
-
- /**
- * Rule
- */
- protected abstract class Rule {
-
- public void begin(final String name, final Attributes attrs)
- throws SAXException {
- }
-
- public void end(final String name) {
- }
-
- protected final Object getValue(final String desc, final String val)
- throws SAXException {
- Object value = null;
- if (val != null) {
- if ("Ljava/lang/String;".equals(desc)) {
- value = decode(val);
- } else if ("Ljava/lang/Integer;".equals(desc)
- || "I".equals(desc) || "S".equals(desc)
- || "B".equals(desc) || "C".equals(desc)
- || "Z".equals(desc)) {
- value = new Integer(val);
-
- } else if ("Ljava/lang/Short;".equals(desc)) {
- value = new Short(val);
-
- } else if ("Ljava/lang/Byte;".equals(desc)) {
- value = new Byte(val);
-
- } else if ("Ljava/lang/Character;".equals(desc)) {
- value = new Character(decode(val).charAt(0));
-
- } else if ("Ljava/lang/Boolean;".equals(desc)) {
- value = Boolean.valueOf(val);
-
- } else if ("Ljava/lang/Long;".equals(desc) || "J".equals(desc)) {
- value = new Long(val);
- } else if ("Ljava/lang/Float;".equals(desc) || "F".equals(desc)) {
- value = new Float(val);
- } else if ("Ljava/lang/Double;".equals(desc)
- || "D".equals(desc)) {
- value = new Double(val);
- } else if (Type.getDescriptor(Type.class).equals(desc)) {
- value = Type.getType(val);
-
- } else if (Type.getDescriptor(Handle.class).equals(desc)) {
- value = decodeHandle(val);
-
- } else {
- // TODO use of default toString().
- throw new SAXException("Invalid value:" + val + " desc:"
- + desc + " ctx:" + this);
- }
- }
- return value;
- }
-
- Handle decodeHandle(final String val) throws SAXException {
- try {
- int dotIndex = val.indexOf('.');
- int descIndex = val.indexOf('(', dotIndex + 1);
- int tagIndex = val.lastIndexOf('(');
- int itfIndex = val.indexOf(' ', tagIndex + 1);
-
- boolean itf = itfIndex != -1;
- int tag = Integer.parseInt(
- val.substring(tagIndex + 1,
- itf? val.length() - 1: itfIndex));
- String owner = val.substring(0, dotIndex);
- String name = val.substring(dotIndex + 1, descIndex);
- String desc = val.substring(descIndex, tagIndex - 1);
- return new Handle(tag, owner, name, desc, itf);
-
- } catch (RuntimeException e) {
- throw new SAXException("Malformed handle " + val, e);
- }
- }
-
- private final String decode(final String val) throws SAXException {
- StringBuilder sb = new StringBuilder(val.length());
- try {
- int n = 0;
- while (n < val.length()) {
- char c = val.charAt(n);
- if (c == '\\') {
- n++;
- c = val.charAt(n);
- if (c == '\\') {
- sb.append('\\');
- } else {
- n++; // skip 'u'
- sb.append((char) Integer.parseInt(
- val.substring(n, n + 4), 16));
- n += 3;
- }
- } else {
- sb.append(c);
- }
- n++;
- }
-
- } catch (RuntimeException ex) {
- throw new SAXException(ex);
- }
- return sb.toString();
- }
-
- protected final Label getLabel(final Object label) {
- Label lbl = labels.get(label);
- if (lbl == null) {
- lbl = new Label();
- labels.put(label, lbl);
- }
- return lbl;
- }
-
- // TODO verify move to stack
- protected final MethodVisitor getCodeVisitor() {
- return (MethodVisitor) peek();
- }
-
- protected final int getAccess(final String s) {
- int access = 0;
- if (s.indexOf("public") != -1) {
- access |= ACC_PUBLIC;
- }
- if (s.indexOf("private") != -1) {
- access |= ACC_PRIVATE;
- }
- if (s.indexOf("protected") != -1) {
- access |= ACC_PROTECTED;
- }
- if (s.indexOf("static") != -1) {
- access |= ACC_STATIC;
- }
- if (s.indexOf("final") != -1) {
- access |= ACC_FINAL;
- }
- if (s.indexOf("super") != -1) {
- access |= ACC_SUPER;
- }
- if (s.indexOf("synchronized") != -1) {
- access |= ACC_SYNCHRONIZED;
- }
- if (s.indexOf("volatile") != -1) {
- access |= ACC_VOLATILE;
- }
- if (s.indexOf("bridge") != -1) {
- access |= ACC_BRIDGE;
- }
- if (s.indexOf("varargs") != -1) {
- access |= ACC_VARARGS;
- }
- if (s.indexOf("transient") != -1) {
- access |= ACC_TRANSIENT;
- }
- if (s.indexOf("native") != -1) {
- access |= ACC_NATIVE;
- }
- if (s.indexOf("interface") != -1) {
- access |= ACC_INTERFACE;
- }
- if (s.indexOf("abstract") != -1) {
- access |= ACC_ABSTRACT;
- }
- if (s.indexOf("strict") != -1) {
- access |= ACC_STRICT;
- }
- if (s.indexOf("synthetic") != -1) {
- access |= ACC_SYNTHETIC;
- }
- if (s.indexOf("annotation") != -1) {
- access |= ACC_ANNOTATION;
- }
- if (s.indexOf("enum") != -1) {
- access |= ACC_ENUM;
- }
- if (s.indexOf("deprecated") != -1) {
- access |= ACC_DEPRECATED;
- }
- if (s.indexOf("mandated") != -1) {
- access |= ACC_MANDATED;
- }
- if (s.indexOf("module") != -1) {
- access |= ACC_MODULE;
- }
- if (s.indexOf("open") != -1) {
- access |= ACC_OPEN;
- }
- if (s.indexOf("transitive") != -1) {
- access |= ACC_TRANSITIVE;
- }
- return access;
- }
- }
-
- /**
- * ClassRule
- */
- final class ClassRule extends Rule {
-
- @Override
- public final void begin(final String name, final Attributes attrs) {
- int major = Integer.parseInt(attrs.getValue("major"));
- int minor = Integer.parseInt(attrs.getValue("minor"));
- HashMap<String, Object> vals = new HashMap<String, Object>();
- vals.put("version", minor << 16 | major);
- vals.put("access", attrs.getValue("access"));
- vals.put("name", attrs.getValue("name"));
- vals.put("parent", attrs.getValue("parent"));
- vals.put("source", attrs.getValue("source"));
- vals.put("signature", attrs.getValue("signature"));
- vals.put("interfaces", new ArrayList<String>());
- push(vals);
- // values will be extracted in InterfacesRule.end();
- }
- }
-
- final class SourceRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- String file = attrs.getValue("file");
- String debug = attrs.getValue("debug");
- cv.visitSource(file, debug);
- }
- }
-
- /**
- * InterfaceRule
- */
- final class InterfaceRule extends Rule {
-
- @Override
- @SuppressWarnings("unchecked")
- public final void begin(final String name, final Attributes attrs) {
- ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("interfaces"))
- .add(attrs.getValue("name"));
- }
- }
-
- /**
- * InterfacesRule
- */
- final class InterfacesRule extends Rule {
-
- @Override
- public final void end(final String element) {
- HashMap<?, ?> vals = (HashMap<?, ?>) pop();
- int version = ((Integer) vals.get("version")).intValue();
- int access = getAccess((String) vals.get("access"));
- String name = (String) vals.get("name");
- String signature = (String) vals.get("signature");
- String parent = (String) vals.get("parent");
- ArrayList<?> infs = (ArrayList<?>) vals.get("interfaces");
- String[] interfaces = infs.toArray(new String[infs.size()]);
- cv.visit(version, access, name, signature, parent, interfaces);
- push(cv);
- }
- }
-
- /**
- * ModuleRule: module, requires, exports, opens, uses and provides
- */
- final class ModuleRule extends Rule {
- @Override
- public final void begin(final String element, final Attributes attrs)
- throws SAXException {
- if ("module".equals(element)) {
- push(cv.visitModule(attrs.getValue("name"),
- getAccess(attrs.getValue("access")),
- attrs.getValue("version")));
- } else if ("main-class".equals(element)) {
- ModuleVisitor mv = (ModuleVisitor) peek();
- mv.visitMainClass(attrs.getValue("name"));
- } else if ("packages".equals(element)) {
- ModuleVisitor mv = (ModuleVisitor) peek();
- mv.visitPackage(attrs.getValue("name"));
- } else if ("requires".equals(element)) {
- ModuleVisitor mv = (ModuleVisitor) peek();
- int access = getAccess(attrs.getValue("access"));
- if ((access & Opcodes.ACC_STATIC) != 0) {
- access = access & ~Opcodes.ACC_STATIC | Opcodes.ACC_STATIC_PHASE;
- }
- mv.visitRequire(attrs.getValue("module"),
- access, attrs.getValue("version"));
- } else if ("exports".equals(element)) {
- push(attrs.getValue("name"));
- push(getAccess(attrs.getValue("access")));
- ArrayList<String> list = new ArrayList<String>();
- push(list);
- } else if ("opens".equals(element)) {
- push(attrs.getValue("name"));
- push(getAccess(attrs.getValue("access")));
- ArrayList<String> list = new ArrayList<String>();
- push(list);
- } else if ("to".equals(element)) {
- @SuppressWarnings("unchecked")
- ArrayList<String> list = (ArrayList<String>) peek();
- list.add(attrs.getValue("module"));
- } else if ("uses".equals(element)) {
- ModuleVisitor mv = (ModuleVisitor) peek();
- mv.visitUse(attrs.getValue("service"));
- } else if ("provides".equals(element)) {
- push(attrs.getValue("service"));
- push(0); // see end() below
- ArrayList<String> list = new ArrayList<String>();
- push(list);
- } else if ("with".equals(element)) {
- @SuppressWarnings("unchecked")
- ArrayList<String> list = (ArrayList<String>) peek();
- list.add(attrs.getValue("provider"));
- }
- }
-
- @Override
- public void end(final String element) {
- boolean exports = "exports".equals(element);
- boolean opens = "opens".equals(element);
- boolean provides = "provides".equals(element);
- if (exports | opens | provides) {
- @SuppressWarnings("unchecked")
- ArrayList<String> list = (ArrayList<String>) pop();
- int access = (Integer) pop();
- String name = (String) pop();
- String[] tos = null;
- if (!list.isEmpty()) {
- tos = list.toArray(new String[list.size()]);
- }
- ModuleVisitor mv = (ModuleVisitor) peek();
- if (exports) {
- mv.visitExport(name, access, tos);
- } else {
- if (opens) {
- mv.visitOpen(name, access, tos);
- } else {
- mv.visitProvide(name, tos);
- }
- }
- } else if ("module".equals(element)) {
- ((ModuleVisitor) pop()).visitEnd();
- }
- }
- }
-
- /**
- * OuterClassRule
- */
- final class OuterClassRule extends Rule {
-
- @Override
- public final void begin(final String element, final Attributes attrs) {
- String owner = attrs.getValue("owner");
- String name = attrs.getValue("name");
- String desc = attrs.getValue("desc");
- cv.visitOuterClass(owner, name, desc);
- }
- }
-
- /**
- * InnerClassRule
- */
- final class InnerClassRule extends Rule {
-
- @Override
- public final void begin(final String element, final Attributes attrs) {
- int access = getAccess(attrs.getValue("access"));
- String name = attrs.getValue("name");
- String outerName = attrs.getValue("outerName");
- String innerName = attrs.getValue("innerName");
- cv.visitInnerClass(name, outerName, innerName, access);
- }
- }
-
- /**
- * FieldRule
- */
- final class FieldRule extends Rule {
-
- @Override
- public final void begin(final String element, final Attributes attrs)
- throws SAXException {
- int access = getAccess(attrs.getValue("access"));
- String name = attrs.getValue("name");
- String signature = attrs.getValue("signature");
- String desc = attrs.getValue("desc");
- Object value = getValue(desc, attrs.getValue("value"));
- push(cv.visitField(access, name, desc, signature, value));
- }
-
- @Override
- public void end(final String name) {
- ((FieldVisitor) pop()).visitEnd();
- }
- }
-
- /**
- * MethodRule
- */
- final class MethodRule extends Rule {
-
- @Override
- public final void begin(final String name, final Attributes attrs) {
- labels = new HashMap<Object, Label>();
- HashMap<String, Object> vals = new HashMap<String, Object>();
- vals.put("access", attrs.getValue("access"));
- vals.put("name", attrs.getValue("name"));
- vals.put("desc", attrs.getValue("desc"));
- vals.put("signature", attrs.getValue("signature"));
- vals.put("exceptions", new ArrayList<String>());
- push(vals);
- // values will be extracted in ExceptionsRule.end();
- }
-
- @Override
- public final void end(final String name) {
- ((MethodVisitor) pop()).visitEnd();
- labels = null;
- }
- }
-
- /**
- * ExceptionRule
- */
- final class ExceptionRule extends Rule {
-
- @Override
- @SuppressWarnings("unchecked")
- public final void begin(final String name, final Attributes attrs) {
- ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("exceptions"))
- .add(attrs.getValue("name"));
- }
- }
-
- /**
- * ExceptionsRule
- */
- final class ExceptionsRule extends Rule {
-
- @Override
- public final void end(final String element) {
- HashMap<?, ?> vals = (HashMap<?, ?>) pop();
- int access = getAccess((String) vals.get("access"));
- String name = (String) vals.get("name");
- String desc = (String) vals.get("desc");
- String signature = (String) vals.get("signature");
- ArrayList<?> excs = (ArrayList<?>) vals.get("exceptions");
- String[] exceptions = excs.toArray(new String[excs.size()]);
-
- push(cv.visitMethod(access, name, desc, signature, exceptions));
- }
- }
-
- /**
- * MethodParameterRule
- */
- final class MethodParameterRule extends Rule {
- @Override
- public void begin(final String nm, final Attributes attrs) {
- String name = attrs.getValue("name");
- int access = getAccess(attrs.getValue("access"));
- getCodeVisitor().visitParameter(name, access);
- }
- }
-
- /**
- * TableSwitchRule
- */
- final class TableSwitchRule extends Rule {
-
- @Override
- public final void begin(final String name, final Attributes attrs) {
- HashMap<String, Object> vals = new HashMap<String, Object>();
- vals.put("min", attrs.getValue("min"));
- vals.put("max", attrs.getValue("max"));
- vals.put("dflt", attrs.getValue("dflt"));
- vals.put("labels", new ArrayList<String>());
- push(vals);
- }
-
- @Override
- public final void end(final String name) {
- HashMap<?, ?> vals = (HashMap<?, ?>) pop();
- int min = Integer.parseInt((String) vals.get("min"));
- int max = Integer.parseInt((String) vals.get("max"));
- Label dflt = getLabel(vals.get("dflt"));
- ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
- Label[] labels = lbls.toArray(new Label[lbls.size()]);
- getCodeVisitor().visitTableSwitchInsn(min, max, dflt, labels);
- }
- }
-
- /**
- * TableSwitchLabelRule
- */
- final class TableSwitchLabelRule extends Rule {
-
- @Override
- @SuppressWarnings("unchecked")
- public final void begin(final String name, final Attributes attrs) {
- ((ArrayList<Label>) ((HashMap<?, ?>) peek()).get("labels"))
- .add(getLabel(attrs.getValue("name")));
- }
- }
-
- /**
- * LookupSwitchRule
- */
- final class LookupSwitchRule extends Rule {
-
- @Override
- public final void begin(final String name, final Attributes attrs) {
- HashMap<String, Object> vals = new HashMap<String, Object>();
- vals.put("dflt", attrs.getValue("dflt"));
- vals.put("labels", new ArrayList<Label>());
- vals.put("keys", new ArrayList<String>());
- push(vals);
- }
-
- @Override
- public final void end(final String name) {
- HashMap<?, ?> vals = (HashMap<?, ?>) pop();
- Label dflt = getLabel(vals.get("dflt"));
- @SuppressWarnings("unchecked")
- ArrayList<String> keyList = (ArrayList<String>) vals.get("keys");
- ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
- Label[] labels = lbls.toArray(new Label[lbls.size()]);
- int[] keys = new int[keyList.size()];
- for (int i = 0; i < keys.length; i++) {
- keys[i] = Integer.parseInt(keyList.get(i));
- }
- getCodeVisitor().visitLookupSwitchInsn(dflt, keys, labels);
- }
- }
-
- /**
- * LookupSwitchLabelRule
- */
- final class LookupSwitchLabelRule extends Rule {
-
- @Override
- @SuppressWarnings("unchecked")
- public final void begin(final String name, final Attributes attrs) {
- HashMap<?, ?> vals = (HashMap<?, ?>) peek();
- ((ArrayList<Label>) vals.get("labels")).add(getLabel(attrs
- .getValue("name")));
- ((ArrayList<String>) vals.get("keys")).add(attrs.getValue("key"));
- }
- }
-
- /**
- * FrameRule
- */
- final class FrameRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- HashMap<String, Object> typeLists = new HashMap<String, Object>();
- typeLists.put("local", new ArrayList<Object>());
- typeLists.put("stack", new ArrayList<Object>());
- push(attrs.getValue("type"));
- push(attrs.getValue("count") == null ? "0" : attrs
- .getValue("count"));
- push(typeLists);
- }
-
- @Override
- public void end(final String name) {
- HashMap<?, ?> typeLists = (HashMap<?, ?>) pop();
- ArrayList<?> locals = (ArrayList<?>) typeLists.get("local");
- int nLocal = locals.size();
- Object[] local = locals.toArray();
- ArrayList<?> stacks = (ArrayList<?>) typeLists.get("stack");
- int nStack = stacks.size();
- Object[] stack = stacks.toArray();
- String count = (String) pop();
- String type = (String) pop();
- if ("NEW".equals(type)) {
- getCodeVisitor()
- .visitFrame(F_NEW, nLocal, local, nStack, stack);
- } else if ("FULL".equals(type)) {
- getCodeVisitor().visitFrame(F_FULL, nLocal, local, nStack,
- stack);
- } else if ("APPEND".equals(type)) {
- getCodeVisitor().visitFrame(F_APPEND, nLocal, local, 0, null);
- } else if ("CHOP".equals(type)) {
- getCodeVisitor().visitFrame(F_CHOP, Integer.parseInt(count),
- null, 0, null);
- } else if ("SAME".equals(type)) {
- getCodeVisitor().visitFrame(F_SAME, 0, null, 0, null);
- } else if ("SAME1".equals(type)) {
- getCodeVisitor().visitFrame(F_SAME1, 0, null, nStack, stack);
- }
- }
- }
-
- final class FrameTypeRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- @SuppressWarnings("unchecked")
- ArrayList<Object> types = (ArrayList<Object>) ((HashMap<?, ?>) peek())
- .get(name);
- String type = attrs.getValue("type");
- if ("uninitialized".equals(type)) {
- types.add(getLabel(attrs.getValue("label")));
- } else {
- Integer t = TYPES.get(type);
- if (t == null) {
- types.add(type);
- } else {
- types.add(t);
- }
- }
- }
- }
-
- /**
- * LabelRule
- */
- final class LabelRule extends Rule {
-
- @Override
- public final void begin(final String name, final Attributes attrs) {
- getCodeVisitor().visitLabel(getLabel(attrs.getValue("name")));
- }
- }
-
- /**
- * TryCatchRule
- */
- final class TryCatchRule extends Rule {
-
- @Override
- public final void begin(final String name, final Attributes attrs) {
- Label start = getLabel(attrs.getValue("start"));
- Label end = getLabel(attrs.getValue("end"));
- Label handler = getLabel(attrs.getValue("handler"));
- String type = attrs.getValue("type");
- getCodeVisitor().visitTryCatchBlock(start, end, handler, type);
- }
- }
-
- /**
- * LineNumberRule
- */
- final class LineNumberRule extends Rule {
-
- @Override
- public final void begin(final String name, final Attributes attrs) {
- int line = Integer.parseInt(attrs.getValue("line"));
- Label start = getLabel(attrs.getValue("start"));
- getCodeVisitor().visitLineNumber(line, start);
- }
- }
-
- /**
- * LocalVarRule
- */
- final class LocalVarRule extends Rule {
-
- @Override
- public final void begin(final String element, final Attributes attrs) {
- String name = attrs.getValue("name");
- String desc = attrs.getValue("desc");
- String signature = attrs.getValue("signature");
- Label start = getLabel(attrs.getValue("start"));
- Label end = getLabel(attrs.getValue("end"));
- int var = Integer.parseInt(attrs.getValue("var"));
- getCodeVisitor().visitLocalVariable(name, desc, signature, start,
- end, var);
- }
- }
-
- /**
- * InvokeDynamicRule
- */
- final class InvokeDynamicRule extends Rule {
- @Override
- public final void begin(final String element, final Attributes attrs)
- throws SAXException {
- push(attrs.getValue("name"));
- push(attrs.getValue("desc"));
- push(decodeHandle(attrs.getValue("bsm")));
- push(new ArrayList<Object>());
- }
-
- @Override
- public final void end(final String element) {
- ArrayList<?> bsmArgs = (ArrayList<?>) pop();
- Handle bsm = (Handle) pop();
- String desc = (String) pop();
- String name = (String) pop();
- getCodeVisitor().visitInvokeDynamicInsn(name, desc, bsm,
- bsmArgs.toArray());
- }
- }
-
- /**
- * InvokeDynamicBsmArgumentsRule
- */
- final class InvokeDynamicBsmArgumentsRule extends Rule {
- @Override
- public final void begin(final String element, final Attributes attrs)
- throws SAXException {
- @SuppressWarnings("unchecked")
- ArrayList<Object> bsmArgs = (ArrayList<Object>) peek();
- bsmArgs.add(getValue(attrs.getValue("desc"), attrs.getValue("cst")));
- }
- }
-
- /**
- * OpcodesRule
- */
- final class OpcodesRule extends Rule {
-
- // public boolean match( String match, String element) {
- // return match.startsWith( path) && OPCODES.containsKey( element);
- // }
-
- @Override
- public final void begin(final String element, final Attributes attrs)
- throws SAXException {
- Opcode o = OPCODES.get(element);
- if (o == null) {
- throw new SAXException("Invalid element: " + element + " at "
- + match);
- }
-
- switch (o.type) {
- case OpcodeGroup.INSN:
- getCodeVisitor().visitInsn(o.opcode);
- break;
-
- case OpcodeGroup.INSN_FIELD:
- getCodeVisitor().visitFieldInsn(o.opcode,
- attrs.getValue("owner"), attrs.getValue("name"),
- attrs.getValue("desc"));
- break;
-
- case OpcodeGroup.INSN_INT:
- getCodeVisitor().visitIntInsn(o.opcode,
- Integer.parseInt(attrs.getValue("value")));
- break;
-
- case OpcodeGroup.INSN_JUMP:
- getCodeVisitor().visitJumpInsn(o.opcode,
- getLabel(attrs.getValue("label")));
- break;
-
- case OpcodeGroup.INSN_METHOD:
- getCodeVisitor().visitMethodInsn(o.opcode,
- attrs.getValue("owner"), attrs.getValue("name"),
- attrs.getValue("desc"),
- attrs.getValue("itf").equals("true"));
- break;
-
- case OpcodeGroup.INSN_TYPE:
- getCodeVisitor()
- .visitTypeInsn(o.opcode, attrs.getValue("desc"));
- break;
-
- case OpcodeGroup.INSN_VAR:
- getCodeVisitor().visitVarInsn(o.opcode,
- Integer.parseInt(attrs.getValue("var")));
- break;
-
- case OpcodeGroup.INSN_IINC:
- getCodeVisitor().visitIincInsn(
- Integer.parseInt(attrs.getValue("var")),
- Integer.parseInt(attrs.getValue("inc")));
- break;
-
- case OpcodeGroup.INSN_LDC:
- getCodeVisitor()
- .visitLdcInsn(
- getValue(attrs.getValue("desc"),
- attrs.getValue("cst")));
- break;
-
- case OpcodeGroup.INSN_MULTIANEWARRAY:
- getCodeVisitor().visitMultiANewArrayInsn(
- attrs.getValue("desc"),
- Integer.parseInt(attrs.getValue("dims")));
- break;
-
- default:
- throw new Error("Internal error");
-
- }
- }
- }
-
- /**
- * MaxRule
- */
- final class MaxRule extends Rule {
-
- @Override
- public final void begin(final String element, final Attributes attrs) {
- int maxStack = Integer.parseInt(attrs.getValue("maxStack"));
- int maxLocals = Integer.parseInt(attrs.getValue("maxLocals"));
- getCodeVisitor().visitMaxs(maxStack, maxLocals);
- }
- }
-
- final class AnnotationRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- String desc = attrs.getValue("desc");
- boolean visible = Boolean.valueOf(attrs.getValue("visible"))
- .booleanValue();
-
- Object v = peek();
- if (v instanceof ClassVisitor) {
- push(((ClassVisitor) v).visitAnnotation(desc, visible));
- } else if (v instanceof FieldVisitor) {
- push(((FieldVisitor) v).visitAnnotation(desc, visible));
- } else if (v instanceof MethodVisitor) {
- push(((MethodVisitor) v).visitAnnotation(desc, visible));
- }
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- final class TypeAnnotationRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- String desc = attrs.getValue("desc");
- boolean visible = Boolean.valueOf(attrs.getValue("visible"))
- .booleanValue();
- int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
- TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
-
- Object v = peek();
- if (v instanceof ClassVisitor) {
- push(((ClassVisitor) v).visitTypeAnnotation(typeRef, typePath,
- desc, visible));
- } else if (v instanceof FieldVisitor) {
- push(((FieldVisitor) v).visitTypeAnnotation(typeRef, typePath,
- desc, visible));
- } else if (v instanceof MethodVisitor) {
- push(((MethodVisitor) v).visitTypeAnnotation(typeRef, typePath,
- desc, visible));
- }
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- final class AnnotationParameterRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- int parameter = Integer.parseInt(attrs.getValue("parameter"));
- String desc = attrs.getValue("desc");
- boolean visible = Boolean.valueOf(attrs.getValue("visible"))
- .booleanValue();
-
- push(((MethodVisitor) peek()).visitParameterAnnotation(parameter,
- desc, visible));
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- final class InsnAnnotationRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- String desc = attrs.getValue("desc");
- boolean visible = Boolean.valueOf(attrs.getValue("visible"))
- .booleanValue();
- int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
- TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
- push(((MethodVisitor) peek()).visitInsnAnnotation(typeRef,
- typePath, desc, visible));
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- final class TryCatchAnnotationRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- String desc = attrs.getValue("desc");
- boolean visible = Boolean.valueOf(attrs.getValue("visible"))
- .booleanValue();
- int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
- TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
- push(((MethodVisitor) peek()).visitTryCatchAnnotation(typeRef,
- typePath, desc, visible));
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- final class LocalVariableAnnotationRule extends Rule {
-
- @Override
- public void begin(final String name, final Attributes attrs) {
- String desc = attrs.getValue("desc");
- boolean visible = Boolean.valueOf(attrs.getValue("visible"))
- .booleanValue();
- int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
- TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
- String[] s = attrs.getValue("start").split(" ");
- Label[] start = new Label[s.length];
- for (int i = 0; i < start.length; ++i) {
- start[i] = getLabel(s[i]);
- }
- String[] e = attrs.getValue("end").split(" ");
- Label[] end = new Label[e.length];
- for (int i = 0; i < end.length; ++i) {
- end[i] = getLabel(e[i]);
- }
- String[] v = attrs.getValue("index").split(" ");
- int[] index = new int[v.length];
- for (int i = 0; i < index.length; ++i) {
- index[i] = Integer.parseInt(v[i]);
- }
- push(((MethodVisitor) peek()).visitLocalVariableAnnotation(typeRef,
- typePath, start, end, index, desc, visible));
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- final class AnnotationValueRule extends Rule {
-
- @Override
- public void begin(final String nm, final Attributes attrs)
- throws SAXException {
- AnnotationVisitor av = (AnnotationVisitor) peek();
- if (av != null) {
- av.visit(
- attrs.getValue("name"),
- getValue(attrs.getValue("desc"),
- attrs.getValue("value")));
- }
- }
- }
-
- final class AnnotationValueEnumRule extends Rule {
-
- @Override
- public void begin(final String nm, final Attributes attrs) {
- AnnotationVisitor av = (AnnotationVisitor) peek();
- if (av != null) {
- av.visitEnum(attrs.getValue("name"), attrs.getValue("desc"),
- attrs.getValue("value"));
- }
- }
- }
-
- final class AnnotationValueAnnotationRule extends Rule {
-
- @Override
- public void begin(final String nm, final Attributes attrs) {
- AnnotationVisitor av = (AnnotationVisitor) peek();
- push(av == null ? null : av.visitAnnotation(attrs.getValue("name"),
- attrs.getValue("desc")));
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- final class AnnotationValueArrayRule extends Rule {
-
- @Override
- public void begin(final String nm, final Attributes attrs) {
- AnnotationVisitor av = (AnnotationVisitor) peek();
- push(av == null ? null : av.visitArray(attrs.getValue("name")));
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- final class AnnotationDefaultRule extends Rule {
-
- @Override
- public void begin(final String nm, final Attributes attrs) {
- MethodVisitor av = (MethodVisitor) peek();
- push(av == null ? null : av.visitAnnotationDefault());
- }
-
- @Override
- public void end(final String name) {
- AnnotationVisitor av = (AnnotationVisitor) pop();
- if (av != null) {
- av.visitEnd();
- }
- }
- }
-
- /**
- * Opcode
- */
- static final class Opcode {
-
- public final int opcode;
-
- public final int type;
-
- Opcode(final int opcode, final int type) {
- this.opcode = opcode;
- this.type = type;
- }
- }
-}
[44/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
old mode 100644
new mode 100755
index 6d810e0..41b6de2
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
@@ -1,2756 +1,3603 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
- * A Java class parser to make a {@link ClassVisitor} visit an existing class.
- * This class parses a byte array conforming to the Java class file format and
- * calls the appropriate visit methods of a given class visitor for each field,
- * method and bytecode instruction encountered.
- *
+ * A parser to make a {@link ClassVisitor} visit a ClassFile structure, as defined in the Java
+ * Virtual Machine Specification (JVMS). This class parses the ClassFile content and calls the
+ * appropriate visit methods of a given {@link ClassVisitor} for each field, method and bytecode
+ * instruction encountered.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a>
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
public class ClassReader {
- /**
- * Flag to skip method code. If this class is set <code>CODE</code>
- * attribute won't be visited. This can be used, for example, to retrieve
- * annotations for methods and method parameters.
- */
- public static final int SKIP_CODE = 1;
-
- /**
- * Flag to skip the debug information in the class. If this flag is set the
- * debug information of the class is not visited, i.e. the
- * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
- * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
- * called.
- */
- public static final int SKIP_DEBUG = 2;
-
- /**
- * Flag to skip the stack map frames in the class. If this flag is set the
- * stack map frames of the class is not visited, i.e. the
- * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
- * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
- * used: it avoids visiting frames that will be ignored and recomputed from
- * scratch in the class writer.
- */
- public static final int SKIP_FRAMES = 4;
-
- /**
- * Flag to expand the stack map frames. By default stack map frames are
- * visited in their original format (i.e. "expanded" for classes whose
- * version is less than V1_6, and "compressed" for the other classes). If
- * this flag is set, stack map frames are always visited in expanded format
- * (this option adds a decompression/recompression step in ClassReader and
- * ClassWriter which degrades performances quite a lot).
- */
- public static final int EXPAND_FRAMES = 8;
-
- /**
- * Flag to expand the ASM pseudo instructions into an equivalent sequence of
- * standard bytecode instructions. When resolving a forward jump it may
- * happen that the signed 2 bytes offset reserved for it is not sufficient
- * to store the bytecode offset. In this case the jump instruction is
- * replaced with a temporary ASM pseudo instruction using an unsigned 2
- * bytes offset (see Label#resolve). This internal flag is used to re-read
- * classes containing such instructions, in order to replace them with
- * standard instructions. In addition, when this flag is used, GOTO_W and
- * JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
- * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
- * converted back to a GOTO_W in ClassWriter cannot occur.
- */
- static final int EXPAND_ASM_INSNS = 256;
-
- /**
- * The class to be parsed. <i>The content of this array must not be
- * modified. This field is intended for {@link Attribute} sub classes, and
- * is normally not needed by class generators or adapters.</i>
- */
- public final byte[] b;
-
- /**
- * The start index of each constant pool item in {@link #b b}, plus one. The
- * one byte offset skips the constant pool item tag that indicates its type.
- */
- private final int[] items;
-
- /**
- * The String objects corresponding to the CONSTANT_Utf8 items. This cache
- * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
- * which GREATLY improves performances (by a factor 2 to 3). This caching
- * strategy could be extended to all constant pool items, but its benefit
- * would not be so great for these items (because they are much less
- * expensive to parse than CONSTANT_Utf8 items).
- */
- private final String[] strings;
-
- /**
- * Maximum length of the strings contained in the constant pool of the
- * class.
- */
- private final int maxStringLength;
-
- /**
- * Start index of the class header information (access, name...) in
- * {@link #b b}.
- */
- public final int header;
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param b
- * the bytecode of the class to be read.
- */
- public ClassReader(final byte[] b) {
- this(b, 0, b.length);
- }
-
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param b
- * the bytecode of the class to be read.
- * @param off
- * the start offset of the class data.
- * @param len
- * the length of the class data.
- */
- public ClassReader(final byte[] b, final int off, final int len) {
- this.b = b;
- // checks the class version
- if (readShort(off + 6) > Opcodes.V9) {
- throw new IllegalArgumentException();
- }
- // parses the constant pool
- items = new int[readUnsignedShort(off + 8)];
- int n = items.length;
- strings = new String[n];
- int max = 0;
- int index = off + 10;
- for (int i = 1; i < n; ++i) {
- items[i] = index + 1;
- int size;
- switch (b[index]) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- case ClassWriter.NAME_TYPE:
- case ClassWriter.INDY:
- size = 5;
- break;
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- size = 9;
- ++i;
- break;
- case ClassWriter.UTF8:
- size = 3 + readUnsignedShort(index + 1);
- if (size > max) {
- max = size;
- }
- break;
- case ClassWriter.HANDLE:
- size = 4;
- break;
- // case ClassWriter.CLASS:
- // case ClassWriter.STR:
- // case ClassWriter.MTYPE
- // case ClassWriter.PACKAGE:
- // case ClassWriter.MODULE:
- default:
- size = 3;
- break;
- }
- index += size;
- }
- maxStringLength = max;
- // the class header information starts just after the constant pool
- header = index;
- }
-
- /**
- * Returns the class's access flags (see {@link Opcodes}). This value may
- * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
- * and those flags are represented by attributes.
- *
- * @return the class access flags
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public int getAccess() {
- return readUnsignedShort(header);
- }
-
- /**
- * Returns the internal name of the class (see
- * {@link Type#getInternalName() getInternalName}).
- *
- * @return the internal class name
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String getClassName() {
- return readClass(header + 2, new char[maxStringLength]);
- }
-
- /**
- * Returns the internal of name of the super class (see
- * {@link Type#getInternalName() getInternalName}). For interfaces, the
- * super class is {@link Object}.
- *
- * @return the internal name of super class, or <tt>null</tt> for
- * {@link Object} class.
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String getSuperName() {
- return readClass(header + 4, new char[maxStringLength]);
- }
-
- /**
- * Returns the internal names of the class's interfaces (see
- * {@link Type#getInternalName() getInternalName}).
- *
- * @return the array of internal names for all implemented interfaces or
- * <tt>null</tt>.
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String[] getInterfaces() {
- int index = header + 6;
- int n = readUnsignedShort(index);
- String[] interfaces = new String[n];
- if (n > 0) {
- char[] buf = new char[maxStringLength];
- for (int i = 0; i < n; ++i) {
- index += 2;
- interfaces[i] = readClass(index, buf);
- }
- }
- return interfaces;
- }
-
- /**
- * Copies the constant pool data into the given {@link ClassWriter}. Should
- * be called before the {@link #accept(ClassVisitor,int)} method.
- *
- * @param classWriter
- * the {@link ClassWriter} to copy constant pool into.
- */
- void copyPool(final ClassWriter classWriter) {
- char[] buf = new char[maxStringLength];
- int ll = items.length;
- Item[] items2 = new Item[ll];
- for (int i = 1; i < ll; i++) {
- int index = items[i];
- int tag = b[index - 1];
- Item item = new Item(i);
- int nameType;
- switch (tag) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- nameType = items[readUnsignedShort(index + 2)];
- item.set(tag, readClass(index, buf), readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf));
- break;
- case ClassWriter.INT:
- item.set(readInt(index));
- break;
- case ClassWriter.FLOAT:
- item.set(Float.intBitsToFloat(readInt(index)));
- break;
- case ClassWriter.NAME_TYPE:
- item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),
- null);
- break;
- case ClassWriter.LONG:
- item.set(readLong(index));
- ++i;
- break;
- case ClassWriter.DOUBLE:
- item.set(Double.longBitsToDouble(readLong(index)));
- ++i;
- break;
- case ClassWriter.UTF8: {
- String s = strings[i];
- if (s == null) {
- index = items[i];
- s = strings[i] = readUTF(index + 2,
- readUnsignedShort(index), buf);
- }
- item.set(tag, s, null, null);
- break;
- }
- case ClassWriter.HANDLE: {
- int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
- nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
- item.set(ClassWriter.HANDLE_BASE + readByte(index),
- readClass(fieldOrMethodRef, buf),
- readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
- break;
- }
- case ClassWriter.INDY:
- if (classWriter.bootstrapMethods == null) {
- copyBootstrapMethods(classWriter, items2, buf);
- }
- nameType = items[readUnsignedShort(index + 2)];
- item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
- readUnsignedShort(index));
- break;
- // case ClassWriter.STR:
- // case ClassWriter.CLASS:
- // case ClassWriter.MTYPE:
- // case ClassWriter.MODULE:
- // case ClassWriter.PACKAGE:
- default:
- item.set(tag, readUTF8(index, buf), null, null);
- break;
- }
+ /**
+ * A flag to skip the Code attributes. If this flag is set the Code attributes are neither parsed
+ * nor visited.
+ */
+ public static final int SKIP_CODE = 1;
+
+ /**
+ * A flag to skip the SourceFile, SourceDebugExtension, LocalVariableTable, LocalVariableTypeTable
+ * and LineNumberTable attributes. If this flag is set these attributes are neither parsed nor
+ * visited (i.e. {@link ClassVisitor#visitSource}, {@link MethodVisitor#visitLocalVariable} and
+ * {@link MethodVisitor#visitLineNumber} are not called).
+ */
+ public static final int SKIP_DEBUG = 2;
+
+ /**
+ * A flag to skip the StackMap and StackMapTable attributes. If this flag is set these attributes
+ * are neither parsed nor visited (i.e. {@link MethodVisitor#visitFrame} is not called). This flag
+ * is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is used: it avoids visiting frames
+ * that will be ignored and recomputed from scratch.
+ */
+ public static final int SKIP_FRAMES = 4;
+
+ /**
+ * A flag to expand the stack map frames. By default stack map frames are visited in their
+ * original format (i.e. "expanded" for classes whose version is less than V1_6, and "compressed"
+ * for the other classes). If this flag is set, stack map frames are always visited in expanded
+ * format (this option adds a decompression/compression step in ClassReader and ClassWriter which
+ * degrades performance quite a lot).
+ */
+ public static final int EXPAND_FRAMES = 8;
+
+ /**
+ * A flag to expand the ASM specific instructions into an equivalent sequence of standard bytecode
+ * instructions. When resolving a forward jump it may happen that the signed 2 bytes offset
+ * reserved for it is not sufficient to store the bytecode offset. In this case the jump
+ * instruction is replaced with a temporary ASM specific instruction using an unsigned 2 bytes
+ * offset (see {@link Label#resolve}). This internal flag is used to re-read classes containing
+ * such instructions, in order to replace them with standard instructions. In addition, when this
+ * flag is used, goto_w and jsr_w are <i>not</i> converted into goto and jsr, to make sure that
+ * infinite loops where a goto_w is replaced with a goto in ClassReader and converted back to a
+ * goto_w in ClassWriter cannot occur.
+ */
+ static final int EXPAND_ASM_INSNS = 256;
+
+ /** The size of the temporary byte array used to read class input streams chunk by chunk. */
+ private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;
+
+ /**
+ * A byte array containing the JVMS ClassFile structure to be parsed. <i>The content of this array
+ * must not be modified. This field is intended for {@link Attribute} sub classes, and is normally
+ * not needed by class visitors.</i>
+ *
+ * <p>NOTE: the ClassFile structure can start at any offset within this array, i.e. it does not
+ * necessarily start at offset 0. Use {@link #getItem} and {@link #header} to get correct
+ * ClassFile element offsets within this byte array.
+ */
+ // DontCheck(MemberName): can't be renamed (for backward binary compatibility).
+ public final byte[] b;
+
+ /**
+ * The offset in bytes, in {@link #b}, of each cp_info entry of the ClassFile's constant_pool
+ * array, <i>plus one</i>. In other words, the offset of constant pool entry i is given by
+ * cpInfoOffsets[i] - 1, i.e. its cp_info's tag field is given by b[cpInfoOffsets[i] - 1].
+ */
+ private final int[] cpInfoOffsets;
+
+ /**
+ * The String objects corresponding to the CONSTANT_Utf8 constant pool items. This cache avoids
+ * multiple parsing of a given CONSTANT_Utf8 constant pool item.
+ */
+ private final String[] constantUtf8Values;
+
+ /**
+ * The ConstantDynamic objects corresponding to the CONSTANT_Dynamic constant pool items. This
+ * cache avoids multiple parsing of a given CONSTANT_Dynamic constant pool item.
+ */
+ private final ConstantDynamic[] constantDynamicValues;
+
+ /**
+ * The start offsets in {@link #b} of each element of the bootstrap_methods array (in the
+ * BootstrapMethods attribute).
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
+ * 4.7.23</a>
+ */
+ private final int[] bootstrapMethodOffsets;
+
+ /**
+ * A conservative estimate of the maximum length of the strings contained in the constant pool of
+ * the class.
+ */
+ private final int maxStringLength;
+
+ /** The offset in bytes, in {@link #b}, of the ClassFile's access_flags field. */
+ public final int header;
+
+ // -----------------------------------------------------------------------------------------------
+ // Constructors
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param classFile the JVMS ClassFile structure to be read.
+ */
+ public ClassReader(final byte[] classFile) {
+ this(classFile, 0, classFile.length);
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.
+ * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.
+ * @param classFileLength the length in bytes of the ClassFile to be read.
+ */
+ public ClassReader(
+ final byte[] classFileBuffer,
+ final int classFileOffset,
+ final int classFileLength) { // NOPMD(UnusedFormalParameter) used for backward compatibility.
+ this(classFileBuffer, classFileOffset, /* checkClassVersion = */ true);
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object. <i>This internal constructor must not be exposed
+ * as a public API</i>.
+ *
+ * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.
+ * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.
+ * @param checkClassVersion whether to check the class version or not.
+ */
+ ClassReader(
+ final byte[] classFileBuffer, final int classFileOffset, final boolean checkClassVersion) {
+ b = classFileBuffer;
+ // Check the class' major_version. This field is after the magic and minor_version fields, which
+ // use 4 and 2 bytes respectively.
+ if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V12) {
+ throw new IllegalArgumentException(
+ "Unsupported class file major version " + readShort(classFileOffset + 6));
+ }
+ // Create the constant pool arrays. The constant_pool_count field is after the magic,
+ // minor_version and major_version fields, which use 4, 2 and 2 bytes respectively.
+ int constantPoolCount = readUnsignedShort(classFileOffset + 8);
+ cpInfoOffsets = new int[constantPoolCount];
+ constantUtf8Values = new String[constantPoolCount];
+ // Compute the offset of each constant pool entry, as well as a conservative estimate of the
+ // maximum length of the constant pool strings. The first constant pool entry is after the
+ // magic, minor_version, major_version and constant_pool_count fields, which use 4, 2, 2 and 2
+ // bytes respectively.
+ int currentCpInfoIndex = 1;
+ int currentCpInfoOffset = classFileOffset + 10;
+ int currentMaxStringLength = 0;
+ boolean hasConstantDynamic = false;
+ boolean hasConstantInvokeDynamic = false;
+ // The offset of the other entries depend on the total size of all the previous entries.
+ while (currentCpInfoIndex < constantPoolCount) {
+ cpInfoOffsets[currentCpInfoIndex++] = currentCpInfoOffset + 1;
+ int cpInfoSize;
+ switch (classFileBuffer[currentCpInfoOffset]) {
+ case Symbol.CONSTANT_FIELDREF_TAG:
+ case Symbol.CONSTANT_METHODREF_TAG:
+ case Symbol.CONSTANT_INTERFACE_METHODREF_TAG:
+ case Symbol.CONSTANT_INTEGER_TAG:
+ case Symbol.CONSTANT_FLOAT_TAG:
+ case Symbol.CONSTANT_NAME_AND_TYPE_TAG:
+ cpInfoSize = 5;
+ break;
+ case Symbol.CONSTANT_DYNAMIC_TAG:
+ cpInfoSize = 5;
+ hasConstantDynamic = true;
+ break;
+ case Symbol.CONSTANT_INVOKE_DYNAMIC_TAG:
+ cpInfoSize = 5;
+ hasConstantInvokeDynamic = true;
+ break;
+ case Symbol.CONSTANT_LONG_TAG:
+ case Symbol.CONSTANT_DOUBLE_TAG:
+ cpInfoSize = 9;
+ currentCpInfoIndex++;
+ break;
+ case Symbol.CONSTANT_UTF8_TAG:
+ cpInfoSize = 3 + readUnsignedShort(currentCpInfoOffset + 1);
+ if (cpInfoSize > currentMaxStringLength) {
+ // The size in bytes of this CONSTANT_Utf8 structure provides a conservative estimate
+ // of the length in characters of the corresponding string, and is much cheaper to
+ // compute than this exact length.
+ currentMaxStringLength = cpInfoSize;
+ }
+ break;
+ case Symbol.CONSTANT_METHOD_HANDLE_TAG:
+ cpInfoSize = 4;
+ break;
+ case Symbol.CONSTANT_CLASS_TAG:
+ case Symbol.CONSTANT_STRING_TAG:
+ case Symbol.CONSTANT_METHOD_TYPE_TAG:
+ case Symbol.CONSTANT_PACKAGE_TAG:
+ case Symbol.CONSTANT_MODULE_TAG:
+ cpInfoSize = 3;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ currentCpInfoOffset += cpInfoSize;
+ }
+ maxStringLength = currentMaxStringLength;
+ // The Classfile's access_flags field is just after the last constant pool entry.
+ header = currentCpInfoOffset;
+
+ // Allocate the cache of ConstantDynamic values, if there is at least one.
+ constantDynamicValues = hasConstantDynamic ? new ConstantDynamic[constantPoolCount] : null;
+
+ // Read the BootstrapMethods attribute, if any (only get the offset of each method).
+ bootstrapMethodOffsets =
+ (hasConstantDynamic | hasConstantInvokeDynamic)
+ ? readBootstrapMethodsAttribute(currentMaxStringLength)
+ : null;
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param inputStream an input stream of the JVMS ClassFile structure to be read. This input
+ * stream must contain nothing more than the ClassFile structure itself. It is read from its
+ * current position to its end.
+ * @throws IOException if a problem occurs during reading.
+ */
+ public ClassReader(final InputStream inputStream) throws IOException {
+ this(readStream(inputStream, false));
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param className the fully qualified name of the class to be read. The ClassFile structure is
+ * retrieved with the current class loader's {@link ClassLoader#getSystemResourceAsStream}.
+ * @throws IOException if an exception occurs during reading.
+ */
+ public ClassReader(final String className) throws IOException {
+ this(
+ readStream(
+ ClassLoader.getSystemResourceAsStream(className.replace('.', '/') + ".class"), true));
+ }
+
+ /**
+ * Reads the given input stream and returns its content as a byte array.
+ *
+ * @param inputStream an input stream.
+ * @param close true to close the input stream after reading.
+ * @return the content of the given input stream.
+ * @throws IOException if a problem occurs during reading.
+ */
+ private static byte[] readStream(final InputStream inputStream, final boolean close)
+ throws IOException {
+ if (inputStream == null) {
+ throw new IOException("Class not found");
+ }
+ try {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ byte[] data = new byte[INPUT_STREAM_DATA_CHUNK_SIZE];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
+ outputStream.write(data, 0, bytesRead);
+ }
+ outputStream.flush();
+ return outputStream.toByteArray();
+ } finally {
+ if (close) {
+ inputStream.close();
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Accessors
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the class's access flags (see {@link Opcodes}). This value may not reflect Deprecated
+ * and Synthetic flags when bytecode is before 1.5 and those flags are represented by attributes.
+ *
+ * @return the class access flags.
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public int getAccess() {
+ return readUnsignedShort(header);
+ }
+
+ /**
+ * Returns the internal name of the class (see {@link Type#getInternalName()}).
+ *
+ * @return the internal class name.
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getClassName() {
+ // this_class is just after the access_flags field (using 2 bytes).
+ return readClass(header + 2, new char[maxStringLength]);
+ }
+
+ /**
+ * Returns the internal of name of the super class (see {@link Type#getInternalName()}). For
+ * interfaces, the super class is {@link Object}.
+ *
+ * @return the internal name of the super class, or {@literal null} for {@link Object} class.
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getSuperName() {
+ // super_class is after the access_flags and this_class fields (2 bytes each).
+ return readClass(header + 4, new char[maxStringLength]);
+ }
+
+ /**
+ * Returns the internal names of the implemented interfaces (see {@link Type#getInternalName()}).
+ *
+ * @return the internal names of the directly implemented interfaces. Inherited implemented
+ * interfaces are not returned.
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String[] getInterfaces() {
+ // interfaces_count is after the access_flags, this_class and super_class fields (2 bytes each).
+ int currentOffset = header + 6;
+ int interfacesCount = readUnsignedShort(currentOffset);
+ String[] interfaces = new String[interfacesCount];
+ if (interfacesCount > 0) {
+ char[] charBuffer = new char[maxStringLength];
+ for (int i = 0; i < interfacesCount; ++i) {
+ currentOffset += 2;
+ interfaces[i] = readClass(currentOffset, charBuffer);
+ }
+ }
+ return interfaces;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Public methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
+ * {@link ClassReader}.
+ *
+ * @param classVisitor the visitor that must visit this class.
+ * @param parsingOptions the options to use to parse this class. One or more of {@link
+ * #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}.
+ */
+ public void accept(final ClassVisitor classVisitor, final int parsingOptions) {
+ accept(classVisitor, new Attribute[0], parsingOptions);
+ }
+
+ /**
+ * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
+ * {@link ClassReader}.
+ *
+ * @param classVisitor the visitor that must visit this class.
+ * @param attributePrototypes prototypes of the attributes that must be parsed during the visit of
+ * the class. Any attribute whose type is not equal to the type of one the prototypes will not
+ * be parsed: its byte array value will be passed unchanged to the ClassWriter. <i>This may
+ * corrupt it if this value contains references to the constant pool, or has syntactic or
+ * semantic links with a class element that has been transformed by a class adapter between
+ * the reader and the writer</i>.
+ * @param parsingOptions the options to use to parse this class. One or more of {@link
+ * #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}.
+ */
+ public void accept(
+ final ClassVisitor classVisitor,
+ final Attribute[] attributePrototypes,
+ final int parsingOptions) {
+ Context context = new Context();
+ context.attributePrototypes = attributePrototypes;
+ context.parsingOptions = parsingOptions;
+ context.charBuffer = new char[maxStringLength];
+
+ // Read the access_flags, this_class, super_class, interface_count and interfaces fields.
+ char[] charBuffer = context.charBuffer;
+ int currentOffset = header;
+ int accessFlags = readUnsignedShort(currentOffset);
+ String thisClass = readClass(currentOffset + 2, charBuffer);
+ String superClass = readClass(currentOffset + 4, charBuffer);
+ String[] interfaces = new String[readUnsignedShort(currentOffset + 6)];
+ currentOffset += 8;
+ for (int i = 0; i < interfaces.length; ++i) {
+ interfaces[i] = readClass(currentOffset, charBuffer);
+ currentOffset += 2;
+ }
- int index2 = item.hashCode % items2.length;
- item.next = items2[index2];
- items2[index2] = item;
- }
+ // Read the class attributes (the variables are ordered as in Section 4.7 of the JVMS).
+ // Attribute offsets exclude the attribute_name_index and attribute_length fields.
+ // - The offset of the InnerClasses attribute, or 0.
+ int innerClassesOffset = 0;
+ // - The offset of the EnclosingMethod attribute, or 0.
+ int enclosingMethodOffset = 0;
+ // - The string corresponding to the Signature attribute, or null.
+ String signature = null;
+ // - The string corresponding to the SourceFile attribute, or null.
+ String sourceFile = null;
+ // - The string corresponding to the SourceDebugExtension attribute, or null.
+ String sourceDebugExtension = null;
+ // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
+ int runtimeVisibleAnnotationsOffset = 0;
+ // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
+ int runtimeInvisibleAnnotationsOffset = 0;
+ // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
+ int runtimeVisibleTypeAnnotationsOffset = 0;
+ // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
+ int runtimeInvisibleTypeAnnotationsOffset = 0;
+ // - The offset of the Module attribute, or 0.
+ int moduleOffset = 0;
+ // - The offset of the ModulePackages attribute, or 0.
+ int modulePackagesOffset = 0;
+ // - The string corresponding to the ModuleMainClass attribute, or null.
+ String moduleMainClass = null;
+ // - The string corresponding to the NestHost attribute, or null.
+ String nestHostClass = null;
+ // - The offset of the NestMembers attribute, or 0.
+ int nestMembersOffset = 0;
+ // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
+ // This list in the <i>reverse order</i> or their order in the ClassFile structure.
+ Attribute attributes = null;
+
+ int currentAttributeOffset = getFirstAttributeOffset();
+ for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) {
+ // Read the attribute_info's attribute_name and attribute_length fields.
+ String attributeName = readUTF8(currentAttributeOffset, charBuffer);
+ int attributeLength = readInt(currentAttributeOffset + 2);
+ currentAttributeOffset += 6;
+ // The tests are sorted in decreasing frequency order (based on frequencies observed on
+ // typical classes).
+ if (Constants.SOURCE_FILE.equals(attributeName)) {
+ sourceFile = readUTF8(currentAttributeOffset, charBuffer);
+ } else if (Constants.INNER_CLASSES.equals(attributeName)) {
+ innerClassesOffset = currentAttributeOffset;
+ } else if (Constants.ENCLOSING_METHOD.equals(attributeName)) {
+ enclosingMethodOffset = currentAttributeOffset;
+ } else if (Constants.NEST_HOST.equals(attributeName)) {
+ nestHostClass = readClass(currentAttributeOffset, charBuffer);
+ } else if (Constants.NEST_MEMBERS.equals(attributeName)) {
+ nestMembersOffset = currentAttributeOffset;
+ } else if (Constants.SIGNATURE.equals(attributeName)) {
+ signature = readUTF8(currentAttributeOffset, charBuffer);
+ } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
+ runtimeVisibleAnnotationsOffset = currentAttributeOffset;
+ } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
+ runtimeVisibleTypeAnnotationsOffset = currentAttributeOffset;
+ } else if (Constants.DEPRECATED.equals(attributeName)) {
+ accessFlags |= Opcodes.ACC_DEPRECATED;
+ } else if (Constants.SYNTHETIC.equals(attributeName)) {
+ accessFlags |= Opcodes.ACC_SYNTHETIC;
+ } else if (Constants.SOURCE_DEBUG_EXTENSION.equals(attributeName)) {
+ sourceDebugExtension =
+ readUtf(currentAttributeOffset, attributeLength, new char[attributeLength]);
+ } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
+ runtimeInvisibleAnnotationsOffset = currentAttributeOffset;
+ } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
+ runtimeInvisibleTypeAnnotationsOffset = currentAttributeOffset;
+ } else if (Constants.MODULE.equals(attributeName)) {
+ moduleOffset = currentAttributeOffset;
+ } else if (Constants.MODULE_MAIN_CLASS.equals(attributeName)) {
+ moduleMainClass = readClass(currentAttributeOffset, charBuffer);
+ } else if (Constants.MODULE_PACKAGES.equals(attributeName)) {
+ modulePackagesOffset = currentAttributeOffset;
+ } else if (!Constants.BOOTSTRAP_METHODS.equals(attributeName)) {
+ // The BootstrapMethods attribute is read in the constructor.
+ Attribute attribute =
+ readAttribute(
+ attributePrototypes,
+ attributeName,
+ currentAttributeOffset,
+ attributeLength,
+ charBuffer,
+ -1,
+ null);
+ attribute.nextAttribute = attributes;
+ attributes = attribute;
+ }
+ currentAttributeOffset += attributeLength;
+ }
- int off = items[1] - 1;
- classWriter.pool.putByteArray(b, off, header - off);
- classWriter.items = items2;
- classWriter.threshold = (int) (0.75d * ll);
- classWriter.index = ll;
- }
-
- /**
- * Copies the bootstrap method data into the given {@link ClassWriter}.
- * Should be called before the {@link #accept(ClassVisitor,int)} method.
- *
- * @param classWriter
- * the {@link ClassWriter} to copy bootstrap methods into.
- */
- private void copyBootstrapMethods(final ClassWriter classWriter,
- final Item[] items, final char[] c) {
- // finds the "BootstrapMethods" attribute
- int u = getAttributes();
- boolean found = false;
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- if ("BootstrapMethods".equals(attrName)) {
- found = true;
- break;
- }
- u += 6 + readInt(u + 4);
- }
- if (!found) {
- return;
- }
- // copies the bootstrap methods in the class writer
- int boostrapMethodCount = readUnsignedShort(u + 8);
- for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {
- int position = v - u - 10;
- int hashCode = readConst(readUnsignedShort(v), c).hashCode();
- for (int k = readUnsignedShort(v + 2); k > 0; --k) {
- hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
- v += 2;
- }
- v += 4;
- Item item = new Item(j);
- item.set(position, hashCode & 0x7FFFFFFF);
- int index = item.hashCode % items.length;
- item.next = items[index];
- items[index] = item;
- }
- int attrSize = readInt(u + 4);
- ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
- bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
- classWriter.bootstrapMethodsCount = boostrapMethodCount;
- classWriter.bootstrapMethods = bootstrapMethods;
- }
-
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param is
- * an input stream from which to read the class.
- * @throws IOException
- * if a problem occurs during reading.
- */
- public ClassReader(final InputStream is) throws IOException {
- this(readClass(is, false));
- }
-
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param name
- * the binary qualified name of the class to be read.
- * @throws IOException
- * if an exception occurs during reading.
- */
- public ClassReader(final String name) throws IOException {
- this(readClass(
- ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
- + ".class"), true));
- }
-
- /**
- * Reads the bytecode of a class.
- *
- * @param is
- * an input stream from which to read the class.
- * @param close
- * true to close the input stream after reading.
- * @return the bytecode read from the given input stream.
- * @throws IOException
- * if a problem occurs during reading.
- */
- private static byte[] readClass(final InputStream is, boolean close)
- throws IOException {
- if (is == null) {
- throw new IOException("Class not found");
- }
- try {
- byte[] b = new byte[is.available()];
- int len = 0;
- while (true) {
- int n = is.read(b, len, b.length - len);
- if (n == -1) {
- if (len < b.length) {
- byte[] c = new byte[len];
- System.arraycopy(b, 0, c, 0, len);
- b = c;
- }
- return b;
- }
- len += n;
- if (len == b.length) {
- int last = is.read();
- if (last < 0) {
- return b;
- }
- byte[] c = new byte[b.length + 1000];
- System.arraycopy(b, 0, c, 0, len);
- c[len++] = (byte) last;
- b = c;
- }
- }
- } finally {
- if (close) {
- is.close();
- }
- }
+ // Visit the class declaration. The minor_version and major_version fields start 6 bytes before
+ // the first constant pool entry, which itself starts at cpInfoOffsets[1] - 1 (by definition).
+ classVisitor.visit(
+ readInt(cpInfoOffsets[1] - 7), accessFlags, thisClass, signature, superClass, interfaces);
+
+ // Visit the SourceFile and SourceDebugExtenstion attributes.
+ if ((parsingOptions & SKIP_DEBUG) == 0
+ && (sourceFile != null || sourceDebugExtension != null)) {
+ classVisitor.visitSource(sourceFile, sourceDebugExtension);
}
- // ------------------------------------------------------------------------
- // Public methods
- // ------------------------------------------------------------------------
-
- /**
- * Makes the given visitor visit the Java class of this {@link ClassReader}
- * . This class is the one specified in the constructor (see
- * {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor
- * the visitor that must visit this class.
- * @param flags
- * option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
- * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
- */
- public void accept(final ClassVisitor classVisitor, final int flags) {
- accept(classVisitor, new Attribute[0], flags);
- }
-
- /**
- * Makes the given visitor visit the Java class of this {@link ClassReader}.
- * This class is the one specified in the constructor (see
- * {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor
- * the visitor that must visit this class.
- * @param attrs
- * prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to
- * the type of one the prototypes will not be parsed: its byte
- * array value will be passed unchanged to the ClassWriter.
- * <i>This may corrupt it if this value contains references to
- * the constant pool, or has syntactic or semantic links with a
- * class element that has been transformed by a class adapter
- * between the reader and the writer</i>.
- * @param flags
- * option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
- * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
- */
- public void accept(final ClassVisitor classVisitor,
- final Attribute[] attrs, final int flags) {
- int u = header; // current offset in the class file
- char[] c = new char[maxStringLength]; // buffer used to read strings
-
- Context context = new Context();
- context.attrs = attrs;
- context.flags = flags;
- context.buffer = c;
-
- // reads the class declaration
- int access = readUnsignedShort(u);
- String name = readClass(u + 2, c);
- String superClass = readClass(u + 4, c);
- String[] interfaces = new String[readUnsignedShort(u + 6)];
- u += 8;
- for (int i = 0; i < interfaces.length; ++i) {
- interfaces[i] = readClass(u, c);
- u += 2;
- }
+ // Visit the Module, ModulePackages and ModuleMainClass attributes.
+ if (moduleOffset != 0) {
+ readModuleAttributes(
+ classVisitor, context, moduleOffset, modulePackagesOffset, moduleMainClass);
+ }
- // reads the class attributes
- String signature = null;
- String sourceFile = null;
- String sourceDebug = null;
- String enclosingOwner = null;
- String enclosingName = null;
- String enclosingDesc = null;
- String moduleMainClass = null;
- int anns = 0;
- int ianns = 0;
- int tanns = 0;
- int itanns = 0;
- int innerClasses = 0;
- int module = 0;
- int packages = 0;
- Attribute attributes = null;
-
- u = getAttributes();
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("SourceFile".equals(attrName)) {
- sourceFile = readUTF8(u + 8, c);
- } else if ("InnerClasses".equals(attrName)) {
- innerClasses = u + 8;
- } else if ("EnclosingMethod".equals(attrName)) {
- enclosingOwner = readClass(u + 8, c);
- int item = readUnsignedShort(u + 10);
- if (item != 0) {
- enclosingName = readUTF8(items[item], c);
- enclosingDesc = readUTF8(items[item] + 2, c);
- }
- } else if ("Signature".equals(attrName)) {
- signature = readUTF8(u + 8, c);
- } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 8;
- } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
- tanns = u + 8;
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if ("SourceDebugExtension".equals(attrName)) {
- int len = readInt(u + 4);
- sourceDebug = readUTF(u + 8, len, new char[len]);
- } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 8;
- } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
- itanns = u + 8;
- } else if ("Module".equals(attrName)) {
- module = u + 8;
- } else if ("ModuleMainClass".equals(attrName)) {
- moduleMainClass = readClass(u + 8, c);
- } else if ("ModulePackages".equals(attrName)) {
- packages = u + 10;
- } else if ("BootstrapMethods".equals(attrName)) {
- int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
- for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
- bootstrapMethods[j] = v;
- v += 2 + readUnsignedShort(v + 2) << 1;
- }
- context.bootstrapMethods = bootstrapMethods;
- } else {
- Attribute attr = readAttribute(attrs, attrName, u + 8,
- readInt(u + 4), c, -1, null);
- if (attr != null) {
- attr.next = attributes;
- attributes = attr;
- }
- }
- u += 6 + readInt(u + 4);
- }
+ // Visit the NestHost attribute.
+ if (nestHostClass != null) {
+ classVisitor.visitNestHost(nestHostClass);
+ }
- // visits the class declaration
- classVisitor.visit(readInt(items[1] - 7), access, name, signature,
- superClass, interfaces);
+ // Visit the EnclosingMethod attribute.
+ if (enclosingMethodOffset != 0) {
+ String className = readClass(enclosingMethodOffset, charBuffer);
+ int methodIndex = readUnsignedShort(enclosingMethodOffset + 2);
+ String name = methodIndex == 0 ? null : readUTF8(cpInfoOffsets[methodIndex], charBuffer);
+ String type = methodIndex == 0 ? null : readUTF8(cpInfoOffsets[methodIndex] + 2, charBuffer);
+ classVisitor.visitOuterClass(className, name, type);
+ }
- // visits the source and debug info
- if ((flags & SKIP_DEBUG) == 0
- && (sourceFile != null || sourceDebug != null)) {
- classVisitor.visitSource(sourceFile, sourceDebug);
- }
+ // Visit the RuntimeVisibleAnnotations attribute.
+ if (runtimeVisibleAnnotationsOffset != 0) {
+ int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
+ int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
+ while (numAnnotations-- > 0) {
+ // Parse the type_index field.
+ String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
+ currentAnnotationOffset += 2;
+ // Parse num_element_value_pairs and element_value_pairs and visit these values.
+ currentAnnotationOffset =
+ readElementValues(
+ classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
+ currentAnnotationOffset,
+ /* named = */ true,
+ charBuffer);
+ }
+ }
- // visits the module info and associated attributes
- if (module != 0) {
- readModule(classVisitor, context, module,
- moduleMainClass, packages);
- }
-
- // visits the outer class
- if (enclosingOwner != null) {
- classVisitor.visitOuterClass(enclosingOwner, enclosingName,
- enclosingDesc);
- }
+ // Visit the RuntimeInvisibleAnnotations attribute.
+ if (runtimeInvisibleAnnotationsOffset != 0) {
+ int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
+ int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
+ while (numAnnotations-- > 0) {
+ // Parse the type_index field.
+ String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
+ currentAnnotationOffset += 2;
+ // Parse num_element_value_pairs and element_value_pairs and visit these values.
+ currentAnnotationOffset =
+ readElementValues(
+ classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
+ currentAnnotationOffset,
+ /* named = */ true,
+ charBuffer);
+ }
+ }
- // visits the class annotations and type annotations
- if (anns != 0) {
- for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- classVisitor.visitAnnotation(readUTF8(v, c), true));
- }
- }
- if (ianns != 0) {
- for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- classVisitor.visitAnnotation(readUTF8(v, c), false));
- }
- }
- if (tanns != 0) {
- for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
- v = readAnnotationTarget(context, v);
- v = readAnnotationValues(v + 2, c, true,
- classVisitor.visitTypeAnnotation(context.typeRef,
- context.typePath, readUTF8(v, c), true));
- }
- }
- if (itanns != 0) {
- for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
- v = readAnnotationTarget(context, v);
- v = readAnnotationValues(v + 2, c, true,
- classVisitor.visitTypeAnnotation(context.typeRef,
- context.typePath, readUTF8(v, c), false));
- }
- }
+ // Visit the RuntimeVisibleTypeAnnotations attribute.
+ if (runtimeVisibleTypeAnnotationsOffset != 0) {
+ int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
+ int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
+ while (numAnnotations-- > 0) {
+ // Parse the target_type, target_info and target_path fields.
+ currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
+ // Parse the type_index field.
+ String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
+ currentAnnotationOffset += 2;
+ // Parse num_element_value_pairs and element_value_pairs and visit these values.
+ currentAnnotationOffset =
+ readElementValues(
+ classVisitor.visitTypeAnnotation(
+ context.currentTypeAnnotationTarget,
+ context.currentTypeAnnotationTargetPath,
+ annotationDescriptor,
+ /* visible = */ true),
+ currentAnnotationOffset,
+ /* named = */ true,
+ charBuffer);
+ }
+ }
- // visits the attributes
- while (attributes != null) {
- Attribute attr = attributes.next;
- attributes.next = null;
- classVisitor.visitAttribute(attributes);
- attributes = attr;
- }
+ // Visit the RuntimeInvisibleTypeAnnotations attribute.
+ if (runtimeInvisibleTypeAnnotationsOffset != 0) {
+ int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
+ int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
+ while (numAnnotations-- > 0) {
+ // Parse the target_type, target_info and target_path fields.
+ currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
+ // Parse the type_index field.
+ String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
+ currentAnnotationOffset += 2;
+ // Parse num_element_value_pairs and element_value_pairs and visit these values.
+ currentAnnotationOffset =
+ readElementValues(
+ classVisitor.visitTypeAnnotation(
+ context.currentTypeAnnotationTarget,
+ context.currentTypeAnnotationTargetPath,
+ annotationDescriptor,
+ /* visible = */ false),
+ currentAnnotationOffset,
+ /* named = */ true,
+ charBuffer);
+ }
+ }
- // visits the inner classes
- if (innerClasses != 0) {
- int v = innerClasses + 2;
- for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
- classVisitor.visitInnerClass(readClass(v, c),
- readClass(v + 2, c), readUTF8(v + 4, c),
- readUnsignedShort(v + 6));
- v += 8;
- }
- }
+ // Visit the non standard attributes.
+ while (attributes != null) {
+ // Copy and reset the nextAttribute field so that it can also be used in ClassWriter.
+ Attribute nextAttribute = attributes.nextAttribute;
+ attributes.nextAttribute = null;
+ classVisitor.visitAttribute(attributes);
+ attributes = nextAttribute;
+ }
- // visits the fields and methods
- u = header + 10 + 2 * interfaces.length;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- u = readField(classVisitor, context, u);
- }
- u += 2;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- u = readMethod(classVisitor, context, u);
- }
+ // Visit the NestedMembers attribute.
+ if (nestMembersOffset != 0) {
+ int numberOfNestMembers = readUnsignedShort(nestMembersOffset);
+ int currentNestMemberOffset = nestMembersOffset + 2;
+ while (numberOfNestMembers-- > 0) {
+ classVisitor.visitNestMember(readClass(currentNestMemberOffset, charBuffer));
+ currentNestMemberOffset += 2;
+ }
+ }
- // visits the end of the class
- classVisitor.visitEnd();
- }
-
- /**
- * Reads the module attribute and visit it.
- *
- * @param classVisitor
- * the current class visitor
- * @param context
- * information about the class being parsed.
- * @param u
- * start offset of the module attribute in the class file.
- * @param mainClass
- * name of the main class of a module or null.
- * @param packages
- * start offset of the concealed package attribute.
- */
- private void readModule(final ClassVisitor classVisitor,
- final Context context, int u,
- final String mainClass, int packages) {
-
- char[] buffer = context.buffer;
-
- // reads module name, flags and version
- String name = readModule(u, buffer);
- int flags = readUnsignedShort(u + 2);
- String version = readUTF8(u + 4, buffer);
- u += 6;
-
- ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
- if (mv == null) {
- return;
- }
-
- // module attributes (main class, packages)
- if (mainClass != null) {
- mv.visitMainClass(mainClass);
- }
-
- if (packages != 0) {
- for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
- String packaze = readPackage(packages, buffer);
- mv.visitPackage(packaze);
- packages += 2;
- }
- }
-
- // reads requires
- u += 2;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- String module = readModule(u, buffer);
- int access = readUnsignedShort(u + 2);
- String requireVersion = readUTF8(u + 4, buffer);
- mv.visitRequire(module, access, requireVersion);
- u += 6;
- }
-
- // reads exports
- u += 2;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- String export = readPackage(u, buffer);
- int access = readUnsignedShort(u + 2);
- int exportToCount = readUnsignedShort(u + 4);
- u += 6;
- String[] tos = null;
- if (exportToCount != 0) {
- tos = new String[exportToCount];
- for (int j = 0; j < tos.length; ++j) {
- tos[j] = readModule(u, buffer);
- u += 2;
- }
- }
- mv.visitExport(export, access, tos);
- }
-
- // reads opens
- u += 2;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- String open = readPackage(u, buffer);
- int access = readUnsignedShort(u + 2);
- int openToCount = readUnsignedShort(u + 4);
- u += 6;
- String[] tos = null;
- if (openToCount != 0) {
- tos = new String[openToCount];
- for (int j = 0; j < tos.length; ++j) {
- tos[j] = readModule(u, buffer);
- u += 2;
- }
- }
- mv.visitOpen(open, access, tos);
- }
-
- // read uses
- u += 2;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- mv.visitUse(readClass(u, buffer));
- u += 2;
- }
-
- // read provides
- u += 2;
- for (int i = readUnsignedShort(u - 2); i > 0; --i) {
- String service = readClass(u, buffer);
- int provideWithCount = readUnsignedShort(u + 2);
- u += 4;
- String[] withs = new String[provideWithCount];
- for (int j = 0; j < withs.length; ++j) {
- withs[j] = readClass(u, buffer);
- u += 2;
- }
- mv.visitProvide(service, withs);
- }
-
- mv.visitEnd();
- }
-
- /**
- * Reads a field and makes the given visitor visit it.
- *
- * @param classVisitor
- * the visitor that must visit the field.
- * @param context
- * information about the class being parsed.
- * @param u
- * the start offset of the field in the class file.
- * @return the offset of the first byte following the field in the class.
- */
- private int readField(final ClassVisitor classVisitor,
- final Context context, int u) {
- // reads the field declaration
- char[] c = context.buffer;
- int access = readUnsignedShort(u);
- String name = readUTF8(u + 2, c);
- String desc = readUTF8(u + 4, c);
- u += 6;
-
- // reads the field attributes
- String signature = null;
- int anns = 0;
- int ianns = 0;
- int tanns = 0;
- int itanns = 0;
- Object value = null;
- Attribute attributes = null;
-
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("ConstantValue".equals(attrName)) {
- int item = readUnsignedShort(u + 8);
- value = item == 0 ? null : readConst(item, c);
- } else if ("Signature".equals(attrName)) {
- signature = readUTF8(u + 8, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 8;
- } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
- tanns = u + 8;
- } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 8;
- } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
- itanns = u + 8;
- } else {
- Attribute attr = readAttribute(context.attrs, attrName, u + 8,
- readInt(u + 4), c, -1, null);
- if (attr != null) {
- attr.next = attributes;
- attributes = attr;
- }
- }
- u += 6 + readInt(u + 4);
- }
- u += 2;
+ // Visit the InnerClasses attribute.
+ if (innerClassesOffset != 0) {
+ int numberOfClasses = readUnsignedShort(innerClassesOffset);
+ int currentClassesOffset = innerClassesOffset + 2;
+ while (numberOfClasses-- > 0) {
+ classVisitor.visitInnerClass(
+ readClass(currentClassesOffset, charBuffer),
+ readClass(currentClassesOffset + 2, charBuffer),
+ readUTF8(currentClassesOffset + 4, charBuffer),
+ readUnsignedShort(currentClassesOffset + 6));
+ currentClassesOffset += 8;
+ }
+ }
- // visits the field declaration
- FieldVisitor fv = classVisitor.visitField(access, name, desc,
- signature, value);
- if (fv == null) {
- return u;
- }
+ // Visit the fields and methods.
+ int fieldsCount = readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ while (fieldsCount-- > 0) {
+ currentOffset = readField(classVisitor, context, currentOffset);
+ }
+ int methodsCount = readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ while (methodsCount-- > 0) {
+ currentOffset = readMethod(classVisitor, context, currentOffset);
+ }
- // visits the field annotations and type annotations
- if (anns != 0) {
- for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- fv.visitAnnotation(readUTF8(v, c), true));
- }
- }
- if (ianns != 0) {
- for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- fv.visitAnnotation(readUTF8(v, c), false));
- }
- }
- if (tanns != 0) {
- for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
- v = readAnnotationTarget(context, v);
- v = readAnnotationValues(v + 2, c, true,
- fv.visitTypeAnnotation(context.typeRef,
- context.typePath, readUTF8(v, c), true));
- }
- }
- if (itanns != 0) {
- for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
- v = readAnnotationTarget(context, v);
- v = readAnnotationValues(v + 2, c, true,
- fv.visitTypeAnnotation(context.typeRef,
- context.typePath, readUTF8(v, c), false));
- }
- }
+ // Visit the end of the class.
+ classVisitor.visitEnd();
+ }
+
+ // ----------------------------------------------------------------------------------------------
+ // Methods to parse modules, fields and methods
+ // ----------------------------------------------------------------------------------------------
+
+ /**
+ * Reads the Module, ModulePackages and ModuleMainClass attributes and visit them.
+ *
+ * @param classVisitor the current class visitor
+ * @param context information about the class being parsed.
+ * @param moduleOffset the offset of the Module attribute (excluding the attribute_info's
+ * attribute_name_index and attribute_length fields).
+ * @param modulePackagesOffset the offset of the ModulePackages attribute (excluding the
+ * attribute_info's attribute_name_index and attribute_length fields), or 0.
+ * @param moduleMainClass the string corresponding to the ModuleMainClass attribute, or null.
+ */
+ private void readModuleAttributes(
+ final ClassVisitor classVisitor,
+ final Context context,
+ final int moduleOffset,
+ final int modulePackagesOffset,
+ final String moduleMainClass) {
+ char[] buffer = context.charBuffer;
+
+ // Read the module_name_index, module_flags and module_version_index fields and visit them.
+ int currentOffset = moduleOffset;
+ String moduleName = readModule(currentOffset, buffer);
+ int moduleFlags = readUnsignedShort(currentOffset + 2);
+ String moduleVersion = readUTF8(currentOffset + 4, buffer);
+ currentOffset += 6;
+ ModuleVisitor moduleVisitor = classVisitor.visitModule(moduleName, moduleFlags, moduleVersion);
+ if (moduleVisitor == null) {
+ return;
+ }
- // visits the field attributes
- while (attributes != null) {
- Attribute attr = attributes.next;
- attributes.next = null;
- fv.visitAttribute(attributes);
- attributes = attr;
- }
+ // Visit the ModuleMainClass attribute.
+ if (moduleMainClass != null) {
+ moduleVisitor.visitMainClass(moduleMainClass);
+ }
- // visits the end of the field
- fv.visitEnd();
-
- return u;
- }
-
- /**
- * Reads a method and makes the given visitor visit it.
- *
- * @param classVisitor
- * the visitor that must visit the method.
- * @param context
- * information about the class being parsed.
- * @param u
- * the start offset of the method in the class file.
- * @return the offset of the first byte following the method in the class.
- */
- private int readMethod(final ClassVisitor classVisitor,
- final Context context, int u) {
- // reads the method declaration
- char[] c = context.buffer;
- context.access = readUnsignedShort(u);
- context.name = readUTF8(u + 2, c);
- context.desc = readUTF8(u + 4, c);
- u += 6;
-
- // reads the method attributes
- int code = 0;
- int exception = 0;
- String[] exceptions = null;
- String signature = null;
- int methodParameters = 0;
- int anns = 0;
- int ianns = 0;
- int tanns = 0;
- int itanns = 0;
- int dann = 0;
- int mpanns = 0;
- int impanns = 0;
- int firstAttribute = u;
- Attribute attributes = null;
-
- for (int i = readUnsignedShort(u); i > 0; --i) {
- String attrName = readUTF8(u + 2, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("Code".equals(attrName)) {
- if ((context.flags & SKIP_CODE) == 0) {
- code = u + 8;
- }
- } else if ("Exceptions".equals(attrName)) {
- exceptions = new String[readUnsignedShort(u + 8)];
- exception = u + 10;
- for (int j = 0; j < exceptions.length; ++j) {
- exceptions[j] = readClass(exception, c);
- exception += 2;
- }
- } else if ("Signature".equals(attrName)) {
- signature = readUTF8(u + 8, c);
- } else if ("Deprecated".equals(attrName)) {
- context.access |= Opcodes.ACC_DEPRECATED;
- } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 8;
- } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
- tanns = u + 8;
- } else if ("AnnotationDefault".equals(attrName)) {
- dann = u + 8;
- } else if ("Synthetic".equals(attrName)) {
- context.access |= Opcodes.ACC_SYNTHETIC
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 8;
- } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
- itanns = u + 8;
- } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) {
- mpanns = u + 8;
- } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {
- impanns = u + 8;
- } else if ("MethodParameters".equals(attrName)) {
- methodParameters = u + 8;
- } else {
- Attribute attr = readAttribute(context.attrs, attrName, u + 8,
- readInt(u + 4), c, -1, null);
- if (attr != null) {
- attr.next = attributes;
- attributes = attr;
- }
- }
- u += 6 + readInt(u + 4);
- }
- u += 2;
+ // Visit the ModulePackages attribute.
+ if (modulePackagesOffset != 0) {
+ int packageCount = readUnsignedShort(modulePackagesOffset);
+ int currentPackageOffset = modulePackagesOffset + 2;
+ while (packageCount-- > 0) {
+ moduleVisitor.visitPackage(readPackage(currentPackageOffset, buffer));
+ currentPackageOffset += 2;
+ }
+ }
- // visits the method declaration
- MethodVisitor mv = classVisitor.visitMethod(context.access,
- context.name, context.desc, signature, exceptions);
- if (mv == null) {
- return u;
- }
+ // Read the 'requires_count' and 'requires' fields.
+ int requiresCount = readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ while (requiresCount-- > 0) {
+ // Read the requires_index, requires_flags and requires_version fields and visit them.
+ String requires = readModule(currentOffset, buffer);
+ int requiresFlags = readUnsignedShort(currentOffset + 2);
+ String requiresVersion = readUTF8(currentOffset + 4, buffer);
+ currentOffset += 6;
+ moduleVisitor.visitRequire(requires, requiresFlags, requiresVersion);
+ }
- /*
- * if the returned MethodVisitor is in fact a MethodWriter, it means
- * there is no method adapter between the reader and the writer. If, in
- * addition, the writer's constant pool was copied from this reader
- * (mw.cw.cr == this), and the signature and exceptions of the method
- * have not been changed, then it is possible to skip all visit events
- * and just copy the original code of the method to the writer (the
- * access, name and descriptor can have been changed, this is not
- * important since they are not copied as is from the reader).
- */
- if (mv instanceof MethodWriter) {
- MethodWriter mw = (MethodWriter) mv;
- if (mw.cw.cr == this && signature == mw.signature) {
- boolean sameExceptions = false;
- if (exceptions == null) {
- sameExceptions = mw.exceptionCount == 0;
- } else if (exceptions.length == mw.exceptionCount) {
- sameExceptions = true;
- for (int j = exceptions.length - 1; j >= 0; --j) {
- exception -= 2;
- if (mw.exceptions[j] != readUnsignedShort(exception)) {
- sameExceptions = false;
- break;
- }
- }
- }
- if (sameExceptions) {
- /*
- * we do not copy directly the code into MethodWriter to
- * save a byte array copy operation. The real copy will be
- * done in ClassWriter.toByteArray().
- */
- mw.classReaderOffset = firstAttribute;
- mw.classReaderLength = u - firstAttribute;
- return u;
- }
- }
- }
+ // Read the 'exports_count' and 'exports' fields.
+ int exportsCount = readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ while (exportsCount-- > 0) {
+ // Read the exports_index, exports_flags, exports_to_count and exports_to_index fields
+ // and visit them.
+ String exports = readPackage(currentOffset, buffer);
+ int exportsFlags = readUnsignedShort(currentOffset + 2);
+ int exportsToCount = readUnsignedShort(currentOffset + 4);
+ currentOffset += 6;
+ String[] exportsTo = null;
+ if (exportsToCount != 0) {
+ exportsTo = new String[exportsToCount];
+ for (int i = 0; i < exportsToCount; ++i) {
+ exportsTo[i] = readModule(currentOffset, buffer);
+ currentOffset += 2;
+ }
+ }
+ moduleVisitor.visitExport(exports, exportsFlags, exportsTo);
+ }
- // visit the method parameters
- if (methodParameters != 0) {
- for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
- mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
- }
- }
+ // Reads the 'opens_count' and 'opens' fields.
+ int opensCount = readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ while (opensCount-- > 0) {
+ // Read the opens_index, opens_flags, opens_to_count and opens_to_index fields and visit them.
+ String opens = readPackage(currentOffset, buffer);
+ int opensFlags = readUnsignedShort(currentOffset + 2);
+ int opensToCount = readUnsignedShort(currentOffset + 4);
+ currentOffset += 6;
+ String[] opensTo = null;
+ if (opensToCount != 0) {
+ opensTo = new String[opensToCount];
+ for (int i = 0; i < opensToCount; ++i) {
+ opensTo[i] = readModule(currentOffset, buffer);
+ currentOffset += 2;
+ }
+ }
+ moduleVisitor.visitOpen(opens, opensFlags, opensTo);
+ }
- // visits the method annotations
- if (dann != 0) {
- AnnotationVisitor dv = mv.visitAnnotationDefault();
- readAnnotationValue(dann, c, null, dv);
- if (dv != null) {
- dv.visitEnd();
- }
- }
- if (anns != 0) {
- for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- mv.visitAnnotation(readUTF8(v, c), true));
- }
- }
- if (ianns != 0) {
- for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
- v = readAnnotationValues(v + 2, c, true,
- mv.visitAnnotation(readUTF8(v, c), false));
- }
- }
- if (tanns != 0) {
- for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
- v = readAnnotationTarget(context, v);
- v = readAnnotationValues(v + 2, c, true,
- mv.visitTypeAnnotation(context.typeRef,
- context.typePath, readUTF8(v, c), true));
- }
- }
- if (itanns != 0) {
- for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
- v = readAnnotationTarget(context, v);
- v = readAnnotationValues(v + 2, c, true,
- mv.visitTypeAnnotation(context.typeRef,
- context.typePath, readUTF8(v, c), false));
- }
- }
- if (mpanns != 0) {
- readParameterAnnotations(mv, context, mpanns, true);
- }
- if (impanns != 0) {
- readParameterAnnotations(mv, context, impanns, false);
- }
+ // Read the 'uses_count' and 'uses' fields.
+ int usesCount = readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ while (usesCount-- > 0) {
+ moduleVisitor.visitUse(readClass(currentOffset, buffer));
+ currentOffset += 2;
+ }
- // visits the method attributes
- while (attributes != null) {
- Attribute attr = attributes.next;
- attributes.next = null;
- mv.visitAttribute(attributes);
- attributes = attr;
- }
+ // Read the 'provides_count' and 'provides' fields.
+ int providesCount = readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ while (providesCount-- > 0) {
+ // Read the provides_index, provides_with_count and provides_with_index fields and visit them.
+ String provides = readClass(currentOffset, buffer);
+ int providesWithCount = readUnsignedShort(currentOffset + 2);
+ currentOffset += 4;
+ String[] providesWith = new String[providesWithCount];
+ for (int i = 0; i < providesWithCount; ++i) {
+ providesWith[i] = readClass(currentOffset, buffer);
+ currentOffset += 2;
+ }
+ moduleVisitor.visitProvide(provides, providesWith);
+ }
- // visits the method code
- if (code != 0) {
- mv.visitCode();
- readCode(mv, context, code);
- }
+ // Visit the end of the module attributes.
+ moduleVisitor.visitEnd();
+ }
+
+ /**
+ * Reads a JVMS field_info structure and makes the given visitor visit it.
+ *
+ * @param classVisitor the visitor that must visit the field.
+ * @param context information about the class being parsed.
+ * @param fieldInfoOffset the start offset of the field_info structure.
+ * @return the offset of the first byte following the field_info structure.
+ */
+ private int readField(
+ final ClassVisitor classVisitor, final Context context, final int fieldInfoOffset) {
+ char[] charBuffer = context.charBuffer;
+
+ // Read the access_flags, name_index and descriptor_index fields.
+ int currentOffset = fieldInfoOffset;
+ int accessFlags = readUnsignedShort(currentOffset);
+ String name = readUTF8(currentOffset + 2, charBuffer);
+ String descriptor = readUTF8(currentOffset + 4, charBuffer);
+ currentOffset += 6;
+
+ // Read the field attributes (the variables are ordered as in Section 4.7 of the JVMS).
+ // Attribute offsets exclude the attribute_name_index and attribute_length fields.
+ // - The value corresponding to the ConstantValue attribute, or null.
+ Object constantValue = null;
+ // - The string corresponding to the Signature attribute, or null.
+ String signature = null;
+ // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
+ int runtimeVisibleAnnotationsOffset = 0;
+ // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
+ int runtimeInvisibleAnnotationsOffset = 0;
+ // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
+ int runtimeVisibleTypeAnnotationsOffset = 0;
+ // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
+ int runtimeInvisibleTypeAnnotationsOffset = 0;
+ // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
+ // This list in the <i>reverse order</i> or their order in the ClassFile structure.
+ Attribute attributes = null;
+
+ int attributesCount = readUnsignedShort(currentOffset);
+ currentOffset += 2;
+ while (attributesCount-- > 0) {
+ // Read the attribute_info's attribute_name and attribute_length fields.
+ String attributeName = readUTF8(currentOffset, charBuffer);
+ int attributeLength = readInt(currentOffset + 2);
+ currentOffset += 6;
+ // The tests are sorted in decreasing frequency order (based on frequencies observed on
+ // typical classes).
+ if (Constants.CONSTANT_VALUE.equals(attributeName)) {
+ int constantvalueIndex = readUnsignedShort(currentOffset);
+ constantValue = constantvalueIndex == 0 ? null : readConst(constantvalueIndex, charBuffer);
+ } else if (Constants.SIGNATURE.equals(attributeName)) {
+ signature = readUTF8(currentOffset, charBuffer);
+ } else if (Constants.DEPRECATED.equals(attributeName)) {
+ accessFlags |= Opcodes.ACC_DEPRECATED;
+ } else if (Constants.SYNTHETIC.equals(attributeName)) {
+ accessFlags |= Opcodes.ACC_SYNTHETIC;
+ } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
+ runtimeVisibleAnnotationsOffset = currentOffset;
+ } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
+ runtimeVisibleTypeAnnotationsOffset = currentOffset;
+ } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
+ runtimeInvisibleAnnotationsOffset = currentOffset;
+ } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
+ runtimeInvisibleTypeAnnotationsOffset = currentOffset;
+ } else {
+ Attribute attribute =
+ readAttribute(
+ context.attributePrototypes,
+ attributeName,
+ currentOffset,
+ attributeLength,
+ charBuffer,
+ -1,
+ null);
+ attribute.nextAttribute = attributes;
+ attributes = attribute;
+ }
+ currentOffset += attributeLength;
+ }
- // visits the end of the method
- mv.visitEnd();
-
- return u;
- }
-
- /**
- * Reads the bytecode of a method and makes the given visitor visit it.
- *
- * @param mv
- * the visitor that must visit the method's code.
- * @param context
- * information about the class being parsed.
- * @param u
- * the start offset of the code attribute in the class file.
- */
- private void readCode(final MethodVisitor mv, final Context context, int u) {
- // reads the header
- byte[] b = this.b;
- char[] c = context.buffer;
- int maxStack = readUnsignedShort(u);
- int maxLocals = readUnsignedShort(u + 2);
- int codeLength = readInt(u + 4);
- u += 8;
-
- // reads the bytecode to find the labels
- int codeStart = u;
- int codeEnd = u + codeLength;
- Label[] labels = context.labels = new Label[codeLength + 2];
- createLabel(codeLength + 1, labels);
- while (u < codeEnd) {
- int offset = u - codeStart;
- int opcode = b[u] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- createLabel(offset + readShort(u + 1), labels);
- u += 3;
- break;
- case ClassWriter.ASM_LABEL_INSN:
- createLabel(offset + readUnsignedShort(u + 1), labels);
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- case ClassWriter.ASM_LABELW_INSN:
- createLabel(offset + readInt(u + 1), labels);
- u += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- u += 6;
- } else {
- u += 4;
- }
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- u = u + 4 - (offset & 3);
- // reads instruction
- createLabel(offset + readInt(u), labels);
- for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
- createLabel(offset + readInt(u + 12), labels);
- u += 4;
- }
- u += 12;
- break;
- case ClassWri
<TRUNCATED>
[23/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
old mode 100644
new mode 100755
index 878cd8d..d1c063c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
@@ -1,228 +1,252 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.signature;
/**
- * A type signature parser to make a signature visitor visit an existing
- * signature.
- *
+ * A parser for signature literals, as defined in the Java Virtual Machine Specification (JVMS), to
+ * visit them with a SignatureVisitor.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1">JVMS
+ * 4.7.9.1</a>
* @author Thomas Hallgren
* @author Eric Bruneton
*/
public class SignatureReader {
- /**
- * The signature to be read.
- */
- private final String signature;
-
- /**
- * Constructs a {@link SignatureReader} for the given signature.
- *
- * @param signature
- * A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or
- * <i>FieldTypeSignature</i>.
- */
- public SignatureReader(final String signature) {
- this.signature = signature;
- }
+ /** The JVMS signature to be read. */
+ private final String signatureValue;
+
+ /**
+ * Constructs a {@link SignatureReader} for the given signature.
+ *
+ * @param signature A <i>JavaTypeSignature</i>, <i>ClassSignature</i> or <i>MethodSignature</i>.
+ */
+ public SignatureReader(final String signature) {
+ this.signatureValue = signature;
+ }
- /**
- * Makes the given visitor visit the signature of this
- * {@link SignatureReader}. This signature is the one specified in the
- * constructor (see {@link #SignatureReader(String) SignatureReader}). This
- * method is intended to be called on a {@link SignatureReader} that was
- * created using a <i>ClassSignature</i> (such as the <code>signature</code>
- * parameter of the {@link org.objectweb.asm.ClassVisitor#visit
- * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the
- * <code>signature</code> parameter of the
- * {@link org.objectweb.asm.ClassVisitor#visitMethod
- * ClassVisitor.visitMethod} method).
- *
- * @param v
- * the visitor that must visit this signature.
- */
- public void accept(final SignatureVisitor v) {
- String signature = this.signature;
- int len = signature.length();
- int pos;
- char c;
-
- if (signature.charAt(0) == '<') {
- pos = 2;
- do {
- int end = signature.indexOf(':', pos);
- v.visitFormalTypeParameter(signature.substring(pos - 1, end));
- pos = end + 1;
-
- c = signature.charAt(pos);
- if (c == 'L' || c == '[' || c == 'T') {
- pos = parseType(signature, pos, v.visitClassBound());
- }
-
- while ((c = signature.charAt(pos++)) == ':') {
- pos = parseType(signature, pos, v.visitInterfaceBound());
- }
- } while (c != '>');
- } else {
- pos = 0;
+ /**
+ * Makes the given visitor visit the signature of this {@link SignatureReader}. This signature is
+ * the one specified in the constructor (see {@link #SignatureReader}). This method is intended to
+ * be called on a {@link SignatureReader} that was created using a <i>ClassSignature</i> (such as
+ * the <code>signature</code> parameter of the {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}
+ * method) or a <i>MethodSignature</i> (such as the <code>signature</code> parameter of the {@link
+ * org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod} method).
+ *
+ * @param signatureVistor the visitor that must visit this signature.
+ */
+ public void accept(final SignatureVisitor signatureVistor) {
+ String signature = this.signatureValue;
+ int length = signature.length();
+ int offset; // Current offset in the parsed signature (parsed from left to right).
+ char currentChar; // The signature character at 'offset', or just before.
+
+ // If the signature starts with '<', it starts with TypeParameters, i.e. a formal type parameter
+ // identifier, followed by one or more pair ':',ReferenceTypeSignature (for its class bound and
+ // interface bounds).
+ if (signature.charAt(0) == '<') {
+ // Invariant: offset points to the second character of a formal type parameter name at the
+ // beginning of each iteration of the loop below.
+ offset = 2;
+ do {
+ // The formal type parameter name is everything between offset - 1 and the first ':'.
+ int classBoundStartOffset = signature.indexOf(':', offset);
+ signatureVistor.visitFormalTypeParameter(
+ signature.substring(offset - 1, classBoundStartOffset));
+
+ // If the character after the ':' class bound marker is not the start of a
+ // ReferenceTypeSignature, it means the class bound is empty (which is a valid case).
+ offset = classBoundStartOffset + 1;
+ currentChar = signature.charAt(offset);
+ if (currentChar == 'L' || currentChar == '[' || currentChar == 'T') {
+ offset = parseType(signature, offset, signatureVistor.visitClassBound());
}
- if (signature.charAt(pos) == '(') {
- pos++;
- while (signature.charAt(pos) != ')') {
- pos = parseType(signature, pos, v.visitParameterType());
- }
- pos = parseType(signature, pos + 1, v.visitReturnType());
- while (pos < len) {
- pos = parseType(signature, pos + 1, v.visitExceptionType());
- }
- } else {
- pos = parseType(signature, pos, v.visitSuperclass());
- while (pos < len) {
- pos = parseType(signature, pos, v.visitInterface());
- }
+ // While the character after the class bound or after the last parsed interface bound
+ // is ':', we need to parse another interface bound.
+ while ((currentChar = signature.charAt(offset++)) == ':') {
+ offset = parseType(signature, offset, signatureVistor.visitInterfaceBound());
}
+
+ // At this point a TypeParameter has been fully parsed, and we need to parse the next one
+ // (note that currentChar is now the first character of the next TypeParameter, and that
+ // offset points to the second character), unless the character just after this
+ // TypeParameter signals the end of the TypeParameters.
+ } while (currentChar != '>');
+ } else {
+ offset = 0;
}
- /**
- * Makes the given visitor visit the signature of this
- * {@link SignatureReader}. This signature is the one specified in the
- * constructor (see {@link #SignatureReader(String) SignatureReader}). This
- * method is intended to be called on a {@link SignatureReader} that was
- * created using a <i>FieldTypeSignature</i>, such as the
- * <code>signature</code> parameter of the
- * {@link org.objectweb.asm.ClassVisitor#visitField ClassVisitor.visitField}
- * or {@link org.objectweb.asm.MethodVisitor#visitLocalVariable
- * MethodVisitor.visitLocalVariable} methods.
- *
- * @param v
- * the visitor that must visit this signature.
- */
- public void acceptType(final SignatureVisitor v) {
- parseType(this.signature, 0, v);
+ // If the (optional) TypeParameters is followed by '(' this means we are parsing a
+ // MethodSignature, which has JavaTypeSignature type inside parentheses, followed by a Result
+ // type and optional ThrowsSignature types.
+ if (signature.charAt(offset) == '(') {
+ offset++;
+ while (signature.charAt(offset) != ')') {
+ offset = parseType(signature, offset, signatureVistor.visitParameterType());
+ }
+ // Use offset + 1 to skip ')'.
+ offset = parseType(signature, offset + 1, signatureVistor.visitReturnType());
+ while (offset < length) {
+ // Use offset + 1 to skip the first character of a ThrowsSignature, i.e. '^'.
+ offset = parseType(signature, offset + 1, signatureVistor.visitExceptionType());
+ }
+ } else {
+ // Otherwise we are parsing a ClassSignature (by hypothesis on the method input), which has
+ // one or more ClassTypeSignature for the super class and the implemented interfaces.
+ offset = parseType(signature, offset, signatureVistor.visitSuperclass());
+ while (offset < length) {
+ offset = parseType(signature, offset, signatureVistor.visitInterface());
+ }
}
+ }
+
+ /**
+ * Makes the given visitor visit the signature of this {@link SignatureReader}. This signature is
+ * the one specified in the constructor (see {@link #SignatureReader}). This method is intended to
+ * be called on a {@link SignatureReader} that was created using a <i>JavaTypeSignature</i>, such
+ * as the <code>signature</code> parameter of the {@link
+ * org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable} methods.
+ *
+ * @param signatureVisitor the visitor that must visit this signature.
+ */
+ public void acceptType(final SignatureVisitor signatureVisitor) {
+ parseType(signatureValue, 0, signatureVisitor);
+ }
+
+ /**
+ * Parses a JavaTypeSignature and makes the given visitor visit it.
+ *
+ * @param signature a string containing the signature that must be parsed.
+ * @param startOffset index of the first character of the signature to parsed.
+ * @param signatureVisitor the visitor that must visit this signature.
+ * @return the index of the first character after the parsed signature.
+ */
+ private static int parseType(
+ final String signature, final int startOffset, final SignatureVisitor signatureVisitor) {
+ int offset = startOffset; // Current offset in the parsed signature.
+ char currentChar = signature.charAt(offset++); // The signature character at 'offset'.
+
+ // Switch based on the first character of the JavaTypeSignature, which indicates its kind.
+ switch (currentChar) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ case 'V':
+ // Case of a BaseType or a VoidDescriptor.
+ signatureVisitor.visitBaseType(currentChar);
+ return offset;
+
+ case '[':
+ // Case of an ArrayTypeSignature, a '[' followed by a JavaTypeSignature.
+ return parseType(signature, offset, signatureVisitor.visitArrayType());
- /**
- * Parses a field type signature and makes the given visitor visit it.
- *
- * @param signature
- * a string containing the signature that must be parsed.
- * @param pos
- * index of the first character of the signature to parsed.
- * @param v
- * the visitor that must visit this signature.
- * @return the index of the first character after the parsed signature.
- */
- private static int parseType(final String signature, int pos,
- final SignatureVisitor v) {
- char c;
- int start, end;
- boolean visited, inner;
- String name;
-
- switch (c = signature.charAt(pos++)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- case 'F':
- case 'J':
- case 'D':
- case 'V':
- v.visitBaseType(c);
- return pos;
-
- case '[':
- return parseType(signature, pos, v.visitArrayType());
-
- case 'T':
- end = signature.indexOf(';', pos);
- v.visitTypeVariable(signature.substring(pos, end));
- return end + 1;
-
- default: // case 'L':
- start = pos;
+ case 'T':
+ // Case of TypeVariableSignature, an identifier between 'T' and ';'.
+ int endOffset = signature.indexOf(';', offset);
+ signatureVisitor.visitTypeVariable(signature.substring(offset, endOffset));
+ return endOffset + 1;
+
+ case 'L':
+ // Case of a ClassTypeSignature, which ends with ';'.
+ // These signatures have a main class type followed by zero or more inner class types
+ // (separated by '.'). Each can have type arguments, inside '<' and '>'.
+ int start = offset; // The start offset of the currently parsed main or inner class name.
+ boolean visited = false; // Whether the currently parsed class name has been visited.
+ boolean inner = false; // Whether we are currently parsing an inner class type.
+ // Parses the signature, one character at a time.
+ while (true) {
+ currentChar = signature.charAt(offset++);
+ if (currentChar == '.' || currentChar == ';') {
+ // If a '.' or ';' is encountered, this means we have fully parsed the main class name
+ // or an inner class name. This name may already have been visited it is was followed by
+ // type arguments between '<' and '>'. If not, we need to visit it here.
+ if (!visited) {
+ String name = signature.substring(start, offset - 1);
+ if (inner) {
+ signatureVisitor.visitInnerClassType(name);
+ } else {
+ signatureVisitor.visitClassType(name);
+ }
+ }
+ // If we reached the end of the ClassTypeSignature return, otherwise start the parsing
+ // of a new class name, which is necessarily an inner class name.
+ if (currentChar == ';') {
+ signatureVisitor.visitEnd();
+ break;
+ }
+ start = offset;
visited = false;
- inner = false;
- for (;;) {
- switch (c = signature.charAt(pos++)) {
- case '.':
- case ';':
- if (!visited) {
- name = signature.substring(start, pos - 1);
- if (inner) {
- v.visitInnerClassType(name);
- } else {
- v.visitClassType(name);
- }
- }
- if (c == ';') {
- v.visitEnd();
- return pos;
- }
- start = pos;
- visited = false;
- inner = true;
- break;
-
- case '<':
- name = signature.substring(start, pos - 1);
- if (inner) {
- v.visitInnerClassType(name);
- } else {
- v.visitClassType(name);
- }
- visited = true;
- top: for (;;) {
- switch (c = signature.charAt(pos)) {
- case '>':
- break top;
- case '*':
- ++pos;
- v.visitTypeArgument();
- break;
- case '+':
- case '-':
- pos = parseType(signature, pos + 1,
- v.visitTypeArgument(c));
- break;
- default:
- pos = parseType(signature, pos,
- v.visitTypeArgument('='));
- break;
- }
- }
- }
+ inner = true;
+ } else if (currentChar == '<') {
+ // If a '<' is encountered, this means we have fully parsed the main class name or an
+ // inner class name, and that we now need to parse TypeArguments. First, we need to
+ // visit the parsed class name.
+ String name = signature.substring(start, offset - 1);
+ if (inner) {
+ signatureVisitor.visitInnerClassType(name);
+ } else {
+ signatureVisitor.visitClassType(name);
}
+ visited = true;
+ // Now, parse the TypeArgument(s), one at a time.
+ while ((currentChar = signature.charAt(offset)) != '>') {
+ switch (currentChar) {
+ case '*':
+ // Unbounded TypeArgument.
+ ++offset;
+ signatureVisitor.visitTypeArgument();
+ break;
+ case '+':
+ case '-':
+ // Extends or Super TypeArgument. Use offset + 1 to skip the '+' or '-'.
+ offset =
+ parseType(
+ signature, offset + 1, signatureVisitor.visitTypeArgument(currentChar));
+ break;
+ default:
+ // Instanceof TypeArgument. The '=' is implicit.
+ offset = parseType(signature, offset, signatureVisitor.visitTypeArgument('='));
+ break;
+ }
+ }
+ }
}
+ return offset;
+
+ default:
+ throw new IllegalArgumentException();
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
old mode 100644
new mode 100755
index 4277ade..3f0cc9a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
@@ -1,238 +1,203 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.signature;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * A visitor to visit a generic signature. The methods of this interface must be
- * called in one of the three following orders (the last one is the only valid
- * order for a {@link SignatureVisitor} that is returned by a method of this
- * interface):
+ * A visitor to visit a generic signature. The methods of this interface must be called in one of
+ * the three following orders (the last one is the only valid order for a {@link SignatureVisitor}
+ * that is returned by a method of this interface):
+ *
* <ul>
- * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
- * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
- * <tt>visitSuperclass</tt> <tt>visitInterface</tt>* )</li>
- * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
- * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
- * <tt>visitParameterType</tt>* <tt>visitReturnType</tt>
- * <tt>visitExceptionType</tt>* )</li>
- * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> |
- * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | (
- * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
- * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt>
- * ) )</li>
+ * <li><i>ClassSignature</i> = ( {@code visitFormalTypeParameter} {@code visitClassBound}? {@code
+ * visitInterfaceBound}* )* ({@code visitSuperclass} {@code visitInterface}* )
+ * <li><i>MethodSignature</i> = ( {@code visitFormalTypeParameter} {@code visitClassBound}? {@code
+ * visitInterfaceBound}* )* ({@code visitParameterType}* {@code visitReturnType} {@code
+ * visitExceptionType}* )
+ * <li><i>TypeSignature</i> = {@code visitBaseType} | {@code visitTypeVariable} | {@code
+ * visitArrayType} | ( {@code visitClassType} {@code visitTypeArgument}* ( {@code
+ * visitInnerClassType} {@code visitTypeArgument}* )* {@code visitEnd} ) )
* </ul>
- *
+ *
* @author Thomas Hallgren
* @author Eric Bruneton
*/
public abstract class SignatureVisitor {
- /**
- * Wildcard for an "extends" type argument.
- */
- public final static char EXTENDS = '+';
-
- /**
- * Wildcard for a "super" type argument.
- */
- public final static char SUPER = '-';
-
- /**
- * Wildcard for a normal type argument.
- */
- public final static char INSTANCEOF = '=';
-
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- protected final int api;
-
- /**
- * Constructs a new {@link SignatureVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public SignatureVisitor(final int api) {
- if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- }
-
- /**
- * Visits a formal type parameter.
- *
- * @param name
- * the name of the formal parameter.
- */
- public void visitFormalTypeParameter(String name) {
- }
-
- /**
- * Visits the class bound of the last visited formal type parameter.
- *
- * @return a non null visitor to visit the signature of the class bound.
- */
- public SignatureVisitor visitClassBound() {
- return this;
- }
-
- /**
- * Visits an interface bound of the last visited formal type parameter.
- *
- * @return a non null visitor to visit the signature of the interface bound.
- */
- public SignatureVisitor visitInterfaceBound() {
- return this;
- }
-
- /**
- * Visits the type of the super class.
- *
- * @return a non null visitor to visit the signature of the super class
- * type.
- */
- public SignatureVisitor visitSuperclass() {
- return this;
- }
-
- /**
- * Visits the type of an interface implemented by the class.
- *
- * @return a non null visitor to visit the signature of the interface type.
- */
- public SignatureVisitor visitInterface() {
- return this;
- }
-
- /**
- * Visits the type of a method parameter.
- *
- * @return a non null visitor to visit the signature of the parameter type.
- */
- public SignatureVisitor visitParameterType() {
- return this;
- }
-
- /**
- * Visits the return type of the method.
- *
- * @return a non null visitor to visit the signature of the return type.
- */
- public SignatureVisitor visitReturnType() {
- return this;
- }
-
- /**
- * Visits the type of a method exception.
- *
- * @return a non null visitor to visit the signature of the exception type.
- */
- public SignatureVisitor visitExceptionType() {
- return this;
- }
-
- /**
- * Visits a signature corresponding to a primitive type.
- *
- * @param descriptor
- * the descriptor of the primitive type, or 'V' for <tt>void</tt>
- * .
- */
- public void visitBaseType(char descriptor) {
- }
-
- /**
- * Visits a signature corresponding to a type variable.
- *
- * @param name
- * the name of the type variable.
- */
- public void visitTypeVariable(String name) {
- }
-
- /**
- * Visits a signature corresponding to an array type.
- *
- * @return a non null visitor to visit the signature of the array element
- * type.
- */
- public SignatureVisitor visitArrayType() {
- return this;
- }
-
- /**
- * Starts the visit of a signature corresponding to a class or interface
- * type.
- *
- * @param name
- * the internal name of the class or interface.
- */
- public void visitClassType(String name) {
- }
-
- /**
- * Visits an inner class.
- *
- * @param name
- * the local name of the inner class in its enclosing class.
- */
- public void visitInnerClassType(String name) {
- }
-
- /**
- * Visits an unbounded type argument of the last visited class or inner
- * class type.
- */
- public void visitTypeArgument() {
- }
-
- /**
- * Visits a type argument of the last visited class or inner class type.
- *
- * @param wildcard
- * '+', '-' or '='.
- * @return a non null visitor to visit the signature of the type argument.
- */
- public SignatureVisitor visitTypeArgument(char wildcard) {
- return this;
- }
-
- /**
- * Ends the visit of a signature corresponding to a class or interface type.
- */
- public void visitEnd() {
- }
+ /** Wildcard for an "extends" type argument. */
+ public static final char EXTENDS = '+';
+
+ /** Wildcard for a "super" type argument. */
+ public static final char SUPER = '-';
+
+ /** Wildcard for a normal type argument. */
+ public static final char INSTANCEOF = '=';
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected final int api;
+
+ /**
+ * Constructs a new {@link SignatureVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public SignatureVisitor(final int api) {
+ if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
+ throw new IllegalArgumentException();
+ }
+ this.api = api;
+ }
+
+ /**
+ * Visits a formal type parameter.
+ *
+ * @param name the name of the formal parameter.
+ */
+ public void visitFormalTypeParameter(final String name) {}
+
+ /**
+ * Visits the class bound of the last visited formal type parameter.
+ *
+ * @return a non null visitor to visit the signature of the class bound.
+ */
+ public SignatureVisitor visitClassBound() {
+ return this;
+ }
+
+ /**
+ * Visits an interface bound of the last visited formal type parameter.
+ *
+ * @return a non null visitor to visit the signature of the interface bound.
+ */
+ public SignatureVisitor visitInterfaceBound() {
+ return this;
+ }
+
+ /**
+ * Visits the type of the super class.
+ *
+ * @return a non null visitor to visit the signature of the super class type.
+ */
+ public SignatureVisitor visitSuperclass() {
+ return this;
+ }
+
+ /**
+ * Visits the type of an interface implemented by the class.
+ *
+ * @return a non null visitor to visit the signature of the interface type.
+ */
+ public SignatureVisitor visitInterface() {
+ return this;
+ }
+
+ /**
+ * Visits the type of a method parameter.
+ *
+ * @return a non null visitor to visit the signature of the parameter type.
+ */
+ public SignatureVisitor visitParameterType() {
+ return this;
+ }
+
+ /**
+ * Visits the return type of the method.
+ *
+ * @return a non null visitor to visit the signature of the return type.
+ */
+ public SignatureVisitor visitReturnType() {
+ return this;
+ }
+
+ /**
+ * Visits the type of a method exception.
+ *
+ * @return a non null visitor to visit the signature of the exception type.
+ */
+ public SignatureVisitor visitExceptionType() {
+ return this;
+ }
+
+ /**
+ * Visits a signature corresponding to a primitive type.
+ *
+ * @param descriptor the descriptor of the primitive type, or 'V' for {@code void} .
+ */
+ public void visitBaseType(final char descriptor) {}
+
+ /**
+ * Visits a signature corresponding to a type variable.
+ *
+ * @param name the name of the type variable.
+ */
+ public void visitTypeVariable(final String name) {}
+
+ /**
+ * Visits a signature corresponding to an array type.
+ *
+ * @return a non null visitor to visit the signature of the array element type.
+ */
+ public SignatureVisitor visitArrayType() {
+ return this;
+ }
+
+ /**
+ * Starts the visit of a signature corresponding to a class or interface type.
+ *
+ * @param name the internal name of the class or interface.
+ */
+ public void visitClassType(final String name) {}
+
+ /**
+ * Visits an inner class.
+ *
+ * @param name the local name of the inner class in its enclosing class.
+ */
+ public void visitInnerClassType(final String name) {}
+
+ /** Visits an unbounded type argument of the last visited class or inner class type. */
+ public void visitTypeArgument() {}
+
+ /**
+ * Visits a type argument of the last visited class or inner class type.
+ *
+ * @param wildcard '+', '-' or '='.
+ * @return a non null visitor to visit the signature of the type argument.
+ */
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ return this;
+ }
+
+ /** Ends the visit of a signature corresponding to a class or interface type. */
+ public void visitEnd() {}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
old mode 100644
new mode 100755
index 8d98cd1..4adc4e2
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
@@ -1,227 +1,240 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.signature;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * A signature visitor that generates signatures in string format.
- *
+ * A SignatureVisitor that generates signature literals, as defined in the Java Virtual Machine
+ * Specification (JVMS).
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1">JVMS
+ * 4.7.9.1</a>
* @author Thomas Hallgren
* @author Eric Bruneton
*/
public class SignatureWriter extends SignatureVisitor {
- /**
- * Builder used to construct the signature.
- */
- private final StringBuilder buf = new StringBuilder();
-
- /**
- * Indicates if the signature contains formal type parameters.
- */
- private boolean hasFormals;
-
- /**
- * Indicates if the signature contains method parameter types.
- */
- private boolean hasParameters;
-
- /**
- * Stack used to keep track of class types that have arguments. Each element
- * of this stack is a boolean encoded in one bit. The top of the stack is
- * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
- * /2.
- */
- private int argumentStack;
-
- /**
- * Constructs a new {@link SignatureWriter} object.
- */
- public SignatureWriter() {
- super(Opcodes.ASM6);
- }
-
- // ------------------------------------------------------------------------
- // Implementation of the SignatureVisitor interface
- // ------------------------------------------------------------------------
-
- @Override
- public void visitFormalTypeParameter(final String name) {
- if (!hasFormals) {
- hasFormals = true;
- buf.append('<');
- }
- buf.append(name);
- buf.append(':');
- }
-
- @Override
- public SignatureVisitor visitClassBound() {
- return this;
- }
-
- @Override
- public SignatureVisitor visitInterfaceBound() {
- buf.append(':');
- return this;
- }
-
- @Override
- public SignatureVisitor visitSuperclass() {
- endFormals();
- return this;
- }
-
- @Override
- public SignatureVisitor visitInterface() {
- return this;
- }
-
- @Override
- public SignatureVisitor visitParameterType() {
- endFormals();
- if (!hasParameters) {
- hasParameters = true;
- buf.append('(');
- }
- return this;
- }
-
- @Override
- public SignatureVisitor visitReturnType() {
- endFormals();
- if (!hasParameters) {
- buf.append('(');
- }
- buf.append(')');
- return this;
- }
-
- @Override
- public SignatureVisitor visitExceptionType() {
- buf.append('^');
- return this;
- }
-
- @Override
- public void visitBaseType(final char descriptor) {
- buf.append(descriptor);
- }
-
- @Override
- public void visitTypeVariable(final String name) {
- buf.append('T');
- buf.append(name);
- buf.append(';');
- }
-
- @Override
- public SignatureVisitor visitArrayType() {
- buf.append('[');
- return this;
- }
-
- @Override
- public void visitClassType(final String name) {
- buf.append('L');
- buf.append(name);
- argumentStack *= 2;
- }
-
- @Override
- public void visitInnerClassType(final String name) {
- endArguments();
- buf.append('.');
- buf.append(name);
- argumentStack *= 2;
- }
-
- @Override
- public void visitTypeArgument() {
- if (argumentStack % 2 == 0) {
- ++argumentStack;
- buf.append('<');
- }
- buf.append('*');
- }
-
- @Override
- public SignatureVisitor visitTypeArgument(final char wildcard) {
- if (argumentStack % 2 == 0) {
- ++argumentStack;
- buf.append('<');
- }
- if (wildcard != '=') {
- buf.append(wildcard);
- }
- return this;
- }
-
- @Override
- public void visitEnd() {
- endArguments();
- buf.append(';');
- }
-
- /**
- * Returns the signature that was built by this signature writer.
- *
- * @return the signature that was built by this signature writer.
- */
- @Override
- public String toString() {
- return buf.toString();
- }
-
- // ------------------------------------------------------------------------
- // Utility methods
- // ------------------------------------------------------------------------
-
- /**
- * Ends the formal type parameters section of the signature.
- */
- private void endFormals() {
- if (hasFormals) {
- hasFormals = false;
- buf.append('>');
- }
- }
-
- /**
- * Ends the type arguments of a class or inner class type.
- */
- private void endArguments() {
- if (argumentStack % 2 != 0) {
- buf.append('>');
- }
- argumentStack /= 2;
- }
-}
\ No newline at end of file
+ /** The builder used to construct the visited signature. */
+ private final StringBuilder stringBuilder = new StringBuilder();
+
+ /** Whether the visited signature contains formal type parameters. */
+ private boolean hasFormals;
+
+ /** Whether the visited signature contains method parameter types. */
+ private boolean hasParameters;
+
+ /**
+ * The stack used to keep track of class types that have arguments. Each element of this stack is
+ * a boolean encoded in one bit. The top of the stack is the least significant bit. Pushing false
+ * = *2, pushing true = *2+1, popping = /2.
+ *
+ * <p>Class type arguments must be surrounded with '<' and '>' and, because
+ *
+ * <ol>
+ * <li>class types can be nested (because type arguments can themselves be class types),
+ * <li>SignatureWriter always returns 'this' in each visit* method (to avoid allocating new
+ * SignatureWriter instances),
+ * </ol>
+ *
+ * <p>we need a stack to properly balance these 'parentheses'. A new element is pushed on this
+ * stack for each new visited type, and popped when the visit of this type ends (either is
+ * visitEnd, or because visitInnerClassType is called).
+ */
+ private int argumentStack;
+
+ /** Constructs a new {@link SignatureWriter}. */
+ public SignatureWriter() {
+ super(Opcodes.ASM7);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the SignatureVisitor interface
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ if (!hasFormals) {
+ hasFormals = true;
+ stringBuilder.append('<');
+ }
+ stringBuilder.append(name);
+ stringBuilder.append(':');
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ stringBuilder.append(':');
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ endFormals();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ endFormals();
+ if (!hasParameters) {
+ hasParameters = true;
+ stringBuilder.append('(');
+ }
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ endFormals();
+ if (!hasParameters) {
+ stringBuilder.append('(');
+ }
+ stringBuilder.append(')');
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ stringBuilder.append('^');
+ return this;
+ }
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ stringBuilder.append(descriptor);
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ stringBuilder.append('T');
+ stringBuilder.append(name);
+ stringBuilder.append(';');
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ stringBuilder.append('[');
+ return this;
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ stringBuilder.append('L');
+ stringBuilder.append(name);
+ // Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as
+ // we can tell at this point).
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ endArguments();
+ stringBuilder.append('.');
+ stringBuilder.append(name);
+ // Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as
+ // we can tell at this point).
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ // If the top of the stack is 'false', this means we are visiting the first type argument of the
+ // currently visited type. We therefore need to append a '<', and to replace the top stack
+ // element with 'true' (meaning that the current type does have type arguments).
+ if (argumentStack % 2 == 0) {
+ argumentStack |= 1;
+ stringBuilder.append('<');
+ }
+ stringBuilder.append('*');
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ // If the top of the stack is 'false', this means we are visiting the first type argument of the
+ // currently visited type. We therefore need to append a '<', and to replace the top stack
+ // element with 'true' (meaning that the current type does have type arguments).
+ if (argumentStack % 2 == 0) {
+ argumentStack |= 1;
+ stringBuilder.append('<');
+ }
+ if (wildcard != '=') {
+ stringBuilder.append(wildcard);
+ }
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ endArguments();
+ stringBuilder.append(';');
+ }
+
+ /**
+ * Returns the signature that was built by this signature writer.
+ *
+ * @return the signature that was built by this signature writer.
+ */
+ @Override
+ public String toString() {
+ return stringBuilder.toString();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
+
+ /** Ends the formal type parameters section of the signature. */
+ private void endFormals() {
+ if (hasFormals) {
+ hasFormals = false;
+ stringBuilder.append('>');
+ }
+ }
+
+ /** Ends the type arguments of a class or inner class type. */
+ private void endArguments() {
+ // If the top of the stack is 'true', this means that some type arguments have been visited for
+ // the type whose visit is now ending. We therefore need to append a '>', and to pop one element
+ // from the stack.
+ if (argumentStack % 2 == 1) {
+ stringBuilder.append('>');
+ }
+ argumentStack /= 2;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/package.html
old mode 100644
new mode 100755
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
old mode 100644
new mode 100755
index a6a01d6..9005565
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
@@ -1,326 +1,265 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
- * A node that represents a bytecode instruction. <i>An instruction can appear
- * at most once in at most one {@link InsnList} at a time</i>.
- *
+ * A node that represents a bytecode instruction. <i>An instruction can appear at most once in at
+ * most one {@link InsnList} at a time</i>.
+ *
* @author Eric Bruneton
*/
public abstract class AbstractInsnNode {
- /**
- * The type of {@link InsnNode} instructions.
- */
- public static final int INSN = 0;
-
- /**
- * The type of {@link IntInsnNode} instructions.
- */
- public static final int INT_INSN = 1;
-
- /**
- * The type of {@link VarInsnNode} instructions.
- */
- public static final int VAR_INSN = 2;
-
- /**
- * The type of {@link TypeInsnNode} instructions.
- */
- public static final int TYPE_INSN = 3;
-
- /**
- * The type of {@link FieldInsnNode} instructions.
- */
- public static final int FIELD_INSN = 4;
-
- /**
- * The type of {@link MethodInsnNode} instructions.
- */
- public static final int METHOD_INSN = 5;
-
- /**
- * The type of {@link InvokeDynamicInsnNode} instructions.
- */
- public static final int INVOKE_DYNAMIC_INSN = 6;
-
- /**
- * The type of {@link JumpInsnNode} instructions.
- */
- public static final int JUMP_INSN = 7;
-
- /**
- * The type of {@link LabelNode} "instructions".
- */
- public static final int LABEL = 8;
-
- /**
- * The type of {@link LdcInsnNode} instructions.
- */
- public static final int LDC_INSN = 9;
-
- /**
- * The type of {@link IincInsnNode} instructions.
- */
- public static final int IINC_INSN = 10;
-
- /**
- * The type of {@link TableSwitchInsnNode} instructions.
- */
- public static final int TABLESWITCH_INSN = 11;
-
- /**
- * The type of {@link LookupSwitchInsnNode} instructions.
- */
- public static final int LOOKUPSWITCH_INSN = 12;
-
- /**
- * The type of {@link MultiANewArrayInsnNode} instructions.
- */
- public static final int MULTIANEWARRAY_INSN = 13;
-
- /**
- * The type of {@link FrameNode} "instructions".
- */
- public static final int FRAME = 14;
-
- /**
- * The type of {@link LineNumberNode} "instructions".
- */
- public static final int LINE = 15;
-
- /**
- * The opcode of this instruction.
- */
- protected int opcode;
-
- /**
- * The runtime visible type annotations of this instruction. This field is
- * only used for real instructions (i.e. not for labels, frames, or line
- * number nodes). This list is a list of {@link TypeAnnotationNode} objects.
- * May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label visible
- */
- public List<TypeAnnotationNode> visibleTypeAnnotations;
-
- /**
- * The runtime invisible type annotations of this instruction. This field is
- * only used for real instructions (i.e. not for labels, frames, or line
- * number nodes). This list is a list of {@link TypeAnnotationNode} objects.
- * May be <tt>null</tt>.
- *
- * @associates org.objectweb.asm.tree.TypeAnnotationNode
- * @label invisible
- */
- public List<TypeAnnotationNode> invisibleTypeAnnotations;
-
- /**
- * Previous instruction in the list to which this instruction belongs.
- */
- AbstractInsnNode prev;
-
- /**
- * Next instruction in the list to which this instruction belongs.
- */
- AbstractInsnNode next;
-
- /**
- * Index of this instruction in the list to which it belongs. The value of
- * this field is correct only when {@link InsnList#cache} is not null. A
- * value of -1 indicates that this instruction does not belong to any
- * {@link InsnList}.
- */
- int index;
-
- /**
- * Constructs a new {@link AbstractInsnNode}.
- *
- * @param opcode
- * the opcode of the instruction to be constructed.
- */
- protected AbstractInsnNode(final int opcode) {
- this.opcode = opcode;
- this.index = -1;
- }
-
- /**
- * Returns the opcode of this instruction.
- *
- * @return the opcode of this instruction.
- */
- public int getOpcode() {
- return opcode;
- }
+ /** The type of {@link InsnNode} instructions. */
+ public static final int INSN = 0;
+
+ /** The type of {@link IntInsnNode} instructions. */
+ public static final int INT_INSN = 1;
- /**
- * Returns the type of this instruction.
- *
- * @return the type of this instruction, i.e. one the constants defined in
- * this class.
- */
- public abstract int getType();
-
- /**
- * Returns the previous instruction in the list to which this instruction
- * belongs, if any.
- *
- * @return the previous instruction in the list to which this instruction
- * belongs, if any. May be <tt>null</tt>.
- */
- public AbstractInsnNode getPrevious() {
- return prev;
+ /** The type of {@link VarInsnNode} instructions. */
+ public static final int VAR_INSN = 2;
+
+ /** The type of {@link TypeInsnNode} instructions. */
+ public static final int TYPE_INSN = 3;
+
+ /** The type of {@link FieldInsnNode} instructions. */
+ public static final int FIELD_INSN = 4;
+
+ /** The type of {@link MethodInsnNode} instructions. */
+ public static final int METHOD_INSN = 5;
+
+ /** The type of {@link InvokeDynamicInsnNode} instructions. */
+ public static final int INVOKE_DYNAMIC_INSN = 6;
+
+ /** The type of {@link JumpInsnNode} instructions. */
+ public static final int JUMP_INSN = 7;
+
+ /** The type of {@link LabelNode} "instructions". */
+ public static final int LABEL = 8;
+
+ /** The type of {@link LdcInsnNode} instructions. */
+ public static final int LDC_INSN = 9;
+
+ /** The type of {@link IincInsnNode} instructions. */
+ public static final int IINC_INSN = 10;
+
+ /** The type of {@link TableSwitchInsnNode} instructions. */
+ public static final int TABLESWITCH_INSN = 11;
+
+ /** The type of {@link LookupSwitchInsnNode} instructions. */
+ public static final int LOOKUPSWITCH_INSN = 12;
+
+ /** The type of {@link MultiANewArrayInsnNode} instructions. */
+ public static final int MULTIANEWARRAY_INSN = 13;
+
+ /** The type of {@link FrameNode} "instructions". */
+ public static final int FRAME = 14;
+
+ /** The type of {@link LineNumberNode} "instructions". */
+ public static final int LINE = 15;
+
+ /** The opcode of this instruction. */
+ protected int opcode;
+
+ /**
+ * The runtime visible type annotations of this instruction. This field is only used for real
+ * instructions (i.e. not for labels, frames, or line number nodes). This list is a list of {@link
+ * TypeAnnotationNode} objects. May be {@literal null}.
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this instruction. This field is only used for real
+ * instructions (i.e. not for labels, frames, or line number nodes). This list is a list of {@link
+ * TypeAnnotationNode} objects. May be {@literal null}.
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /** The previous instruction in the list to which this instruction belongs. */
+ AbstractInsnNode previousInsn;
+
+ /** The next instruction in the list to which this instruction belongs. */
+ AbstractInsnNode nextInsn;
+
+ /**
+ * The index of this instruction in the list to which it belongs. The value of this field is
+ * correct only when {@link InsnList#cache} is not null. A value of -1 indicates that this
+ * instruction does not belong to any {@link InsnList}.
+ */
+ int index;
+
+ /**
+ * Constructs a new {@link AbstractInsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed.
+ */
+ protected AbstractInsnNode(final int opcode) {
+ this.opcode = opcode;
+ this.index = -1;
+ }
+
+ /**
+ * Returns the opcode of this instruction.
+ *
+ * @return the opcode of this instruction.
+ */
+ public int getOpcode() {
+ return opcode;
+ }
+
+ /**
+ * Returns the type of this instruction.
+ *
+ * @return the type of this instruction, i.e. one the constants defined in this class.
+ */
+ public abstract int getType();
+
+ /**
+ * Returns the previous instruction in the list to which this instruction belongs, if any.
+ *
+ * @return the previous instruction in the list to which this instruction belongs, if any. May be
+ * {@literal null}.
+ */
+ public AbstractInsnNode getPrevious() {
+ return previousInsn;
+ }
+
+ /**
+ * Returns the next instruction in the list to which this instruction belongs, if any.
+ *
+ * @return the next instruction in the list to which this instruction belongs, if any. May be
+ * {@literal null}.
+ */
+ public AbstractInsnNode getNext() {
+ return nextInsn;
+ }
+
+ /**
+ * Makes the given method visitor visit this instruction.
+ *
+ * @param methodVisitor a method visitor.
+ */
+ public abstract void accept(MethodVisitor methodVisitor);
+
+ /**
+ * Makes the given visitor visit the annotations of this instruction.
+ *
+ * @param methodVisitor a method visitor.
+ */
+ protected final void acceptAnnotations(final MethodVisitor methodVisitor) {
+ if (visibleTypeAnnotations != null) {
+ for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ methodVisitor.visitInsnAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
+ }
}
-
- /**
- * Returns the next instruction in the list to which this instruction
- * belongs, if any.
- *
- * @return the next instruction in the list to which this instruction
- * belongs, if any. May be <tt>null</tt>.
- */
- public AbstractInsnNode getNext() {
- return next;
+ if (invisibleTypeAnnotations != null) {
+ for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
+ typeAnnotation.accept(
+ methodVisitor.visitInsnAnnotation(
+ typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
+ }
}
-
- /**
- * Makes the given code visitor visit this instruction.
- *
- * @param cv
- * a code visitor.
- */
- public abstract void accept(final MethodVisitor cv);
-
- /**
- * Makes the given visitor visit the annotations of this instruction.
- *
- * @param mv
- * a method visitor.
- */
- protected final void acceptAnnotations(final MethodVisitor mv) {
- int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
- .size();
- for (int i = 0; i < n; ++i) {
- TypeAnnotationNode an = visibleTypeAnnotations.get(i);
- an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
- true));
- }
- n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
- .size();
- for (int i = 0; i < n; ++i) {
- TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
- an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
- false));
- }
+ }
+
+ /**
+ * Returns a copy of this instruction.
+ *
+ * @param clonedLabels a map from LabelNodes to cloned LabelNodes.
+ * @return a copy of this instruction. The returned instruction does not belong to any {@link
+ * InsnList}.
+ */
+ public abstract AbstractInsnNode clone(Map<LabelNode, LabelNode> clonedLabels);
+
+ /**
+ * Returns the clone of the given label.
+ *
+ * @param label a label.
+ * @param clonedLabels a map from LabelNodes to cloned LabelNodes.
+ * @return the clone of the given label.
+ */
+ static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> clonedLabels) {
+ return clonedLabels.get(label);
+ }
+
+ /**
+ * Returns the clones of the given labels.
+ *
+ * @param labels a list of labels.
+ * @param clonedLabels a map from LabelNodes to cloned LabelNodes.
+ * @return the clones of the given labels.
+ */
+ static LabelNode[] clone(
+ final List<LabelNode> labels, final Map<LabelNode, LabelNode> clonedLabels) {
+ LabelNode[] clones = new LabelNode[labels.size()];
+ for (int i = 0, n = clones.length; i < n; ++i) {
+ clones[i] = clonedLabels.get(labels.get(i));
}
-
- /**
- * Returns a copy of this instruction.
- *
- * @param labels
- * a map from LabelNodes to cloned LabelNodes.
- * @return a copy of this instruction. The returned instruction does not
- * belong to any {@link InsnList}.
- */
- public abstract AbstractInsnNode clone(
- final Map<LabelNode, LabelNode> labels);
-
- /**
- * Returns the clone of the given label.
- *
- * @param label
- * a label.
- * @param map
- * a map from LabelNodes to cloned LabelNodes.
- * @return the clone of the given label.
- */
- static LabelNode clone(final LabelNode label,
- final Map<LabelNode, LabelNode> map) {
- return map.get(label);
+ return clones;
+ }
+
+ /**
+ * Clones the annotations of the given instruction into this instruction.
+ *
+ * @param insnNode the source instruction.
+ * @return this instruction.
+ */
+ protected final AbstractInsnNode cloneAnnotations(final AbstractInsnNode insnNode) {
+ if (insnNode.visibleTypeAnnotations != null) {
+ this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+ for (int i = 0, n = insnNode.visibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode sourceAnnotation = insnNode.visibleTypeAnnotations.get(i);
+ TypeAnnotationNode cloneAnnotation =
+ new TypeAnnotationNode(
+ sourceAnnotation.typeRef, sourceAnnotation.typePath, sourceAnnotation.desc);
+ sourceAnnotation.accept(cloneAnnotation);
+ this.visibleTypeAnnotations.add(cloneAnnotation);
+ }
}
-
- /**
- * Returns the clones of the given labels.
- *
- * @param labels
- * a list of labels.
- * @param map
- * a map from LabelNodes to cloned LabelNodes.
- * @return the clones of the given labels.
- */
- static LabelNode[] clone(final List<LabelNode> labels,
- final Map<LabelNode, LabelNode> map) {
- LabelNode[] clones = new LabelNode[labels.size()];
- for (int i = 0; i < clones.length; ++i) {
- clones[i] = map.get(labels.get(i));
- }
- return clones;
- }
-
- /**
- * Clones the annotations of the given instruction into this instruction.
- *
- * @param insn
- * the source instruction.
- * @return this instruction.
- */
- protected final AbstractInsnNode cloneAnnotations(
- final AbstractInsnNode insn) {
- if (insn.visibleTypeAnnotations != null) {
- this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
- for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) {
- TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i);
- TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
- src.typePath, src.desc);
- src.accept(ann);
- this.visibleTypeAnnotations.add(ann);
- }
- }
- if (insn.invisibleTypeAnnotations != null) {
- this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
- for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) {
- TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i);
- TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
- src.typePath, src.desc);
- src.accept(ann);
- this.invisibleTypeAnnotations.add(ann);
- }
- }
- return this;
+ if (insnNode.invisibleTypeAnnotations != null) {
+ this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+ for (int i = 0, n = insnNode.invisibleTypeAnnotations.size(); i < n; ++i) {
+ TypeAnnotationNode sourceAnnotation = insnNode.invisibleTypeAnnotations.get(i);
+ TypeAnnotationNode cloneAnnotation =
+ new TypeAnnotationNode(
+ sourceAnnotation.typeRef, sourceAnnotation.typePath, sourceAnnotation.desc);
+ sourceAnnotation.accept(cloneAnnotation);
+ this.invisibleTypeAnnotations.add(cloneAnnotation);
+ }
}
+ return this;
+ }
}
[17/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
old mode 100644
new mode 100755
index fc88d8e..62de39d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
@@ -1,39 +1,36 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
@@ -48,503 +45,559 @@ import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
/**
- * A semantic bytecode analyzer. <i>This class does not fully check that JSR and
- * RET instructions are valid.</i>
- *
- * @param <V>
- * type of the Value used for the analysis.
- *
+ * A semantic bytecode analyzer. <i>This class does not fully check that JSR and RET instructions
+ * are valid.</i>
+ *
+ * @param <V> type of the Value used for the analysis.
* @author Eric Bruneton
*/
public class Analyzer<V extends Value> implements Opcodes {
- private final Interpreter<V> interpreter;
-
- private int n;
-
- private InsnList insns;
-
- private List<TryCatchBlockNode>[] handlers;
-
- private Frame<V>[] frames;
-
- private Subroutine[] subroutines;
-
- private boolean[] queued;
-
- private int[] queue;
-
- private int top;
+ /** The interpreter to use to symbolically interpret the bytecode instructions. */
+ private final Interpreter<V> interpreter;
+
+ /** The instructions of the currently analyzed method. */
+ private InsnList insnList;
+
+ /** The size of {@link #insnList}. */
+ private int insnListSize;
+
+ /** The exception handlers of the currently analyzed method (one list per instruction index). */
+ private List<TryCatchBlockNode>[] handlers;
+
+ /** The execution stack frames of the currently analyzed method (one per instruction index). */
+ private Frame<V>[] frames;
+
+ /** The subroutines of the currently analyzed method (one per instruction index). */
+ private Subroutine[] subroutines;
+
+ /** The instructions that remain to process (one boolean per instruction index). */
+ private boolean[] inInstructionsToProcess;
+
+ /** The indices of the instructions that remain to process in the currently analyzed method. */
+ private int[] instructionsToProcess;
+
+ /** The number of instructions that remain to process in the currently analyzed method. */
+ private int numInstructionsToProcess;
+
+ /**
+ * Constructs a new {@link Analyzer}.
+ *
+ * @param interpreter the interpreter to use to symbolically interpret the bytecode instructions.
+ */
+ public Analyzer(final Interpreter<V> interpreter) {
+ this.interpreter = interpreter;
+ }
+
+ /**
+ * Analyzes the given method.
+ *
+ * @param owner the internal name of the class to which 'method' belongs.
+ * @param method the method to be analyzed.
+ * @return the symbolic state of the execution stack frame at each bytecode instruction of the
+ * method. The size of the returned array is equal to the number of instructions (and labels)
+ * of the method. A given frame is {@literal null} if and only if the corresponding
+ * instruction cannot be reached (dead code).
+ * @throws AnalyzerException if a problem occurs during the analysis.
+ */
+ @SuppressWarnings("unchecked")
+ public Frame<V>[] analyze(final String owner, final MethodNode method) throws AnalyzerException {
+ if ((method.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+ frames = (Frame<V>[]) new Frame<?>[0];
+ return frames;
+ }
+ insnList = method.instructions;
+ insnListSize = insnList.size();
+ handlers = (List<TryCatchBlockNode>[]) new List<?>[insnListSize];
+ frames = (Frame<V>[]) new Frame<?>[insnListSize];
+ subroutines = new Subroutine[insnListSize];
+ inInstructionsToProcess = new boolean[insnListSize];
+ instructionsToProcess = new int[insnListSize];
+ numInstructionsToProcess = 0;
+
+ // For each exception handler, and each instruction within its range, record in 'handlers' the
+ // fact that execution can flow from this instruction to the exception handler.
+ for (int i = 0; i < method.tryCatchBlocks.size(); ++i) {
+ TryCatchBlockNode tryCatchBlock = method.tryCatchBlocks.get(i);
+ int startIndex = insnList.indexOf(tryCatchBlock.start);
+ int endIndex = insnList.indexOf(tryCatchBlock.end);
+ for (int j = startIndex; j < endIndex; ++j) {
+ List<TryCatchBlockNode> insnHandlers = handlers[j];
+ if (insnHandlers == null) {
+ insnHandlers = new ArrayList<TryCatchBlockNode>();
+ handlers[j] = insnHandlers;
+ }
+ insnHandlers.add(tryCatchBlock);
+ }
+ }
- /**
- * Constructs a new {@link Analyzer}.
- *
- * @param interpreter
- * the interpreter to be used to symbolically interpret the
- * bytecode instructions.
- */
- public Analyzer(final Interpreter<V> interpreter) {
- this.interpreter = interpreter;
+ // For each instruction, compute the subroutine to which it belongs.
+ // Follow the main 'subroutine', and collect the jsr instructions to nested subroutines.
+ Subroutine main = new Subroutine(null, method.maxLocals, null);
+ List<AbstractInsnNode> jsrInsns = new ArrayList<AbstractInsnNode>();
+ findSubroutine(0, main, jsrInsns);
+ // Follow the nested subroutines, and collect their own nested subroutines, until all
+ // subroutines are found.
+ Map<LabelNode, Subroutine> jsrSubroutines = new HashMap<LabelNode, Subroutine>();
+ while (!jsrInsns.isEmpty()) {
+ JumpInsnNode jsrInsn = (JumpInsnNode) jsrInsns.remove(0);
+ Subroutine subroutine = jsrSubroutines.get(jsrInsn.label);
+ if (subroutine == null) {
+ subroutine = new Subroutine(jsrInsn.label, method.maxLocals, jsrInsn);
+ jsrSubroutines.put(jsrInsn.label, subroutine);
+ findSubroutine(insnList.indexOf(jsrInsn.label), subroutine, jsrInsns);
+ } else {
+ subroutine.callers.add(jsrInsn);
+ }
+ }
+ // Clear the main 'subroutine', which is not a real subroutine (and was used only as an
+ // intermediate step above to find the real ones).
+ for (int i = 0; i < insnListSize; ++i) {
+ if (subroutines[i] != null && subroutines[i].start == null) {
+ subroutines[i] = null;
+ }
}
- /**
- * Analyzes the given method.
- *
- * @param owner
- * the internal name of the class to which the method belongs.
- * @param m
- * the method to be analyzed.
- * @return the symbolic state of the execution stack frame at each bytecode
- * instruction of the method. The size of the returned array is
- * equal to the number of instructions (and labels) of the method. A
- * given frame is <tt>null</tt> if and only if the corresponding
- * instruction cannot be reached (dead code).
- * @throws AnalyzerException
- * if a problem occurs during the analysis.
- */
- @SuppressWarnings("unchecked")
- public Frame<V>[] analyze(final String owner, final MethodNode m)
- throws AnalyzerException {
- if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
- frames = (Frame<V>[]) new Frame<?>[0];
- return frames;
- }
- n = m.instructions.size();
- insns = m.instructions;
- handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
- frames = (Frame<V>[]) new Frame<?>[n];
- subroutines = new Subroutine[n];
- queued = new boolean[n];
- queue = new int[n];
- top = 0;
-
- // computes exception handlers for each instruction
- for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
- TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
- int begin = insns.indexOf(tcb.start);
- int end = insns.indexOf(tcb.end);
- for (int j = begin; j < end; ++j) {
- List<TryCatchBlockNode> insnHandlers = handlers[j];
- if (insnHandlers == null) {
- insnHandlers = new ArrayList<TryCatchBlockNode>();
- handlers[j] = insnHandlers;
- }
- insnHandlers.add(tcb);
+ // Initializes the data structures for the control flow analysis.
+ Frame<V> currentFrame = computeInitialFrame(owner, method);
+ merge(0, currentFrame, null);
+ init(owner, method);
+
+ // Control flow analysis.
+ while (numInstructionsToProcess > 0) {
+ // Get and remove one instruction from the list of instructions to process.
+ int insnIndex = instructionsToProcess[--numInstructionsToProcess];
+ Frame<V> oldFrame = frames[insnIndex];
+ Subroutine subroutine = subroutines[insnIndex];
+ inInstructionsToProcess[insnIndex] = false;
+
+ // Simulate the execution of this instruction.
+ AbstractInsnNode insnNode = null;
+ try {
+ insnNode = method.instructions.get(insnIndex);
+ int insnOpcode = insnNode.getOpcode();
+ int insnType = insnNode.getType();
+
+ if (insnType == AbstractInsnNode.LABEL
+ || insnType == AbstractInsnNode.LINE
+ || insnType == AbstractInsnNode.FRAME) {
+ merge(insnIndex + 1, oldFrame, subroutine);
+ newControlFlowEdge(insnIndex, insnIndex + 1);
+ } else {
+ currentFrame.init(oldFrame).execute(insnNode, interpreter);
+ subroutine = subroutine == null ? null : new Subroutine(subroutine);
+
+ if (insnNode instanceof JumpInsnNode) {
+ JumpInsnNode jumpInsn = (JumpInsnNode) insnNode;
+ if (insnOpcode != GOTO && insnOpcode != JSR) {
+ currentFrame.initJumpTarget(insnOpcode, /* target = */ null);
+ merge(insnIndex + 1, currentFrame, subroutine);
+ newControlFlowEdge(insnIndex, insnIndex + 1);
}
- }
-
- // computes the subroutine for each instruction:
- Subroutine main = new Subroutine(null, m.maxLocals, null);
- List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
- Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
- findSubroutine(0, main, subroutineCalls);
- while (!subroutineCalls.isEmpty()) {
- JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
- Subroutine sub = subroutineHeads.get(jsr.label);
- if (sub == null) {
- sub = new Subroutine(jsr.label, m.maxLocals, jsr);
- subroutineHeads.put(jsr.label, sub);
- findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
+ int jumpInsnIndex = insnList.indexOf(jumpInsn.label);
+ currentFrame.initJumpTarget(insnOpcode, jumpInsn.label);
+ if (insnOpcode == JSR) {
+ merge(
+ jumpInsnIndex,
+ currentFrame,
+ new Subroutine(jumpInsn.label, method.maxLocals, jumpInsn));
} else {
- sub.callers.add(jsr);
+ merge(jumpInsnIndex, currentFrame, subroutine);
}
- }
- for (int i = 0; i < n; ++i) {
- if (subroutines[i] != null && subroutines[i].start == null) {
- subroutines[i] = null;
+ newControlFlowEdge(insnIndex, jumpInsnIndex);
+ } else if (insnNode instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) insnNode;
+ int targetInsnIndex = insnList.indexOf(lookupSwitchInsn.dflt);
+ currentFrame.initJumpTarget(insnOpcode, lookupSwitchInsn.dflt);
+ merge(targetInsnIndex, currentFrame, subroutine);
+ newControlFlowEdge(insnIndex, targetInsnIndex);
+ for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) {
+ LabelNode label = lookupSwitchInsn.labels.get(i);
+ targetInsnIndex = insnList.indexOf(label);
+ currentFrame.initJumpTarget(insnOpcode, label);
+ merge(targetInsnIndex, currentFrame, subroutine);
+ newControlFlowEdge(insnIndex, targetInsnIndex);
}
- }
-
- // initializes the data structures for the control flow analysis
- Frame<V> current = newFrame(m.maxLocals, m.maxStack);
- Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
- current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
- Type[] args = Type.getArgumentTypes(m.desc);
- int local = 0;
- if ((m.access & ACC_STATIC) == 0) {
- Type ctype = Type.getObjectType(owner);
- current.setLocal(local++, interpreter.newValue(ctype));
- }
- for (int i = 0; i < args.length; ++i) {
- current.setLocal(local++, interpreter.newValue(args[i]));
- if (args[i].getSize() == 2) {
- current.setLocal(local++, interpreter.newValue(null));
+ } else if (insnNode instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) insnNode;
+ int targetInsnIndex = insnList.indexOf(tableSwitchInsn.dflt);
+ currentFrame.initJumpTarget(insnOpcode, tableSwitchInsn.dflt);
+ merge(targetInsnIndex, currentFrame, subroutine);
+ newControlFlowEdge(insnIndex, targetInsnIndex);
+ for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) {
+ LabelNode label = tableSwitchInsn.labels.get(i);
+ currentFrame.initJumpTarget(insnOpcode, label);
+ targetInsnIndex = insnList.indexOf(label);
+ merge(targetInsnIndex, currentFrame, subroutine);
+ newControlFlowEdge(insnIndex, targetInsnIndex);
}
- }
- while (local < m.maxLocals) {
- current.setLocal(local++, interpreter.newValue(null));
- }
- merge(0, current, null);
-
- init(owner, m);
-
- // control flow analysis
- while (top > 0) {
- int insn = queue[--top];
- Frame<V> f = frames[insn];
- Subroutine subroutine = subroutines[insn];
- queued[insn] = false;
-
- AbstractInsnNode insnNode = null;
- try {
- insnNode = m.instructions.get(insn);
- int insnOpcode = insnNode.getOpcode();
- int insnType = insnNode.getType();
-
- if (insnType == AbstractInsnNode.LABEL
- || insnType == AbstractInsnNode.LINE
- || insnType == AbstractInsnNode.FRAME) {
- merge(insn + 1, f, subroutine);
- newControlFlowEdge(insn, insn + 1);
- } else {
- current.init(f).execute(insnNode, interpreter);
- subroutine = subroutine == null ? null : subroutine.copy();
-
- if (insnNode instanceof JumpInsnNode) {
- JumpInsnNode j = (JumpInsnNode) insnNode;
- if (insnOpcode != GOTO && insnOpcode != JSR) {
- merge(insn + 1, current, subroutine);
- newControlFlowEdge(insn, insn + 1);
- }
- int jump = insns.indexOf(j.label);
- if (insnOpcode == JSR) {
- merge(jump, current, new Subroutine(j.label,
- m.maxLocals, j));
- } else {
- merge(jump, current, subroutine);
- }
- newControlFlowEdge(insn, jump);
- } else if (insnNode instanceof LookupSwitchInsnNode) {
- LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
- int jump = insns.indexOf(lsi.dflt);
- merge(jump, current, subroutine);
- newControlFlowEdge(insn, jump);
- for (int j = 0; j < lsi.labels.size(); ++j) {
- LabelNode label = lsi.labels.get(j);
- jump = insns.indexOf(label);
- merge(jump, current, subroutine);
- newControlFlowEdge(insn, jump);
- }
- } else if (insnNode instanceof TableSwitchInsnNode) {
- TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
- int jump = insns.indexOf(tsi.dflt);
- merge(jump, current, subroutine);
- newControlFlowEdge(insn, jump);
- for (int j = 0; j < tsi.labels.size(); ++j) {
- LabelNode label = tsi.labels.get(j);
- jump = insns.indexOf(label);
- merge(jump, current, subroutine);
- newControlFlowEdge(insn, jump);
- }
- } else if (insnOpcode == RET) {
- if (subroutine == null) {
- throw new AnalyzerException(insnNode,
- "RET instruction outside of a sub routine");
- }
- for (int i = 0; i < subroutine.callers.size(); ++i) {
- JumpInsnNode caller = subroutine.callers.get(i);
- int call = insns.indexOf(caller);
- if (frames[call] != null) {
- merge(call + 1, frames[call], current,
- subroutines[call], subroutine.access);
- newControlFlowEdge(insn, call + 1);
- }
- }
- } else if (insnOpcode != ATHROW
- && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
- if (subroutine != null) {
- if (insnNode instanceof VarInsnNode) {
- int var = ((VarInsnNode) insnNode).var;
- subroutine.access[var] = true;
- if (insnOpcode == LLOAD || insnOpcode == DLOAD
- || insnOpcode == LSTORE
- || insnOpcode == DSTORE) {
- subroutine.access[var + 1] = true;
- }
- } else if (insnNode instanceof IincInsnNode) {
- int var = ((IincInsnNode) insnNode).var;
- subroutine.access[var] = true;
- }
- }
- merge(insn + 1, current, subroutine);
- newControlFlowEdge(insn, insn + 1);
- }
- }
-
- List<TryCatchBlockNode> insnHandlers = handlers[insn];
- if (insnHandlers != null) {
- for (int i = 0; i < insnHandlers.size(); ++i) {
- TryCatchBlockNode tcb = insnHandlers.get(i);
- Type type;
- if (tcb.type == null) {
- type = Type.getObjectType("java/lang/Throwable");
- } else {
- type = Type.getObjectType(tcb.type);
- }
- int jump = insns.indexOf(tcb.handler);
- if (newControlFlowExceptionEdge(insn, tcb)) {
- handler.init(f);
- handler.clearStack();
- handler.push(interpreter.newValue(type));
- merge(jump, handler, subroutine);
- }
- }
- }
- } catch (AnalyzerException e) {
- throw new AnalyzerException(e.node, "Error at instruction "
- + insn + ": " + e.getMessage(), e);
- } catch (Exception e) {
- throw new AnalyzerException(insnNode, "Error at instruction "
- + insn + ": " + e.getMessage(), e);
+ } else if (insnOpcode == RET) {
+ if (subroutine == null) {
+ throw new AnalyzerException(insnNode, "RET instruction outside of a sub routine");
}
- }
-
- return frames;
- }
-
- private void findSubroutine(int insn, final Subroutine sub,
- final List<AbstractInsnNode> calls) throws AnalyzerException {
- while (true) {
- if (insn < 0 || insn >= n) {
- throw new AnalyzerException(null,
- "Execution can fall off end of the code");
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ JumpInsnNode caller = subroutine.callers.get(i);
+ int jsrInsnIndex = insnList.indexOf(caller);
+ if (frames[jsrInsnIndex] != null) {
+ merge(
+ jsrInsnIndex + 1,
+ frames[jsrInsnIndex],
+ currentFrame,
+ subroutines[jsrInsnIndex],
+ subroutine.localsUsed);
+ newControlFlowEdge(insnIndex, jsrInsnIndex + 1);
+ }
}
- if (subroutines[insn] != null) {
- return;
- }
- subroutines[insn] = sub.copy();
- AbstractInsnNode node = insns.get(insn);
-
- // calls findSubroutine recursively on normal successors
- if (node instanceof JumpInsnNode) {
- if (node.getOpcode() == JSR) {
- // do not follow a JSR, it leads to another subroutine!
- calls.add(node);
- } else {
- JumpInsnNode jnode = (JumpInsnNode) node;
- findSubroutine(insns.indexOf(jnode.label), sub, calls);
- }
- } else if (node instanceof TableSwitchInsnNode) {
- TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
- findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
- for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
- LabelNode l = tsnode.labels.get(i);
- findSubroutine(insns.indexOf(l), sub, calls);
- }
- } else if (node instanceof LookupSwitchInsnNode) {
- LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
- findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
- for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
- LabelNode l = lsnode.labels.get(i);
- findSubroutine(insns.indexOf(l), sub, calls);
+ } else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
+ if (subroutine != null) {
+ if (insnNode instanceof VarInsnNode) {
+ int var = ((VarInsnNode) insnNode).var;
+ subroutine.localsUsed[var] = true;
+ if (insnOpcode == LLOAD
+ || insnOpcode == DLOAD
+ || insnOpcode == LSTORE
+ || insnOpcode == DSTORE) {
+ subroutine.localsUsed[var + 1] = true;
}
+ } else if (insnNode instanceof IincInsnNode) {
+ int var = ((IincInsnNode) insnNode).var;
+ subroutine.localsUsed[var] = true;
+ }
}
+ merge(insnIndex + 1, currentFrame, subroutine);
+ newControlFlowEdge(insnIndex, insnIndex + 1);
+ }
+ }
- // calls findSubroutine recursively on exception handler successors
- List<TryCatchBlockNode> insnHandlers = handlers[insn];
- if (insnHandlers != null) {
- for (int i = 0; i < insnHandlers.size(); ++i) {
- TryCatchBlockNode tcb = insnHandlers.get(i);
- findSubroutine(insns.indexOf(tcb.handler), sub, calls);
- }
+ List<TryCatchBlockNode> insnHandlers = handlers[insnIndex];
+ if (insnHandlers != null) {
+ for (TryCatchBlockNode tryCatchBlock : insnHandlers) {
+ Type catchType;
+ if (tryCatchBlock.type == null) {
+ catchType = Type.getObjectType("java/lang/Throwable");
+ } else {
+ catchType = Type.getObjectType(tryCatchBlock.type);
}
-
- // if insn does not falls through to the next instruction, return.
- switch (node.getOpcode()) {
- case GOTO:
- case RET:
- case TABLESWITCH:
- case LOOKUPSWITCH:
- case IRETURN:
- case LRETURN:
- case FRETURN:
- case DRETURN:
- case ARETURN:
- case RETURN:
- case ATHROW:
- return;
+ if (newControlFlowExceptionEdge(insnIndex, tryCatchBlock)) {
+ Frame<V> handler = newFrame(oldFrame);
+ handler.clearStack();
+ handler.push(interpreter.newExceptionValue(tryCatchBlock, handler, catchType));
+ merge(insnList.indexOf(tryCatchBlock.handler), handler, subroutine);
}
- insn++;
+ }
}
+ } catch (AnalyzerException e) {
+ throw new AnalyzerException(
+ e.node, "Error at instruction " + insnIndex + ": " + e.getMessage(), e);
+ } catch (RuntimeException e) {
+ // DontCheck(IllegalCatch): can't be fixed, for backward compatibility.
+ throw new AnalyzerException(
+ insnNode, "Error at instruction " + insnIndex + ": " + e.getMessage(), e);
+ }
}
- /**
- * Returns the symbolic stack frame for each instruction of the last
- * recently analyzed method.
- *
- * @return the symbolic state of the execution stack frame at each bytecode
- * instruction of the method. The size of the returned array is
- * equal to the number of instructions (and labels) of the method. A
- * given frame is <tt>null</tt> if the corresponding instruction
- * cannot be reached, or if an error occured during the analysis of
- * the method.
- */
- public Frame<V>[] getFrames() {
- return frames;
- }
+ return frames;
+ }
+
+ /**
+ * Follows the control flow graph of the currently analyzed method, starting at the given
+ * instruction index, and stores a copy of the given subroutine in {@link #subroutines} for each
+ * encountered instruction. Jumps to nested subroutines are <i>not</i> followed: instead, the
+ * corresponding instructions are put in the given list.
+ *
+ * @param insnIndex an instruction index.
+ * @param subroutine a subroutine.
+ * @param jsrInsns where the jsr instructions for nested subroutines must be put.
+ * @throws AnalyzerException if the control flow graph can fall off the end of the code.
+ */
+ private void findSubroutine(
+ final int insnIndex, final Subroutine subroutine, final List<AbstractInsnNode> jsrInsns)
+ throws AnalyzerException {
+ ArrayList<Integer> instructionIndicesToProcess = new ArrayList<Integer>();
+ instructionIndicesToProcess.add(insnIndex);
+ while (!instructionIndicesToProcess.isEmpty()) {
+ int currentInsnIndex =
+ instructionIndicesToProcess.remove(instructionIndicesToProcess.size() - 1);
+ if (currentInsnIndex < 0 || currentInsnIndex >= insnListSize) {
+ throw new AnalyzerException(null, "Execution can fall off the end of the code");
+ }
+ if (subroutines[currentInsnIndex] != null) {
+ continue;
+ }
+ subroutines[currentInsnIndex] = new Subroutine(subroutine);
+ AbstractInsnNode currentInsn = insnList.get(currentInsnIndex);
+
+ // Push the normal successors of currentInsn onto instructionIndicesToProcess.
+ if (currentInsn instanceof JumpInsnNode) {
+ if (currentInsn.getOpcode() == JSR) {
+ // Do not follow a jsr, it leads to another subroutine!
+ jsrInsns.add(currentInsn);
+ } else {
+ JumpInsnNode jumpInsn = (JumpInsnNode) currentInsn;
+ instructionIndicesToProcess.add(insnList.indexOf(jumpInsn.label));
+ }
+ } else if (currentInsn instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) currentInsn;
+ findSubroutine(insnList.indexOf(tableSwitchInsn.dflt), subroutine, jsrInsns);
+ for (int i = tableSwitchInsn.labels.size() - 1; i >= 0; --i) {
+ LabelNode labelNode = tableSwitchInsn.labels.get(i);
+ instructionIndicesToProcess.add(insnList.indexOf(labelNode));
+ }
+ } else if (currentInsn instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) currentInsn;
+ findSubroutine(insnList.indexOf(lookupSwitchInsn.dflt), subroutine, jsrInsns);
+ for (int i = lookupSwitchInsn.labels.size() - 1; i >= 0; --i) {
+ LabelNode labelNode = lookupSwitchInsn.labels.get(i);
+ instructionIndicesToProcess.add(insnList.indexOf(labelNode));
+ }
+ }
- /**
- * Returns the exception handlers for the given instruction.
- *
- * @param insn
- * the index of an instruction of the last recently analyzed
- * method.
- * @return a list of {@link TryCatchBlockNode} objects.
- */
- public List<TryCatchBlockNode> getHandlers(final int insn) {
- return handlers[insn];
+ // Push the exception handler successors of currentInsn onto instructionIndicesToProcess.
+ List<TryCatchBlockNode> insnHandlers = handlers[currentInsnIndex];
+ if (insnHandlers != null) {
+ for (TryCatchBlockNode tryCatchBlock : insnHandlers) {
+ instructionIndicesToProcess.add(insnList.indexOf(tryCatchBlock.handler));
+ }
+ }
+
+ // Push the next instruction, if the control flow can go from currentInsn to the next.
+ switch (currentInsn.getOpcode()) {
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ break;
+ default:
+ instructionIndicesToProcess.add(currentInsnIndex + 1);
+ break;
+ }
}
-
- /**
- * Initializes this analyzer. This method is called just before the
- * execution of control flow analysis loop in #analyze. The default
- * implementation of this method does nothing.
- *
- * @param owner
- * the internal name of the class to which the method belongs.
- * @param m
- * the method to be analyzed.
- * @throws AnalyzerException
- * if a problem occurs.
- */
- protected void init(String owner, MethodNode m) throws AnalyzerException {
+ }
+
+ /**
+ * Computes the initial execution stack frame of the given method.
+ *
+ * @param owner the internal name of the class to which 'method' belongs.
+ * @param method the method to be analyzed.
+ * @return the initial execution stack frame of the 'method'.
+ */
+ private Frame<V> computeInitialFrame(final String owner, final MethodNode method) {
+ Frame<V> frame = newFrame(method.maxLocals, method.maxStack);
+ int currentLocal = 0;
+ boolean isInstanceMethod = (method.access & ACC_STATIC) == 0;
+ if (isInstanceMethod) {
+ Type ownerType = Type.getObjectType(owner);
+ frame.setLocal(
+ currentLocal, interpreter.newParameterValue(isInstanceMethod, currentLocal, ownerType));
+ currentLocal++;
}
-
- /**
- * Constructs a new frame with the given size.
- *
- * @param nLocals
- * the maximum number of local variables of the frame.
- * @param nStack
- * the maximum stack size of the frame.
- * @return the created frame.
- */
- protected Frame<V> newFrame(final int nLocals, final int nStack) {
- return new Frame<V>(nLocals, nStack);
+ Type[] argumentTypes = Type.getArgumentTypes(method.desc);
+ for (Type argumentType : argumentTypes) {
+ frame.setLocal(
+ currentLocal,
+ interpreter.newParameterValue(isInstanceMethod, currentLocal, argumentType));
+ currentLocal++;
+ if (argumentType.getSize() == 2) {
+ frame.setLocal(currentLocal, interpreter.newEmptyValue(currentLocal));
+ currentLocal++;
+ }
}
-
- /**
- * Constructs a new frame that is identical to the given frame.
- *
- * @param src
- * a frame.
- * @return the created frame.
- */
- protected Frame<V> newFrame(final Frame<? extends V> src) {
- return new Frame<V>(src);
+ while (currentLocal < method.maxLocals) {
+ frame.setLocal(currentLocal, interpreter.newEmptyValue(currentLocal));
+ currentLocal++;
}
-
- /**
- * Creates a control flow graph edge. The default implementation of this
- * method does nothing. It can be overriden in order to construct the
- * control flow graph of a method (this method is called by the
- * {@link #analyze analyze} method during its visit of the method's code).
- *
- * @param insn
- * an instruction index.
- * @param successor
- * index of a successor instruction.
- */
- protected void newControlFlowEdge(final int insn, final int successor) {
+ frame.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(method.desc)));
+ return frame;
+ }
+
+ /**
+ * Returns the symbolic execution stack frame for each instruction of the last analyzed method.
+ *
+ * @return the symbolic state of the execution stack frame at each bytecode instruction of the
+ * method. The size of the returned array is equal to the number of instructions (and labels)
+ * of the method. A given frame is {@literal null} if the corresponding instruction cannot be
+ * reached, or if an error occurred during the analysis of the method.
+ */
+ public Frame<V>[] getFrames() {
+ return frames;
+ }
+
+ /**
+ * Returns the exception handlers for the given instruction.
+ *
+ * @param insnIndex the index of an instruction of the last analyzed method.
+ * @return a list of {@link TryCatchBlockNode} objects.
+ */
+ public List<TryCatchBlockNode> getHandlers(final int insnIndex) {
+ return handlers[insnIndex];
+ }
+
+ /**
+ * Initializes this analyzer. This method is called just before the execution of control flow
+ * analysis loop in #analyze. The default implementation of this method does nothing.
+ *
+ * @param owner the internal name of the class to which the method belongs.
+ * @param method the method to be analyzed.
+ * @throws AnalyzerException if a problem occurs.
+ */
+ protected void init(final String owner, final MethodNode method) throws AnalyzerException {
+ // Nothing to do.
+ }
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param numLocals the maximum number of local variables of the frame.
+ * @param numStack the maximum stack size of the frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final int numLocals, final int numStack) {
+ return new Frame<V>(numLocals, numStack);
+ }
+
+ /**
+ * Constructs a copy of the given frame.
+ *
+ * @param frame a frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final Frame<? extends V> frame) {
+ return new Frame<V>(frame);
+ }
+
+ /**
+ * Creates a control flow graph edge. The default implementation of this method does nothing. It
+ * can be overridden in order to construct the control flow graph of a method (this method is
+ * called by the {@link #analyze} method during its visit of the method's code).
+ *
+ * @param insnIndex an instruction index.
+ * @param successorIndex index of a successor instruction.
+ */
+ protected void newControlFlowEdge(final int insnIndex, final int successorIndex) {
+ // Nothing to do.
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler. The default
+ * implementation of this method does nothing. It can be overridden in order to construct the
+ * control flow graph of a method (this method is called by the {@link #analyze} method during its
+ * visit of the method's code).
+ *
+ * @param insnIndex an instruction index.
+ * @param successorIndex index of a successor instruction.
+ * @return true if this edge must be considered in the data flow analysis performed by this
+ * analyzer, or false otherwise. The default implementation of this method always returns
+ * true.
+ */
+ protected boolean newControlFlowExceptionEdge(final int insnIndex, final int successorIndex) {
+ return true;
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler. The default
+ * implementation of this method delegates to {@link #newControlFlowExceptionEdge(int, int)}. It
+ * can be overridden in order to construct the control flow graph of a method (this method is
+ * called by the {@link #analyze} method during its visit of the method's code).
+ *
+ * @param insnIndex an instruction index.
+ * @param tryCatchBlock TryCatchBlockNode corresponding to this edge.
+ * @return true if this edge must be considered in the data flow analysis performed by this
+ * analyzer, or false otherwise. The default implementation of this method delegates to {@link
+ * #newControlFlowExceptionEdge(int, int)}.
+ */
+ protected boolean newControlFlowExceptionEdge(
+ final int insnIndex, final TryCatchBlockNode tryCatchBlock) {
+ return newControlFlowExceptionEdge(insnIndex, insnList.indexOf(tryCatchBlock.handler));
+ }
+
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Merges the given frame and subroutine into the frame and subroutines at the given instruction
+ * index. If the frame or the subroutine at the given instruction index changes as a result of
+ * this merge, the instruction index is added to the list of instructions to process (if it is not
+ * already the case).
+ *
+ * @param insnIndex an instruction index.
+ * @param frame a frame. This frame is left unchanged by this method.
+ * @param subroutine a subroutine. This subroutine is left unchanged by this method.
+ * @throws AnalyzerException if the frames have incompatible sizes.
+ */
+ private void merge(final int insnIndex, final Frame<V> frame, final Subroutine subroutine)
+ throws AnalyzerException {
+ boolean changed;
+ Frame<V> oldFrame = frames[insnIndex];
+ if (oldFrame == null) {
+ frames[insnIndex] = newFrame(frame);
+ changed = true;
+ } else {
+ changed = oldFrame.merge(frame, interpreter);
}
-
- /**
- * Creates a control flow graph edge corresponding to an exception handler.
- * The default implementation of this method does nothing. It can be
- * overridden in order to construct the control flow graph of a method (this
- * method is called by the {@link #analyze analyze} method during its visit
- * of the method's code).
- *
- * @param insn
- * an instruction index.
- * @param successor
- * index of a successor instruction.
- * @return true if this edge must be considered in the data flow analysis
- * performed by this analyzer, or false otherwise. The default
- * implementation of this method always returns true.
- */
- protected boolean newControlFlowExceptionEdge(final int insn,
- final int successor) {
- return true;
+ Subroutine oldSubroutine = subroutines[insnIndex];
+ if (oldSubroutine == null) {
+ if (subroutine != null) {
+ subroutines[insnIndex] = new Subroutine(subroutine);
+ changed = true;
+ }
+ } else {
+ if (subroutine != null) {
+ changed |= oldSubroutine.merge(subroutine);
+ }
}
-
- /**
- * Creates a control flow graph edge corresponding to an exception handler.
- * The default implementation of this method delegates to
- * {@link #newControlFlowExceptionEdge(int, int)
- * newControlFlowExceptionEdge(int, int)}. It can be overridden in order to
- * construct the control flow graph of a method (this method is called by
- * the {@link #analyze analyze} method during its visit of the method's
- * code).
- *
- * @param insn
- * an instruction index.
- * @param tcb
- * TryCatchBlockNode corresponding to this edge.
- * @return true if this edge must be considered in the data flow analysis
- * performed by this analyzer, or false otherwise. The default
- * implementation of this method delegates to
- * {@link #newControlFlowExceptionEdge(int, int)
- * newControlFlowExceptionEdge(int, int)}.
- */
- protected boolean newControlFlowExceptionEdge(final int insn,
- final TryCatchBlockNode tcb) {
- return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
+ if (changed && !inInstructionsToProcess[insnIndex]) {
+ inInstructionsToProcess[insnIndex] = true;
+ instructionsToProcess[numInstructionsToProcess++] = insnIndex;
}
-
- // -------------------------------------------------------------------------
-
- private void merge(final int insn, final Frame<V> frame,
- final Subroutine subroutine) throws AnalyzerException {
- Frame<V> oldFrame = frames[insn];
- Subroutine oldSubroutine = subroutines[insn];
- boolean changes;
-
- if (oldFrame == null) {
- frames[insn] = newFrame(frame);
- changes = true;
- } else {
- changes = oldFrame.merge(frame, interpreter);
- }
-
- if (oldSubroutine == null) {
- if (subroutine != null) {
- subroutines[insn] = subroutine.copy();
- changes = true;
- }
- } else {
- if (subroutine != null) {
- changes |= oldSubroutine.merge(subroutine);
- }
- }
- if (changes && !queued[insn]) {
- queued[insn] = true;
- queue[top++] = insn;
- }
+ }
+
+ /**
+ * Merges the given frame and subroutine into the frame and subroutines at the given instruction
+ * index (case of a RET instruction). If the frame or the subroutine at the given instruction
+ * index changes as a result of this merge, the instruction index is added to the list of
+ * instructions to process (if it is not already the case).
+ *
+ * @param insnIndex the index of an instruction immediately following a jsr instruction.
+ * @param frameBeforeJsr the execution stack frame before the jsr instruction. This frame is
+ * merged into 'frameAfterRet'.
+ * @param frameAfterRet the execution stack frame after a ret instruction of the subroutine. This
+ * frame is merged into the frame at 'insnIndex' (after it has itself been merge with
+ * 'frameBeforeJsr').
+ * @param subroutineBeforeJsr if the jsr is itself part of a subroutine (case of nested
+ * subroutine), the subroutine it belongs to.
+ * @param localsUsed the local variables read or written in the subroutine.
+ * @throws AnalyzerException if the frames have incompatible sizes.
+ */
+ private void merge(
+ final int insnIndex,
+ final Frame<V> frameBeforeJsr,
+ final Frame<V> frameAfterRet,
+ final Subroutine subroutineBeforeJsr,
+ final boolean[] localsUsed)
+ throws AnalyzerException {
+ frameAfterRet.merge(frameBeforeJsr, localsUsed);
+
+ boolean changed;
+ Frame<V> oldFrame = frames[insnIndex];
+ if (oldFrame == null) {
+ frames[insnIndex] = newFrame(frameAfterRet);
+ changed = true;
+ } else {
+ changed = oldFrame.merge(frameAfterRet, interpreter);
}
-
- private void merge(final int insn, final Frame<V> beforeJSR,
- final Frame<V> afterRET, final Subroutine subroutineBeforeJSR,
- final boolean[] access) throws AnalyzerException {
- Frame<V> oldFrame = frames[insn];
- Subroutine oldSubroutine = subroutines[insn];
- boolean changes;
-
- afterRET.merge(beforeJSR, access);
-
- if (oldFrame == null) {
- frames[insn] = newFrame(afterRET);
- changes = true;
- } else {
- changes = oldFrame.merge(afterRET, interpreter);
- }
-
- if (oldSubroutine != null && subroutineBeforeJSR != null) {
- changes |= oldSubroutine.merge(subroutineBeforeJSR);
- }
- if (changes && !queued[insn]) {
- queued[insn] = true;
- queue[top++] = insn;
- }
+ Subroutine oldSubroutine = subroutines[insnIndex];
+ if (oldSubroutine != null && subroutineBeforeJsr != null) {
+ changed |= oldSubroutine.merge(subroutineBeforeJsr);
+ }
+ if (changed && !inInstructionsToProcess[insnIndex]) {
+ inInstructionsToProcess[insnIndex] = true;
+ instructionsToProcess[numInstructionsToProcess++] = insnIndex;
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
old mode 100644
new mode 100755
index 14f5cff..fc4d0f1
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
@@ -1,62 +1,89 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
/**
- * Thrown if a problem occurs during the analysis of a method.
- *
+ * An exception thrown if a problem occurs during the analysis of a method.
+ *
* @author Bing Ran
* @author Eric Bruneton
*/
-@SuppressWarnings("serial")
public class AnalyzerException extends Exception {
- public final AbstractInsnNode node;
+ private static final long serialVersionUID = 3154190448018943333L;
+
+ /** The bytecode instruction where the analysis failed. */
+ public final transient AbstractInsnNode node;
- public AnalyzerException(final AbstractInsnNode node, final String msg) {
- super(msg);
- this.node = node;
- }
+ /**
+ * Constructs a new {@link AnalyzerException}.
+ *
+ * @param insn the bytecode instruction where the analysis failed.
+ * @param message the reason why the analysis failed.
+ */
+ public AnalyzerException(final AbstractInsnNode insn, final String message) {
+ super(message);
+ this.node = insn;
+ }
- public AnalyzerException(final AbstractInsnNode node, final String msg,
- final Throwable exception) {
- super(msg, exception);
- this.node = node;
- }
+ /**
+ * Constructs a new {@link AnalyzerException}.
+ *
+ * @param insn the bytecode instruction where the analysis failed.
+ * @param message the reason why the analysis failed.
+ * @param cause the cause of the failure.
+ */
+ public AnalyzerException(
+ final AbstractInsnNode insn, final String message, final Throwable cause) {
+ super(message, cause);
+ this.node = insn;
+ }
- public AnalyzerException(final AbstractInsnNode node, final String msg,
- final Object expected, final Value encountered) {
- super((msg == null ? "Expected " : msg + ": expected ") + expected
- + ", but found " + encountered);
- this.node = node;
- }
+ /**
+ * Constructs a new {@link AnalyzerException}.
+ *
+ * @param insn the bytecode instruction where the analysis failed.
+ * @param message the reason why the analysis failed.
+ * @param expected an expected value.
+ * @param actual the actual value, different from the expected one.
+ */
+ public AnalyzerException(
+ final AbstractInsnNode insn,
+ final String message,
+ final Object expected,
+ final Value actual) {
+ super(
+ (message == null ? "Expected " : message + ": expected ")
+ + expected
+ + ", but found "
+ + actual);
+ this.node = insn;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
old mode 100644
new mode 100755
index b025094..037df4c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
@@ -1,36 +1,34 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.List;
-
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
@@ -45,314 +43,334 @@ import org.apache.tapestry5.internal.plastic.asm.tree.TypeInsnNode;
/**
* An {@link Interpreter} for {@link BasicValue} values.
- *
+ *
* @author Eric Bruneton
* @author Bing Ran
*/
-public class BasicInterpreter extends Interpreter<BasicValue> implements
- Opcodes {
+public class BasicInterpreter extends Interpreter<BasicValue> implements Opcodes {
- public BasicInterpreter() {
- super(ASM6);
- }
+ /**
+ * Special type used for the {@literal null} literal. This is an object reference type with
+ * descriptor 'Lnull;'.
+ */
+ public static final Type NULL_TYPE = Type.getObjectType("null");
- protected BasicInterpreter(final int api) {
- super(api);
+ /**
+ * Constructs a new {@link BasicInterpreter} for the latest ASM API version. <i>Subclasses must
+ * not use this constructor</i>. Instead, they must use the {@link #BasicInterpreter(int)}
+ * version.
+ */
+ public BasicInterpreter() {
+ super(ASM7);
+ if (getClass() != BasicInterpreter.class) {
+ throw new IllegalStateException();
}
+ }
- @Override
- public BasicValue newValue(final Type type) {
- if (type == null) {
- return BasicValue.UNINITIALIZED_VALUE;
- }
- switch (type.getSort()) {
- case Type.VOID:
- return null;
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- case Type.INT:
- return BasicValue.INT_VALUE;
- case Type.FLOAT:
- return BasicValue.FLOAT_VALUE;
- case Type.LONG:
- return BasicValue.LONG_VALUE;
- case Type.DOUBLE:
- return BasicValue.DOUBLE_VALUE;
- case Type.ARRAY:
- case Type.OBJECT:
- return BasicValue.REFERENCE_VALUE;
- default:
- throw new Error("Internal error");
- }
- }
+ /**
+ * Constructs a new {@link BasicInterpreter}.
+ *
+ * @param api the ASM API version supported by this interpreter. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+ */
+ protected BasicInterpreter(final int api) {
+ super(api);
+ }
- @Override
- public BasicValue newOperation(final AbstractInsnNode insn)
- throws AnalyzerException {
- switch (insn.getOpcode()) {
- case ACONST_NULL:
- return newValue(Type.getObjectType("null"));
- case ICONST_M1:
- case ICONST_0:
- case ICONST_1:
- case ICONST_2:
- case ICONST_3:
- case ICONST_4:
- case ICONST_5:
- return BasicValue.INT_VALUE;
- case LCONST_0:
- case LCONST_1:
- return BasicValue.LONG_VALUE;
- case FCONST_0:
- case FCONST_1:
- case FCONST_2:
- return BasicValue.FLOAT_VALUE;
- case DCONST_0:
- case DCONST_1:
- return BasicValue.DOUBLE_VALUE;
- case BIPUSH:
- case SIPUSH:
- return BasicValue.INT_VALUE;
- case LDC:
- Object cst = ((LdcInsnNode) insn).cst;
- if (cst instanceof Integer) {
- return BasicValue.INT_VALUE;
- } else if (cst instanceof Float) {
- return BasicValue.FLOAT_VALUE;
- } else if (cst instanceof Long) {
- return BasicValue.LONG_VALUE;
- } else if (cst instanceof Double) {
- return BasicValue.DOUBLE_VALUE;
- } else if (cst instanceof String) {
- return newValue(Type.getObjectType("java/lang/String"));
- } else if (cst instanceof Type) {
- int sort = ((Type) cst).getSort();
- if (sort == Type.OBJECT || sort == Type.ARRAY) {
- return newValue(Type.getObjectType("java/lang/Class"));
- } else if (sort == Type.METHOD) {
- return newValue(Type
- .getObjectType("java/lang/invoke/MethodType"));
- } else {
- throw new IllegalArgumentException("Illegal LDC constant "
- + cst);
- }
- } else if (cst instanceof Handle) {
- return newValue(Type
- .getObjectType("java/lang/invoke/MethodHandle"));
- } else {
- throw new IllegalArgumentException("Illegal LDC constant "
- + cst);
- }
- case JSR:
- return BasicValue.RETURNADDRESS_VALUE;
- case GETSTATIC:
- return newValue(Type.getType(((FieldInsnNode) insn).desc));
- case NEW:
- return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
- default:
- throw new Error("Internal error.");
- }
+ @Override
+ public BasicValue newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
}
-
- @Override
- public BasicValue copyOperation(final AbstractInsnNode insn,
- final BasicValue value) throws AnalyzerException {
- return value;
+ switch (type.getSort()) {
+ case Type.VOID:
+ return null;
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ return BasicValue.INT_VALUE;
+ case Type.FLOAT:
+ return BasicValue.FLOAT_VALUE;
+ case Type.LONG:
+ return BasicValue.LONG_VALUE;
+ case Type.DOUBLE:
+ return BasicValue.DOUBLE_VALUE;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ return BasicValue.REFERENCE_VALUE;
+ default:
+ throw new AssertionError();
}
+ }
- @Override
- public BasicValue unaryOperation(final AbstractInsnNode insn,
- final BasicValue value) throws AnalyzerException {
- switch (insn.getOpcode()) {
- case INEG:
- case IINC:
- case L2I:
- case F2I:
- case D2I:
- case I2B:
- case I2C:
- case I2S:
- return BasicValue.INT_VALUE;
- case FNEG:
- case I2F:
- case L2F:
- case D2F:
- return BasicValue.FLOAT_VALUE;
- case LNEG:
- case I2L:
- case F2L:
- case D2L:
- return BasicValue.LONG_VALUE;
- case DNEG:
- case I2D:
- case L2D:
- case F2D:
- return BasicValue.DOUBLE_VALUE;
- case IFEQ:
- case IFNE:
- case IFLT:
- case IFGE:
- case IFGT:
- case IFLE:
- case TABLESWITCH:
- case LOOKUPSWITCH:
- case IRETURN:
- case LRETURN:
- case FRETURN:
- case DRETURN:
- case ARETURN:
- case PUTSTATIC:
- return null;
- case GETFIELD:
- return newValue(Type.getType(((FieldInsnNode) insn).desc));
- case NEWARRAY:
- switch (((IntInsnNode) insn).operand) {
- case T_BOOLEAN:
- return newValue(Type.getType("[Z"));
- case T_CHAR:
- return newValue(Type.getType("[C"));
- case T_BYTE:
- return newValue(Type.getType("[B"));
- case T_SHORT:
- return newValue(Type.getType("[S"));
- case T_INT:
- return newValue(Type.getType("[I"));
- case T_FLOAT:
- return newValue(Type.getType("[F"));
- case T_DOUBLE:
- return newValue(Type.getType("[D"));
- case T_LONG:
- return newValue(Type.getType("[J"));
- default:
- throw new AnalyzerException(insn, "Invalid array type");
- }
- case ANEWARRAY:
- String desc = ((TypeInsnNode) insn).desc;
- return newValue(Type.getType("[" + Type.getObjectType(desc)));
- case ARRAYLENGTH:
- return BasicValue.INT_VALUE;
- case ATHROW:
- return null;
- case CHECKCAST:
- desc = ((TypeInsnNode) insn).desc;
- return newValue(Type.getObjectType(desc));
- case INSTANCEOF:
- return BasicValue.INT_VALUE;
- case MONITORENTER:
- case MONITOREXIT:
- case IFNULL:
- case IFNONNULL:
- return null;
- default:
- throw new Error("Internal error.");
+ @Override
+ public BasicValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case ACONST_NULL:
+ return newValue(NULL_TYPE);
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ return BasicValue.INT_VALUE;
+ case LCONST_0:
+ case LCONST_1:
+ return BasicValue.LONG_VALUE;
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ return BasicValue.FLOAT_VALUE;
+ case DCONST_0:
+ case DCONST_1:
+ return BasicValue.DOUBLE_VALUE;
+ case BIPUSH:
+ case SIPUSH:
+ return BasicValue.INT_VALUE;
+ case LDC:
+ Object value = ((LdcInsnNode) insn).cst;
+ if (value instanceof Integer) {
+ return BasicValue.INT_VALUE;
+ } else if (value instanceof Float) {
+ return BasicValue.FLOAT_VALUE;
+ } else if (value instanceof Long) {
+ return BasicValue.LONG_VALUE;
+ } else if (value instanceof Double) {
+ return BasicValue.DOUBLE_VALUE;
+ } else if (value instanceof String) {
+ return newValue(Type.getObjectType("java/lang/String"));
+ } else if (value instanceof Type) {
+ int sort = ((Type) value).getSort();
+ if (sort == Type.OBJECT || sort == Type.ARRAY) {
+ return newValue(Type.getObjectType("java/lang/Class"));
+ } else if (sort == Type.METHOD) {
+ return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
+ } else {
+ throw new AnalyzerException(insn, "Illegal LDC value " + value);
+ }
+ } else if (value instanceof Handle) {
+ return newValue(Type.getObjectType("java/lang/invoke/MethodHandle"));
+ } else if (value instanceof ConstantDynamic) {
+ return newValue(Type.getType(((ConstantDynamic) value).getDescriptor()));
+ } else {
+ throw new AnalyzerException(insn, "Illegal LDC value " + value);
}
+ case JSR:
+ return BasicValue.RETURNADDRESS_VALUE;
+ case GETSTATIC:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEW:
+ return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+ default:
+ throw new AssertionError();
}
+ }
+
+ @Override
+ public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value)
+ throws AnalyzerException {
+ return value;
+ }
- @Override
- public BasicValue binaryOperation(final AbstractInsnNode insn,
- final BasicValue value1, final BasicValue value2)
- throws AnalyzerException {
- switch (insn.getOpcode()) {
- case IALOAD:
- case BALOAD:
- case CALOAD:
- case SALOAD:
- case IADD:
- case ISUB:
- case IMUL:
- case IDIV:
- case IREM:
- case ISHL:
- case ISHR:
- case IUSHR:
- case IAND:
- case IOR:
- case IXOR:
- return BasicValue.INT_VALUE;
- case FALOAD:
- case FADD:
- case FSUB:
- case FMUL:
- case FDIV:
- case FREM:
- return BasicValue.FLOAT_VALUE;
- case LALOAD:
- case LADD:
- case LSUB:
- case LMUL:
- case LDIV:
- case LREM:
- case LSHL:
- case LSHR:
- case LUSHR:
- case LAND:
- case LOR:
- case LXOR:
- return BasicValue.LONG_VALUE;
- case DALOAD:
- case DADD:
- case DSUB:
- case DMUL:
- case DDIV:
- case DREM:
- return BasicValue.DOUBLE_VALUE;
- case AALOAD:
- return BasicValue.REFERENCE_VALUE;
- case LCMP:
- case FCMPL:
- case FCMPG:
- case DCMPL:
- case DCMPG:
- return BasicValue.INT_VALUE;
- case IF_ICMPEQ:
- case IF_ICMPNE:
- case IF_ICMPLT:
- case IF_ICMPGE:
- case IF_ICMPGT:
- case IF_ICMPLE:
- case IF_ACMPEQ:
- case IF_ACMPNE:
- case PUTFIELD:
- return null;
- default:
- throw new Error("Internal error.");
+ @Override
+ public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value)
+ throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case L2I:
+ case F2I:
+ case D2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ return BasicValue.INT_VALUE;
+ case FNEG:
+ case I2F:
+ case L2F:
+ case D2F:
+ return BasicValue.FLOAT_VALUE;
+ case LNEG:
+ case I2L:
+ case F2L:
+ case D2L:
+ return BasicValue.LONG_VALUE;
+ case DNEG:
+ case I2D:
+ case L2D:
+ case F2D:
+ return BasicValue.DOUBLE_VALUE;
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case PUTSTATIC:
+ return null;
+ case GETFIELD:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEWARRAY:
+ switch (((IntInsnNode) insn).operand) {
+ case T_BOOLEAN:
+ return newValue(Type.getType("[Z"));
+ case T_CHAR:
+ return newValue(Type.getType("[C"));
+ case T_BYTE:
+ return newValue(Type.getType("[B"));
+ case T_SHORT:
+ return newValue(Type.getType("[S"));
+ case T_INT:
+ return newValue(Type.getType("[I"));
+ case T_FLOAT:
+ return newValue(Type.getType("[F"));
+ case T_DOUBLE:
+ return newValue(Type.getType("[D"));
+ case T_LONG:
+ return newValue(Type.getType("[J"));
+ default:
+ break;
}
+ throw new AnalyzerException(insn, "Invalid array type");
+ case ANEWARRAY:
+ return newValue(Type.getType("[" + Type.getObjectType(((TypeInsnNode) insn).desc)));
+ case ARRAYLENGTH:
+ return BasicValue.INT_VALUE;
+ case ATHROW:
+ return null;
+ case CHECKCAST:
+ return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+ case INSTANCEOF:
+ return BasicValue.INT_VALUE;
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ return null;
+ default:
+ throw new AssertionError();
}
+ }
- @Override
- public BasicValue ternaryOperation(final AbstractInsnNode insn,
- final BasicValue value1, final BasicValue value2,
- final BasicValue value3) throws AnalyzerException {
+ @Override
+ public BasicValue binaryOperation(
+ final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2)
+ throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ case BALOAD:
+ case CALOAD:
+ case SALOAD:
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ return BasicValue.INT_VALUE;
+ case FALOAD:
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ return BasicValue.FLOAT_VALUE;
+ case LALOAD:
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ return BasicValue.LONG_VALUE;
+ case DALOAD:
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ return BasicValue.DOUBLE_VALUE;
+ case AALOAD:
+ return BasicValue.REFERENCE_VALUE;
+ case LCMP:
+ case FCMPL:
+ case FCMPG:
+ case DCMPL:
+ case DCMPG:
+ return BasicValue.INT_VALUE;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case PUTFIELD:
return null;
+ default:
+ throw new AssertionError();
}
+ }
- @Override
- public BasicValue naryOperation(final AbstractInsnNode insn,
- final List<? extends BasicValue> values) throws AnalyzerException {
- int opcode = insn.getOpcode();
- if (opcode == MULTIANEWARRAY) {
- return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
- } else if (opcode == INVOKEDYNAMIC) {
- return newValue(Type
- .getReturnType(((InvokeDynamicInsnNode) insn).desc));
- } else {
- return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
- }
- }
+ @Override
+ public BasicValue ternaryOperation(
+ final AbstractInsnNode insn,
+ final BasicValue value1,
+ final BasicValue value2,
+ final BasicValue value3)
+ throws AnalyzerException {
+ return null;
+ }
- @Override
- public void returnOperation(final AbstractInsnNode insn,
- final BasicValue value, final BasicValue expected)
- throws AnalyzerException {
+ @Override
+ public BasicValue naryOperation(
+ final AbstractInsnNode insn, final List<? extends BasicValue> values)
+ throws AnalyzerException {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+ } else if (opcode == INVOKEDYNAMIC) {
+ return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
+ } else {
+ return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
}
+ }
- @Override
- public BasicValue merge(final BasicValue v, final BasicValue w) {
- if (!v.equals(w)) {
- return BasicValue.UNINITIALIZED_VALUE;
- }
- return v;
+ @Override
+ public void returnOperation(
+ final AbstractInsnNode insn, final BasicValue value, final BasicValue expected)
+ throws AnalyzerException {
+ // Nothing to do.
+ }
+
+ @Override
+ public BasicValue merge(final BasicValue value1, final BasicValue value2) {
+ if (!value1.equals(value2)) {
+ return BasicValue.UNINITIALIZED_VALUE;
}
+ return value1;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
old mode 100644
new mode 100755
index 44b0704..71c3d5e
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
@@ -1,111 +1,129 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import org.apache.tapestry5.internal.plastic.asm.Type;
/**
- * A {@link Value} that is represented by its type in a seven types type system.
- * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
- * REFERENCE and RETURNADDRESS types.
- *
+ * A {@link Value} that is represented with its type in a seven types type system. This type system
+ * distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
+ *
* @author Eric Bruneton
*/
public class BasicValue implements Value {
- public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null);
-
- public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE);
-
- public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
-
- public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE);
-
- public static final BasicValue DOUBLE_VALUE = new BasicValue(
- Type.DOUBLE_TYPE);
-
- public static final BasicValue REFERENCE_VALUE = new BasicValue(
- Type.getObjectType("java/lang/Object"));
-
- public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(
- Type.VOID_TYPE);
-
- private final Type type;
-
- public BasicValue(final Type type) {
- this.type = type;
+ /** An uninitialized value. */
+ public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null);
+
+ /** A byte, boolean, char, short, or int value. */
+ public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+ /** A float value. */
+ public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+ /** A long value. */
+ public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+ /** A double value. */
+ public static final BasicValue DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE);
+
+ /** An object or array reference value. */
+ public static final BasicValue REFERENCE_VALUE =
+ new BasicValue(Type.getObjectType("java/lang/Object"));
+
+ /** A return address value (produced by a jsr instruction). */
+ public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(Type.VOID_TYPE);
+
+ /** The {@link Type} of this value, or {@literal null} for uninitialized values. */
+ private final Type type;
+
+ /**
+ * Constructs a new {@link BasicValue} of the given type.
+ *
+ * @param type the value type.
+ */
+ public BasicValue(final Type type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the {@link Type} of this value.
+ *
+ * @return the {@link Type} of this value.
+ */
+ public Type getType() {
+ return type;
+ }
+
+ @Override
+ public int getSize() {
+ return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+ }
+
+ /**
+ * Returns whether this value corresponds to an object or array reference.
+ *
+ * @return whether this value corresponds to an object or array reference.
+ */
+ public boolean isReference() {
+ return type != null && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+ }
+
+ @Override
+ public boolean equals(final Object value) {
+ if (value == this) {
+ return true;
+ } else if (value instanceof BasicValue) {
+ if (type == null) {
+ return ((BasicValue) value).type == null;
+ } else {
+ return type.equals(((BasicValue) value).type);
+ }
+ } else {
+ return false;
}
-
- public Type getType() {
- return type;
- }
-
- public int getSize() {
- return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
- }
-
- public boolean isReference() {
- return type != null
- && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
- }
-
- @Override
- public boolean equals(final Object value) {
- if (value == this) {
- return true;
- } else if (value instanceof BasicValue) {
- if (type == null) {
- return ((BasicValue) value).type == null;
- } else {
- return type.equals(((BasicValue) value).type);
- }
- } else {
- return false;
- }
- }
-
- @Override
- public int hashCode() {
- return type == null ? 0 : type.hashCode();
- }
-
- @Override
- public String toString() {
- if (this == UNINITIALIZED_VALUE) {
- return ".";
- } else if (this == RETURNADDRESS_VALUE) {
- return "A";
- } else if (this == REFERENCE_VALUE) {
- return "R";
- } else {
- return type.getDescriptor();
- }
+ }
+
+ @Override
+ public int hashCode() {
+ return type == null ? 0 : type.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ if (this == UNINITIALIZED_VALUE) {
+ return ".";
+ } else if (this == RETURNADDRESS_VALUE) {
+ return "A";
+ } else if (this == REFERENCE_VALUE) {
+ return "R";
+ } else {
+ return type.getDescriptor();
}
+ }
}
[40/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
old mode 100644
new mode 100755
index de81b55..7d2cdf8
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
@@ -1,1566 +1,1468 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * Information about the input and output stack map frames of a basic block.
- *
+ * The input and output stack map frames of a basic block.
+ *
+ * <p>Stack map frames are computed in two steps:
+ *
+ * <ul>
+ * <li>During the visit of each instruction in MethodWriter, the state of the frame at the end of
+ * the current basic block is updated by simulating the action of the instruction on the
+ * previous state of this so called "output frame".
+ * <li>After all instructions have been visited, a fix point algorithm is used in MethodWriter to
+ * compute the "input frame" of each basic block (i.e. the stack map frame at the beginning of
+ * the basic block). See {@link MethodWriter#computeAllFrames}.
+ * </ul>
+ *
+ * <p>Output stack map frames are computed relatively to the input frame of the basic block, which
+ * is not yet known when output frames are computed. It is therefore necessary to be able to
+ * represent abstract types such as "the type at position x in the input frame locals" or "the type
+ * at position x from the top of the input frame stack" or even "the type at position x in the input
+ * frame, with y more (or less) array dimensions". This explains the rather complicated type format
+ * used in this class, explained below.
+ *
+ * <p>The local variables and the operand stack of input and output frames contain values called
+ * "abstract types" hereafter. An abstract type is represented with 4 fields named DIM, KIND, FLAGS
+ * and VALUE, packed in a single int value for better performance and memory efficiency:
+ *
+ * <pre>
+ * =====================================
+ * |.DIM|KIND|FLAG|...............VALUE|
+ * =====================================
+ * </pre>
+ *
+ * <ul>
+ * <li>the DIM field, stored in the 4 most significant bits, is a signed number of array
+ * dimensions (from -8 to 7, included). It can be retrieved with {@link #DIM_MASK} and a right
+ * shift of {@link #DIM_SHIFT}.
+ * <li>the KIND field, stored in 4 bits, indicates the kind of VALUE used. These 4 bits can be
+ * retrieved with {@link #KIND_MASK} and, without any shift, must be equal to {@link
+ * #CONSTANT_KIND}, {@link #REFERENCE_KIND}, {@link #UNINITIALIZED_KIND}, {@link #LOCAL_KIND}
+ * or {@link #STACK_KIND}.
+ * <li>the FLAGS field, stored in 4 bits, contains up to 4 boolean flags. Currently only one flag
+ * is defined, namely {@link #TOP_IF_LONG_OR_DOUBLE_FLAG}.
+ * <li>the VALUE field, stored in the remaining 20 bits, contains either
+ * <ul>
+ * <li>one of the constants {@link #ITEM_TOP}, {@link #ITEM_ASM_BOOLEAN}, {@link
+ * #ITEM_ASM_BYTE}, {@link #ITEM_ASM_CHAR} or {@link #ITEM_ASM_SHORT}, {@link
+ * #ITEM_INTEGER}, {@link #ITEM_FLOAT}, {@link #ITEM_LONG}, {@link #ITEM_DOUBLE}, {@link
+ * #ITEM_NULL} or {@link #ITEM_UNINITIALIZED_THIS}, if KIND is equal to {@link
+ * #CONSTANT_KIND}.
+ * <li>the index of a {@link Symbol#TYPE_TAG} {@link Symbol} in the type table of a {@link
+ * SymbolTable}, if KIND is equal to {@link #REFERENCE_KIND}.
+ * <li>the index of an {@link Symbol#UNINITIALIZED_TYPE_TAG} {@link Symbol} in the type
+ * table of a SymbolTable, if KIND is equal to {@link #UNINITIALIZED_KIND}.
+ * <li>the index of a local variable in the input stack frame, if KIND is equal to {@link
+ * #LOCAL_KIND}.
+ * <li>a position relatively to the top of the stack of the input stack frame, if KIND is
+ * equal to {@link #STACK_KIND},
+ * </ul>
+ * </ul>
+ *
+ * <p>Output frames can contain abstract types of any kind and with a positive or negative array
+ * dimension (and even unassigned types, represented by 0 - which does not correspond to any valid
+ * abstract type value). Input frames can only contain CONSTANT_KIND, REFERENCE_KIND or
+ * UNINITIALIZED_KIND abstract types of positive or null array dimension. In all cases the type
+ * table contains only internal type names (array type descriptors are forbidden - array dimensions
+ * must be represented through the DIM field).
+ *
+ * <p>The LONG and DOUBLE types are always represented by using two slots (LONG + TOP or DOUBLE +
+ * TOP), for local variables as well as in the operand stack. This is necessary to be able to
+ * simulate DUPx_y instructions, whose effect would be dependent on the concrete types represented
+ * by the abstract types in the stack (which are not always known).
+ *
* @author Eric Bruneton
*/
class Frame {
- /*
- * Frames are computed in a two steps process: during the visit of each
- * instruction, the state of the frame at the end of current basic block is
- * updated by simulating the action of the instruction on the previous state
- * of this so called "output frame". In visitMaxs, a fix point algorithm is
- * used to compute the "input frame" of each basic block, i.e. the stack map
- * frame at the beginning of the basic block, starting from the input frame
- * of the first basic block (which is computed from the method descriptor),
- * and by using the previously computed output frames to compute the input
- * state of the other blocks.
- *
- * All output and input frames are stored as arrays of integers. Reference
- * and array types are represented by an index into a type table (which is
- * not the same as the constant pool of the class, in order to avoid adding
- * unnecessary constants in the pool - not all computed frames will end up
- * being stored in the stack map table). This allows very fast type
- * comparisons.
- *
- * Output stack map frames are computed relatively to the input frame of the
- * basic block, which is not yet known when output frames are computed. It
- * is therefore necessary to be able to represent abstract types such as
- * "the type at position x in the input frame locals" or "the type at
- * position x from the top of the input frame stack" or even "the type at
- * position x in the input frame, with y more (or less) array dimensions".
- * This explains the rather complicated type format used in output frames.
- *
- * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
- * signed number of array dimensions (from -8 to 7). KIND is either BASE,
- * LOCAL or STACK. BASE is used for types that are not relative to the input
- * frame. LOCAL is used for types that are relative to the input local
- * variable types. STACK is used for types that are relative to the input
- * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
- * the input local variable types. For STACK types, it is a position
- * relatively to the top of input frame stack. For BASE types, it is either
- * one of the constants defined below, or for OBJECT and UNINITIALIZED
- * types, a tag and an index in the type table.
- *
- * Output frames can contain types of any kind and with a positive or
- * negative dimension (and even unassigned types, represented by 0 - which
- * does not correspond to any valid type value). Input frames can only
- * contain BASE types of positive or null dimension. In all cases the type
- * table contains only internal type names (array type descriptors are
- * forbidden - dimensions must be represented through the DIM field).
- *
- * The LONG and DOUBLE types are always represented by using two slots (LONG
- * + TOP or DOUBLE + TOP), for local variable types as well as in the
- * operand stack. This is necessary to be able to simulate DUPx_y
- * instructions, whose effect would be dependent on the actual type values
- * if types were always represented by a single slot in the stack (and this
- * is not possible, since actual type values are not always known - cf LOCAL
- * and STACK type kinds).
- */
+ // Constants used in the StackMapTable attribute.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.4.
- /**
- * Mask to get the dimension of a frame type. This dimension is a signed
- * integer between -8 and 7.
- */
- static final int DIM = 0xF0000000;
+ static final int SAME_FRAME = 0;
+ static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64;
+ static final int RESERVED = 128;
+ static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247;
+ static final int CHOP_FRAME = 248;
+ static final int SAME_FRAME_EXTENDED = 251;
+ static final int APPEND_FRAME = 252;
+ static final int FULL_FRAME = 255;
- /**
- * Constant to be added to a type to get a type with one more dimension.
- */
- static final int ARRAY_OF = 0x10000000;
+ static final int ITEM_TOP = 0;
+ static final int ITEM_INTEGER = 1;
+ static final int ITEM_FLOAT = 2;
+ static final int ITEM_DOUBLE = 3;
+ static final int ITEM_LONG = 4;
+ static final int ITEM_NULL = 5;
+ static final int ITEM_UNINITIALIZED_THIS = 6;
+ static final int ITEM_OBJECT = 7;
+ static final int ITEM_UNINITIALIZED = 8;
+ // Additional, ASM specific constants used in abstract types below.
+ private static final int ITEM_ASM_BOOLEAN = 9;
+ private static final int ITEM_ASM_BYTE = 10;
+ private static final int ITEM_ASM_CHAR = 11;
+ private static final int ITEM_ASM_SHORT = 12;
- /**
- * Constant to be added to a type to get a type with one less dimension.
- */
- static final int ELEMENT_OF = 0xF0000000;
+ // Bitmasks to get each field of an abstract type.
- /**
- * Mask to get the kind of a frame type.
- *
- * @see #BASE
- * @see #LOCAL
- * @see #STACK
- */
- static final int KIND = 0xF000000;
+ private static final int DIM_MASK = 0xF0000000;
+ private static final int KIND_MASK = 0x0F000000;
+ private static final int FLAGS_MASK = 0x00F00000;
+ private static final int VALUE_MASK = 0x000FFFFF;
- /**
- * Flag used for LOCAL and STACK types. Indicates that if this type happens
- * to be a long or double type (during the computations of input frames),
- * then it must be set to TOP because the second word of this value has been
- * reused to store other data in the basic block. Hence the first word no
- * longer stores a valid long or double value.
- */
- static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
+ // Constants to manipulate the DIM field of an abstract type.
- /**
- * Mask to get the value of a frame type.
- */
- static final int VALUE = 0x7FFFFF;
+ /** The number of right shift bits to use to get the array dimensions of an abstract type. */
+ private static final int DIM_SHIFT = 28;
- /**
- * Mask to get the kind of base types.
- */
- static final int BASE_KIND = 0xFF00000;
+ /** The constant to be added to an abstract type to get one with one more array dimension. */
+ private static final int ARRAY_OF = +1 << DIM_SHIFT;
- /**
- * Mask to get the value of base types.
- */
- static final int BASE_VALUE = 0xFFFFF;
+ /** The constant to be added to an abstract type to get one with one less array dimension. */
+ private static final int ELEMENT_OF = -1 << DIM_SHIFT;
- /**
- * Kind of the types that are not relative to an input stack map frame.
- */
- static final int BASE = 0x1000000;
+ // Possible values for the KIND field of an abstract type.
- /**
- * Base kind of the base reference types. The BASE_VALUE of such types is an
- * index into the type table.
- */
- static final int OBJECT = BASE | 0x700000;
+ private static final int CONSTANT_KIND = 0x01000000;
+ private static final int REFERENCE_KIND = 0x02000000;
+ private static final int UNINITIALIZED_KIND = 0x03000000;
+ private static final int LOCAL_KIND = 0x04000000;
+ private static final int STACK_KIND = 0x05000000;
- /**
- * Base kind of the uninitialized base types. The BASE_VALUE of such types
- * in an index into the type table (the Item at that index contains both an
- * instruction offset and an internal class name).
- */
- static final int UNINITIALIZED = BASE | 0x800000;
+ // Possible flags for the FLAGS field of an abstract type.
- /**
- * Kind of the types that are relative to the local variable types of an
- * input stack map frame. The value of such types is a local variable index.
- */
- private static final int LOCAL = 0x2000000;
+ /**
+ * A flag used for LOCAL_KIND and STACK_KIND abstract types, indicating that if the resolved,
+ * concrete type is LONG or DOUBLE, TOP should be used instead (because the value has been
+ * partially overridden with an xSTORE instruction).
+ */
+ private static final int TOP_IF_LONG_OR_DOUBLE_FLAG = 0x00100000 & FLAGS_MASK;
- /**
- * Kind of the the types that are relative to the stack of an input stack
- * map frame. The value of such types is a position relatively to the top of
- * this stack.
- */
- private static final int STACK = 0x3000000;
+ // Useful predefined abstract types (all the possible CONSTANT_KIND types).
- /**
- * The TOP type. This is a BASE type.
- */
- static final int TOP = BASE | 0;
+ private static final int TOP = CONSTANT_KIND | ITEM_TOP;
+ private static final int BOOLEAN = CONSTANT_KIND | ITEM_ASM_BOOLEAN;
+ private static final int BYTE = CONSTANT_KIND | ITEM_ASM_BYTE;
+ private static final int CHAR = CONSTANT_KIND | ITEM_ASM_CHAR;
+ private static final int SHORT = CONSTANT_KIND | ITEM_ASM_SHORT;
+ private static final int INTEGER = CONSTANT_KIND | ITEM_INTEGER;
+ private static final int FLOAT = CONSTANT_KIND | ITEM_FLOAT;
+ private static final int LONG = CONSTANT_KIND | ITEM_LONG;
+ private static final int DOUBLE = CONSTANT_KIND | ITEM_DOUBLE;
+ private static final int NULL = CONSTANT_KIND | ITEM_NULL;
+ private static final int UNINITIALIZED_THIS = CONSTANT_KIND | ITEM_UNINITIALIZED_THIS;
- /**
- * The BOOLEAN type. This is a BASE type mainly used for array types.
- */
- static final int BOOLEAN = BASE | 9;
+ // -----------------------------------------------------------------------------------------------
+ // Instance fields
+ // -----------------------------------------------------------------------------------------------
- /**
- * The BYTE type. This is a BASE type mainly used for array types.
- */
- static final int BYTE = BASE | 10;
+ /** The basic block to which these input and output stack map frames correspond. */
+ Label owner;
- /**
- * The CHAR type. This is a BASE type mainly used for array types.
- */
- static final int CHAR = BASE | 11;
+ /** The input stack map frame locals. This is an array of abstract types. */
+ private int[] inputLocals;
- /**
- * The SHORT type. This is a BASE type mainly used for array types.
- */
- static final int SHORT = BASE | 12;
+ /** The input stack map frame stack. This is an array of abstract types. */
+ private int[] inputStack;
- /**
- * The INTEGER type. This is a BASE type.
- */
- static final int INTEGER = BASE | 1;
+ /** The output stack map frame locals. This is an array of abstract types. */
+ private int[] outputLocals;
- /**
- * The FLOAT type. This is a BASE type.
- */
- static final int FLOAT = BASE | 2;
+ /** The output stack map frame stack. This is an array of abstract types. */
+ private int[] outputStack;
- /**
- * The DOUBLE type. This is a BASE type.
- */
- static final int DOUBLE = BASE | 3;
+ /**
+ * The start of the output stack, relatively to the input stack. This offset is always negative or
+ * null. A null offset means that the output stack must be appended to the input stack. A -n
+ * offset means that the first n output stack elements must replace the top n input stack
+ * elements, and that the other elements must be appended to the input stack.
+ */
+ private short outputStackStart;
- /**
- * The LONG type. This is a BASE type.
- */
- static final int LONG = BASE | 4;
+ /** The index of the top stack element in {@link #outputStack}. */
+ private short outputStackTop;
- /**
- * The NULL type. This is a BASE type.
- */
- static final int NULL = BASE | 5;
+ /** The number of types that are initialized in the basic block. See {@link #initializations}. */
+ private int initializationCount;
- /**
- * The UNINITIALIZED_THIS type. This is a BASE type.
- */
- static final int UNINITIALIZED_THIS = BASE | 6;
+ /**
+ * The abstract types that are initialized in the basic block. A constructor invocation on an
+ * UNINITIALIZED or UNINITIALIZED_THIS abstract type must replace <i>every occurrence</i> of this
+ * type in the local variables and in the operand stack. This cannot be done during the first step
+ * of the algorithm since, during this step, the local variables and the operand stack types are
+ * still abstract. It is therefore necessary to store the abstract types of the constructors which
+ * are invoked in the basic block, in order to do this replacement during the second step of the
+ * algorithm, where the frames are fully computed. Note that this array can contain abstract types
+ * that are relative to the input locals or to the input stack.
+ */
+ private int[] initializations;
- /**
- * The stack size variation corresponding to each JVM instruction. This
- * stack variation is equal to the size of the values produced by an
- * instruction, minus the size of the values consumed by this instruction.
- */
- static final int[] SIZE;
+ // -----------------------------------------------------------------------------------------------
+ // Constructor
+ // -----------------------------------------------------------------------------------------------
- /**
- * Computes the stack size variation corresponding to each JVM instruction.
- */
- static {
- int i;
- int[] b = new int[202];
- String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
- + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
- + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
- + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
- for (i = 0; i < b.length; ++i) {
- b[i] = s.charAt(i) - 'E';
- }
- SIZE = b;
-
- // code to generate the above string
- //
- // int NA = 0; // not applicable (unused opcode or variable size opcode)
- //
- // b = new int[] {
- // 0, //NOP, // visitInsn
- // 1, //ACONST_NULL, // -
- // 1, //ICONST_M1, // -
- // 1, //ICONST_0, // -
- // 1, //ICONST_1, // -
- // 1, //ICONST_2, // -
- // 1, //ICONST_3, // -
- // 1, //ICONST_4, // -
- // 1, //ICONST_5, // -
- // 2, //LCONST_0, // -
- // 2, //LCONST_1, // -
- // 1, //FCONST_0, // -
- // 1, //FCONST_1, // -
- // 1, //FCONST_2, // -
- // 2, //DCONST_0, // -
- // 2, //DCONST_1, // -
- // 1, //BIPUSH, // visitIntInsn
- // 1, //SIPUSH, // -
- // 1, //LDC, // visitLdcInsn
- // NA, //LDC_W, // -
- // NA, //LDC2_W, // -
- // 1, //ILOAD, // visitVarInsn
- // 2, //LLOAD, // -
- // 1, //FLOAD, // -
- // 2, //DLOAD, // -
- // 1, //ALOAD, // -
- // NA, //ILOAD_0, // -
- // NA, //ILOAD_1, // -
- // NA, //ILOAD_2, // -
- // NA, //ILOAD_3, // -
- // NA, //LLOAD_0, // -
- // NA, //LLOAD_1, // -
- // NA, //LLOAD_2, // -
- // NA, //LLOAD_3, // -
- // NA, //FLOAD_0, // -
- // NA, //FLOAD_1, // -
- // NA, //FLOAD_2, // -
- // NA, //FLOAD_3, // -
- // NA, //DLOAD_0, // -
- // NA, //DLOAD_1, // -
- // NA, //DLOAD_2, // -
- // NA, //DLOAD_3, // -
- // NA, //ALOAD_0, // -
- // NA, //ALOAD_1, // -
- // NA, //ALOAD_2, // -
- // NA, //ALOAD_3, // -
- // -1, //IALOAD, // visitInsn
- // 0, //LALOAD, // -
- // -1, //FALOAD, // -
- // 0, //DALOAD, // -
- // -1, //AALOAD, // -
- // -1, //BALOAD, // -
- // -1, //CALOAD, // -
- // -1, //SALOAD, // -
- // -1, //ISTORE, // visitVarInsn
- // -2, //LSTORE, // -
- // -1, //FSTORE, // -
- // -2, //DSTORE, // -
- // -1, //ASTORE, // -
- // NA, //ISTORE_0, // -
- // NA, //ISTORE_1, // -
- // NA, //ISTORE_2, // -
- // NA, //ISTORE_3, // -
- // NA, //LSTORE_0, // -
- // NA, //LSTORE_1, // -
- // NA, //LSTORE_2, // -
- // NA, //LSTORE_3, // -
- // NA, //FSTORE_0, // -
- // NA, //FSTORE_1, // -
- // NA, //FSTORE_2, // -
- // NA, //FSTORE_3, // -
- // NA, //DSTORE_0, // -
- // NA, //DSTORE_1, // -
- // NA, //DSTORE_2, // -
- // NA, //DSTORE_3, // -
- // NA, //ASTORE_0, // -
- // NA, //ASTORE_1, // -
- // NA, //ASTORE_2, // -
- // NA, //ASTORE_3, // -
- // -3, //IASTORE, // visitInsn
- // -4, //LASTORE, // -
- // -3, //FASTORE, // -
- // -4, //DASTORE, // -
- // -3, //AASTORE, // -
- // -3, //BASTORE, // -
- // -3, //CASTORE, // -
- // -3, //SASTORE, // -
- // -1, //POP, // -
- // -2, //POP2, // -
- // 1, //DUP, // -
- // 1, //DUP_X1, // -
- // 1, //DUP_X2, // -
- // 2, //DUP2, // -
- // 2, //DUP2_X1, // -
- // 2, //DUP2_X2, // -
- // 0, //SWAP, // -
- // -1, //IADD, // -
- // -2, //LADD, // -
- // -1, //FADD, // -
- // -2, //DADD, // -
- // -1, //ISUB, // -
- // -2, //LSUB, // -
- // -1, //FSUB, // -
- // -2, //DSUB, // -
- // -1, //IMUL, // -
- // -2, //LMUL, // -
- // -1, //FMUL, // -
- // -2, //DMUL, // -
- // -1, //IDIV, // -
- // -2, //LDIV, // -
- // -1, //FDIV, // -
- // -2, //DDIV, // -
- // -1, //IREM, // -
- // -2, //LREM, // -
- // -1, //FREM, // -
- // -2, //DREM, // -
- // 0, //INEG, // -
- // 0, //LNEG, // -
- // 0, //FNEG, // -
- // 0, //DNEG, // -
- // -1, //ISHL, // -
- // -1, //LSHL, // -
- // -1, //ISHR, // -
- // -1, //LSHR, // -
- // -1, //IUSHR, // -
- // -1, //LUSHR, // -
- // -1, //IAND, // -
- // -2, //LAND, // -
- // -1, //IOR, // -
- // -2, //LOR, // -
- // -1, //IXOR, // -
- // -2, //LXOR, // -
- // 0, //IINC, // visitIincInsn
- // 1, //I2L, // visitInsn
- // 0, //I2F, // -
- // 1, //I2D, // -
- // -1, //L2I, // -
- // -1, //L2F, // -
- // 0, //L2D, // -
- // 0, //F2I, // -
- // 1, //F2L, // -
- // 1, //F2D, // -
- // -1, //D2I, // -
- // 0, //D2L, // -
- // -1, //D2F, // -
- // 0, //I2B, // -
- // 0, //I2C, // -
- // 0, //I2S, // -
- // -3, //LCMP, // -
- // -1, //FCMPL, // -
- // -1, //FCMPG, // -
- // -3, //DCMPL, // -
- // -3, //DCMPG, // -
- // -1, //IFEQ, // visitJumpInsn
- // -1, //IFNE, // -
- // -1, //IFLT, // -
- // -1, //IFGE, // -
- // -1, //IFGT, // -
- // -1, //IFLE, // -
- // -2, //IF_ICMPEQ, // -
- // -2, //IF_ICMPNE, // -
- // -2, //IF_ICMPLT, // -
- // -2, //IF_ICMPGE, // -
- // -2, //IF_ICMPGT, // -
- // -2, //IF_ICMPLE, // -
- // -2, //IF_ACMPEQ, // -
- // -2, //IF_ACMPNE, // -
- // 0, //GOTO, // -
- // 1, //JSR, // -
- // 0, //RET, // visitVarInsn
- // -1, //TABLESWITCH, // visiTableSwitchInsn
- // -1, //LOOKUPSWITCH, // visitLookupSwitch
- // -1, //IRETURN, // visitInsn
- // -2, //LRETURN, // -
- // -1, //FRETURN, // -
- // -2, //DRETURN, // -
- // -1, //ARETURN, // -
- // 0, //RETURN, // -
- // NA, //GETSTATIC, // visitFieldInsn
- // NA, //PUTSTATIC, // -
- // NA, //GETFIELD, // -
- // NA, //PUTFIELD, // -
- // NA, //INVOKEVIRTUAL, // visitMethodInsn
- // NA, //INVOKESPECIAL, // -
- // NA, //INVOKESTATIC, // -
- // NA, //INVOKEINTERFACE, // -
- // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn
- // 1, //NEW, // visitTypeInsn
- // 0, //NEWARRAY, // visitIntInsn
- // 0, //ANEWARRAY, // visitTypeInsn
- // 0, //ARRAYLENGTH, // visitInsn
- // NA, //ATHROW, // -
- // 0, //CHECKCAST, // visitTypeInsn
- // 0, //INSTANCEOF, // -
- // -1, //MONITORENTER, // visitInsn
- // -1, //MONITOREXIT, // -
- // NA, //WIDE, // NOT VISITED
- // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
- // -1, //IFNULL, // visitJumpInsn
- // -1, //IFNONNULL, // -
- // NA, //GOTO_W, // -
- // NA, //JSR_W, // -
- // };
- // for (i = 0; i < b.length; ++i) {
- // System.err.print((char)('E' + b[i]));
- // }
- // System.err.println();
- }
-
- /**
- * The label (i.e. basic block) to which these input and output stack map
- * frames correspond.
- */
- Label owner;
-
- /**
- * The input stack map frame locals.
- */
- int[] inputLocals;
-
- /**
- * The input stack map frame stack.
- */
- int[] inputStack;
+ /**
+ * Constructs a new Frame.
+ *
+ * @param owner the basic block to which these input and output stack map frames correspond.
+ */
+ Frame(final Label owner) {
+ this.owner = owner;
+ }
- /**
- * The output stack map frame locals.
- */
- private int[] outputLocals;
+ /**
+ * Sets this frame to the value of the given frame.
+ *
+ * <p>WARNING: after this method is called the two frames share the same data structures. It is
+ * recommended to discard the given frame to avoid unexpected side effects.
+ *
+ * @param frame The new frame value.
+ */
+ final void copyFrom(final Frame frame) {
+ inputLocals = frame.inputLocals;
+ inputStack = frame.inputStack;
+ outputStackStart = 0;
+ outputLocals = frame.outputLocals;
+ outputStack = frame.outputStack;
+ outputStackTop = frame.outputStackTop;
+ initializationCount = frame.initializationCount;
+ initializations = frame.initializations;
+ }
- /**
- * The output stack map frame stack.
- */
- private int[] outputStack;
+ // -----------------------------------------------------------------------------------------------
+ // Static methods to get abstract types from other type formats
+ // -----------------------------------------------------------------------------------------------
- /**
- * Relative size of the output stack. The exact semantics of this field
- * depends on the algorithm that is used.
- *
- * When only the maximum stack size is computed, this field is the size of
- * the output stack relatively to the top of the input stack.
- *
- * When the stack map frames are completely computed, this field is the
- * actual number of types in {@link #outputStack}.
- */
- int outputStackTop;
-
- /**
- * Number of types that are initialized in the basic block.
- *
- * @see #initializations
- */
- private int initializationCount;
+ /**
+ * Returns the abstract type corresponding to the given public API frame element type.
+ *
+ * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
+ * @param type a frame element type described using the same format as in {@link
+ * MethodVisitor#visitFrame}, i.e. either {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link
+ * Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL}, or
+ * {@link Opcodes#UNINITIALIZED_THIS}, or the internal name of a class, or a Label designating
+ * a NEW instruction (for uninitialized types).
+ * @return the abstract type corresponding to the given frame element type.
+ */
+ static int getAbstractTypeFromApiFormat(final SymbolTable symbolTable, final Object type) {
+ if (type instanceof Integer) {
+ return CONSTANT_KIND | ((Integer) type).intValue();
+ } else if (type instanceof String) {
+ String descriptor = Type.getObjectType((String) type).getDescriptor();
+ return getAbstractTypeFromDescriptor(symbolTable, descriptor, 0);
+ } else {
+ return UNINITIALIZED_KIND
+ | symbolTable.addUninitializedType("", ((Label) type).bytecodeOffset);
+ }
+ }
- /**
- * The types that are initialized in the basic block. A constructor
- * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
- * <i>every occurence</i> of this type in the local variables and in the
- * operand stack. This cannot be done during the first phase of the
- * algorithm since, during this phase, the local variables and the operand
- * stack are not completely computed. It is therefore necessary to store the
- * types on which constructors are invoked in the basic block, in order to
- * do this replacement during the second phase of the algorithm, where the
- * frames are fully computed. Note that this array can contain types that
- * are relative to input locals or to the input stack (see below for the
- * description of the algorithm).
- */
- private int[] initializations;
+ /**
+ * Returns the abstract type corresponding to the internal name of a class.
+ *
+ * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
+ * @param internalName the internal name of a class. This must <i>not</i> be an array type
+ * descriptor.
+ * @return the abstract type value corresponding to the given internal name.
+ */
+ static int getAbstractTypeFromInternalName(
+ final SymbolTable symbolTable, final String internalName) {
+ return REFERENCE_KIND | symbolTable.addType(internalName);
+ }
- /**
- * Sets this frame to the given value.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param nLocal
- * the number of local variables.
- * @param local
- * the local variable types. Primitive types are represented by
- * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
- * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
- * represented by a single element). Reference types are
- * represented by String objects (representing internal names),
- * and uninitialized types by Label objects (this label
- * designates the NEW instruction that created this uninitialized
- * value).
- * @param nStack
- * the number of operand stack elements.
- * @param stack
- * the operand stack types (same format as the "local" array).
- */
- final void set(ClassWriter cw, final int nLocal, final Object[] local,
- final int nStack, final Object[] stack) {
- int i = convert(cw, nLocal, local, inputLocals);
- while (i < local.length) {
- inputLocals[i++] = TOP;
+ /**
+ * Returns the abstract type corresponding to the given type descriptor.
+ *
+ * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
+ * @param buffer a string ending with a type descriptor.
+ * @param offset the start offset of the type descriptor in buffer.
+ * @return the abstract type corresponding to the given type descriptor.
+ */
+ private static int getAbstractTypeFromDescriptor(
+ final SymbolTable symbolTable, final String buffer, final int offset) {
+ String internalName;
+ switch (buffer.charAt(offset)) {
+ case 'V':
+ return 0;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ return INTEGER;
+ case 'F':
+ return FLOAT;
+ case 'J':
+ return LONG;
+ case 'D':
+ return DOUBLE;
+ case 'L':
+ internalName = buffer.substring(offset + 1, buffer.length() - 1);
+ return REFERENCE_KIND | symbolTable.addType(internalName);
+ case '[':
+ int elementDescriptorOffset = offset + 1;
+ while (buffer.charAt(elementDescriptorOffset) == '[') {
+ ++elementDescriptorOffset;
}
- int nStackTop = 0;
- for (int j = 0; j < nStack; ++j) {
- if (stack[j] == Opcodes.LONG || stack[j] == Opcodes.DOUBLE) {
- ++nStackTop;
- }
+ int typeValue;
+ switch (buffer.charAt(elementDescriptorOffset)) {
+ case 'Z':
+ typeValue = BOOLEAN;
+ break;
+ case 'C':
+ typeValue = CHAR;
+ break;
+ case 'B':
+ typeValue = BYTE;
+ break;
+ case 'S':
+ typeValue = SHORT;
+ break;
+ case 'I':
+ typeValue = INTEGER;
+ break;
+ case 'F':
+ typeValue = FLOAT;
+ break;
+ case 'J':
+ typeValue = LONG;
+ break;
+ case 'D':
+ typeValue = DOUBLE;
+ break;
+ case 'L':
+ internalName = buffer.substring(elementDescriptorOffset + 1, buffer.length() - 1);
+ typeValue = REFERENCE_KIND | symbolTable.addType(internalName);
+ break;
+ default:
+ throw new IllegalArgumentException();
}
- inputStack = new int[nStack + nStackTop];
- convert(cw, nStack, stack, inputStack);
- outputStackTop = 0;
- initializationCount = 0;
+ return ((elementDescriptorOffset - offset) << DIM_SHIFT) | typeValue;
+ default:
+ throw new IllegalArgumentException();
}
+ }
- /**
- * Converts types from the MethodWriter.visitFrame() format to the Frame
- * format.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param nInput
- * the number of types to convert.
- * @param input
- * the types to convert. Primitive types are represented by
- * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
- * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
- * represented by a single element). Reference types are
- * represented by String objects (representing internal names),
- * and uninitialized types by Label objects (this label
- * designates the NEW instruction that created this uninitialized
- * value).
- * @param output
- * where to store the converted types.
- * @return the number of output elements.
- */
- private static int convert(ClassWriter cw, int nInput, Object[] input,
- int[] output) {
- int i = 0;
- for (int j = 0; j < nInput; ++j) {
- if (input[j] instanceof Integer) {
- output[i++] = BASE | ((Integer) input[j]).intValue();
- if (input[j] == Opcodes.LONG || input[j] == Opcodes.DOUBLE) {
- output[i++] = TOP;
- }
- } else if (input[j] instanceof String) {
- output[i++] = type(cw, Type.getObjectType((String) input[j])
- .getDescriptor());
- } else {
- output[i++] = UNINITIALIZED
- | cw.addUninitializedType("",
- ((Label) input[j]).position);
- }
- }
- return i;
- }
+ // -----------------------------------------------------------------------------------------------
+ // Methods related to the input frame
+ // -----------------------------------------------------------------------------------------------
- /**
- * Sets this frame to the value of the given frame. WARNING: after this
- * method is called the two frames share the same data structures. It is
- * recommended to discard the given frame f to avoid unexpected side
- * effects.
- *
- * @param f
- * The new frame value.
- */
- final void set(final Frame f) {
- inputLocals = f.inputLocals;
- inputStack = f.inputStack;
- outputLocals = f.outputLocals;
- outputStack = f.outputStack;
- outputStackTop = f.outputStackTop;
- initializationCount = f.initializationCount;
- initializations = f.initializations;
+ /**
+ * Sets the input frame from the given method description. This method is used to initialize the
+ * first frame of a method, which is implicit (i.e. not stored explicitly in the StackMapTable
+ * attribute).
+ *
+ * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
+ * @param access the method's access flags.
+ * @param descriptor the method descriptor.
+ * @param maxLocals the maximum number of local variables of the method.
+ */
+ final void setInputFrameFromDescriptor(
+ final SymbolTable symbolTable,
+ final int access,
+ final String descriptor,
+ final int maxLocals) {
+ inputLocals = new int[maxLocals];
+ inputStack = new int[0];
+ int inputLocalIndex = 0;
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ((access & Constants.ACC_CONSTRUCTOR) == 0) {
+ inputLocals[inputLocalIndex++] =
+ REFERENCE_KIND | symbolTable.addType(symbolTable.getClassName());
+ } else {
+ inputLocals[inputLocalIndex++] = UNINITIALIZED_THIS;
+ }
}
-
- /**
- * Returns the output frame local variable type at the given index.
- *
- * @param local
- * the index of the local that must be returned.
- * @return the output frame local variable type at the given index.
- */
- private int get(final int local) {
- if (outputLocals == null || local >= outputLocals.length) {
- // this local has never been assigned in this basic block,
- // so it is still equal to its value in the input frame
- return LOCAL | local;
- } else {
- int type = outputLocals[local];
- if (type == 0) {
- // this local has never been assigned in this basic block,
- // so it is still equal to its value in the input frame
- type = outputLocals[local] = LOCAL | local;
- }
- return type;
- }
+ for (Type argumentType : Type.getArgumentTypes(descriptor)) {
+ int abstractType =
+ getAbstractTypeFromDescriptor(symbolTable, argumentType.getDescriptor(), 0);
+ inputLocals[inputLocalIndex++] = abstractType;
+ if (abstractType == LONG || abstractType == DOUBLE) {
+ inputLocals[inputLocalIndex++] = TOP;
+ }
+ }
+ while (inputLocalIndex < maxLocals) {
+ inputLocals[inputLocalIndex++] = TOP;
}
+ }
- /**
- * Sets the output frame local variable type at the given index.
- *
- * @param local
- * the index of the local that must be set.
- * @param type
- * the value of the local that must be set.
- */
- private void set(final int local, final int type) {
- // creates and/or resizes the output local variables array if necessary
- if (outputLocals == null) {
- outputLocals = new int[10];
- }
- int n = outputLocals.length;
- if (local >= n) {
- int[] t = new int[Math.max(local + 1, 2 * n)];
- System.arraycopy(outputLocals, 0, t, 0, n);
- outputLocals = t;
- }
- // sets the local variable
- outputLocals[local] = type;
+ /**
+ * Sets the input frame from the given public API frame description.
+ *
+ * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
+ * @param numLocal the number of local variables.
+ * @param local the local variable types, described using the same format as in {@link
+ * MethodVisitor#visitFrame}.
+ * @param numStack the number of operand stack elements.
+ * @param stack the operand stack types, described using the same format as in {@link
+ * MethodVisitor#visitFrame}.
+ */
+ final void setInputFrameFromApiFormat(
+ final SymbolTable symbolTable,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ int inputLocalIndex = 0;
+ for (int i = 0; i < numLocal; ++i) {
+ inputLocals[inputLocalIndex++] = getAbstractTypeFromApiFormat(symbolTable, local[i]);
+ if (local[i] == Opcodes.LONG || local[i] == Opcodes.DOUBLE) {
+ inputLocals[inputLocalIndex++] = TOP;
+ }
+ }
+ while (inputLocalIndex < inputLocals.length) {
+ inputLocals[inputLocalIndex++] = TOP;
+ }
+ int numStackTop = 0;
+ for (int i = 0; i < numStack; ++i) {
+ if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
+ ++numStackTop;
+ }
}
+ inputStack = new int[numStack + numStackTop];
+ int inputStackIndex = 0;
+ for (int i = 0; i < numStack; ++i) {
+ inputStack[inputStackIndex++] = getAbstractTypeFromApiFormat(symbolTable, stack[i]);
+ if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
+ inputStack[inputStackIndex++] = TOP;
+ }
+ }
+ outputStackTop = 0;
+ initializationCount = 0;
+ }
- /**
- * Pushes a new type onto the output frame stack.
- *
- * @param type
- * the type that must be pushed.
- */
- private void push(final int type) {
- // creates and/or resizes the output stack array if necessary
- if (outputStack == null) {
- outputStack = new int[10];
- }
- int n = outputStack.length;
- if (outputStackTop >= n) {
- int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
- System.arraycopy(outputStack, 0, t, 0, n);
- outputStack = t;
- }
- // pushes the type on the output stack
- outputStack[outputStackTop++] = type;
- // updates the maximum height reached by the output stack, if needed
- int top = owner.inputStackTop + outputStackTop;
- if (top > owner.outputStackMax) {
- owner.outputStackMax = top;
- }
+ final int getInputStackSize() {
+ return inputStack.length;
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods related to the output frame
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the abstract type stored at the given local variable index in the output frame.
+ *
+ * @param localIndex the index of the local variable whose value must be returned.
+ * @return the abstract type stored at the given local variable index in the output frame.
+ */
+ private int getLocal(final int localIndex) {
+ if (outputLocals == null || localIndex >= outputLocals.length) {
+ // If this local has never been assigned in this basic block, it is still equal to its value
+ // in the input frame.
+ return LOCAL_KIND | localIndex;
+ } else {
+ int abstractType = outputLocals[localIndex];
+ if (abstractType == 0) {
+ // If this local has never been assigned in this basic block, so it is still equal to its
+ // value in the input frame.
+ abstractType = outputLocals[localIndex] = LOCAL_KIND | localIndex;
+ }
+ return abstractType;
}
+ }
- /**
- * Pushes a new type onto the output frame stack.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param desc
- * the descriptor of the type to be pushed. Can also be a method
- * descriptor (in this case this method pushes its return type
- * onto the output frame stack).
- */
- private void push(final ClassWriter cw, final String desc) {
- int type = type(cw, desc);
- if (type != 0) {
- push(type);
- if (type == LONG || type == DOUBLE) {
- push(TOP);
- }
- }
+ /**
+ * Replaces the abstract type stored at the given local variable index in the output frame.
+ *
+ * @param localIndex the index of the output frame local variable that must be set.
+ * @param abstractType the value that must be set.
+ */
+ private void setLocal(final int localIndex, final int abstractType) {
+ // Create and/or resize the output local variables array if necessary.
+ if (outputLocals == null) {
+ outputLocals = new int[10];
}
+ int outputLocalsLength = outputLocals.length;
+ if (localIndex >= outputLocalsLength) {
+ int[] newOutputLocals = new int[Math.max(localIndex + 1, 2 * outputLocalsLength)];
+ System.arraycopy(outputLocals, 0, newOutputLocals, 0, outputLocalsLength);
+ outputLocals = newOutputLocals;
+ }
+ // Set the local variable.
+ outputLocals[localIndex] = abstractType;
+ }
- /**
- * Returns the int encoding of the given type.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param desc
- * a type descriptor.
- * @return the int encoding of the given type.
- */
- static int type(final ClassWriter cw, final String desc) {
- String t;
- int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
- switch (desc.charAt(index)) {
- case 'V':
- return 0;
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- return INTEGER;
- case 'F':
- return FLOAT;
- case 'J':
- return LONG;
- case 'D':
- return DOUBLE;
- case 'L':
- // stores the internal name, not the descriptor!
- t = desc.substring(index + 1, desc.length() - 1);
- return OBJECT | cw.addType(t);
- // case '[':
- default:
- // extracts the dimensions and the element type
- int data;
- int dims = index + 1;
- while (desc.charAt(dims) == '[') {
- ++dims;
- }
- switch (desc.charAt(dims)) {
- case 'Z':
- data = BOOLEAN;
- break;
- case 'C':
- data = CHAR;
- break;
- case 'B':
- data = BYTE;
- break;
- case 'S':
- data = SHORT;
- break;
- case 'I':
- data = INTEGER;
- break;
- case 'F':
- data = FLOAT;
- break;
- case 'J':
- data = LONG;
- break;
- case 'D':
- data = DOUBLE;
- break;
- // case 'L':
- default:
- // stores the internal name, not the descriptor
- t = desc.substring(dims + 1, desc.length() - 1);
- data = OBJECT | cw.addType(t);
- }
- return (dims - index) << 28 | data;
- }
+ /**
+ * Pushes the given abstract type on the output frame stack.
+ *
+ * @param abstractType an abstract type.
+ */
+ private void push(final int abstractType) {
+ // Create and/or resize the output stack array if necessary.
+ if (outputStack == null) {
+ outputStack = new int[10];
+ }
+ int outputStackLength = outputStack.length;
+ if (outputStackTop >= outputStackLength) {
+ int[] newOutputStack = new int[Math.max(outputStackTop + 1, 2 * outputStackLength)];
+ System.arraycopy(outputStack, 0, newOutputStack, 0, outputStackLength);
+ outputStack = newOutputStack;
}
+ // Pushes the abstract type on the output stack.
+ outputStack[outputStackTop++] = abstractType;
+ // Updates the maximum size reached by the output stack, if needed (note that this size is
+ // relative to the input stack size, which is not known yet).
+ short outputStackSize = (short) (outputStackStart + outputStackTop);
+ if (outputStackSize > owner.outputStackMax) {
+ owner.outputStackMax = outputStackSize;
+ }
+ }
- /**
- * Pops a type from the output frame stack and returns its value.
- *
- * @return the type that has been popped from the output frame stack.
- */
- private int pop() {
- if (outputStackTop > 0) {
- return outputStack[--outputStackTop];
- } else {
- // if the output frame stack is empty, pops from the input stack
- return STACK | -(--owner.inputStackTop);
- }
+ /**
+ * Pushes the abstract type corresponding to the given descriptor on the output frame stack.
+ *
+ * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
+ * @param descriptor a type or method descriptor (in which case its return type is pushed).
+ */
+ private void push(final SymbolTable symbolTable, final String descriptor) {
+ int typeDescriptorOffset = descriptor.charAt(0) == '(' ? descriptor.indexOf(')') + 1 : 0;
+ int abstractType = getAbstractTypeFromDescriptor(symbolTable, descriptor, typeDescriptorOffset);
+ if (abstractType != 0) {
+ push(abstractType);
+ if (abstractType == LONG || abstractType == DOUBLE) {
+ push(TOP);
+ }
}
+ }
- /**
- * Pops the given number of types from the output frame stack.
- *
- * @param elements
- * the number of types that must be popped.
- */
- private void pop(final int elements) {
- if (outputStackTop >= elements) {
- outputStackTop -= elements;
- } else {
- // if the number of elements to be popped is greater than the number
- // of elements in the output stack, clear it, and pops the remaining
- // elements from the input stack.
- owner.inputStackTop -= elements - outputStackTop;
- outputStackTop = 0;
- }
+ /**
+ * Pops an abstract type from the output frame stack and returns its value.
+ *
+ * @return the abstract type that has been popped from the output frame stack.
+ */
+ private int pop() {
+ if (outputStackTop > 0) {
+ return outputStack[--outputStackTop];
+ } else {
+ // If the output frame stack is empty, pop from the input stack.
+ return STACK_KIND | -(--outputStackStart);
}
+ }
- /**
- * Pops a type from the output frame stack.
- *
- * @param desc
- * the descriptor of the type to be popped. Can also be a method
- * descriptor (in this case this method pops the types
- * corresponding to the method arguments).
- */
- private void pop(final String desc) {
- char c = desc.charAt(0);
- if (c == '(') {
- pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
- } else if (c == 'J' || c == 'D') {
- pop(2);
- } else {
- pop(1);
- }
+ /**
+ * Pops the given number of abstract types from the output frame stack.
+ *
+ * @param elements the number of abstract types that must be popped.
+ */
+ private void pop(final int elements) {
+ if (outputStackTop >= elements) {
+ outputStackTop -= elements;
+ } else {
+ // If the number of elements to be popped is greater than the number of elements in the output
+ // stack, clear it, and pop the remaining elements from the input stack.
+ outputStackStart -= elements - outputStackTop;
+ outputStackTop = 0;
}
+ }
- /**
- * Adds a new type to the list of types on which a constructor is invoked in
- * the basic block.
- *
- * @param var
- * a type on a which a constructor is invoked.
- */
- private void init(final int var) {
- // creates and/or resizes the initializations array if necessary
- if (initializations == null) {
- initializations = new int[2];
- }
- int n = initializations.length;
- if (initializationCount >= n) {
- int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
- System.arraycopy(initializations, 0, t, 0, n);
- initializations = t;
- }
- // stores the type to be initialized
- initializations[initializationCount++] = var;
+ /**
+ * Pops as many abstract types from the output frame stack as described by the given descriptor.
+ *
+ * @param descriptor a type or method descriptor (in which case its argument types are popped).
+ */
+ private void pop(final String descriptor) {
+ char firstDescriptorChar = descriptor.charAt(0);
+ if (firstDescriptorChar == '(') {
+ pop((Type.getArgumentsAndReturnSizes(descriptor) >> 2) - 1);
+ } else if (firstDescriptorChar == 'J' || firstDescriptorChar == 'D') {
+ pop(2);
+ } else {
+ pop(1);
}
+ }
- /**
- * Replaces the given type with the appropriate type if it is one of the
- * types on which a constructor is invoked in the basic block.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param t
- * a type
- * @return t or, if t is one of the types on which a constructor is invoked
- * in the basic block, the type corresponding to this constructor.
- */
- private int init(final ClassWriter cw, final int t) {
- int s;
- if (t == UNINITIALIZED_THIS) {
- s = OBJECT | cw.addType(cw.thisName);
- } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
- String type = cw.typeTable[t & BASE_VALUE].strVal1;
- s = OBJECT | cw.addType(type);
- } else {
- return t;
- }
- for (int j = 0; j < initializationCount; ++j) {
- int u = initializations[j];
- int dim = u & DIM;
- int kind = u & KIND;
- if (kind == LOCAL) {
- u = dim + inputLocals[u & VALUE];
- } else if (kind == STACK) {
- u = dim + inputStack[inputStack.length - (u & VALUE)];
- }
- if (t == u) {
- return s;
- }
- }
- return t;
+ // -----------------------------------------------------------------------------------------------
+ // Methods to handle uninitialized types
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Adds an abstract type to the list of types on which a constructor is invoked in the basic
+ * block.
+ *
+ * @param abstractType an abstract type on a which a constructor is invoked.
+ */
+ private void addInitializedType(final int abstractType) {
+ // Create and/or resize the initializations array if necessary.
+ if (initializations == null) {
+ initializations = new int[2];
}
+ int initializationsLength = initializations.length;
+ if (initializationCount >= initializationsLength) {
+ int[] newInitializations =
+ new int[Math.max(initializationCount + 1, 2 * initializationsLength)];
+ System.arraycopy(initializations, 0, newInitializations, 0, initializationsLength);
+ initializations = newInitializations;
+ }
+ // Store the abstract type.
+ initializations[initializationCount++] = abstractType;
+ }
- /**
- * Initializes the input frame of the first basic block from the method
- * descriptor.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param access
- * the access flags of the method to which this label belongs.
- * @param args
- * the formal parameter types of this method.
- * @param maxLocals
- * the maximum number of local variables of this method.
- */
- final void initInputFrame(final ClassWriter cw, final int access,
- final Type[] args, final int maxLocals) {
- inputLocals = new int[maxLocals];
- inputStack = new int[0];
- int i = 0;
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
- inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
- } else {
- inputLocals[i++] = UNINITIALIZED_THIS;
- }
- }
- for (int j = 0; j < args.length; ++j) {
- int t = type(cw, args[j].getDescriptor());
- inputLocals[i++] = t;
- if (t == LONG || t == DOUBLE) {
- inputLocals[i++] = TOP;
- }
+ /**
+ * Returns the "initialized" abstract type corresponding to the given abstract type.
+ *
+ * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
+ * @param abstractType an abstract type.
+ * @return the REFERENCE_KIND abstract type corresponding to abstractType if it is
+ * UNINITIALIZED_THIS or an UNINITIALIZED_KIND abstract type for one of the types on which a
+ * constructor is invoked in the basic block. Otherwise returns abstractType.
+ */
+ private int getInitializedType(final SymbolTable symbolTable, final int abstractType) {
+ if (abstractType == UNINITIALIZED_THIS
+ || (abstractType & (DIM_MASK | KIND_MASK)) == UNINITIALIZED_KIND) {
+ for (int i = 0; i < initializationCount; ++i) {
+ int initializedType = initializations[i];
+ int dim = initializedType & DIM_MASK;
+ int kind = initializedType & KIND_MASK;
+ int value = initializedType & VALUE_MASK;
+ if (kind == LOCAL_KIND) {
+ initializedType = dim + inputLocals[value];
+ } else if (kind == STACK_KIND) {
+ initializedType = dim + inputStack[inputStack.length - value];
}
- while (i < maxLocals) {
- inputLocals[i++] = TOP;
+ if (abstractType == initializedType) {
+ if (abstractType == UNINITIALIZED_THIS) {
+ return REFERENCE_KIND | symbolTable.addType(symbolTable.getClassName());
+ } else {
+ return REFERENCE_KIND
+ | symbolTable.addType(symbolTable.getType(abstractType & VALUE_MASK).value);
+ }
}
+ }
}
+ return abstractType;
+ }
- /**
- * Simulates the action of the given instruction on the output stack frame.
- *
- * @param opcode
- * the opcode of the instruction.
- * @param arg
- * the operand of the instruction, if any.
- * @param cw
- * the class writer to which this label belongs.
- * @param item
- * the operand of the instructions, if any.
- */
- void execute(final int opcode, final int arg, final ClassWriter cw,
- final Item item) {
- int t1, t2, t3, t4;
- switch (opcode) {
- case Opcodes.NOP:
- case Opcodes.INEG:
- case Opcodes.LNEG:
- case Opcodes.FNEG:
- case Opcodes.DNEG:
- case Opcodes.I2B:
- case Opcodes.I2C:
- case Opcodes.I2S:
- case Opcodes.GOTO:
- case Opcodes.RETURN:
- break;
- case Opcodes.ACONST_NULL:
- push(NULL);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- case Opcodes.BIPUSH:
- case Opcodes.SIPUSH:
- case Opcodes.ILOAD:
- push(INTEGER);
- break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- case Opcodes.LLOAD:
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- case Opcodes.FLOAD:
- push(FLOAT);
- break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- case Opcodes.DLOAD:
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.LDC:
- switch (item.type) {
- case ClassWriter.INT:
- push(INTEGER);
- break;
- case ClassWriter.LONG:
- push(LONG);
- push(TOP);
- break;
- case ClassWriter.FLOAT:
- push(FLOAT);
- break;
- case ClassWriter.DOUBLE:
- push(DOUBLE);
- push(TOP);
- break;
- case ClassWriter.CLASS:
- push(OBJECT | cw.addType("java/lang/Class"));
- break;
- case ClassWriter.STR:
- push(OBJECT | cw.addType("java/lang/String"));
- break;
- case ClassWriter.MTYPE:
- push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
- break;
- // case ClassWriter.HANDLE_BASE + [1..9]:
- default:
- push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
- }
- break;
- case Opcodes.ALOAD:
- push(get(arg));
- break;
- case Opcodes.IALOAD:
- case Opcodes.BALOAD:
- case Opcodes.CALOAD:
- case Opcodes.SALOAD:
- pop(2);
- push(INTEGER);
- break;
- case Opcodes.LALOAD:
- case Opcodes.D2L:
- pop(2);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FALOAD:
- pop(2);
- push(FLOAT);
- break;
- case Opcodes.DALOAD:
- case Opcodes.L2D:
- pop(2);
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.AALOAD:
- pop(1);
- t1 = pop();
- push(t1 == NULL ? t1 : ELEMENT_OF + t1);
- break;
- case Opcodes.ISTORE:
- case Opcodes.FSTORE:
- case Opcodes.ASTORE:
- t1 = pop();
- set(arg, t1);
- if (arg > 0) {
- t2 = get(arg - 1);
- // if t2 is of kind STACK or LOCAL we cannot know its size!
- if (t2 == LONG || t2 == DOUBLE) {
- set(arg - 1, TOP);
- } else if ((t2 & KIND) != BASE) {
- set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
- }
- }
- break;
- case Opcodes.LSTORE:
- case Opcodes.DSTORE:
- pop(1);
- t1 = pop();
- set(arg, t1);
- set(arg + 1, TOP);
- if (arg > 0) {
- t2 = get(arg - 1);
- // if t2 is of kind STACK or LOCAL we cannot know its size!
- if (t2 == LONG || t2 == DOUBLE) {
- set(arg - 1, TOP);
- } else if ((t2 & KIND) != BASE) {
- set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
- }
- }
- break;
- case Opcodes.IASTORE:
- case Opcodes.BASTORE:
- case Opcodes.CASTORE:
- case Opcodes.SASTORE:
- case Opcodes.FASTORE:
- case Opcodes.AASTORE:
- pop(3);
- break;
- case Opcodes.LASTORE:
- case Opcodes.DASTORE:
- pop(4);
- break;
- case Opcodes.POP:
- case Opcodes.IFEQ:
- case Opcodes.IFNE:
- case Opcodes.IFLT:
- case Opcodes.IFGE:
- case Opcodes.IFGT:
- case Opcodes.IFLE:
- case Opcodes.IRETURN:
- case Opcodes.FRETURN:
- case Opcodes.ARETURN:
- case Opcodes.TABLESWITCH:
- case Opcodes.LOOKUPSWITCH:
- case Opcodes.ATHROW:
- case Opcodes.MONITORENTER:
- case Opcodes.MONITOREXIT:
- case Opcodes.IFNULL:
- case Opcodes.IFNONNULL:
- pop(1);
- break;
- case Opcodes.POP2:
- case Opcodes.IF_ICMPEQ:
- case Opcodes.IF_ICMPNE:
- case Opcodes.IF_ICMPLT:
- case Opcodes.IF_ICMPGE:
- case Opcodes.IF_ICMPGT:
- case Opcodes.IF_ICMPLE:
- case Opcodes.IF_ACMPEQ:
- case Opcodes.IF_ACMPNE:
- case Opcodes.LRETURN:
- case Opcodes.DRETURN:
- pop(2);
- break;
- case Opcodes.DUP:
- t1 = pop();
- push(t1);
- push(t1);
- break;
- case Opcodes.DUP_X1:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2:
- t1 = pop();
- t2 = pop();
- push(t2);
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X1:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t2);
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- t4 = pop();
- push(t2);
- push(t1);
- push(t4);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.SWAP:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- break;
- case Opcodes.IADD:
- case Opcodes.ISUB:
- case Opcodes.IMUL:
- case Opcodes.IDIV:
- case Opcodes.IREM:
- case Opcodes.IAND:
- case Opcodes.IOR:
- case Opcodes.IXOR:
- case Opcodes.ISHL:
- case Opcodes.ISHR:
- case Opcodes.IUSHR:
- case Opcodes.L2I:
- case Opcodes.D2I:
- case Opcodes.FCMPL:
- case Opcodes.FCMPG:
- pop(2);
+ // -----------------------------------------------------------------------------------------------
+ // Main method, to simulate the execution of each instruction on the output frame
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Simulates the action of the given instruction on the output stack frame.
+ *
+ * @param opcode the opcode of the instruction.
+ * @param arg the numeric operand of the instruction, if any.
+ * @param argSymbol the Symbol operand of the instruction, if any.
+ * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
+ */
+ void execute(
+ final int opcode, final int arg, final Symbol argSymbol, final SymbolTable symbolTable) {
+ // Abstract types popped from the stack or read from local variables.
+ int abstractType1;
+ int abstractType2;
+ int abstractType3;
+ int abstractType4;
+ switch (opcode) {
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.ILOAD:
+ push(INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.LLOAD:
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.FLOAD:
+ push(FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.DLOAD:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LDC:
+ switch (argSymbol.tag) {
+ case Symbol.CONSTANT_INTEGER_TAG:
push(INTEGER);
break;
- case Opcodes.LADD:
- case Opcodes.LSUB:
- case Opcodes.LMUL:
- case Opcodes.LDIV:
- case Opcodes.LREM:
- case Opcodes.LAND:
- case Opcodes.LOR:
- case Opcodes.LXOR:
- pop(4);
+ case Symbol.CONSTANT_LONG_TAG:
push(LONG);
push(TOP);
break;
- case Opcodes.FADD:
- case Opcodes.FSUB:
- case Opcodes.FMUL:
- case Opcodes.FDIV:
- case Opcodes.FREM:
- case Opcodes.L2F:
- case Opcodes.D2F:
- pop(2);
+ case Symbol.CONSTANT_FLOAT_TAG:
push(FLOAT);
break;
- case Opcodes.DADD:
- case Opcodes.DSUB:
- case Opcodes.DMUL:
- case Opcodes.DDIV:
- case Opcodes.DREM:
- pop(4);
+ case Symbol.CONSTANT_DOUBLE_TAG:
push(DOUBLE);
push(TOP);
break;
- case Opcodes.LSHL:
- case Opcodes.LSHR:
- case Opcodes.LUSHR:
- pop(3);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.IINC:
- set(arg, INTEGER);
- break;
- case Opcodes.I2L:
- case Opcodes.F2L:
- pop(1);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.I2F:
- pop(1);
- push(FLOAT);
- break;
- case Opcodes.I2D:
- case Opcodes.F2D:
- pop(1);
- push(DOUBLE);
- push(TOP);
+ case Symbol.CONSTANT_CLASS_TAG:
+ push(REFERENCE_KIND | symbolTable.addType("java/lang/Class"));
break;
- case Opcodes.F2I:
- case Opcodes.ARRAYLENGTH:
- case Opcodes.INSTANCEOF:
- pop(1);
- push(INTEGER);
+ case Symbol.CONSTANT_STRING_TAG:
+ push(REFERENCE_KIND | symbolTable.addType("java/lang/String"));
break;
- case Opcodes.LCMP:
- case Opcodes.DCMPL:
- case Opcodes.DCMPG:
- pop(4);
- push(INTEGER);
+ case Symbol.CONSTANT_METHOD_TYPE_TAG:
+ push(REFERENCE_KIND | symbolTable.addType("java/lang/invoke/MethodType"));
break;
- case Opcodes.JSR:
- case Opcodes.RET:
- throw new RuntimeException(
- "JSR/RET are not supported with computeFrames option");
- case Opcodes.GETSTATIC:
- push(cw, item.strVal3);
+ case Symbol.CONSTANT_METHOD_HANDLE_TAG:
+ push(REFERENCE_KIND | symbolTable.addType("java/lang/invoke/MethodHandle"));
break;
- case Opcodes.PUTSTATIC:
- pop(item.strVal3);
+ case Symbol.CONSTANT_DYNAMIC_TAG:
+ push(symbolTable, argSymbol.value);
break;
- case Opcodes.GETFIELD:
- pop(1);
- push(cw, item.strVal3);
+ default:
+ throw new AssertionError();
+ }
+ break;
+ case Opcodes.ALOAD:
+ push(getLocal(arg));
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ abstractType1 = pop();
+ push(abstractType1 == NULL ? abstractType1 : ELEMENT_OF + abstractType1);
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ abstractType1 = pop();
+ setLocal(arg, abstractType1);
+ if (arg > 0) {
+ int previousLocalType = getLocal(arg - 1);
+ if (previousLocalType == LONG || previousLocalType == DOUBLE) {
+ setLocal(arg - 1, TOP);
+ } else if ((previousLocalType & KIND_MASK) == LOCAL_KIND
+ || (previousLocalType & KIND_MASK) == STACK_KIND) {
+ // The type of the previous local variable is not known yet, but if it later appears
+ // to be LONG or DOUBLE, we should then use TOP instead.
+ setLocal(arg - 1, previousLocalType | TOP_IF_LONG_OR_DOUBLE_FLAG);
+ }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ abstractType1 = pop();
+ setLocal(arg, abstractType1);
+ setLocal(arg + 1, TOP);
+ if (arg > 0) {
+ int previousLocalType = getLocal(arg - 1);
+ if (previousLocalType == LONG || previousLocalType == DOUBLE) {
+ setLocal(arg - 1, TOP);
+ } else if ((previousLocalType & KIND_MASK) == LOCAL_KIND
+ || (previousLocalType & KIND_MASK) == STACK_KIND) {
+ // The type of the previous local variable is not known yet, but if it later appears
+ // to be LONG or DOUBLE, we should then use TOP instead.
+ setLocal(arg - 1, previousLocalType | TOP_IF_LONG_OR_DOUBLE_FLAG);
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ abstractType1 = pop();
+ push(abstractType1);
+ push(abstractType1);
+ break;
+ case Opcodes.DUP_X1:
+ abstractType1 = pop();
+ abstractType2 = pop();
+ push(abstractType1);
+ push(abstractType2);
+ push(abstractType1);
+ break;
+ case Opcodes.DUP_X2:
+ abstractType1 = pop();
+ abstractType2 = pop();
+ abstractType3 = pop();
+ push(abstractType1);
+ push(abstractType3);
+ push(abstractType2);
+ push(abstractType1);
+ break;
+ case Opcodes.DUP2:
+ abstractType1 = pop();
+ abstractType2 = pop();
+ push(abstractType2);
+ push(abstractType1);
+ push(abstractType2);
+ push(abstractType1);
+ break;
+ case Opcodes.DUP2_X1:
+ abstractType1 = pop();
+ abstractType2 = pop();
+ abstractType3 = pop();
+ push(abstractType2);
+ push(abstractType1);
+ push(abstractType3);
+ push(abstractType2);
+ push(abstractType1);
+ break;
+ case Opcodes.DUP2_X2:
+ abstractType1 = pop();
+ abstractType2 = pop();
+ abstractType3 = pop();
+ abstractType4 = pop();
+ push(abstractType2);
+ push(abstractType1);
+ push(abstractType4);
+ push(abstractType3);
+ push(abstractType2);
+ push(abstractType1);
+ break;
+ case Opcodes.SWAP:
+ abstractType1 = pop();
+ abstractType2 = pop();
+ push(abstractType1);
+ push(abstractType2);
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FALOAD:
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.IINC:
+ setLocal(arg, INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new IllegalArgumentException("JSR/RET are not supported with computeFrames option");
+ case Opcodes.GETSTATIC:
+ push(symbolTable, argSymbol.value);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(argSymbol.value);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ push(symbolTable, argSymbol.value);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(argSymbol.value);
+ pop();
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ pop(argSymbol.value);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ abstractType1 = pop();
+ if (opcode == Opcodes.INVOKESPECIAL && argSymbol.name.charAt(0) == '<') {
+ addInitializedType(abstractType1);
+ }
+ }
+ push(symbolTable, argSymbol.value);
+ break;
+ case Opcodes.INVOKEDYNAMIC:
+ pop(argSymbol.value);
+ push(symbolTable, argSymbol.value);
+ break;
+ case Opcodes.NEW:
+ push(UNINITIALIZED_KIND | symbolTable.addUninitializedType(argSymbol.value, arg));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (arg) {
+ case Opcodes.T_BOOLEAN:
+ push(ARRAY_OF | BOOLEAN);
break;
- case Opcodes.PUTFIELD:
- pop(item.strVal3);
- pop();
+ case Opcodes.T_CHAR:
+ push(ARRAY_OF | CHAR);
break;
- case Opcodes.INVOKEVIRTUAL:
- case Opcodes.INVOKESPECIAL:
- case Opcodes.INVOKESTATIC:
- case Opcodes.INVOKEINTERFACE:
- pop(item.strVal3);
- if (opcode != Opcodes.INVOKESTATIC) {
- t1 = pop();
- if (opcode == Opcodes.INVOKESPECIAL
- && item.strVal2.charAt(0) == '<') {
- init(t1);
- }
- }
- push(cw, item.strVal3);
+ case Opcodes.T_BYTE:
+ push(ARRAY_OF | BYTE);
break;
- case Opcodes.INVOKEDYNAMIC:
- pop(item.strVal2);
- push(cw, item.strVal2);
+ case Opcodes.T_SHORT:
+ push(ARRAY_OF | SHORT);
break;
- case Opcodes.NEW:
- push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+ case Opcodes.T_INT:
+ push(ARRAY_OF | INTEGER);
break;
- case Opcodes.NEWARRAY:
- pop();
- switch (arg) {
- case Opcodes.T_BOOLEAN:
- push(ARRAY_OF | BOOLEAN);
- break;
- case Opcodes.T_CHAR:
- push(ARRAY_OF | CHAR);
- break;
- case Opcodes.T_BYTE:
- push(ARRAY_OF | BYTE);
- break;
- case Opcodes.T_SHORT:
- push(ARRAY_OF | SHORT);
- break;
- case Opcodes.T_INT:
- push(ARRAY_OF | INTEGER);
- break;
- case Opcodes.T_FLOAT:
- push(ARRAY_OF | FLOAT);
- break;
- case Opcodes.T_DOUBLE:
- push(ARRAY_OF | DOUBLE);
- break;
- // case Opcodes.T_LONG:
- default:
- push(ARRAY_OF | LONG);
- break;
- }
+ case Opcodes.T_FLOAT:
+ push(ARRAY_OF | FLOAT);
break;
- case Opcodes.ANEWARRAY:
- String s = item.strVal1;
- pop();
- if (s.charAt(0) == '[') {
- push(cw, '[' + s);
- } else {
- push(ARRAY_OF | OBJECT | cw.addType(s));
- }
+ case Opcodes.T_DOUBLE:
+ push(ARRAY_OF | DOUBLE);
break;
- case Opcodes.CHECKCAST:
- s = item.strVal1;
- pop();
- if (s.charAt(0) == '[') {
- push(cw, s);
- } else {
- push(OBJECT | cw.addType(s));
- }
- break;
- // case Opcodes.MULTIANEWARRAY:
- default:
- pop(arg);
- push(cw, item.strVal1);
+ case Opcodes.T_LONG:
+ push(ARRAY_OF | LONG);
break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ String arrayElementType = argSymbol.value;
+ pop();
+ if (arrayElementType.charAt(0) == '[') {
+ push(symbolTable, '[' + arrayElementType);
+ } else {
+ push(ARRAY_OF | REFERENCE_KIND | symbolTable.addType(arrayElementType));
+ }
+ break;
+ case Opcodes.CHECKCAST:
+ String castType = argSymbol.value;
+ pop();
+ if (castType.charAt(0) == '[') {
+ push(symbolTable, castType);
+ } else {
+ push(REFERENCE_KIND | symbolTable.addType(castType));
}
+ break;
+ case Opcodes.MULTIANEWARRAY:
+ pop(arg);
+ push(symbolTable, argSymbol.value);
+ break;
+ default:
+ throw new IllegalArgumentException();
}
+ }
- /**
- * Merges the input frame of the given basic block with the input and output
- * frames of this basic block. Returns <tt>true</tt> if the input frame of
- * the given label has been changed by this operation.
- *
- * @param cw
- * the ClassWriter to which this label belongs.
- * @param frame
- * the basic block whose input frame must be updated.
- * @param edge
- * the kind of the {@link Edge} between this label and 'label'.
- *
<TRUNCATED>
[14/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
old mode 100644
new mode 100755
index 2032d59..d921aea
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
@@ -1,90 +1,107 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
import java.util.ArrayList;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
/**
* A method subroutine (corresponds to a JSR instruction).
- *
+ *
* @author Eric Bruneton
*/
-class Subroutine {
+final class Subroutine {
- LabelNode start;
+ /** The start of this subroutine. */
+ final LabelNode start;
- boolean[] access;
+ /**
+ * The local variables that are read or written by this subroutine. The i-th element is true if
+ * and only if the local variable at index i is read or written by this subroutine.
+ */
+ final boolean[] localsUsed;
- List<JumpInsnNode> callers;
+ /** The JSR instructions that jump to this subroutine. */
+ final List<JumpInsnNode> callers;
- private Subroutine() {
- }
+ /**
+ * Constructs a new {@link Subroutine}.
+ *
+ * @param start the start of this subroutine.
+ * @param maxLocals the local variables that are read or written by this subroutine.
+ * @param caller a JSR instruction that jump to this subroutine.
+ */
+ Subroutine(final LabelNode start, final int maxLocals, final JumpInsnNode caller) {
+ this.start = start;
+ this.localsUsed = new boolean[maxLocals];
+ this.callers = new ArrayList<JumpInsnNode>();
+ callers.add(caller);
+ }
- Subroutine(final LabelNode start, final int maxLocals,
- final JumpInsnNode caller) {
- this.start = start;
- this.access = new boolean[maxLocals];
- this.callers = new ArrayList<JumpInsnNode>();
- callers.add(caller);
- }
+ /**
+ * Constructs a copy of the given {@link Subroutine}.
+ *
+ * @param subroutine the subroutine to copy.
+ */
+ Subroutine(final Subroutine subroutine) {
+ this.start = subroutine.start;
+ this.localsUsed = new boolean[subroutine.localsUsed.length];
+ this.callers = new ArrayList<JumpInsnNode>(subroutine.callers);
+ System.arraycopy(subroutine.localsUsed, 0, this.localsUsed, 0, subroutine.localsUsed.length);
+ }
- public Subroutine copy() {
- Subroutine result = new Subroutine();
- result.start = start;
- result.access = new boolean[access.length];
- System.arraycopy(access, 0, result.access, 0, access.length);
- result.callers = new ArrayList<JumpInsnNode>(callers);
- return result;
+ /**
+ * Merges the given subroutine into this subroutine. The local variables read or written by the
+ * given subroutine are marked as read or written by this one, and the callers of the given
+ * subroutine are added as callers of this one (if both have the same start).
+ *
+ * @param subroutine another subroutine. This subroutine is left unchanged by this method.
+ * @return whether this subroutine has been modified by this method.
+ */
+ public boolean merge(final Subroutine subroutine) {
+ boolean changed = false;
+ for (int i = 0; i < localsUsed.length; ++i) {
+ if (subroutine.localsUsed[i] && !localsUsed[i]) {
+ localsUsed[i] = true;
+ changed = true;
+ }
}
-
- public boolean merge(final Subroutine subroutine) throws AnalyzerException {
- boolean changes = false;
- for (int i = 0; i < access.length; ++i) {
- if (subroutine.access[i] && !access[i]) {
- access[i] = true;
- changes = true;
- }
- }
- if (subroutine.start == start) {
- for (int i = 0; i < subroutine.callers.size(); ++i) {
- JumpInsnNode caller = subroutine.callers.get(i);
- if (!callers.contains(caller)) {
- callers.add(caller);
- changes = true;
- }
- }
+ if (subroutine.start == start) {
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ JumpInsnNode caller = subroutine.callers.get(i);
+ if (!callers.contains(caller)) {
+ callers.add(caller);
+ changed = true;
}
- return changes;
+ }
}
-}
\ No newline at end of file
+ return changed;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
old mode 100644
new mode 100755
index b0d657c..8592c66
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
@@ -1,45 +1,44 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree.analysis;
/**
- * An immutable symbolic value for semantic interpretation of bytecode.
- *
+ * An immutable symbolic value for the semantic interpretation of bytecode.
+ *
* @author Eric Bruneton
*/
public interface Value {
- /**
- * Returns the size of this value in words.
- *
- * @return either 1 or 2.
- */
- int getSize();
+ /**
+ * Returns the size of this value in 32 bits words. This size should be 1 for byte, boolean, char,
+ * short, int, float, object and array types, and 2 for long and double.
+ *
+ * @return either 1 or 2.
+ */
+ int getSize();
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
old mode 100644
new mode 100755
index 228da02..b60c7dd
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
@@ -39,23 +39,21 @@ Basic usage:
</p>
<pre>
-ClassReader cr = new ClassReader(bytecode);
-ClassNode cn = new ClassNode();
-cr.accept(cn, ClassReader.SKIP_DEBUG);
+ClassReader classReader = new ClassReader(bytecode);
+ClassNode classNode = new ClassNode();
+classReader.accept(classNode, ClassReader.SKIP_DEBUG);
-List methods = cn.methods;
-for (int i = 0; i < methods.size(); ++i) {
- MethodNode method = (MethodNode) methods.get(i);
- if (method.instructions.size() > 0) {
- Analyzer a = new Analyzer(new BasicInterpreter());
- a.analyze(cn.name, method);
- Frame[] frames = a.getFrames();
- // Elements of the frames arrray now contains info for each instruction
- // from the analyzed method. BasicInterpreter creates BasicValue, that
- // is using simplified type system that distinguishes the UNINITIALZED,
- // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
- ...
- }
+for (MethodNode method : classNode.methods) {
+ if (method.instructions.size() > 0) {
+ Analyzer analyzer = new Analyzer(new BasicInterpreter());
+ analyzer.analyze(classNode.name, method);
+ Frame[] frames = analyzer.getFrames();
+ // Elements of the frames array now contains info for each instruction
+ // from the analyzed method. BasicInterpreter creates BasicValue, that
+ // is using simplified type system that distinguishes the UNINITIALZED,
+ // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
+ ...
+ }
}
</pre>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html
old mode 100644
new mode 100755
index 940b876..ab295ac
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/package.html
@@ -43,8 +43,8 @@ However, this class adapter has a cost: it makes ASM bigger and slower. Indeed
it requires more than twenty new classes, and multiplies the time needed to
transform a class by almost two (it is almost two times faster to read, "modify"
and write a class with a ClassVisitor than with a ClassNode). This is why
-this package is bundled in an optional <tt>asm-tree.jar</tt> library that
-is separated from (but requires) the <tt>asm.jar</tt> library, which contains
+this package is bundled in an optional <code>asm-tree.jar</code> library that
+is separated from (but requires) the <code>asm.jar</code> library, which contains
the core ASM framework. This is also why <i><font color="red">it is recommended
not to use this class adapter when it is possible</font></i>.
</p>
@@ -54,9 +54,9 @@ The root class is the ClassNode, that can be created from existing bytecode. For
</p>
<pre>
- ClassReader cr = new ClassReader(source);
- ClassNode cn = new ClassNode();
- cr.accept(cn, true);
+ ClassReader classReader = new ClassReader(source);
+ ClassNode classNode = new ClassNode();
+ classReader.accept(classNode, 0);
</pre>
<p>
@@ -65,8 +65,8 @@ serialized back into bytecode:
</p>
<pre>
- ClassWriter cw = new ClassWriter(true);
- cn.accept(cw);
+ ClassWriter classWriter = new ClassWriter(0);
+ classNode.accept(classWriter);
</pre>
<p>
@@ -75,21 +75,22 @@ In this example MethodNode is acting as a buffer that is flushed out at visitEnd
</p>
<pre>
- ClassReader cr = new ClassReader(source);
- ClassWriter cw = new ClassWriter();
- ClassVisitor cv = new ClassVisitor(cw) {
+ ClassReader classReader = new ClassReader(source);
+ ClassWriter classWriter = new ClassWriter(0);
+ ClassVisitor classVisitor = new ClassVisitor(ASM7, classWriter) {
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
- final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
- MethodNode mn = new MethodNode(access, name, desc, signature, exceptions) {
+ final MethodVisitor methodVisitor =
+ super.visitMethod(access, name, desc, signature, exceptions);
+ MethodNode methodNode = new MethodNode(access, name, desc, signature, exceptions) {
public void visitEnd() {
// transform or analyze method code using tree API
- accept(mv);
+ accept(methodVisitor);
}
};
}
};
- cr.accept(cv, true);
+ classReader.accept(classVisitor, 0);
</pre>
<p>
@@ -99,8 +100,8 @@ add them to the instructions list:
</p>
<pre>
-MethodNode m = new MethodNode(...);
-m.instructions.add(new VarInsnNode(ALOAD, 0));
+MethodNode methodNode = new MethodNode(...);
+methodNode.instructions.add(new VarInsnNode(ALOAD, 0));
...
</pre>
@@ -111,8 +112,8 @@ the standard MethodVisitor methods:
</p>
<pre>
-MethodNode m = new MethodNode(...);
-m.visitVarInsn(ALOAD, 0);
+MethodNode methodNode = new MethodNode(...);
+methodNode.visitVarInsn(ALOAD, 0);
...
</pre>
@@ -124,12 +125,12 @@ methods insert() and insertBefore() to insert instructions at a saved pointer.
</p>
<pre>
-MethodNode m = new MethodNode(...);
-m.visitVarInsn(ALOAD, 0);
-AbstractInsnNode ptr = m.instructions.getLast();
-m.visitVarInsn(ALOAD, 1);
+MethodNode methodNode = new MethodNode(...);
+methodNode.visitVarInsn(ALOAD, 0);
+AbstractInsnNode ptr = methodNode.instructions.getLast();
+methodNode.visitVarInsn(ALOAD, 1);
// inserts an instruction between ALOAD 0 and ALOAD 1
-m.instructions.insert(ptr, new VarInsnNode(ALOAD, 0));
+methodNode.instructions.insert(ptr, new VarInsnNode(ALOAD, 0));
...
</pre>
@@ -140,9 +141,9 @@ ListIterator over the instruction list:
</p>
<pre>
-ListIterator it = m.instructions.iterator();
+ListIterator it = methodNode.instructions.iterator();
while (it.hasNext()) {
- AbstractInsnNode n = (AbstractInsnNode) it.next();
+ AbstractInsnNode insnNode = (AbstractInsnNode) it.next();
if (...) {
it.add(new VarInsnNode(ALOAD, 0));
}
@@ -150,16 +151,16 @@ while (it.hasNext()) {
</pre>
<p>
-It is also possible to convert an instruction list into an array and iterate trough
+It is also possible to convert an instruction list into an array and iterate through
array elements:
</p>
<pre>
-AbstractInsnNode[] insns = m.instructions.toArray();
+AbstractInsnNode[] insns = methodNode.instructions.toArray();
for(int i = 0; i<insns.length; i++) {
- AbstractInsnNode n = insns[i];
+ AbstractInsnNode insn = insns[i];
if (...) {
- m.instructions.insert(n, new VarInsnNode(ALOAD, 0));
+ methodNode.instructions.insert(insn, new VarInsnNode(ALOAD, 0));
}
}
</pre>
@@ -172,14 +173,14 @@ For example:
</p>
<pre>
-AbstractInsnNode[] insns = m.instructions.toArray();
+AbstractInsnNode[] insns = methodNode.instructions.toArray();
for(int i = 0; i<insns.length; i++) {
- AbstractInsnNode n = insns[i];
+ AbstractInsnNode insn = insns[i];
if (...) {
- MethodNode mn = new MethodNode();
- mn.visitVarInsn(ALOAD, 0);
- mn.visitVarInsn(ALOAD, 1);
- m.instructions.insert(n, mn.instructions);
+ MethodNode toInsert = new MethodNode();
+ toInsert.visitVarInsn(ALOAD, 0);
+ toInsert.visitVarInsn(ALOAD, 1);
+ m.instructions.insert(insn, toInsert.instructions);
}
}
</pre>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
old mode 100644
new mode 100755
index 9395df4..302ffde
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
@@ -1,56 +1,44 @@
/**
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
+ * ASM: a very small and fast Java bytecode manipulation framework Copyright (c) 2000-2011 INRIA,
+ * France Telecom 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * <p>Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met: 1. Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions
+ * in binary form must reproduce the above copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
+ * <p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.apache.tapestry5.internal.plastic.asm.util;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Label;
/**
- * An {@link org.objectweb.asm.Attribute Attribute} that can print the ASM code
- * to create an equivalent attribute.
- *
+ * An {@link org.apache.tapestry5.internal.plastic.asm.Attribute} that can generate the ASM code to create an equivalent
+ * attribute.
+ *
* @author Eugene Kuleshov
*/
+// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public interface ASMifiable {
- /**
- * Prints the ASM code to create an attribute equal to this attribute.
- *
- * @param buf
- * a buffer used for printing Java code.
- * @param varName
- * name of the variable in a printed code used to store attribute
- * instance.
- * @param labelNames
- * map of label instances to their names.
- */
- void asmify(StringBuffer buf, String varName, Map<Label, String> labelNames);
+ /**
+ * Generates the ASM code to create an attribute equal to this attribute.
+ *
+ * @param outputBuffer where the generated code must be appended.
+ * @param visitorVariableName the name of the visitor variable in the produced code.
+ * @param labelNames the names of the labels in the generated code.
+ */
+ void asmify(StringBuffer outputBuffer, String visitorVariableName, Map<Label, String> labelNames);
}
[30/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
old mode 100644
new mode 100755
index 3c48404..ecbea50
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
@@ -1,238 +1,231 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * A {@link MethodVisitor} that can be used to approximate method size.
- *
+ * A {@link MethodVisitor} that approximates the size of the methods it visits.
+ *
* @author Eugene Kuleshov
*/
public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
- private int minSize;
-
- private int maxSize;
-
- public CodeSizeEvaluator(final MethodVisitor mv) {
- this(Opcodes.ASM6, mv);
- }
-
- protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {
- super(api, mv);
- }
-
- public int getMinSize() {
- return this.minSize;
- }
-
- public int getMaxSize() {
- return this.maxSize;
- }
-
- @Override
- public void visitInsn(final int opcode) {
- minSize += 1;
- maxSize += 1;
- if (mv != null) {
- mv.visitInsn(opcode);
- }
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- if (opcode == SIPUSH) {
- minSize += 3;
- maxSize += 3;
- } else {
- minSize += 2;
- maxSize += 2;
- }
- if (mv != null) {
- mv.visitIntInsn(opcode, operand);
- }
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- if (var < 4 && opcode != RET) {
- minSize += 1;
- maxSize += 1;
- } else if (var >= 256) {
- minSize += 4;
- maxSize += 4;
- } else {
- minSize += 2;
- maxSize += 2;
- }
- if (mv != null) {
- mv.visitVarInsn(opcode, var);
- }
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- minSize += 3;
- maxSize += 3;
- if (mv != null) {
- mv.visitTypeInsn(opcode, type);
- }
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- minSize += 3;
- maxSize += 3;
- if (mv != null) {
- mv.visitFieldInsn(opcode, owner, name, desc);
- }
- }
-
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
- }
-
- private void doVisitMethodInsn(int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (opcode == INVOKEINTERFACE) {
- minSize += 5;
- maxSize += 5;
- } else {
- minSize += 3;
- maxSize += 3;
- }
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- minSize += 5;
- maxSize += 5;
- if (mv != null) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- minSize += 3;
- if (opcode == GOTO || opcode == JSR) {
- maxSize += 5;
- } else {
- maxSize += 8;
- }
- if (mv != null) {
- mv.visitJumpInsn(opcode, label);
- }
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- if (cst instanceof Long || cst instanceof Double) {
- minSize += 3;
- maxSize += 3;
- } else {
- minSize += 2;
- maxSize += 3;
- }
- if (mv != null) {
- mv.visitLdcInsn(cst);
- }
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- if (var > 255 || increment > 127 || increment < -128) {
- minSize += 6;
- maxSize += 6;
- } else {
- minSize += 3;
- maxSize += 3;
- }
- if (mv != null) {
- mv.visitIincInsn(var, increment);
- }
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- minSize += 13 + labels.length * 4;
- maxSize += 16 + labels.length * 4;
- if (mv != null) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- minSize += 9 + keys.length * 8;
- maxSize += 12 + keys.length * 8;
- if (mv != null) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- minSize += 4;
- maxSize += 4;
- if (mv != null) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
- }
+ /** The minimum size in bytes of the visited method. */
+ private int minSize;
+
+ /** The maximum size in bytes of the visited method. */
+ private int maxSize;
+
+ public CodeSizeEvaluator(final MethodVisitor methodVisitor) {
+ this(Opcodes.ASM7, methodVisitor);
+ }
+
+ protected CodeSizeEvaluator(final int api, final MethodVisitor methodVisitor) {
+ super(api, methodVisitor);
+ }
+
+ public int getMinSize() {
+ return this.minSize;
+ }
+
+ public int getMaxSize() {
+ return this.maxSize;
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ minSize += 1;
+ maxSize += 1;
+ super.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ if (opcode == SIPUSH) {
+ minSize += 3;
+ maxSize += 3;
+ } else {
+ minSize += 2;
+ maxSize += 2;
+ }
+ super.visitIntInsn(opcode, operand);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ if (var < 4 && opcode != RET) {
+ minSize += 1;
+ maxSize += 1;
+ } else if (var >= 256) {
+ minSize += 4;
+ maxSize += 4;
+ } else {
+ minSize += 2;
+ maxSize += 2;
+ }
+ super.visitVarInsn(opcode, var);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ minSize += 3;
+ maxSize += 3;
+ super.visitTypeInsn(opcode, type);
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ minSize += 3;
+ maxSize += 3;
+ super.visitFieldInsn(opcode, owner, name, descriptor);
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (opcode == INVOKEINTERFACE) {
+ minSize += 5;
+ maxSize += 5;
+ } else {
+ minSize += 3;
+ maxSize += 3;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ minSize += 5;
+ maxSize += 5;
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ minSize += 3;
+ if (opcode == GOTO || opcode == JSR) {
+ maxSize += 5;
+ } else {
+ maxSize += 8;
+ }
+ super.visitJumpInsn(opcode, label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ if (value instanceof Long
+ || value instanceof Double
+ || (value instanceof ConstantDynamic && ((ConstantDynamic) value).getSize() == 2)) {
+ minSize += 3;
+ maxSize += 3;
+ } else {
+ minSize += 2;
+ maxSize += 3;
+ }
+ super.visitLdcInsn(value);
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ if (var > 255 || increment > 127 || increment < -128) {
+ minSize += 6;
+ maxSize += 6;
+ } else {
+ minSize += 3;
+ maxSize += 3;
+ }
+ super.visitIincInsn(var, increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ minSize += 13 + labels.length * 4;
+ maxSize += 16 + labels.length * 4;
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ minSize += 9 + keys.length * 8;
+ maxSize += 12 + keys.length * 8;
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ minSize += 4;
+ maxSize += 4;
+ super.visitMultiANewArrayInsn(descriptor, numDimensions);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/FieldRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/FieldRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/FieldRemapper.java
old mode 100644
new mode 100755
index 1873b05..c8cbeed
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/FieldRemapper.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/FieldRemapper.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
@@ -36,36 +34,56 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link FieldVisitor} adapter for type remapping.
- *
+ * A {@link FieldVisitor} that remaps types with a {@link Remapper}.
+ *
* @author Eugene Kuleshov
*/
public class FieldRemapper extends FieldVisitor {
- private final Remapper remapper;
+ /** The remapper used to remap the types in the visited field. */
+ protected final Remapper remapper;
- public FieldRemapper(final FieldVisitor fv, final Remapper remapper) {
- this(Opcodes.ASM6, fv, remapper);
- }
+ /**
+ * Constructs a new {@link FieldRemapper}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #FieldRemapper(int,FieldVisitor,Remapper)} version.
+ *
+ * @param fieldVisitor the field visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited field.
+ */
+ public FieldRemapper(final FieldVisitor fieldVisitor, final Remapper remapper) {
+ this(Opcodes.ASM7, fieldVisitor, remapper);
+ }
- protected FieldRemapper(final int api, final FieldVisitor fv,
- final Remapper remapper) {
- super(api, fv);
- this.remapper = remapper;
- }
+ /**
+ * Constructs a new {@link FieldRemapper}.
+ *
+ * @param api the ASM API version supported by this remapper. Must be one of {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5} or {@link
+ * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6}.
+ * @param fieldVisitor the field visitor this remapper must deleted to.
+ * @param remapper the remapper to use to remap the types in the visited field.
+ */
+ protected FieldRemapper(final int api, final FieldVisitor fieldVisitor, final Remapper remapper) {
+ super(api, fieldVisitor);
+ this.remapper = remapper;
+ }
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
- visible);
- return av == null ? null : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitAnnotation(remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? null
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
- remapper.mapDesc(desc), visible);
- return av == null ? null : new AnnotationRemapper(av, remapper);
- }
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ AnnotationVisitor annotationVisitor =
+ super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
+ return annotationVisitor == null
+ ? null
+ : new AnnotationRemapper(api, annotationVisitor, remapper);
+ }
}
[28/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
old mode 100644
new mode 100755
index 97de573..07d30ee
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
@@ -1,1170 +1,1301 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.apache.tapestry5.internal.plastic.asm.commons;
-
-import org.apache.tapestry5.internal.plastic.asm.Handle;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.Type;
-
-/**
- * A {@link MethodVisitor} providing a more detailed API to generate and
- * transform instructions.
- *
- * @author Eric Bruneton
- */
-public class InstructionAdapter extends MethodVisitor {
-
- public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
-
- /**
- * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #InstructionAdapter(int, MethodVisitor)} version.
- *
- * @param mv
- * the method visitor to which this adapter delegates calls.
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public InstructionAdapter(final MethodVisitor mv) {
- this(Opcodes.ASM6, mv);
- if (getClass() != InstructionAdapter.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Creates a new {@link InstructionAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param mv
- * the method visitor to which this adapter delegates calls.
- */
- protected InstructionAdapter(final int api, final MethodVisitor mv) {
- super(api, mv);
- }
-
- @Override
- public void visitInsn(final int opcode) {
- switch (opcode) {
- case Opcodes.NOP:
- nop();
- break;
- case Opcodes.ACONST_NULL:
- aconst(null);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- iconst(opcode - Opcodes.ICONST_0);
- break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- lconst(opcode - Opcodes.LCONST_0);
- break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- fconst(opcode - Opcodes.FCONST_0);
- break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- dconst(opcode - Opcodes.DCONST_0);
- break;
- case Opcodes.IALOAD:
- aload(Type.INT_TYPE);
- break;
- case Opcodes.LALOAD:
- aload(Type.LONG_TYPE);
- break;
- case Opcodes.FALOAD:
- aload(Type.FLOAT_TYPE);
- break;
- case Opcodes.DALOAD:
- aload(Type.DOUBLE_TYPE);
- break;
- case Opcodes.AALOAD:
- aload(OBJECT_TYPE);
- break;
- case Opcodes.BALOAD:
- aload(Type.BYTE_TYPE);
- break;
- case Opcodes.CALOAD:
- aload(Type.CHAR_TYPE);
- break;
- case Opcodes.SALOAD:
- aload(Type.SHORT_TYPE);
- break;
- case Opcodes.IASTORE:
- astore(Type.INT_TYPE);
- break;
- case Opcodes.LASTORE:
- astore(Type.LONG_TYPE);
- break;
- case Opcodes.FASTORE:
- astore(Type.FLOAT_TYPE);
- break;
- case Opcodes.DASTORE:
- astore(Type.DOUBLE_TYPE);
- break;
- case Opcodes.AASTORE:
- astore(OBJECT_TYPE);
- break;
- case Opcodes.BASTORE:
- astore(Type.BYTE_TYPE);
- break;
- case Opcodes.CASTORE:
- astore(Type.CHAR_TYPE);
- break;
- case Opcodes.SASTORE:
- astore(Type.SHORT_TYPE);
- break;
- case Opcodes.POP:
- pop();
- break;
- case Opcodes.POP2:
- pop2();
- break;
- case Opcodes.DUP:
- dup();
- break;
- case Opcodes.DUP_X1:
- dupX1();
- break;
- case Opcodes.DUP_X2:
- dupX2();
- break;
- case Opcodes.DUP2:
- dup2();
- break;
- case Opcodes.DUP2_X1:
- dup2X1();
- break;
- case Opcodes.DUP2_X2:
- dup2X2();
- break;
- case Opcodes.SWAP:
- swap();
- break;
- case Opcodes.IADD:
- add(Type.INT_TYPE);
- break;
- case Opcodes.LADD:
- add(Type.LONG_TYPE);
- break;
- case Opcodes.FADD:
- add(Type.FLOAT_TYPE);
- break;
- case Opcodes.DADD:
- add(Type.DOUBLE_TYPE);
- break;
- case Opcodes.ISUB:
- sub(Type.INT_TYPE);
- break;
- case Opcodes.LSUB:
- sub(Type.LONG_TYPE);
- break;
- case Opcodes.FSUB:
- sub(Type.FLOAT_TYPE);
- break;
- case Opcodes.DSUB:
- sub(Type.DOUBLE_TYPE);
- break;
- case Opcodes.IMUL:
- mul(Type.INT_TYPE);
- break;
- case Opcodes.LMUL:
- mul(Type.LONG_TYPE);
- break;
- case Opcodes.FMUL:
- mul(Type.FLOAT_TYPE);
- break;
- case Opcodes.DMUL:
- mul(Type.DOUBLE_TYPE);
- break;
- case Opcodes.IDIV:
- div(Type.INT_TYPE);
- break;
- case Opcodes.LDIV:
- div(Type.LONG_TYPE);
- break;
- case Opcodes.FDIV:
- div(Type.FLOAT_TYPE);
- break;
- case Opcodes.DDIV:
- div(Type.DOUBLE_TYPE);
- break;
- case Opcodes.IREM:
- rem(Type.INT_TYPE);
- break;
- case Opcodes.LREM:
- rem(Type.LONG_TYPE);
- break;
- case Opcodes.FREM:
- rem(Type.FLOAT_TYPE);
- break;
- case Opcodes.DREM:
- rem(Type.DOUBLE_TYPE);
- break;
- case Opcodes.INEG:
- neg(Type.INT_TYPE);
- break;
- case Opcodes.LNEG:
- neg(Type.LONG_TYPE);
- break;
- case Opcodes.FNEG:
- neg(Type.FLOAT_TYPE);
- break;
- case Opcodes.DNEG:
- neg(Type.DOUBLE_TYPE);
- break;
- case Opcodes.ISHL:
- shl(Type.INT_TYPE);
- break;
- case Opcodes.LSHL:
- shl(Type.LONG_TYPE);
- break;
- case Opcodes.ISHR:
- shr(Type.INT_TYPE);
- break;
- case Opcodes.LSHR:
- shr(Type.LONG_TYPE);
- break;
- case Opcodes.IUSHR:
- ushr(Type.INT_TYPE);
- break;
- case Opcodes.LUSHR:
- ushr(Type.LONG_TYPE);
- break;
- case Opcodes.IAND:
- and(Type.INT_TYPE);
- break;
- case Opcodes.LAND:
- and(Type.LONG_TYPE);
- break;
- case Opcodes.IOR:
- or(Type.INT_TYPE);
- break;
- case Opcodes.LOR:
- or(Type.LONG_TYPE);
- break;
- case Opcodes.IXOR:
- xor(Type.INT_TYPE);
- break;
- case Opcodes.LXOR:
- xor(Type.LONG_TYPE);
- break;
- case Opcodes.I2L:
- cast(Type.INT_TYPE, Type.LONG_TYPE);
- break;
- case Opcodes.I2F:
- cast(Type.INT_TYPE, Type.FLOAT_TYPE);
- break;
- case Opcodes.I2D:
- cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
- break;
- case Opcodes.L2I:
- cast(Type.LONG_TYPE, Type.INT_TYPE);
- break;
- case Opcodes.L2F:
- cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
- break;
- case Opcodes.L2D:
- cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
- break;
- case Opcodes.F2I:
- cast(Type.FLOAT_TYPE, Type.INT_TYPE);
- break;
- case Opcodes.F2L:
- cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
- break;
- case Opcodes.F2D:
- cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
- break;
- case Opcodes.D2I:
- cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
- break;
- case Opcodes.D2L:
- cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
- break;
- case Opcodes.D2F:
- cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
- break;
- case Opcodes.I2B:
- cast(Type.INT_TYPE, Type.BYTE_TYPE);
- break;
- case Opcodes.I2C:
- cast(Type.INT_TYPE, Type.CHAR_TYPE);
- break;
- case Opcodes.I2S:
- cast(Type.INT_TYPE, Type.SHORT_TYPE);
- break;
- case Opcodes.LCMP:
- lcmp();
- break;
- case Opcodes.FCMPL:
- cmpl(Type.FLOAT_TYPE);
- break;
- case Opcodes.FCMPG:
- cmpg(Type.FLOAT_TYPE);
- break;
- case Opcodes.DCMPL:
- cmpl(Type.DOUBLE_TYPE);
- break;
- case Opcodes.DCMPG:
- cmpg(Type.DOUBLE_TYPE);
- break;
- case Opcodes.IRETURN:
- areturn(Type.INT_TYPE);
- break;
- case Opcodes.LRETURN:
- areturn(Type.LONG_TYPE);
- break;
- case Opcodes.FRETURN:
- areturn(Type.FLOAT_TYPE);
- break;
- case Opcodes.DRETURN:
- areturn(Type.DOUBLE_TYPE);
- break;
- case Opcodes.ARETURN:
- areturn(OBJECT_TYPE);
- break;
- case Opcodes.RETURN:
- areturn(Type.VOID_TYPE);
- break;
- case Opcodes.ARRAYLENGTH:
- arraylength();
- break;
- case Opcodes.ATHROW:
- athrow();
- break;
- case Opcodes.MONITORENTER:
- monitorenter();
- break;
- case Opcodes.MONITOREXIT:
- monitorexit();
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- switch (opcode) {
- case Opcodes.BIPUSH:
- iconst(operand);
- break;
- case Opcodes.SIPUSH:
- iconst(operand);
- break;
- case Opcodes.NEWARRAY:
- switch (operand) {
- case Opcodes.T_BOOLEAN:
- newarray(Type.BOOLEAN_TYPE);
- break;
- case Opcodes.T_CHAR:
- newarray(Type.CHAR_TYPE);
- break;
- case Opcodes.T_BYTE:
- newarray(Type.BYTE_TYPE);
- break;
- case Opcodes.T_SHORT:
- newarray(Type.SHORT_TYPE);
- break;
- case Opcodes.T_INT:
- newarray(Type.INT_TYPE);
- break;
- case Opcodes.T_FLOAT:
- newarray(Type.FLOAT_TYPE);
- break;
- case Opcodes.T_LONG:
- newarray(Type.LONG_TYPE);
- break;
- case Opcodes.T_DOUBLE:
- newarray(Type.DOUBLE_TYPE);
- break;
- default:
- throw new IllegalArgumentException();
- }
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- switch (opcode) {
- case Opcodes.ILOAD:
- load(var, Type.INT_TYPE);
- break;
- case Opcodes.LLOAD:
- load(var, Type.LONG_TYPE);
- break;
- case Opcodes.FLOAD:
- load(var, Type.FLOAT_TYPE);
- break;
- case Opcodes.DLOAD:
- load(var, Type.DOUBLE_TYPE);
- break;
- case Opcodes.ALOAD:
- load(var, OBJECT_TYPE);
- break;
- case Opcodes.ISTORE:
- store(var, Type.INT_TYPE);
- break;
- case Opcodes.LSTORE:
- store(var, Type.LONG_TYPE);
- break;
- case Opcodes.FSTORE:
- store(var, Type.FLOAT_TYPE);
- break;
- case Opcodes.DSTORE:
- store(var, Type.DOUBLE_TYPE);
- break;
- case Opcodes.ASTORE:
- store(var, OBJECT_TYPE);
- break;
- case Opcodes.RET:
- ret(var);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- Type t = Type.getObjectType(type);
- switch (opcode) {
- case Opcodes.NEW:
- anew(t);
- break;
- case Opcodes.ANEWARRAY:
- newarray(t);
- break;
- case Opcodes.CHECKCAST:
- checkcast(t);
- break;
- case Opcodes.INSTANCEOF:
- instanceOf(t);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- switch (opcode) {
- case Opcodes.GETSTATIC:
- getstatic(owner, name, desc);
- break;
- case Opcodes.PUTSTATIC:
- putstatic(owner, name, desc);
- break;
- case Opcodes.GETFIELD:
- getfield(owner, name, desc);
- break;
- case Opcodes.PUTFIELD:
- putfield(owner, name, desc);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
- }
-
- private void doVisitMethodInsn(int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- switch (opcode) {
- case Opcodes.INVOKESPECIAL:
- invokespecial(owner, name, desc, itf);
- break;
- case Opcodes.INVOKEVIRTUAL:
- invokevirtual(owner, name, desc, itf);
- break;
- case Opcodes.INVOKESTATIC:
- invokestatic(owner, name, desc, itf);
- break;
- case Opcodes.INVOKEINTERFACE:
- invokeinterface(owner, name, desc);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- invokedynamic(name, desc, bsm, bsmArgs);
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- switch (opcode) {
- case Opcodes.IFEQ:
- ifeq(label);
- break;
- case Opcodes.IFNE:
- ifne(label);
- break;
- case Opcodes.IFLT:
- iflt(label);
- break;
- case Opcodes.IFGE:
- ifge(label);
- break;
- case Opcodes.IFGT:
- ifgt(label);
- break;
- case Opcodes.IFLE:
- ifle(label);
- break;
- case Opcodes.IF_ICMPEQ:
- ificmpeq(label);
- break;
- case Opcodes.IF_ICMPNE:
- ificmpne(label);
- break;
- case Opcodes.IF_ICMPLT:
- ificmplt(label);
- break;
- case Opcodes.IF_ICMPGE:
- ificmpge(label);
- break;
- case Opcodes.IF_ICMPGT:
- ificmpgt(label);
- break;
- case Opcodes.IF_ICMPLE:
- ificmple(label);
- break;
- case Opcodes.IF_ACMPEQ:
- ifacmpeq(label);
- break;
- case Opcodes.IF_ACMPNE:
- ifacmpne(label);
- break;
- case Opcodes.GOTO:
- goTo(label);
- break;
- case Opcodes.JSR:
- jsr(label);
- break;
- case Opcodes.IFNULL:
- ifnull(label);
- break;
- case Opcodes.IFNONNULL:
- ifnonnull(label);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitLabel(final Label label) {
- mark(label);
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- if (cst instanceof Integer) {
- int val = ((Integer) cst).intValue();
- iconst(val);
- } else if (cst instanceof Byte) {
- int val = ((Byte) cst).intValue();
- iconst(val);
- } else if (cst instanceof Character) {
- int val = ((Character) cst).charValue();
- iconst(val);
- } else if (cst instanceof Short) {
- int val = ((Short) cst).intValue();
- iconst(val);
- } else if (cst instanceof Boolean) {
- int val = ((Boolean) cst).booleanValue() ? 1 : 0;
- iconst(val);
- } else if (cst instanceof Float) {
- float val = ((Float) cst).floatValue();
- fconst(val);
- } else if (cst instanceof Long) {
- long val = ((Long) cst).longValue();
- lconst(val);
- } else if (cst instanceof Double) {
- double val = ((Double) cst).doubleValue();
- dconst(val);
- } else if (cst instanceof String) {
- aconst(cst);
- } else if (cst instanceof Type) {
- tconst((Type) cst);
- } else if (cst instanceof Handle) {
- hconst((Handle) cst);
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- iinc(var, increment);
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- tableswitch(min, max, dflt, labels);
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- lookupswitch(dflt, keys, labels);
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- multianewarray(desc, dims);
- }
-
- // -----------------------------------------------------------------------
-
- public void nop() {
- mv.visitInsn(Opcodes.NOP);
- }
-
- public void aconst(final Object cst) {
- if (cst == null) {
- mv.visitInsn(Opcodes.ACONST_NULL);
- } else {
- mv.visitLdcInsn(cst);
- }
- }
-
- public void iconst(final int cst) {
- if (cst >= -1 && cst <= 5) {
- mv.visitInsn(Opcodes.ICONST_0 + cst);
- } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
- mv.visitIntInsn(Opcodes.BIPUSH, cst);
- } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
- mv.visitIntInsn(Opcodes.SIPUSH, cst);
- } else {
- mv.visitLdcInsn(cst);
- }
- }
-
- public void lconst(final long cst) {
- if (cst == 0L || cst == 1L) {
- mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
- } else {
- mv.visitLdcInsn(cst);
- }
- }
-
- public void fconst(final float cst) {
- int bits = Float.floatToIntBits(cst);
- if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
- mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
- } else {
- mv.visitLdcInsn(cst);
- }
- }
-
- public void dconst(final double cst) {
- long bits = Double.doubleToLongBits(cst);
- if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
- mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
- } else {
- mv.visitLdcInsn(cst);
- }
- }
-
- public void tconst(final Type type) {
- mv.visitLdcInsn(type);
- }
-
- public void hconst(final Handle handle) {
- mv.visitLdcInsn(handle);
- }
-
- public void load(final int var, final Type type) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
- }
-
- public void aload(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
- }
-
- public void store(final int var, final Type type) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
- }
-
- public void astore(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
- }
-
- public void pop() {
- mv.visitInsn(Opcodes.POP);
- }
-
- public void pop2() {
- mv.visitInsn(Opcodes.POP2);
- }
-
- public void dup() {
- mv.visitInsn(Opcodes.DUP);
- }
-
- public void dup2() {
- mv.visitInsn(Opcodes.DUP2);
- }
-
- public void dupX1() {
- mv.visitInsn(Opcodes.DUP_X1);
- }
-
- public void dupX2() {
- mv.visitInsn(Opcodes.DUP_X2);
- }
-
- public void dup2X1() {
- mv.visitInsn(Opcodes.DUP2_X1);
- }
-
- public void dup2X2() {
- mv.visitInsn(Opcodes.DUP2_X2);
- }
-
- public void swap() {
- mv.visitInsn(Opcodes.SWAP);
- }
-
- public void add(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IADD));
- }
-
- public void sub(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.ISUB));
- }
-
- public void mul(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IMUL));
- }
-
- public void div(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IDIV));
- }
-
- public void rem(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IREM));
- }
-
- public void neg(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.INEG));
- }
-
- public void shl(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.ISHL));
- }
-
- public void shr(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.ISHR));
- }
-
- public void ushr(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
- }
-
- public void and(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IAND));
- }
-
- public void or(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IOR));
- }
-
- public void xor(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IXOR));
- }
-
- public void iinc(final int var, final int increment) {
- mv.visitIincInsn(var, increment);
- }
-
- public void cast(final Type from, final Type to) {
- if (from != to) {
- if (from == Type.DOUBLE_TYPE) {
- if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.D2F);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.D2L);
- } else {
- mv.visitInsn(Opcodes.D2I);
- cast(Type.INT_TYPE, to);
- }
- } else if (from == Type.FLOAT_TYPE) {
- if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.F2D);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.F2L);
- } else {
- mv.visitInsn(Opcodes.F2I);
- cast(Type.INT_TYPE, to);
- }
- } else if (from == Type.LONG_TYPE) {
- if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.L2D);
- } else if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.L2F);
- } else {
- mv.visitInsn(Opcodes.L2I);
- cast(Type.INT_TYPE, to);
- }
- } else {
- if (to == Type.BYTE_TYPE) {
- mv.visitInsn(Opcodes.I2B);
- } else if (to == Type.CHAR_TYPE) {
- mv.visitInsn(Opcodes.I2C);
- } else if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.I2D);
- } else if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.I2F);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.I2L);
- } else if (to == Type.SHORT_TYPE) {
- mv.visitInsn(Opcodes.I2S);
- }
- }
- }
- }
-
- public void lcmp() {
- mv.visitInsn(Opcodes.LCMP);
- }
-
- public void cmpl(final Type type) {
- mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
- }
-
- public void cmpg(final Type type) {
- mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
- }
-
- public void ifeq(final Label label) {
- mv.visitJumpInsn(Opcodes.IFEQ, label);
- }
-
- public void ifne(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNE, label);
- }
-
- public void iflt(final Label label) {
- mv.visitJumpInsn(Opcodes.IFLT, label);
- }
-
- public void ifge(final Label label) {
- mv.visitJumpInsn(Opcodes.IFGE, label);
- }
-
- public void ifgt(final Label label) {
- mv.visitJumpInsn(Opcodes.IFGT, label);
- }
-
- public void ifle(final Label label) {
- mv.visitJumpInsn(Opcodes.IFLE, label);
- }
-
- public void ificmpeq(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
- }
-
- public void ificmpne(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
- }
-
- public void ificmplt(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
- }
-
- public void ificmpge(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
- }
-
- public void ificmpgt(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
- }
-
- public void ificmple(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
- }
-
- public void ifacmpeq(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
- }
-
- public void ifacmpne(final Label label) {
- mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
- }
-
- public void goTo(final Label label) {
- mv.visitJumpInsn(Opcodes.GOTO, label);
- }
-
- public void jsr(final Label label) {
- mv.visitJumpInsn(Opcodes.JSR, label);
- }
-
- public void ret(final int var) {
- mv.visitVarInsn(Opcodes.RET, var);
- }
-
- public void tableswitch(final int min, final int max, final Label dflt,
- final Label... labels) {
- mv.visitTableSwitchInsn(min, max, dflt, labels);
- }
-
- public void lookupswitch(final Label dflt, final int[] keys,
- final Label[] labels) {
- mv.visitLookupSwitchInsn(dflt, keys, labels);
- }
-
- public void areturn(final Type t) {
- mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
- }
-
- public void getstatic(final String owner, final String name,
- final String desc) {
- mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
- }
-
- public void putstatic(final String owner, final String name,
- final String desc) {
- mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
- }
-
- public void getfield(final String owner, final String name,
- final String desc) {
- mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
- }
-
- public void putfield(final String owner, final String name,
- final String desc) {
- mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
- }
-
- @Deprecated
- public void invokevirtual(final String owner, final String name,
- final String desc) {
- if (api >= Opcodes.ASM5) {
- invokevirtual(owner, name, desc, false);
- return;
- }
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
- }
-
- public void invokevirtual(final String owner, final String name,
- final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- if (itf) {
- throw new IllegalArgumentException(
- "INVOKEVIRTUAL on interfaces require ASM 5");
- }
- invokevirtual(owner, name, desc);
- return;
- }
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
- }
-
- @Deprecated
- public void invokespecial(final String owner, final String name,
- final String desc) {
- if (api >= Opcodes.ASM5) {
- invokespecial(owner, name, desc, false);
- return;
- }
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false);
- }
-
- public void invokespecial(final String owner, final String name,
- final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- if (itf) {
- throw new IllegalArgumentException(
- "INVOKESPECIAL on interfaces require ASM 5");
- }
- invokespecial(owner, name, desc);
- return;
- }
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf);
- }
-
- @Deprecated
- public void invokestatic(final String owner, final String name,
- final String desc) {
- if (api >= Opcodes.ASM5) {
- invokestatic(owner, name, desc, false);
- return;
- }
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);
- }
-
- public void invokestatic(final String owner, final String name,
- final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- if (itf) {
- throw new IllegalArgumentException(
- "INVOKESTATIC on interfaces require ASM 5");
- }
- invokestatic(owner, name, desc);
- return;
- }
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf);
- }
-
- public void invokeinterface(final String owner, final String name,
- final String desc) {
- mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true);
- }
-
- public void invokedynamic(String name, String desc, Handle bsm,
- Object[] bsmArgs) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
-
- public void anew(final Type type) {
- mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
- }
-
- public void newarray(final Type type) {
- int typ;
- switch (type.getSort()) {
- case Type.BOOLEAN:
- typ = Opcodes.T_BOOLEAN;
- break;
- case Type.CHAR:
- typ = Opcodes.T_CHAR;
- break;
- case Type.BYTE:
- typ = Opcodes.T_BYTE;
- break;
- case Type.SHORT:
- typ = Opcodes.T_SHORT;
- break;
- case Type.INT:
- typ = Opcodes.T_INT;
- break;
- case Type.FLOAT:
- typ = Opcodes.T_FLOAT;
- break;
- case Type.LONG:
- typ = Opcodes.T_LONG;
- break;
- case Type.DOUBLE:
- typ = Opcodes.T_DOUBLE;
- break;
- default:
- mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
- return;
- }
- mv.visitIntInsn(Opcodes.NEWARRAY, typ);
- }
-
- public void arraylength() {
- mv.visitInsn(Opcodes.ARRAYLENGTH);
- }
-
- public void athrow() {
- mv.visitInsn(Opcodes.ATHROW);
- }
-
- public void checkcast(final Type type) {
- mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
- }
-
- public void instanceOf(final Type type) {
- mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
- }
-
- public void monitorenter() {
- mv.visitInsn(Opcodes.MONITORENTER);
- }
-
- public void monitorexit() {
- mv.visitInsn(Opcodes.MONITOREXIT);
- }
-
- public void multianewarray(final String desc, final int dims) {
- mv.visitMultiANewArrayInsn(desc, dims);
- }
-
- public void ifnull(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNULL, label);
- }
-
- public void ifnonnull(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNONNULL, label);
- }
-
- public void mark(final Label label) {
- mv.visitLabel(label);
- }
-}
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.apache.tapestry5.internal.plastic.asm.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link MethodVisitor} providing a more detailed API to generate and transform instructions.
+ *
+ * @author Eric Bruneton
+ */
+public class InstructionAdapter extends MethodVisitor {
+
+ /** The type of the java.lang.Object class. */
+ public static final Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
+
+ /**
+ * Constructs a new {@link InstructionAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #InstructionAdapter(int, MethodVisitor)} version.
+ *
+ * @param methodVisitor the method visitor to which this adapter delegates calls.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public InstructionAdapter(final MethodVisitor methodVisitor) {
+ this(Opcodes.ASM7, methodVisitor);
+ if (getClass() != InstructionAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link InstructionAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param methodVisitor the method visitor to which this adapter delegates calls.
+ */
+ protected InstructionAdapter(final int api, final MethodVisitor methodVisitor) {
+ super(api, methodVisitor);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ switch (opcode) {
+ case Opcodes.NOP:
+ nop();
+ break;
+ case Opcodes.ACONST_NULL:
+ aconst(null);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ iconst(opcode - Opcodes.ICONST_0);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ lconst((long) (opcode - Opcodes.LCONST_0));
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ fconst((float) (opcode - Opcodes.FCONST_0));
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ dconst((double) (opcode - Opcodes.DCONST_0));
+ break;
+ case Opcodes.IALOAD:
+ aload(Type.INT_TYPE);
+ break;
+ case Opcodes.LALOAD:
+ aload(Type.LONG_TYPE);
+ break;
+ case Opcodes.FALOAD:
+ aload(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DALOAD:
+ aload(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.AALOAD:
+ aload(OBJECT_TYPE);
+ break;
+ case Opcodes.BALOAD:
+ aload(Type.BYTE_TYPE);
+ break;
+ case Opcodes.CALOAD:
+ aload(Type.CHAR_TYPE);
+ break;
+ case Opcodes.SALOAD:
+ aload(Type.SHORT_TYPE);
+ break;
+ case Opcodes.IASTORE:
+ astore(Type.INT_TYPE);
+ break;
+ case Opcodes.LASTORE:
+ astore(Type.LONG_TYPE);
+ break;
+ case Opcodes.FASTORE:
+ astore(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DASTORE:
+ astore(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.AASTORE:
+ astore(OBJECT_TYPE);
+ break;
+ case Opcodes.BASTORE:
+ astore(Type.BYTE_TYPE);
+ break;
+ case Opcodes.CASTORE:
+ astore(Type.CHAR_TYPE);
+ break;
+ case Opcodes.SASTORE:
+ astore(Type.SHORT_TYPE);
+ break;
+ case Opcodes.POP:
+ pop();
+ break;
+ case Opcodes.POP2:
+ pop2();
+ break;
+ case Opcodes.DUP:
+ dup();
+ break;
+ case Opcodes.DUP_X1:
+ dupX1();
+ break;
+ case Opcodes.DUP_X2:
+ dupX2();
+ break;
+ case Opcodes.DUP2:
+ dup2();
+ break;
+ case Opcodes.DUP2_X1:
+ dup2X1();
+ break;
+ case Opcodes.DUP2_X2:
+ dup2X2();
+ break;
+ case Opcodes.SWAP:
+ swap();
+ break;
+ case Opcodes.IADD:
+ add(Type.INT_TYPE);
+ break;
+ case Opcodes.LADD:
+ add(Type.LONG_TYPE);
+ break;
+ case Opcodes.FADD:
+ add(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DADD:
+ add(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ISUB:
+ sub(Type.INT_TYPE);
+ break;
+ case Opcodes.LSUB:
+ sub(Type.LONG_TYPE);
+ break;
+ case Opcodes.FSUB:
+ sub(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DSUB:
+ sub(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IMUL:
+ mul(Type.INT_TYPE);
+ break;
+ case Opcodes.LMUL:
+ mul(Type.LONG_TYPE);
+ break;
+ case Opcodes.FMUL:
+ mul(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DMUL:
+ mul(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IDIV:
+ div(Type.INT_TYPE);
+ break;
+ case Opcodes.LDIV:
+ div(Type.LONG_TYPE);
+ break;
+ case Opcodes.FDIV:
+ div(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DDIV:
+ div(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IREM:
+ rem(Type.INT_TYPE);
+ break;
+ case Opcodes.LREM:
+ rem(Type.LONG_TYPE);
+ break;
+ case Opcodes.FREM:
+ rem(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DREM:
+ rem(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.INEG:
+ neg(Type.INT_TYPE);
+ break;
+ case Opcodes.LNEG:
+ neg(Type.LONG_TYPE);
+ break;
+ case Opcodes.FNEG:
+ neg(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DNEG:
+ neg(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ISHL:
+ shl(Type.INT_TYPE);
+ break;
+ case Opcodes.LSHL:
+ shl(Type.LONG_TYPE);
+ break;
+ case Opcodes.ISHR:
+ shr(Type.INT_TYPE);
+ break;
+ case Opcodes.LSHR:
+ shr(Type.LONG_TYPE);
+ break;
+ case Opcodes.IUSHR:
+ ushr(Type.INT_TYPE);
+ break;
+ case Opcodes.LUSHR:
+ ushr(Type.LONG_TYPE);
+ break;
+ case Opcodes.IAND:
+ and(Type.INT_TYPE);
+ break;
+ case Opcodes.LAND:
+ and(Type.LONG_TYPE);
+ break;
+ case Opcodes.IOR:
+ or(Type.INT_TYPE);
+ break;
+ case Opcodes.LOR:
+ or(Type.LONG_TYPE);
+ break;
+ case Opcodes.IXOR:
+ xor(Type.INT_TYPE);
+ break;
+ case Opcodes.LXOR:
+ xor(Type.LONG_TYPE);
+ break;
+ case Opcodes.I2L:
+ cast(Type.INT_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.I2F:
+ cast(Type.INT_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.I2D:
+ cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.L2I:
+ cast(Type.LONG_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.L2F:
+ cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.L2D:
+ cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.F2I:
+ cast(Type.FLOAT_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.F2L:
+ cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.F2D:
+ cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.D2I:
+ cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.D2L:
+ cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.D2F:
+ cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.I2B:
+ cast(Type.INT_TYPE, Type.BYTE_TYPE);
+ break;
+ case Opcodes.I2C:
+ cast(Type.INT_TYPE, Type.CHAR_TYPE);
+ break;
+ case Opcodes.I2S:
+ cast(Type.INT_TYPE, Type.SHORT_TYPE);
+ break;
+ case Opcodes.LCMP:
+ lcmp();
+ break;
+ case Opcodes.FCMPL:
+ cmpl(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.FCMPG:
+ cmpg(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DCMPL:
+ cmpl(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.DCMPG:
+ cmpg(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IRETURN:
+ areturn(Type.INT_TYPE);
+ break;
+ case Opcodes.LRETURN:
+ areturn(Type.LONG_TYPE);
+ break;
+ case Opcodes.FRETURN:
+ areturn(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DRETURN:
+ areturn(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ARETURN:
+ areturn(OBJECT_TYPE);
+ break;
+ case Opcodes.RETURN:
+ areturn(Type.VOID_TYPE);
+ break;
+ case Opcodes.ARRAYLENGTH:
+ arraylength();
+ break;
+ case Opcodes.ATHROW:
+ athrow();
+ break;
+ case Opcodes.MONITORENTER:
+ monitorenter();
+ break;
+ case Opcodes.MONITOREXIT:
+ monitorexit();
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ iconst(operand);
+ break;
+ case Opcodes.SIPUSH:
+ iconst(operand);
+ break;
+ case Opcodes.NEWARRAY:
+ switch (operand) {
+ case Opcodes.T_BOOLEAN:
+ newarray(Type.BOOLEAN_TYPE);
+ break;
+ case Opcodes.T_CHAR:
+ newarray(Type.CHAR_TYPE);
+ break;
+ case Opcodes.T_BYTE:
+ newarray(Type.BYTE_TYPE);
+ break;
+ case Opcodes.T_SHORT:
+ newarray(Type.SHORT_TYPE);
+ break;
+ case Opcodes.T_INT:
+ newarray(Type.INT_TYPE);
+ break;
+ case Opcodes.T_FLOAT:
+ newarray(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.T_LONG:
+ newarray(Type.LONG_TYPE);
+ break;
+ case Opcodes.T_DOUBLE:
+ newarray(Type.DOUBLE_TYPE);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ switch (opcode) {
+ case Opcodes.ILOAD:
+ load(var, Type.INT_TYPE);
+ break;
+ case Opcodes.LLOAD:
+ load(var, Type.LONG_TYPE);
+ break;
+ case Opcodes.FLOAD:
+ load(var, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DLOAD:
+ load(var, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ALOAD:
+ load(var, OBJECT_TYPE);
+ break;
+ case Opcodes.ISTORE:
+ store(var, Type.INT_TYPE);
+ break;
+ case Opcodes.LSTORE:
+ store(var, Type.LONG_TYPE);
+ break;
+ case Opcodes.FSTORE:
+ store(var, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DSTORE:
+ store(var, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ASTORE:
+ store(var, OBJECT_TYPE);
+ break;
+ case Opcodes.RET:
+ ret(var);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ Type objectType = Type.getObjectType(type);
+ switch (opcode) {
+ case Opcodes.NEW:
+ anew(objectType);
+ break;
+ case Opcodes.ANEWARRAY:
+ newarray(objectType);
+ break;
+ case Opcodes.CHECKCAST:
+ checkcast(objectType);
+ break;
+ case Opcodes.INSTANCEOF:
+ instanceOf(objectType);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ switch (opcode) {
+ case Opcodes.GETSTATIC:
+ getstatic(owner, name, descriptor);
+ break;
+ case Opcodes.PUTSTATIC:
+ putstatic(owner, name, descriptor);
+ break;
+ case Opcodes.GETFIELD:
+ getfield(owner, name, descriptor);
+ break;
+ case Opcodes.PUTFIELD:
+ putfield(owner, name, descriptor);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ switch (opcode) {
+ case Opcodes.INVOKESPECIAL:
+ invokespecial(owner, name, descriptor, isInterface);
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ invokevirtual(owner, name, descriptor, isInterface);
+ break;
+ case Opcodes.INVOKESTATIC:
+ invokestatic(owner, name, descriptor, isInterface);
+ break;
+ case Opcodes.INVOKEINTERFACE:
+ invokeinterface(owner, name, descriptor);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ invokedynamic(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ switch (opcode) {
+ case Opcodes.IFEQ:
+ ifeq(label);
+ break;
+ case Opcodes.IFNE:
+ ifne(label);
+ break;
+ case Opcodes.IFLT:
+ iflt(label);
+ break;
+ case Opcodes.IFGE:
+ ifge(label);
+ break;
+ case Opcodes.IFGT:
+ ifgt(label);
+ break;
+ case Opcodes.IFLE:
+ ifle(label);
+ break;
+ case Opcodes.IF_ICMPEQ:
+ ificmpeq(label);
+ break;
+ case Opcodes.IF_ICMPNE:
+ ificmpne(label);
+ break;
+ case Opcodes.IF_ICMPLT:
+ ificmplt(label);
+ break;
+ case Opcodes.IF_ICMPGE:
+ ificmpge(label);
+ break;
+ case Opcodes.IF_ICMPGT:
+ ificmpgt(label);
+ break;
+ case Opcodes.IF_ICMPLE:
+ ificmple(label);
+ break;
+ case Opcodes.IF_ACMPEQ:
+ ifacmpeq(label);
+ break;
+ case Opcodes.IF_ACMPNE:
+ ifacmpne(label);
+ break;
+ case Opcodes.GOTO:
+ goTo(label);
+ break;
+ case Opcodes.JSR:
+ jsr(label);
+ break;
+ case Opcodes.IFNULL:
+ ifnull(label);
+ break;
+ case Opcodes.IFNONNULL:
+ ifnonnull(label);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ mark(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ if (api < Opcodes.ASM5
+ && (value instanceof Handle
+ || (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) {
+ throw new UnsupportedOperationException("This feature requires ASM5");
+ }
+ if (api != Opcodes.ASM7 && value instanceof ConstantDynamic) {
+ throw new UnsupportedOperationException("This feature requires ASM7");
+ }
+ if (value instanceof Integer) {
+ iconst((Integer) value);
+ } else if (value instanceof Byte) {
+ iconst(((Byte) value).intValue());
+ } else if (value instanceof Character) {
+ iconst(((Character) value).charValue());
+ } else if (value instanceof Short) {
+ iconst(((Short) value).intValue());
+ } else if (value instanceof Boolean) {
+ iconst(((Boolean) value).booleanValue() ? 1 : 0);
+ } else if (value instanceof Float) {
+ fconst((Float) value);
+ } else if (value instanceof Long) {
+ lconst((Long) value);
+ } else if (value instanceof Double) {
+ dconst((Double) value);
+ } else if (value instanceof String) {
+ aconst(value);
+ } else if (value instanceof Type) {
+ tconst((Type) value);
+ } else if (value instanceof Handle) {
+ hconst((Handle) value);
+ } else if (value instanceof ConstantDynamic) {
+ cconst((ConstantDynamic) value);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ iinc(var, increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ tableswitch(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ lookupswitch(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ multianewarray(descriptor, numDimensions);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+
+ /** Generates a nop instruction. */
+ public void nop() {
+ mv.visitInsn(Opcodes.NOP);
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value the constant to be pushed on the stack. This parameter must be an {@link Integer},
+ * a {@link Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link Type} of
+ * OBJECT or ARRAY sort for {@code .class} constants, for classes whose version is 49, a
+ * {@link Type} of METHOD sort for MethodType, a {@link Handle} for MethodHandle constants,
+ * for classes whose version is 51 or a {@link ConstantDynamic} for a constant dynamic for
+ * classes whose version is 55.
+ */
+ public void aconst(final Object value) {
+ if (value == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param intValue the constant to be pushed on the stack.
+ */
+ public void iconst(final int intValue) {
+ if (intValue >= -1 && intValue <= 5) {
+ mv.visitInsn(Opcodes.ICONST_0 + intValue);
+ } else if (intValue >= Byte.MIN_VALUE && intValue <= Byte.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.BIPUSH, intValue);
+ } else if (intValue >= Short.MIN_VALUE && intValue <= Short.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.SIPUSH, intValue);
+ } else {
+ mv.visitLdcInsn(intValue);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param longValue the constant to be pushed on the stack.
+ */
+ public void lconst(final long longValue) {
+ if (longValue == 0L || longValue == 1L) {
+ mv.visitInsn(Opcodes.LCONST_0 + (int) longValue);
+ } else {
+ mv.visitLdcInsn(longValue);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param floatValue the constant to be pushed on the stack.
+ */
+ public void fconst(final float floatValue) {
+ int bits = Float.floatToIntBits(floatValue);
+ if (bits == 0L || bits == 0x3F800000 || bits == 0x40000000) { // 0..2
+ mv.visitInsn(Opcodes.FCONST_0 + (int) floatValue);
+ } else {
+ mv.visitLdcInsn(floatValue);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param doubleValue the constant to be pushed on the stack.
+ */
+ public void dconst(final double doubleValue) {
+ long bits = Double.doubleToLongBits(doubleValue);
+ if (bits == 0L || bits == 0x3FF0000000000000L) { // +0.0d and 1.0d
+ mv.visitInsn(Opcodes.DCONST_0 + (int) doubleValue);
+ } else {
+ mv.visitLdcInsn(doubleValue);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given type on the stack.
+ *
+ * @param type the type to be pushed on the stack.
+ */
+ public void tconst(final Type type) {
+ mv.visitLdcInsn(type);
+ }
+
+ /**
+ * Generates the instruction to push the given handle on the stack.
+ *
+ * @param handle the handle to be pushed on the stack.
+ */
+ public void hconst(final Handle handle) {
+ mv.visitLdcInsn(handle);
+ }
+
+ /**
+ * Generates the instruction to push the given constant dynamic on the stack.
+ *
+ * @param constantDynamic the constant dynamic to be pushed on the stack.
+ */
+ public void cconst(final ConstantDynamic constantDynamic) {
+ mv.visitLdcInsn(constantDynamic);
+ }
+
+ public void load(final int var, final Type type) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
+ }
+
+ public void aload(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+ }
+
+ public void store(final int var, final Type type) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
+ }
+
+ public void astore(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+ }
+
+ public void pop() {
+ mv.visitInsn(Opcodes.POP);
+ }
+
+ public void pop2() {
+ mv.visitInsn(Opcodes.POP2);
+ }
+
+ public void dup() {
+ mv.visitInsn(Opcodes.DUP);
+ }
+
+ public void dup2() {
+ mv.visitInsn(Opcodes.DUP2);
+ }
+
+ public void dupX1() {
+ mv.visitInsn(Opcodes.DUP_X1);
+ }
+
+ public void dupX2() {
+ mv.visitInsn(Opcodes.DUP_X2);
+ }
+
+ public void dup2X1() {
+ mv.visitInsn(Opcodes.DUP2_X1);
+ }
+
+ public void dup2X2() {
+ mv.visitInsn(Opcodes.DUP2_X2);
+ }
+
+ public void swap() {
+ mv.visitInsn(Opcodes.SWAP);
+ }
+
+ public void add(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IADD));
+ }
+
+ public void sub(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISUB));
+ }
+
+ public void mul(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IMUL));
+ }
+
+ public void div(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IDIV));
+ }
+
+ public void rem(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IREM));
+ }
+
+ public void neg(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.INEG));
+ }
+
+ public void shl(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISHL));
+ }
+
+ public void shr(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISHR));
+ }
+
+ public void ushr(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
+ }
+
+ public void and(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IAND));
+ }
+
+ public void or(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IOR));
+ }
+
+ public void xor(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IXOR));
+ }
+
+ public void iinc(final int var, final int increment) {
+ mv.visitIincInsn(var, increment);
+ }
+
+ /**
+ * Generates the instruction to cast from the first given type to the other.
+ *
+ * @param from a Type.
+ * @param to a Type.
+ */
+ public void cast(final Type from, final Type to) {
+ if (from != to) {
+ if (from == Type.DOUBLE_TYPE) {
+ if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.D2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.D2L);
+ } else {
+ mv.visitInsn(Opcodes.D2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.FLOAT_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.F2D);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.F2L);
+ } else {
+ mv.visitInsn(Opcodes.F2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.LONG_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.L2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.L2F);
+ } else {
+ mv.visitInsn(Opcodes.L2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else {
+ if (to == Type.BYTE_TYPE) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (to == Type.CHAR_TYPE) {
+ mv.visitInsn(Opcodes.I2C);
+ } else if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.I2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.I2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.I2L);
+ } else if (to == Type.SHORT_TYPE) {
+ mv.visitInsn(Opcodes.I2S);
+ }
+ }
+ }
+ }
+
+ public void lcmp() {
+ mv.visitInsn(Opcodes.LCMP);
+ }
+
+ public void cmpl(final Type type) {
+ mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
+ }
+
+ public void cmpg(final Type type) {
+ mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
+ }
+
+ public void ifeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFEQ, label);
+ }
+
+ public void ifne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNE, label);
+ }
+
+ public void iflt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFLT, label);
+ }
+
+ public void ifge(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFGE, label);
+ }
+
+ public void ifgt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFGT, label);
+ }
+
+ public void ifle(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFLE, label);
+ }
+
+ public void ificmpeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
+ }
+
+ public void ificmpne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
+ }
+
+ public void ificmplt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
+ }
+
+ public void ificmpge(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
+ }
+
+ public void ificmpgt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
+ }
+
+ public void ificmple(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
+ }
+
+ public void ifacmpeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+ }
+
+ public void ifacmpne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+ }
+
+ public void goTo(final Label label) {
+ mv.visitJumpInsn(Opcodes.GOTO, label);
+ }
+
+ public void jsr(final Label label) {
+ mv.visitJumpInsn(Opcodes.JSR, label);
+ }
+
+ public void ret(final int var) {
+ mv.visitVarInsn(Opcodes.RET, var);
+ }
+
+ public void tableswitch(final int min, final int max, final Label dflt, final Label... labels) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ public void lookupswitch(final Label dflt, final int[] keys, final Label[] labels) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ public void areturn(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IRETURN));
+ }
+
+ public void getstatic(final String owner, final String name, final String descriptor) {
+ mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, descriptor);
+ }
+
+ public void putstatic(final String owner, final String name, final String descriptor) {
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, descriptor);
+ }
+
+ public void getfield(final String owner, final String name, final String descriptor) {
+ mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, descriptor);
+ }
+
+ public void putfield(final String owner, final String name, final String descriptor) {
+ mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, descriptor);
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @param owner the internal name of the method's owner class.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @deprecated use {@link #invokevirtual(String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ public void invokevirtual(final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ invokevirtual(owner, name, descriptor, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor);
+ }
+
+ /**
+ * Generates the instruction to call the given virtual method.
+ *
+ * @param owner the internal name of the method's owner class (see {@link
+ * Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param isInterface if the method's owner class is an interface.
+ */
+ public void invokevirtual(
+ final String owner, final String name, final String descriptor, final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ if (isInterface) {
+ throw new IllegalArgumentException("INVOKEVIRTUAL on interfaces require ASM 5");
+ }
+ invokevirtual(owner, name, descriptor);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface);
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @param owner the internal name of the method's owner class.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @deprecated use {@link #invokespecial(String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ public void invokespecial(final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ invokespecial(owner, name, descriptor, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, false);
+ }
+
+ /**
+ * Generates the instruction to call the given special method.
+ *
+ * @param owner the internal name of the method's owner class (see {@link
+ * Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param isInterface if the method's owner class is an interface.
+ */
+ public void invokespecial(
+ final String owner, final String name, final String descriptor, final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ if (isInterface) {
+ throw new IllegalArgumentException("INVOKESPECIAL on interfaces require ASM 5");
+ }
+ invokespecial(owner, name, descriptor);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, isInterface);
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @param owner the internal name of the method's owner class.
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @deprecated use {@link #invokestatic(String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ public void invokestatic(final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ invokestatic(owner, name, descriptor, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, false);
+ }
+
+ /**
+ * Generates the instruction to call the given static method.
+ *
+ * @param owner the internal name of the method's owner class (see {@link
+ * Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param isInterface if the method's owner class is an interface.
+ */
+ public void invokestatic(
+ final String owner, final String name, final String descriptor, final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ if (isInterface) {
+ throw new IllegalArgumentException("INVOKESTATIC on interfaces require ASM 5");
+ }
+ invokestatic(owner, name, descriptor);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, isInterface);
+ }
+
+ /**
+ * Generates the instruction to call the given interface method.
+ *
+ * @param owner the internal name of the method's owner class (see {@link
+ * Type#getInternalName()}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ */
+ public void invokeinterface(final String owner, final String name, final String descriptor) {
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, descriptor, true);
+ }
+
+ /**
+ * Generates the instruction to call the given dynamic method.
+ *
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param bootstrapMethodHandle the bootstrap method.
+ * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link
+ * Type}, {@link Handle} or {@link ConstantDynamic} value. This method is allowed to modify
+ * the content of the array so a caller should expect that this array may change.
+ */
+ public void invokedynamic(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object[] bootstrapMethodArguments) {
+ mv.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ }
+
+ public void anew(final Type type) {
+ mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
+ }
+
+ /**
+ * Generates the instruction to create and push on the stack an array of the given type.
+ *
+ * @param type an array Type.
+ */
+ public void newarray(final Type type) {
+ int arrayType;
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ arrayType = Opcodes.T_BOOLEAN;
+ break;
+ case Type.CHAR:
+ arrayType = Opcodes.T_CHAR;
+ break;
+ case Type.BYTE:
+ arrayType = Opcodes.T_BYTE;
+ break;
+ case Type.SHORT:
+ arrayType = Opcodes.T_SHORT;
+ break;
+ case Type.INT:
+ arrayType = Opcodes.T_INT;
+ break;
+ case Type.FLOAT:
+ arrayType = Opcodes.T_FLOAT;
+ break;
+ case Type.LONG:
+ arrayType = Opcodes.T_LONG;
+ break;
+ case Type.DOUBLE:
+ arrayType = Opcodes.T_DOUBLE;
+ break;
+ default:
+ mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
+ return;
+ }
+ mv.visitIntInsn(Opcodes.NEWARRAY, arrayType);
+ }
+
+ public void arraylength() {
+ mv.visitInsn(Opcodes.ARRAYLENGTH);
+ }
+
+ public void athrow() {
+ mv.visitInsn(Opcodes.ATHROW);
+ }
+
+ public void checkcast(final Type type) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
+ }
+
+ public void instanceOf(final Type type) {
+ mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
+ }
+
+ public void monitorenter() {
+ mv.visitInsn(Opcodes.MONITORENTER);
+ }
+
+ public void monitorexit() {
+ mv.visitInsn(Opcodes.MONITOREXIT);
+ }
+
+ public void multianewarray(final String descriptor, final int numDimensions) {
+ mv.visitMultiANewArrayInsn(descriptor, numDimensions);
+ }
+
+ public void ifnull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNULL, label);
+ }
+
+ public void ifnonnull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+ }
+
+ public void mark(final Label label) {
+ mv.visitLabel(label);
+ }
+}
[36/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
old mode 100644
new mode 100755
index eaae447..363da36
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
@@ -1,2373 +1,2441 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A {@link MethodVisitor} that generates methods in bytecode form. Each visit
- * method of this class appends the bytecode corresponding to the visited
- * instruction to a byte vector, in the order these methods are called.
- *
+ * A {@link MethodVisitor} that generates a corresponding 'method_info' structure, as defined in the
+ * Java Virtual Machine Specification (JVMS).
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.6">JVMS
+ * 4.6</a>
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
-class MethodWriter extends MethodVisitor {
-
- /**
- * Pseudo access flag used to denote constructors.
- */
- static final int ACC_CONSTRUCTOR = 0x80000;
-
- /**
- * Frame has exactly the same locals as the previous stack map frame and
- * number of stack items is zero.
- */
- static final int SAME_FRAME = 0; // to 63 (0-3f)
-
- /**
- * Frame has exactly the same locals as the previous stack map frame and
- * number of stack items is 1
- */
- static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f)
-
- /**
- * Reserved for future use
- */
- static final int RESERVED = 128;
-
- /**
- * Frame has exactly the same locals as the previous stack map frame and
- * number of stack items is 1. Offset is bigger then 63;
- */
- static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7
-
- /**
- * Frame where current locals are the same as the locals in the previous
- * frame, except that the k last locals are absent. The value of k is given
- * by the formula 251-frame_type.
- */
- static final int CHOP_FRAME = 248; // to 250 (f8-fA)
-
- /**
- * Frame has exactly the same locals as the previous stack map frame and
- * number of stack items is zero. Offset is bigger then 63;
- */
- static final int SAME_FRAME_EXTENDED = 251; // fb
-
- /**
- * Frame where current locals are the same as the locals in the previous
- * frame, except that k additional locals are defined. The value of k is
- * given by the formula frame_type-251.
- */
- static final int APPEND_FRAME = 252; // to 254 // fc-fe
-
- /**
- * Full frame
- */
- static final int FULL_FRAME = 255; // ff
-
- /**
- * Indicates that the stack map frames must be recomputed from scratch. In
- * this case the maximum stack size and number of local variables is also
- * recomputed from scratch.
- *
- * @see #compute
- */
- static final int FRAMES = 0;
-
- /**
- * Indicates that the stack map frames of type F_INSERT must be computed.
- * The other frames are not (re)computed. They should all be of type F_NEW
- * and should be sufficient to compute the content of the F_INSERT frames,
- * together with the bytecode instructions between a F_NEW and a F_INSERT
- * frame - and without any knowledge of the type hierarchy (by definition of
- * F_INSERT).
- *
- * @see #compute
- */
- static final int INSERTED_FRAMES = 1;
-
- /**
- * Indicates that the maximum stack size and number of local variables must
- * be automatically computed.
- *
- * @see #compute
- */
- static final int MAXS = 2;
-
- /**
- * Indicates that nothing must be automatically computed.
- *
- * @see #compute
- */
- static final int NOTHING = 3;
-
- /**
- * The class writer to which this method must be added.
- */
- final ClassWriter cw;
-
- /**
- * Access flags of this method.
- */
- private int access;
-
- /**
- * The index of the constant pool item that contains the name of this
- * method.
- */
- private final int name;
-
- /**
- * The index of the constant pool item that contains the descriptor of this
- * method.
- */
- private final int desc;
-
- /**
- * The descriptor of this method.
- */
- private final String descriptor;
-
- /**
- * The signature of this method.
- */
- String signature;
-
- /**
- * If not zero, indicates that the code of this method must be copied from
- * the ClassReader associated to this writer in <code>cw.cr</code>. More
- * precisely, this field gives the index of the first byte to copied from
- * <code>cw.cr.b</code>.
- */
- int classReaderOffset;
-
- /**
- * If not zero, indicates that the code of this method must be copied from
- * the ClassReader associated to this writer in <code>cw.cr</code>. More
- * precisely, this field gives the number of bytes to copied from
- * <code>cw.cr.b</code>.
- */
- int classReaderLength;
-
- /**
- * Number of exceptions that can be thrown by this method.
- */
- int exceptionCount;
-
- /**
- * The exceptions that can be thrown by this method. More precisely, this
- * array contains the indexes of the constant pool items that contain the
- * internal names of these exception classes.
- */
- int[] exceptions;
-
- /**
- * The annotation default attribute of this method. May be <tt>null</tt>.
- */
- private ByteVector annd;
-
- /**
- * The runtime visible annotations of this method. May be <tt>null</tt>.
- */
- private AnnotationWriter anns;
-
- /**
- * The runtime invisible annotations of this method. May be <tt>null</tt>.
- */
- private AnnotationWriter ianns;
-
- /**
- * The runtime visible type annotations of this method. May be <tt>null</tt>
- * .
- */
- private AnnotationWriter tanns;
-
- /**
- * The runtime invisible type annotations of this method. May be
- * <tt>null</tt>.
- */
- private AnnotationWriter itanns;
-
- /**
- * The runtime visible parameter annotations of this method. May be
- * <tt>null</tt>.
- */
- private AnnotationWriter[] panns;
-
- /**
- * The runtime invisible parameter annotations of this method. May be
- * <tt>null</tt>.
- */
- private AnnotationWriter[] ipanns;
-
- /**
- * The number of synthetic parameters of this method.
- */
- private int synthetics;
-
- /**
- * The non standard attributes of the method.
- */
- private Attribute attrs;
-
- /**
- * The bytecode of this method.
- */
- private ByteVector code = new ByteVector();
-
- /**
- * Maximum stack size of this method.
- */
- private int maxStack;
-
- /**
- * Maximum number of local variables for this method.
- */
- private int maxLocals;
-
- /**
- * Number of local variables in the current stack map frame.
- */
- private int currentLocals;
-
- /**
- * Number of stack map frames in the StackMapTable attribute.
- */
- int frameCount;
-
- /**
- * The StackMapTable attribute.
- */
- private ByteVector stackMap;
-
- /**
- * The offset of the last frame that was written in the StackMapTable
- * attribute.
- */
- private int previousFrameOffset;
-
- /**
- * The last frame that was written in the StackMapTable attribute.
- *
- * @see #frame
- */
- private int[] previousFrame;
-
- /**
- * The current stack map frame. The first element contains the offset of the
- * instruction to which the frame corresponds, the second element is the
- * number of locals and the third one is the number of stack elements. The
- * local variables start at index 3 and are followed by the operand stack
- * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =
- * nStack, frame[3] = nLocal. All types are encoded as integers, with the
- * same format as the one used in {@link Label}, but limited to BASE types.
- */
- private int[] frame;
-
- /**
- * Number of elements in the exception handler list.
- */
- private int handlerCount;
-
- /**
- * The first element in the exception handler list.
- */
- private Handler firstHandler;
-
- /**
- * The last element in the exception handler list.
- */
- private Handler lastHandler;
-
- /**
- * Number of entries in the MethodParameters attribute.
- */
- private int methodParametersCount;
-
- /**
- * The MethodParameters attribute.
- */
- private ByteVector methodParameters;
-
- /**
- * Number of entries in the LocalVariableTable attribute.
- */
- private int localVarCount;
-
- /**
- * The LocalVariableTable attribute.
- */
- private ByteVector localVar;
-
- /**
- * Number of entries in the LocalVariableTypeTable attribute.
- */
- private int localVarTypeCount;
-
- /**
- * The LocalVariableTypeTable attribute.
- */
- private ByteVector localVarType;
-
- /**
- * Number of entries in the LineNumberTable attribute.
- */
- private int lineNumberCount;
-
- /**
- * The LineNumberTable attribute.
- */
- private ByteVector lineNumber;
-
- /**
- * The start offset of the last visited instruction.
- */
- private int lastCodeOffset;
-
- /**
- * The runtime visible type annotations of the code. May be <tt>null</tt>.
- */
- private AnnotationWriter ctanns;
-
- /**
- * The runtime invisible type annotations of the code. May be <tt>null</tt>.
- */
- private AnnotationWriter ictanns;
-
- /**
- * The non standard attributes of the method's code.
- */
- private Attribute cattrs;
-
- /**
- * The number of subroutines in this method.
- */
- private int subroutines;
-
- // ------------------------------------------------------------------------
-
- /*
- * Fields for the control flow graph analysis algorithm (used to compute the
- * maximum stack size). A control flow graph contains one node per "basic
- * block", and one edge per "jump" from one basic block to another. Each
- * node (i.e., each basic block) is represented by the Label object that
- * corresponds to the first instruction of this basic block. Each node also
- * stores the list of its successors in the graph, as a linked list of Edge
- * objects.
- */
-
- /**
- * Indicates what must be automatically computed.
- *
- * @see #FRAMES
- * @see #INSERTED_FRAMES
- * @see #MAXS
- * @see #NOTHING
- */
- private final int compute;
-
- /**
- * A list of labels. This list is the list of basic blocks in the method,
- * i.e. a list of Label objects linked to each other by their
- * {@link Label#successor} field, in the order they are visited by
- * {@link MethodVisitor#visitLabel}, and starting with the first basic
- * block.
- */
- private Label labels;
-
- /**
- * The previous basic block.
- */
- private Label previousBlock;
-
- /**
- * The current basic block.
- */
- private Label currentBlock;
-
- /**
- * The (relative) stack size after the last visited instruction. This size
- * is relative to the beginning of the current basic block, i.e., the true
- * stack size after the last visited instruction is equal to the
- * {@link Label#inputStackTop beginStackSize} of the current basic block
- * plus <tt>stackSize</tt>.
- */
- private int stackSize;
-
- /**
- * The (relative) maximum stack size after the last visited instruction.
- * This size is relative to the beginning of the current basic block, i.e.,
- * the true maximum stack size after the last visited instruction is equal
- * to the {@link Label#inputStackTop beginStackSize} of the current basic
- * block plus <tt>stackSize</tt>.
- */
- private int maxStackSize;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link MethodWriter}.
- *
- * @param cw
- * the class writer in which the method must be added.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type}).
- * @param signature
- * the method's signature. May be <tt>null</tt>.
- * @param exceptions
- * the internal names of the method's exceptions. May be
- * <tt>null</tt>.
- * @param compute
- * Indicates what must be automatically computed (see #compute).
- */
- MethodWriter(final ClassWriter cw, final int access, final String name,
- final String desc, final String signature,
- final String[] exceptions, final int compute) {
- super(Opcodes.ASM6);
- if (cw.firstMethod == null) {
- cw.firstMethod = this;
- } else {
- cw.lastMethod.mv = this;
- }
- cw.lastMethod = this;
- this.cw = cw;
- this.access = access;
- if ("<init>".equals(name)) {
- this.access |= ACC_CONSTRUCTOR;
- }
- this.name = cw.newUTF8(name);
- this.desc = cw.newUTF8(desc);
- this.descriptor = desc;
- this.signature = signature;
- if (exceptions != null && exceptions.length > 0) {
- exceptionCount = exceptions.length;
- this.exceptions = new int[exceptionCount];
- for (int i = 0; i < exceptionCount; ++i) {
- this.exceptions[i] = cw.newClass(exceptions[i]);
- }
- }
- this.compute = compute;
- if (compute != NOTHING) {
- // updates maxLocals
- int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
- if ((access & Opcodes.ACC_STATIC) != 0) {
- --size;
- }
- maxLocals = size;
- currentLocals = size;
- // creates and visits the label for the first basic block
- labels = new Label();
- labels.status |= Label.PUSHED;
- visitLabel(labels);
- }
+final class MethodWriter extends MethodVisitor {
+
+ /** Indicates that nothing must be computed. */
+ static final int COMPUTE_NOTHING = 0;
+
+ /**
+ * Indicates that the maximum stack size and the maximum number of local variables must be
+ * computed, from scratch.
+ */
+ static final int COMPUTE_MAX_STACK_AND_LOCAL = 1;
+
+ /**
+ * Indicates that the maximum stack size and the maximum number of local variables must be
+ * computed, from the existing stack map frames. This can be done more efficiently than with the
+ * control flow graph algorithm used for {@link #COMPUTE_MAX_STACK_AND_LOCAL}, by using a linear
+ * scan of the bytecode instructions.
+ */
+ static final int COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES = 2;
+
+ /**
+ * Indicates that the stack map frames of type F_INSERT must be computed. The other frames are not
+ * computed. They should all be of type F_NEW and should be sufficient to compute the content of
+ * the F_INSERT frames, together with the bytecode instructions between a F_NEW and a F_INSERT
+ * frame - and without any knowledge of the type hierarchy (by definition of F_INSERT).
+ */
+ static final int COMPUTE_INSERTED_FRAMES = 3;
+
+ /**
+ * Indicates that all the stack map frames must be computed. In this case the maximum stack size
+ * and the maximum number of local variables is also computed.
+ */
+ static final int COMPUTE_ALL_FRAMES = 4;
+
+ /** Indicates that {@link #STACK_SIZE_DELTA} is not applicable (not constant or never used). */
+ private static final int NA = 0;
+
+ /**
+ * The stack size variation corresponding to each JVM opcode. The stack size variation for opcode
+ * 'o' is given by the array element at index 'o'.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html">JVMS 6</a>
+ */
+ private static final int[] STACK_SIZE_DELTA = {
+ 0, // nop = 0 (0x0)
+ 1, // aconst_null = 1 (0x1)
+ 1, // iconst_m1 = 2 (0x2)
+ 1, // iconst_0 = 3 (0x3)
+ 1, // iconst_1 = 4 (0x4)
+ 1, // iconst_2 = 5 (0x5)
+ 1, // iconst_3 = 6 (0x6)
+ 1, // iconst_4 = 7 (0x7)
+ 1, // iconst_5 = 8 (0x8)
+ 2, // lconst_0 = 9 (0x9)
+ 2, // lconst_1 = 10 (0xa)
+ 1, // fconst_0 = 11 (0xb)
+ 1, // fconst_1 = 12 (0xc)
+ 1, // fconst_2 = 13 (0xd)
+ 2, // dconst_0 = 14 (0xe)
+ 2, // dconst_1 = 15 (0xf)
+ 1, // bipush = 16 (0x10)
+ 1, // sipush = 17 (0x11)
+ 1, // ldc = 18 (0x12)
+ NA, // ldc_w = 19 (0x13)
+ NA, // ldc2_w = 20 (0x14)
+ 1, // iload = 21 (0x15)
+ 2, // lload = 22 (0x16)
+ 1, // fload = 23 (0x17)
+ 2, // dload = 24 (0x18)
+ 1, // aload = 25 (0x19)
+ NA, // iload_0 = 26 (0x1a)
+ NA, // iload_1 = 27 (0x1b)
+ NA, // iload_2 = 28 (0x1c)
+ NA, // iload_3 = 29 (0x1d)
+ NA, // lload_0 = 30 (0x1e)
+ NA, // lload_1 = 31 (0x1f)
+ NA, // lload_2 = 32 (0x20)
+ NA, // lload_3 = 33 (0x21)
+ NA, // fload_0 = 34 (0x22)
+ NA, // fload_1 = 35 (0x23)
+ NA, // fload_2 = 36 (0x24)
+ NA, // fload_3 = 37 (0x25)
+ NA, // dload_0 = 38 (0x26)
+ NA, // dload_1 = 39 (0x27)
+ NA, // dload_2 = 40 (0x28)
+ NA, // dload_3 = 41 (0x29)
+ NA, // aload_0 = 42 (0x2a)
+ NA, // aload_1 = 43 (0x2b)
+ NA, // aload_2 = 44 (0x2c)
+ NA, // aload_3 = 45 (0x2d)
+ -1, // iaload = 46 (0x2e)
+ 0, // laload = 47 (0x2f)
+ -1, // faload = 48 (0x30)
+ 0, // daload = 49 (0x31)
+ -1, // aaload = 50 (0x32)
+ -1, // baload = 51 (0x33)
+ -1, // caload = 52 (0x34)
+ -1, // saload = 53 (0x35)
+ -1, // istore = 54 (0x36)
+ -2, // lstore = 55 (0x37)
+ -1, // fstore = 56 (0x38)
+ -2, // dstore = 57 (0x39)
+ -1, // astore = 58 (0x3a)
+ NA, // istore_0 = 59 (0x3b)
+ NA, // istore_1 = 60 (0x3c)
+ NA, // istore_2 = 61 (0x3d)
+ NA, // istore_3 = 62 (0x3e)
+ NA, // lstore_0 = 63 (0x3f)
+ NA, // lstore_1 = 64 (0x40)
+ NA, // lstore_2 = 65 (0x41)
+ NA, // lstore_3 = 66 (0x42)
+ NA, // fstore_0 = 67 (0x43)
+ NA, // fstore_1 = 68 (0x44)
+ NA, // fstore_2 = 69 (0x45)
+ NA, // fstore_3 = 70 (0x46)
+ NA, // dstore_0 = 71 (0x47)
+ NA, // dstore_1 = 72 (0x48)
+ NA, // dstore_2 = 73 (0x49)
+ NA, // dstore_3 = 74 (0x4a)
+ NA, // astore_0 = 75 (0x4b)
+ NA, // astore_1 = 76 (0x4c)
+ NA, // astore_2 = 77 (0x4d)
+ NA, // astore_3 = 78 (0x4e)
+ -3, // iastore = 79 (0x4f)
+ -4, // lastore = 80 (0x50)
+ -3, // fastore = 81 (0x51)
+ -4, // dastore = 82 (0x52)
+ -3, // aastore = 83 (0x53)
+ -3, // bastore = 84 (0x54)
+ -3, // castore = 85 (0x55)
+ -3, // sastore = 86 (0x56)
+ -1, // pop = 87 (0x57)
+ -2, // pop2 = 88 (0x58)
+ 1, // dup = 89 (0x59)
+ 1, // dup_x1 = 90 (0x5a)
+ 1, // dup_x2 = 91 (0x5b)
+ 2, // dup2 = 92 (0x5c)
+ 2, // dup2_x1 = 93 (0x5d)
+ 2, // dup2_x2 = 94 (0x5e)
+ 0, // swap = 95 (0x5f)
+ -1, // iadd = 96 (0x60)
+ -2, // ladd = 97 (0x61)
+ -1, // fadd = 98 (0x62)
+ -2, // dadd = 99 (0x63)
+ -1, // isub = 100 (0x64)
+ -2, // lsub = 101 (0x65)
+ -1, // fsub = 102 (0x66)
+ -2, // dsub = 103 (0x67)
+ -1, // imul = 104 (0x68)
+ -2, // lmul = 105 (0x69)
+ -1, // fmul = 106 (0x6a)
+ -2, // dmul = 107 (0x6b)
+ -1, // idiv = 108 (0x6c)
+ -2, // ldiv = 109 (0x6d)
+ -1, // fdiv = 110 (0x6e)
+ -2, // ddiv = 111 (0x6f)
+ -1, // irem = 112 (0x70)
+ -2, // lrem = 113 (0x71)
+ -1, // frem = 114 (0x72)
+ -2, // drem = 115 (0x73)
+ 0, // ineg = 116 (0x74)
+ 0, // lneg = 117 (0x75)
+ 0, // fneg = 118 (0x76)
+ 0, // dneg = 119 (0x77)
+ -1, // ishl = 120 (0x78)
+ -1, // lshl = 121 (0x79)
+ -1, // ishr = 122 (0x7a)
+ -1, // lshr = 123 (0x7b)
+ -1, // iushr = 124 (0x7c)
+ -1, // lushr = 125 (0x7d)
+ -1, // iand = 126 (0x7e)
+ -2, // land = 127 (0x7f)
+ -1, // ior = 128 (0x80)
+ -2, // lor = 129 (0x81)
+ -1, // ixor = 130 (0x82)
+ -2, // lxor = 131 (0x83)
+ 0, // iinc = 132 (0x84)
+ 1, // i2l = 133 (0x85)
+ 0, // i2f = 134 (0x86)
+ 1, // i2d = 135 (0x87)
+ -1, // l2i = 136 (0x88)
+ -1, // l2f = 137 (0x89)
+ 0, // l2d = 138 (0x8a)
+ 0, // f2i = 139 (0x8b)
+ 1, // f2l = 140 (0x8c)
+ 1, // f2d = 141 (0x8d)
+ -1, // d2i = 142 (0x8e)
+ 0, // d2l = 143 (0x8f)
+ -1, // d2f = 144 (0x90)
+ 0, // i2b = 145 (0x91)
+ 0, // i2c = 146 (0x92)
+ 0, // i2s = 147 (0x93)
+ -3, // lcmp = 148 (0x94)
+ -1, // fcmpl = 149 (0x95)
+ -1, // fcmpg = 150 (0x96)
+ -3, // dcmpl = 151 (0x97)
+ -3, // dcmpg = 152 (0x98)
+ -1, // ifeq = 153 (0x99)
+ -1, // ifne = 154 (0x9a)
+ -1, // iflt = 155 (0x9b)
+ -1, // ifge = 156 (0x9c)
+ -1, // ifgt = 157 (0x9d)
+ -1, // ifle = 158 (0x9e)
+ -2, // if_icmpeq = 159 (0x9f)
+ -2, // if_icmpne = 160 (0xa0)
+ -2, // if_icmplt = 161 (0xa1)
+ -2, // if_icmpge = 162 (0xa2)
+ -2, // if_icmpgt = 163 (0xa3)
+ -2, // if_icmple = 164 (0xa4)
+ -2, // if_acmpeq = 165 (0xa5)
+ -2, // if_acmpne = 166 (0xa6)
+ 0, // goto = 167 (0xa7)
+ 1, // jsr = 168 (0xa8)
+ 0, // ret = 169 (0xa9)
+ -1, // tableswitch = 170 (0xaa)
+ -1, // lookupswitch = 171 (0xab)
+ -1, // ireturn = 172 (0xac)
+ -2, // lreturn = 173 (0xad)
+ -1, // freturn = 174 (0xae)
+ -2, // dreturn = 175 (0xaf)
+ -1, // areturn = 176 (0xb0)
+ 0, // return = 177 (0xb1)
+ NA, // getstatic = 178 (0xb2)
+ NA, // putstatic = 179 (0xb3)
+ NA, // getfield = 180 (0xb4)
+ NA, // putfield = 181 (0xb5)
+ NA, // invokevirtual = 182 (0xb6)
+ NA, // invokespecial = 183 (0xb7)
+ NA, // invokestatic = 184 (0xb8)
+ NA, // invokeinterface = 185 (0xb9)
+ NA, // invokedynamic = 186 (0xba)
+ 1, // new = 187 (0xbb)
+ 0, // newarray = 188 (0xbc)
+ 0, // anewarray = 189 (0xbd)
+ 0, // arraylength = 190 (0xbe)
+ NA, // athrow = 191 (0xbf)
+ 0, // checkcast = 192 (0xc0)
+ 0, // instanceof = 193 (0xc1)
+ -1, // monitorenter = 194 (0xc2)
+ -1, // monitorexit = 195 (0xc3)
+ NA, // wide = 196 (0xc4)
+ NA, // multianewarray = 197 (0xc5)
+ -1, // ifnull = 198 (0xc6)
+ -1, // ifnonnull = 199 (0xc7)
+ NA, // goto_w = 200 (0xc8)
+ NA // jsr_w = 201 (0xc9)
+ };
+
+ /** Where the constants used in this MethodWriter must be stored. */
+ private final SymbolTable symbolTable;
+
+ // Note: fields are ordered as in the method_info structure, and those related to attributes are
+ // ordered as in Section 4.7 of the JVMS.
+
+ /**
+ * The access_flags field of the method_info JVMS structure. This field can contain ASM specific
+ * access flags, such as {@link Opcodes#ACC_DEPRECATED}, which are removed when generating the
+ * ClassFile structure.
+ */
+ private final int accessFlags;
+
+ /** The name_index field of the method_info JVMS structure. */
+ private final int nameIndex;
+
+ /** The name of this method. */
+ private final String name;
+
+ /** The descriptor_index field of the method_info JVMS structure. */
+ private final int descriptorIndex;
+
+ /** The descriptor of this method. */
+ private final String descriptor;
+
+ // Code attribute fields and sub attributes:
+
+ /** The max_stack field of the Code attribute. */
+ private int maxStack;
+
+ /** The max_locals field of the Code attribute. */
+ private int maxLocals;
+
+ /** The 'code' field of the Code attribute. */
+ private final ByteVector code = new ByteVector();
+
+ /**
+ * The first element in the exception handler list (used to generate the exception_table of the
+ * Code attribute). The next ones can be accessed with the {@link Handler#nextHandler} field. May
+ * be {@literal null}.
+ */
+ private Handler firstHandler;
+
+ /**
+ * The last element in the exception handler list (used to generate the exception_table of the
+ * Code attribute). The next ones can be accessed with the {@link Handler#nextHandler} field. May
+ * be {@literal null}.
+ */
+ private Handler lastHandler;
+
+ /** The line_number_table_length field of the LineNumberTable code attribute. */
+ private int lineNumberTableLength;
+
+ /** The line_number_table array of the LineNumberTable code attribute, or {@literal null}. */
+ private ByteVector lineNumberTable;
+
+ /** The local_variable_table_length field of the LocalVariableTable code attribute. */
+ private int localVariableTableLength;
+
+ /**
+ * The local_variable_table array of the LocalVariableTable code attribute, or {@literal null}.
+ */
+ private ByteVector localVariableTable;
+
+ /** The local_variable_type_table_length field of the LocalVariableTypeTable code attribute. */
+ private int localVariableTypeTableLength;
+
+ /**
+ * The local_variable_type_table array of the LocalVariableTypeTable code attribute, or {@literal
+ * null}.
+ */
+ private ByteVector localVariableTypeTable;
+
+ /** The number_of_entries field of the StackMapTable code attribute. */
+ private int stackMapTableNumberOfEntries;
+
+ /** The 'entries' array of the StackMapTable code attribute. */
+ private ByteVector stackMapTableEntries;
+
+ /**
+ * The last runtime visible type annotation of the Code attribute. The previous ones can be
+ * accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastCodeRuntimeVisibleTypeAnnotation;
+
+ /**
+ * The last runtime invisible type annotation of the Code attribute. The previous ones can be
+ * accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastCodeRuntimeInvisibleTypeAnnotation;
+
+ /**
+ * The first non standard attribute of the Code attribute. The next ones can be accessed with the
+ * {@link Attribute#nextAttribute} field. May be {@literal null}.
+ *
+ * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
+ * firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
+ * #putMethodInfo} method writes the attributes in the order defined by this list, i.e. in the
+ * reverse order specified by the user.
+ */
+ private Attribute firstCodeAttribute;
+
+ // Other method_info attributes:
+
+ /** The number_of_exceptions field of the Exceptions attribute. */
+ private final int numberOfExceptions;
+
+ /** The exception_index_table array of the Exceptions attribute, or {@literal null}. */
+ private final int[] exceptionIndexTable;
+
+ /** The signature_index field of the Signature attribute. */
+ private final int signatureIndex;
+
+ /**
+ * The last runtime visible annotation of this method. The previous ones can be accessed with the
+ * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeVisibleAnnotation;
+
+ /**
+ * The last runtime invisible annotation of this method. The previous ones can be accessed with
+ * the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeInvisibleAnnotation;
+
+ /** The number of method parameters that can have runtime visible annotations, or 0. */
+ private int visibleAnnotableParameterCount;
+
+ /**
+ * The runtime visible parameter annotations of this method. Each array element contains the last
+ * annotation of a parameter (which can be {@literal null} - the previous ones can be accessed
+ * with the {@link AnnotationWriter#previousAnnotation} field). May be {@literal null}.
+ */
+ private AnnotationWriter[] lastRuntimeVisibleParameterAnnotations;
+
+ /** The number of method parameters that can have runtime visible annotations, or 0. */
+ private int invisibleAnnotableParameterCount;
+
+ /**
+ * The runtime invisible parameter annotations of this method. Each array element contains the
+ * last annotation of a parameter (which can be {@literal null} - the previous ones can be
+ * accessed with the {@link AnnotationWriter#previousAnnotation} field). May be {@literal null}.
+ */
+ private AnnotationWriter[] lastRuntimeInvisibleParameterAnnotations;
+
+ /**
+ * The last runtime visible type annotation of this method. The previous ones can be accessed with
+ * the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
+
+ /**
+ * The last runtime invisible type annotation of this method. The previous ones can be accessed
+ * with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+ */
+ private AnnotationWriter lastRuntimeInvisibleTypeAnnotation;
+
+ /** The default_value field of the AnnotationDefault attribute, or {@literal null}. */
+ private ByteVector defaultValue;
+
+ /** The parameters_count field of the MethodParameters attribute. */
+ private int parametersCount;
+
+ /** The 'parameters' array of the MethodParameters attribute, or {@literal null}. */
+ private ByteVector parameters;
+
+ /**
+ * The first non standard attribute of this method. The next ones can be accessed with the {@link
+ * Attribute#nextAttribute} field. May be {@literal null}.
+ *
+ * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
+ * firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
+ * #putMethodInfo} method writes the attributes in the order defined by this list, i.e. in the
+ * reverse order specified by the user.
+ */
+ private Attribute firstAttribute;
+
+ // -----------------------------------------------------------------------------------------------
+ // Fields used to compute the maximum stack size and number of locals, and the stack map frames
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Indicates what must be computed. Must be one of {@link #COMPUTE_ALL_FRAMES}, {@link
+ * #COMPUTE_INSERTED_FRAMES}, {@link #COMPUTE_MAX_STACK_AND_LOCAL} or {@link #COMPUTE_NOTHING}.
+ */
+ private final int compute;
+
+ /**
+ * The first basic block of the method. The next ones (in bytecode offset order) can be accessed
+ * with the {@link Label#nextBasicBlock} field.
+ */
+ private Label firstBasicBlock;
+
+ /**
+ * The last basic block of the method (in bytecode offset order). This field is updated each time
+ * a basic block is encountered, and is used to append it at the end of the basic block list.
+ */
+ private Label lastBasicBlock;
+
+ /**
+ * The current basic block, i.e. the basic block of the last visited instruction. When {@link
+ * #compute} is equal to {@link #COMPUTE_MAX_STACK_AND_LOCAL} or {@link #COMPUTE_ALL_FRAMES}, this
+ * field is {@literal null} for unreachable code. When {@link #compute} is equal to {@link
+ * #COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES} or {@link #COMPUTE_INSERTED_FRAMES}, this field stays
+ * unchanged throughout the whole method (i.e. the whole code is seen as a single basic block;
+ * indeed, the existing frames are sufficient by hypothesis to compute any intermediate frame -
+ * and the maximum stack size as well - without using any control flow graph).
+ */
+ private Label currentBasicBlock;
+
+ /**
+ * The relative stack size after the last visited instruction. This size is relative to the
+ * beginning of {@link #currentBasicBlock}, i.e. the true stack size after the last visited
+ * instruction is equal to the {@link Label#inputStackSize} of the current basic block plus {@link
+ * #relativeStackSize}. When {@link #compute} is equal to {@link
+ * #COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES}, {@link #currentBasicBlock} is always the start of
+ * the method, so this relative size is also equal to the absolute stack size after the last
+ * visited instruction.
+ */
+ private int relativeStackSize;
+
+ /**
+ * The maximum relative stack size after the last visited instruction. This size is relative to
+ * the beginning of {@link #currentBasicBlock}, i.e. the true maximum stack size after the last
+ * visited instruction is equal to the {@link Label#inputStackSize} of the current basic block
+ * plus {@link #maxRelativeStackSize}.When {@link #compute} is equal to {@link
+ * #COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES}, {@link #currentBasicBlock} is always the start of
+ * the method, so this relative size is also equal to the absolute maximum stack size after the
+ * last visited instruction.
+ */
+ private int maxRelativeStackSize;
+
+ /** The number of local variables in the last visited stack map frame. */
+ private int currentLocals;
+
+ /** The bytecode offset of the last frame that was written in {@link #stackMapTableEntries}. */
+ private int previousFrameOffset;
+
+ /**
+ * The last frame that was written in {@link #stackMapTableEntries}. This field has the same
+ * format as {@link #currentFrame}.
+ */
+ private int[] previousFrame;
+
+ /**
+ * The current stack map frame. The first element contains the bytecode offset of the instruction
+ * to which the frame corresponds, the second element is the number of locals and the third one is
+ * the number of stack elements. The local variables start at index 3 and are followed by the
+ * operand stack elements. In summary frame[0] = offset, frame[1] = numLocal, frame[2] = numStack.
+ * Local variables and operand stack entries contain abstract types, as defined in {@link Frame},
+ * but restricted to {@link Frame#CONSTANT_KIND}, {@link Frame#REFERENCE_KIND} or {@link
+ * Frame#UNINITIALIZED_KIND} abstract types. Long and double types use only one array entry.
+ */
+ private int[] currentFrame;
+
+ /** Whether this method contains subroutines. */
+ private boolean hasSubroutines;
+
+ // -----------------------------------------------------------------------------------------------
+ // Other miscellaneous status fields
+ // -----------------------------------------------------------------------------------------------
+
+ /** Whether the bytecode of this method contains ASM specific instructions. */
+ private boolean hasAsmInstructions;
+
+ /**
+ * The start offset of the last visited instruction. Used to set the offset field of type
+ * annotations of type 'offset_target' (see <a
+ * href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.1">JVMS
+ * 4.7.20.1</a>).
+ */
+ private int lastBytecodeOffset;
+
+ /**
+ * The offset in bytes in {@link SymbolTable#getSource} from which the method_info for this method
+ * (excluding its first 6 bytes) must be copied, or 0.
+ */
+ private int sourceOffset;
+
+ /**
+ * The length in bytes in {@link SymbolTable#getSource} which must be copied to get the
+ * method_info for this method (excluding its first 6 bytes for access_flags, name_index and
+ * descriptor_index).
+ */
+ private int sourceLength;
+
+ // -----------------------------------------------------------------------------------------------
+ // Constructor and accessors
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link MethodWriter}.
+ *
+ * @param symbolTable where the constants used in this AnnotationWriter must be stored.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be {@literal null}.
+ * @param exceptions the internal names of the method's exceptions. May be {@literal null}.
+ * @param compute indicates what must be computed (see #compute).
+ */
+ MethodWriter(
+ final SymbolTable symbolTable,
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions,
+ final int compute) {
+ super(Opcodes.ASM7);
+ this.symbolTable = symbolTable;
+ this.accessFlags = "<init>".equals(name) ? access | Constants.ACC_CONSTRUCTOR : access;
+ this.nameIndex = symbolTable.addConstantUtf8(name);
+ this.name = name;
+ this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
+ this.descriptor = descriptor;
+ this.signatureIndex = signature == null ? 0 : symbolTable.addConstantUtf8(signature);
+ if (exceptions != null && exceptions.length > 0) {
+ numberOfExceptions = exceptions.length;
+ this.exceptionIndexTable = new int[numberOfExceptions];
+ for (int i = 0; i < numberOfExceptions; ++i) {
+ this.exceptionIndexTable[i] = symbolTable.addConstantClass(exceptions[i]).index;
+ }
+ } else {
+ numberOfExceptions = 0;
+ this.exceptionIndexTable = null;
}
+ this.compute = compute;
+ if (compute != COMPUTE_NOTHING) {
+ // Update maxLocals and currentLocals.
+ int argumentsSize = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ --argumentsSize;
+ }
+ maxLocals = argumentsSize;
+ currentLocals = argumentsSize;
+ // Create and visit the label for the first basic block.
+ firstBasicBlock = new Label();
+ visitLabel(firstBasicBlock);
+ }
+ }
- // ------------------------------------------------------------------------
- // Implementation of the MethodVisitor abstract class
- // ------------------------------------------------------------------------
+ boolean hasFrames() {
+ return stackMapTableNumberOfEntries > 0;
+ }
- @Override
- public void visitParameter(String name, int access) {
- if (methodParameters == null) {
- methodParameters = new ByteVector();
- }
- ++methodParametersCount;
- methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name))
- .putShort(access);
- }
-
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- annd = new ByteVector();
- return new AnnotationWriter(cw, false, annd, null, 0);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- ByteVector bv = new ByteVector();
- // write type, and reserve space for values count
- bv.putShort(cw.newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
- if (visible) {
- aw.next = anns;
- anns = aw;
- } else {
- aw.next = ianns;
- ianns = aw;
- }
- return aw;
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- ByteVector bv = new ByteVector();
- // write target_type and target_info
- AnnotationWriter.putTarget(typeRef, typePath, bv);
- // write type, and reserve space for values count
- bv.putShort(cw.newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
- bv.length - 2);
- if (visible) {
- aw.next = tanns;
- tanns = aw;
- } else {
- aw.next = itanns;
- itanns = aw;
- }
- return aw;
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- ByteVector bv = new ByteVector();
- if ("Ljava/lang/Synthetic;".equals(desc)) {
- // workaround for a bug in javac with synthetic parameters
- // see ClassReader.readParameterAnnotations
- synthetics = Math.max(synthetics, parameter + 1);
- return new AnnotationWriter(cw, false, bv, null, 0);
- }
- // write type, and reserve space for values count
- bv.putShort(cw.newUTF8(desc)).putShort(0);
- AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
- if (visible) {
- if (panns == null) {
- panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
- }
- aw.next = panns[parameter];
- panns[parameter] = aw;
- } else {
- if (ipanns == null) {
- ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
- }
- aw.next = ipanns[parameter];
- ipanns[parameter] = aw;
- }
- return aw;
- }
+ boolean hasAsmInstructions() {
+ return hasAsmInstructions;
+ }
- @Override
- public void visitAttribute(final Attribute attr) {
- if (attr.isCodeAttribute()) {
- attr.next = cattrs;
- cattrs = attr;
- } else {
- attr.next = attrs;
- attrs = attr;
- }
- }
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the MethodVisitor abstract class
+ // -----------------------------------------------------------------------------------------------
- @Override
- public void visitCode() {
+ @Override
+ public void visitParameter(final String name, final int access) {
+ if (parameters == null) {
+ parameters = new ByteVector();
+ }
+ ++parametersCount;
+ parameters.putShort((name == null) ? 0 : symbolTable.addConstantUtf8(name)).putShort(access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ defaultValue = new ByteVector();
+ return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, defaultValue, null);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ // Create a ByteVector to hold an 'annotation' JVMS structure.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
+ ByteVector annotation = new ByteVector();
+ // Write type_index and reserve space for num_element_value_pairs.
+ annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
+ if (visible) {
+ return lastRuntimeVisibleAnnotation =
+ new AnnotationWriter(symbolTable, annotation, lastRuntimeVisibleAnnotation);
+ } else {
+ return lastRuntimeInvisibleAnnotation =
+ new AnnotationWriter(symbolTable, annotation, lastRuntimeInvisibleAnnotation);
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ // Create a ByteVector to hold a 'type_annotation' JVMS structure.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.
+ ByteVector typeAnnotation = new ByteVector();
+ // Write target_type, target_info, and target_path.
+ TypeReference.putTarget(typeRef, typeAnnotation);
+ TypePath.put(typePath, typeAnnotation);
+ // Write type_index and reserve space for num_element_value_pairs.
+ typeAnnotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
+ if (visible) {
+ return lastRuntimeVisibleTypeAnnotation =
+ new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeVisibleTypeAnnotation);
+ } else {
+ return lastRuntimeInvisibleTypeAnnotation =
+ new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeInvisibleTypeAnnotation);
+ }
+ }
+
+ @Override
+ public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ if (visible) {
+ visibleAnnotableParameterCount = parameterCount;
+ } else {
+ invisibleAnnotableParameterCount = parameterCount;
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter, final String annotationDescriptor, final boolean visible) {
+ // Create a ByteVector to hold an 'annotation' JVMS structure.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
+ ByteVector annotation = new ByteVector();
+ // Write type_index and reserve space for num_element_value_pairs.
+ annotation.putShort(symbolTable.addConstantUtf8(annotationDescriptor)).putShort(0);
+ if (visible) {
+ if (lastRuntimeVisibleParameterAnnotations == null) {
+ lastRuntimeVisibleParameterAnnotations =
+ new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
+ }
+ return lastRuntimeVisibleParameterAnnotations[parameter] =
+ new AnnotationWriter(
+ symbolTable, annotation, lastRuntimeVisibleParameterAnnotations[parameter]);
+ } else {
+ if (lastRuntimeInvisibleParameterAnnotations == null) {
+ lastRuntimeInvisibleParameterAnnotations =
+ new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
+ }
+ return lastRuntimeInvisibleParameterAnnotations[parameter] =
+ new AnnotationWriter(
+ symbolTable, annotation, lastRuntimeInvisibleParameterAnnotations[parameter]);
+ }
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ // Store the attributes in the <i>reverse</i> order of their visit by this method.
+ if (attribute.isCodeAttribute()) {
+ attribute.nextAttribute = firstCodeAttribute;
+ firstCodeAttribute = attribute;
+ } else {
+ attribute.nextAttribute = firstAttribute;
+ firstAttribute = attribute;
+ }
+ }
+
+ @Override
+ public void visitCode() {
+ // Nothing to do.
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ if (compute == COMPUTE_ALL_FRAMES) {
+ return;
}
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- if (compute == FRAMES) {
+ if (compute == COMPUTE_INSERTED_FRAMES) {
+ if (currentBasicBlock.frame == null) {
+ // This should happen only once, for the implicit first frame (which is explicitly visited
+ // in ClassReader if the EXPAND_ASM_INSNS option is used - and COMPUTE_INSERTED_FRAMES
+ // can't be set if EXPAND_ASM_INSNS is not used).
+ currentBasicBlock.frame = new CurrentFrame(currentBasicBlock);
+ currentBasicBlock.frame.setInputFrameFromDescriptor(
+ symbolTable, accessFlags, descriptor, numLocal);
+ currentBasicBlock.frame.accept(this);
+ } else {
+ if (type == Opcodes.F_NEW) {
+ currentBasicBlock.frame.setInputFrameFromApiFormat(
+ symbolTable, numLocal, local, numStack, stack);
+ }
+ // If type is not F_NEW then it is F_INSERT by hypothesis, and currentBlock.frame contains
+ // the stack map frame at the current instruction, computed from the last F_NEW frame and
+ // the bytecode instructions in between (via calls to CurrentFrame#execute).
+ currentBasicBlock.frame.accept(this);
+ }
+ } else if (type == Opcodes.F_NEW) {
+ if (previousFrame == null) {
+ int argumentsSize = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
+ Frame implicitFirstFrame = new Frame(new Label());
+ implicitFirstFrame.setInputFrameFromDescriptor(
+ symbolTable, accessFlags, descriptor, argumentsSize);
+ implicitFirstFrame.accept(this);
+ }
+ currentLocals = numLocal;
+ int frameIndex = visitFrameStart(code.length, numLocal, numStack);
+ for (int i = 0; i < numLocal; ++i) {
+ currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, local[i]);
+ }
+ for (int i = 0; i < numStack; ++i) {
+ currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, stack[i]);
+ }
+ visitFrameEnd();
+ } else {
+ int offsetDelta;
+ if (stackMapTableEntries == null) {
+ stackMapTableEntries = new ByteVector();
+ offsetDelta = code.length;
+ } else {
+ offsetDelta = code.length - previousFrameOffset - 1;
+ if (offsetDelta < 0) {
+ if (type == Opcodes.F_SAME) {
return;
- }
-
- if (compute == INSERTED_FRAMES) {
- if (currentBlock.frame == null) {
- // This should happen only once, for the implicit first frame
- // (which is explicitly visited in ClassReader if the
- // EXPAND_ASM_INSNS option is used).
- currentBlock.frame = new CurrentFrame();
- currentBlock.frame.owner = currentBlock;
- currentBlock.frame.initInputFrame(cw, access,
- Type.getArgumentTypes(descriptor), nLocal);
- visitImplicitFirstFrame();
- } else {
- if (type == Opcodes.F_NEW) {
- currentBlock.frame.set(cw, nLocal, local, nStack, stack);
- } else {
- // In this case type is equal to F_INSERT by hypothesis, and
- // currentBlock.frame contains the stack map frame at the
- // current instruction, computed from the last F_NEW frame
- // and the bytecode instructions in between (via calls to
- // CurrentFrame#execute).
- }
- visitFrame(currentBlock.frame);
- }
- } else if (type == Opcodes.F_NEW) {
- if (previousFrame == null) {
- visitImplicitFirstFrame();
- }
- currentLocals = nLocal;
- int frameIndex = startFrame(code.length, nLocal, nStack);
- for (int i = 0; i < nLocal; ++i) {
- if (local[i] instanceof String) {
- String desc = Type.getObjectType((String) local[i]).getDescriptor();
- frame[frameIndex++] = Frame.type(cw, desc);
- } else if (local[i] instanceof Integer) {
- frame[frameIndex++] = Frame.BASE | ((Integer) local[i]).intValue();
- } else {
- frame[frameIndex++] = Frame.UNINITIALIZED
- | cw.addUninitializedType("",
- ((Label) local[i]).position);
- }
- }
- for (int i = 0; i < nStack; ++i) {
- if (stack[i] instanceof String) {
- String desc = Type.getObjectType((String) stack[i]).getDescriptor();
- frame[frameIndex++] = Frame.type(cw, desc);
- } else if (stack[i] instanceof Integer) {
- frame[frameIndex++] = Frame.BASE | ((Integer) stack[i]).intValue();
- } else {
- frame[frameIndex++] = Frame.UNINITIALIZED
- | cw.addUninitializedType("",
- ((Label) stack[i]).position);
- }
- }
- endFrame();
- } else {
- int delta;
- if (stackMap == null) {
- stackMap = new ByteVector();
- delta = code.length;
- } else {
- delta = code.length - previousFrameOffset - 1;
- if (delta < 0) {
- if (type == Opcodes.F_SAME) {
- return;
- } else {
- throw new IllegalStateException();
- }
- }
- }
-
- switch (type) {
- case Opcodes.F_FULL:
- currentLocals = nLocal;
- stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal);
- for (int i = 0; i < nLocal; ++i) {
- writeFrameType(local[i]);
- }
- stackMap.putShort(nStack);
- for (int i = 0; i < nStack; ++i) {
- writeFrameType(stack[i]);
- }
- break;
- case Opcodes.F_APPEND:
- currentLocals += nLocal;
- stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta);
- for (int i = 0; i < nLocal; ++i) {
- writeFrameType(local[i]);
- }
- break;
- case Opcodes.F_CHOP:
- currentLocals -= nLocal;
- stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta);
- break;
- case Opcodes.F_SAME:
- if (delta < 64) {
- stackMap.putByte(delta);
- } else {
- stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
- }
- break;
- case Opcodes.F_SAME1:
- if (delta < 64) {
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
- } else {
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- .putShort(delta);
- }
- writeFrameType(stack[0]);
- break;
- }
-
- previousFrameOffset = code.length;
- ++frameCount;
- }
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ switch (type) {
+ case Opcodes.F_FULL:
+ currentLocals = numLocal;
+ stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal);
+ for (int i = 0; i < numLocal; ++i) {
+ putFrameType(local[i]);
+ }
+ stackMapTableEntries.putShort(numStack);
+ for (int i = 0; i < numStack; ++i) {
+ putFrameType(stack[i]);
+ }
+ break;
+ case Opcodes.F_APPEND:
+ currentLocals += numLocal;
+ stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + numLocal).putShort(offsetDelta);
+ for (int i = 0; i < numLocal; ++i) {
+ putFrameType(local[i]);
+ }
+ break;
+ case Opcodes.F_CHOP:
+ currentLocals -= numLocal;
+ stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED - numLocal).putShort(offsetDelta);
+ break;
+ case Opcodes.F_SAME:
+ if (offsetDelta < 64) {
+ stackMapTableEntries.putByte(offsetDelta);
+ } else {
+ stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED).putShort(offsetDelta);
+ }
+ break;
+ case Opcodes.F_SAME1:
+ if (offsetDelta < 64) {
+ stackMapTableEntries.putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME + offsetDelta);
+ } else {
+ stackMapTableEntries
+ .putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ .putShort(offsetDelta);
+ }
+ putFrameType(stack[0]);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
- maxStack = Math.max(maxStack, nStack);
- maxLocals = Math.max(maxLocals, currentLocals);
- }
-
- @Override
- public void visitInsn(final int opcode) {
- lastCodeOffset = code.length;
- // adds the instruction to the bytecode of the method
- code.putByte(opcode);
- // update currentBlock
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(opcode, 0, null, null);
- } else {
- // updates current and max stack sizes
- int size = stackSize + Frame.SIZE[opcode];
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- // if opcode == ATHROW or xRETURN, ends current block (no successor)
- if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
- || opcode == Opcodes.ATHROW) {
- noSuccessor();
- }
- }
+ previousFrameOffset = code.length;
+ ++stackMapTableNumberOfEntries;
}
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- lastCodeOffset = code.length;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(opcode, operand, null, null);
- } else if (opcode != Opcodes.NEWARRAY) {
- // updates current and max stack sizes only for NEWARRAY
- // (stack size variation = 0 for BIPUSH or SIPUSH)
- int size = stackSize + 1;
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- if (opcode == Opcodes.SIPUSH) {
- code.put12(opcode, operand);
- } else { // BIPUSH or NEWARRAY
- code.put11(opcode, operand);
+ if (compute == COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES) {
+ relativeStackSize = numStack;
+ for (int i = 0; i < numStack; ++i) {
+ if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
+ relativeStackSize++;
}
+ }
+ if (relativeStackSize > maxRelativeStackSize) {
+ maxRelativeStackSize = relativeStackSize;
+ }
}
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- lastCodeOffset = code.length;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(opcode, var, null, null);
- } else {
- // updates current and max stack sizes
- if (opcode == Opcodes.RET) {
- // no stack change, but end of current block (no successor)
- currentBlock.status |= Label.RET;
- // save 'stackSize' here for future use
- // (see {@link #findSubroutineSuccessors})
- currentBlock.inputStackTop = stackSize;
- noSuccessor();
- } else { // xLOAD or xSTORE
- int size = stackSize + Frame.SIZE[opcode];
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- }
- if (compute != NOTHING) {
- // updates max locals
- int n;
- if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
- || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
- n = var + 2;
- } else {
- n = var + 1;
- }
- if (n > maxLocals) {
- maxLocals = n;
- }
- }
- // adds the instruction to the bytecode of the method
- if (var < 4 && opcode != Opcodes.RET) {
- int opt;
- if (opcode < Opcodes.ISTORE) {
- /* ILOAD_0 */
- opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;
- } else {
- /* ISTORE_0 */
- opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;
- }
- code.putByte(opt);
- } else if (var >= 256) {
- code.putByte(196 /* WIDE */).put12(opcode, var);
- } else {
- code.put11(opcode, var);
- }
- if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) {
- visitLabel(new Label());
- }
+ maxStack = Math.max(maxStack, numStack);
+ maxLocals = Math.max(maxLocals, currentLocals);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ lastBytecodeOffset = code.length;
+ // Add the instruction to the bytecode of the method.
+ code.putByte(opcode);
+ // If needed, update the maximum stack size and number of locals, and stack map frames.
+ if (currentBasicBlock != null) {
+ if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
+ currentBasicBlock.frame.execute(opcode, 0, null, null);
+ } else {
+ int size = relativeStackSize + STACK_SIZE_DELTA[opcode];
+ if (size > maxRelativeStackSize) {
+ maxRelativeStackSize = size;
+ }
+ relativeStackSize = size;
+ }
+ if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
+ endCurrentBasicBlockWithNoSuccessor();
+ }
}
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- lastCodeOffset = code.length;
- Item i = cw.newStringishItem(ClassWriter.CLASS, type);
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(opcode, code.length, cw, i);
- } else if (opcode == Opcodes.NEW) {
- // updates current and max stack sizes only if opcode == NEW
- // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)
- int size = stackSize + 1;
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- code.put12(opcode, i.index);
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- lastCodeOffset = code.length;
- Item i = cw.newFieldItem(owner, name, desc);
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(opcode, 0, cw, i);
- } else {
- int size;
- // computes the stack size variation
- char c = desc.charAt(0);
- switch (opcode) {
- case Opcodes.GETSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
- break;
- case Opcodes.PUTSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
- break;
- case Opcodes.GETFIELD:
- size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
- break;
- // case Constants.PUTFIELD:
- default:
- size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
- break;
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- code.put12(opcode, i.index);
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- lastCodeOffset = code.length;
- Item i = cw.newMethodItem(owner, name, desc, itf);
- int argSize = i.intVal;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(opcode, 0, cw, i);
- } else {
- /*
- * computes the stack size variation. In order not to recompute
- * several times this variation for the same Item, we use the
- * intVal field of this item to store this variation, once it
- * has been computed. More precisely this intVal field stores
- * the sizes of the arguments and of the return value
- * corresponding to desc.
- */
- if (argSize == 0) {
- // the above sizes have not been computed yet,
- // so we compute them...
- argSize = Type.getArgumentsAndReturnSizes(desc);
- // ... and we save them in order
- // not to recompute them in the future
- i.intVal = argSize;
- }
- int size;
- if (opcode == Opcodes.INVOKESTATIC) {
- size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
- } else {
- size = stackSize - (argSize >> 2) + (argSize & 0x03);
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- if (opcode == Opcodes.INVOKEINTERFACE) {
- if (argSize == 0) {
- argSize = Type.getArgumentsAndReturnSizes(desc);
- i.intVal = argSize;
- }
- code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
- } else {
- code.put12(opcode, i.index);
- }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ lastBytecodeOffset = code.length;
+ // Add the instruction to the bytecode of the method.
+ if (opcode == Opcodes.SIPUSH) {
+ code.put12(opcode, operand);
+ } else { // BIPUSH or NEWARRAY
+ code.put11(opcode, operand);
}
-
- @Override
- public void visitInvokeDynamicInsn(final String name, final String desc,
- final Handle bsm, final Object... bsmArgs) {
- lastCodeOffset = code.length;
- Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
- int argSize = i.intVal;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i);
- } else {
- /*
- * computes the stack size variation. In order not to recompute
- * several times this variation for the same Item, we use the
- * intVal field of this item to store this variation, once it
- * has been computed. More precisely this intVal field stores
- * the sizes of the arguments and of the return value
- * corresponding to desc.
- */
- if (argSize == 0) {
- // the above sizes have not been computed yet,
- // so we compute them...
- argSize = Type.getArgumentsAndReturnSizes(desc);
- // ... and we save them in order
- // not to recompute them in the future
- i.intVal = argSize;
- }
- int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
-
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- code.put12(Opcodes.INVOKEDYNAMIC, i.index);
- code.putShort(0);
- }
-
- @Override
- public void visitJumpInsn(int opcode, final Label label) {
- boolean isWide = opcode >= 200; // GOTO_W
- opcode = isWide ? opcode - 33 : opcode;
- lastCodeOffset = code.length;
- Label nextInsn = null;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, 0, null, null);
- // 'label' is the target of a jump instruction
- label.getFirst().status |= Label.TARGET;
- // adds 'label' as a successor of this basic block
- addSuccessor(Edge.NORMAL, label);
- if (opcode != Opcodes.GOTO) {
- // creates a Label for the next basic block
- nextInsn = new Label();
- }
- } else if (compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(opcode, 0, null, null);
- } else {
- if (opcode == Opcodes.JSR) {
- if ((label.status & Label.SUBROUTINE) == 0) {
- label.status |= Label.SUBROUTINE;
- ++subroutines;
- }
- currentBlock.status |= Label.JSR;
- addSuccessor(stackSize + 1, label);
- // creates a Label for the next basic block
- nextInsn = new Label();
- /*
- * note that, by construction in this method, a JSR block
- * has at least two successors in the control flow graph:
- * the first one leads the next instruction after the JSR,
- * while the second one leads to the JSR target.
- */
- } else {
- // updates current stack size (max stack size unchanged
- // because stack size variation always negative in this
- // case)
- stackSize += Frame.SIZE[opcode];
- addSuccessor(stackSize, label);
- }
- }
- }
- // adds the instruction to the bytecode of the method
- if ((label.status & Label.RESOLVED) != 0
- && label.position - code.length < Short.MIN_VALUE) {
- /*
- * case of a backward jump with an offset < -32768. In this case we
- * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
- * <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is the
- * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <L>
- * designates the instruction just after the GOTO_W.
- */
- if (opcode == Opcodes.GOTO) {
- code.putByte(200); // GOTO_W
- } else if (opcode == Opcodes.JSR) {
- code.putByte(201); // JSR_W
- } else {
- // if the IF instruction is transformed into IFNOT GOTO_W the
- // next instruction becomes the target of the IFNOT instruction
- if (nextInsn != null) {
- nextInsn.status |= Label.TARGET;
- }
- code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
- : opcode ^ 1);
- code.putShort(8); // jump offset
- // ASM pseudo GOTO_W insn, see ClassReader. We don't use a real
- // GOTO_W because we might need to insert a frame just after (as
- // the target of the IFNOTxxx jump instruction).
- code.putByte(220);
- cw.hasAsmInsns = true;
- }
- label.put(this, code, code.length - 1, true);
- } else if (isWide) {
- /*
- * case of a GOTO_W or JSR_W specified by the user (normally
- * ClassReader when used to resize instructions). In this case we
- * keep the original instruction.
- */
- code.putByte(opcode + 33);
- label.put(this, code, code.length - 1, true);
- } else {
- /*
- * case of a backward jump with an offset >= -32768, or of a forward
- * jump with, of course, an unknown offset. In these cases we store
- * the offset in 2 bytes (which will be increased in
- * resizeInstructions, if needed).
- */
- code.putByte(opcode);
- label.put(this, code, code.length - 1, false);
- }
- if (currentBlock != null) {
- if (nextInsn != null) {
- // if the jump instruction is not a GOTO, the next instruction
- // is also a successor of this instruction. Calling visitLabel
- // adds the label of this next instruction as a successor of the
- // current block, and starts a new basic block
- visitLabel(nextInsn);
- }
- if (opcode == Opcodes.GOTO) {
- noSuccessor();
- }
- }
+ // If needed, update the maximum stack size and number of locals, and stack map frames.
+ if (currentBasicBlock != null) {
+ if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
+ currentBasicBlock.frame.execute(opcode, operand, null, null);
+ } else if (opcode != Opcodes.NEWARRAY) {
+ // The stack size delta is 1 for BIPUSH or SIPUSH, and 0 for NEWARRAY.
+ int size = relativeStackSize + 1;
+ if (size > maxRelativeStackSize) {
+ maxRelativeStackSize = size;
+ }
+ relativeStackSize = size;
+ }
}
-
- @Override
- public void visitLabel(final Label label) {
- // resolves previous forward references to label, if any
- cw.hasAsmInsns |= label.resolve(this, code.length, code.data);
- // updates currentBlock
- if ((label.status & Label.DEBUG) != 0) {
- return;
- }
- if (compute == FRAMES) {
- if (currentBlock != null) {
- if (label.position == currentBlock.position) {
- // successive labels, do not start a new basic block
- currentBlock.status |= (label.status & Label.TARGET);
- label.frame = currentBlock.frame;
- return;
- }
- // ends current block (with one new successor)
- addSuccessor(Edge.NORMAL, label);
- }
- // begins a new current block
- currentBlock = label;
- if (label.frame == null) {
- label.frame = new Frame();
- label.frame.owner = label;
- }
- // updates the basic block list
- if (previousBlock != null) {
- if (label.position == previousBlock.position) {
- previousBlock.status |= (label.status & Label.TARGET);
- label.frame = previousBlock.frame;
- currentBlock = previousBlock;
- return;
- }
- previousBlock.successor = label;
- }
- previousBlock = label;
- } else if (compute == INSERTED_FRAMES) {
- if (currentBlock == null) {
- // This case should happen only once, for the visitLabel call in
- // the constructor. Indeed, if compute is equal to
- // INSERTED_FRAMES currentBlock can not be set back to null (see
- // #noSuccessor).
- currentBlock = label;
- } else {
- // Updates the frame owner so that a correct frame offset is
- // computed in visitFrame(Frame).
- currentBlock.frame.owner = label;
- }
- } else if (compute == MAXS) {
- if (currentBlock != null) {
- // ends current block (with one new successor)
- currentBlock.outputStackMax = maxStackSize;
- addSuccessor(stackSize, label);
- }
- // begins a new current block
- currentBlock = label;
- // resets the relative current and max stack sizes
- stackSize = 0;
- maxStackSize = 0;
- // updates the basic block list
- if (previousBlock != null) {
- previousBlock.successor = label;
- }
- previousBlock = label;
- }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ lastBytecodeOffset = code.length;
+ // Add the instruction to the bytecode of the method.
+ if (var < 4 && opcode != Opcodes.RET) {
+ int optimizedOpcode;
+ if (opcode < Opcodes.ISTORE) {
+ optimizedOpcode = Constants.ILOAD_0 + ((opcode - Opcodes.ILOAD) << 2) + var;
+ } else {
+ optimizedOpcode = Constants.ISTORE_0 + ((opcode - Opcodes.ISTORE) << 2) + var;
+ }
+ code.putByte(optimizedOpcode);
+ } else if (var >= 256) {
+ code.putByte(Constants.WIDE).put12(opcode, var);
+ } else {
+ code.put11(opcode, var);
}
-
- @Override
- public void visitLdcInsn(final Object cst) {
- lastCodeOffset = code.length;
- Item i = cw.newConstItem(cst);
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);
- } else {
- int size;
- // computes the stack size variation
- if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
- size = stackSize + 2;
- } else {
- size = stackSize + 1;
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- int index = i.index;
- if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
- code.put12(20 /* LDC2_W */, index);
- } else if (index >= 256) {
- code.put12(19 /* LDC_W */, index);
- } else {
- code.put11(Opcodes.LDC, index);
- }
+ // If needed, update the maximum stack size and number of locals, and stack map frames.
+ if (currentBasicBlock != null) {
+ if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
+ currentBasicBlock.frame.execute(opcode, var, null, null);
+ } else {
+ if (opcode == Opcodes.RET) {
+ // No stack size delta.
+ currentBasicBlock.flags |= Label.FLAG_SUBROUTINE_END;
+ currentBasicBlock.outputStackSize = (short) relativeStackSize;
+ endCurrentBasicBlockWithNoSuccessor();
+ } else { // xLOAD or xSTORE
+ int size = relativeStackSize + STACK_SIZE_DELTA[opcode];
+ if (size > maxRelativeStackSize) {
+ maxRelativeStackSize = size;
+ }
+ relativeStackSize = size;
+ }
+ }
}
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- lastCodeOffset = code.length;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(Opcodes.IINC, var, null, null);
- }
- }
- if (compute != NOTHING) {
- // updates max locals
- int n = var + 1;
- if (n > maxLocals) {
- maxLocals = n;
- }
- }
- // adds the instruction to the bytecode of the method
- if ((var > 255) || (increment > 127) || (increment < -128)) {
- code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var)
- .putShort(increment);
- } else {
- code.putByte(Opcodes.IINC).put11(var, increment);
- }
+ if (compute != COMPUTE_NOTHING) {
+ int currentMaxLocals;
+ if (opcode == Opcodes.LLOAD
+ || opcode == Opcodes.DLOAD
+ || opcode == Opcodes.LSTORE
+ || opcode == Opcodes.DSTORE) {
+ currentMaxLocals = var + 2;
+ } else {
+ currentMaxLocals = var + 1;
+ }
+ if (currentMaxLocals > maxLocals) {
+ maxLocals = currentMaxLocals;
+ }
}
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- lastCodeOffset = code.length;
- // adds the instruction to the bytecode of the method
- int source = code.length;
- code.putByte(Opcodes.TABLESWITCH);
- code.putByteArray(null, 0, (4 - code.length % 4) % 4);
- dflt.put(this, code, source, true);
- code.putInt(min).putInt(max);
- for (int i = 0; i < labels.length; ++i) {
- labels[i].put(this, code, source, true);
- }
- // updates currentBlock
- visitSwitchInsn(dflt, labels);
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- lastCodeOffset = code.length;
- // adds the instruction to the bytecode of the method
- int source = code.length;
- code.putByte(Opcodes.LOOKUPSWITCH);
- code.putByteArray(null, 0, (4 - code.length % 4) % 4);
- dflt.put(this, code, source, true);
- code.putInt(labels.length);
- for (int i = 0; i < labels.length; ++i) {
- code.putInt(keys[i]);
- labels[i].put(this, code, source, true);
- }
- // updates currentBlock
- visitSwitchInsn(dflt, labels);
- }
-
- private void visitSwitchInsn(final Label dflt, final Label[] labels) {
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);
- // adds current block successors
- addSuccessor(Edge.NORMAL, dflt);
- dflt.getFirst().status |= Label.TARGET;
- for (int i = 0; i < labels.length; ++i) {
- addSuccessor(Edge.NORMAL, labels[i]);
- labels[i].getFirst().status |= Label.TARGET;
- }
- } else {
- // updates current stack size (max stack size unchanged)
- --stackSize;
- // adds current block successors
- addSuccessor(stackSize, dflt);
- for (int i = 0; i < labels.length; ++i) {
- addSuccessor(stackSize, labels[i]);
- }
- }
- // ends current block
- noSuccessor();
- }
+ if (opcode >= Opcodes.ISTORE && compute == COMPUTE_ALL_FRAMES && firstHandler != null) {
+ // If there are exception handler blocks, each instruction within a handler range is, in
+ // theory, a basic block (since execution can jump from this instruction to the exception
+ // handler). As a consequence, the local variable types at the beginning of the handler
+ // block should be the merge of the local variable types at all the instructions within the
+ // handler range. However, instead of creating a basic block for each instruction, we can
+ // get the same result in a more efficient way. Namely, by starting a new basic block after
+ // each xSTORE instruction, which is what we do here.
+ visitLabel(new Label());
}
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- lastCodeOffset = code.length;
- Item i = cw.newStringishItem(ClassWriter.CLASS, desc);
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES || compute == INSERTED_FRAMES) {
- currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);
- } else {
- // updates current stack size (max stack size unchanged because
- // stack size variation always negative or null)
- stackSize += 1 - dims;
- }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ lastBytecodeOffset = code.length;
+ // Add the instruction to the bytecode of the method.
+ Symbol typeSymbol = symbolTable.addConstantClass(type);
+ code.put12(opcode, typeSymbol.index);
+ // If needed, update the maximum stack size and number of locals, and stack map frames.
+ if (currentBasicBlock != null) {
+ if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
+
<TRUNCATED>
[35/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleVisitor.java
old mode 100644
new mode 100755
index c3a2aac..1967491
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleVisitor.java
@@ -1,190 +1,174 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java module. The methods of this class must be called in
- * the following order: <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> |
- * <tt>visitRequire</tt> | <tt>visitExport</tt> | <tt>visitOpen</tt> |
- * <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
- *
- * The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)},
- * {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)}
- * take as parameter a package name or a module name. Unlike the other names which are internal names
- * (names separated by slash), module and package names are qualified names (names separated by dot).
- *
+ * A visitor to visit a Java module. The methods of this class must be called in the following
+ * order: ( {@code visitMainClass} | ( {@code visitPackage} | {@code visitRequire} | {@code
+ * visitExport} | {@code visitOpen} | {@code visitUse} | {@code visitProvide} )* ) {@code visitEnd}.
+ *
* @author Remi Forax
+ * @author Eric Bruneton
*/
public abstract class ModuleVisitor {
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be {@link Opcodes#ASM6}.
- */
- protected final int api;
-
- /**
- * The module visitor to which this visitor must delegate method calls. May
- * be null.
- */
- protected ModuleVisitor mv;
-
- /**
- * Constructs a new {@link ModuleVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
- */
- public ModuleVisitor(final int api) {
- this(api, null);
- }
+ /**
+ * The ASM API version implemented by this visitor. The value of this field must be one of {@link
+ * Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected final int api;
+
+ /** The module visitor to which this visitor must delegate method calls. May be null. */
+ protected ModuleVisitor mv;
- /**
- * Constructs a new {@link ModuleVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
- * @param mv
- * the module visitor to which this visitor must delegate method
- * calls. May be null.
- */
- public ModuleVisitor(final int api, final ModuleVisitor mv) {
- if (api != Opcodes.ASM6) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.mv = mv;
+ /**
+ * Constructs a new {@link ModuleVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM6}
+ * or {@link Opcodes#ASM7}.
+ */
+ public ModuleVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link ModuleVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM6}
+ * or {@link Opcodes#ASM7}.
+ * @param moduleVisitor the module visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ public ModuleVisitor(final int api, final ModuleVisitor moduleVisitor) {
+ if (api != Opcodes.ASM6 && api != Opcodes.ASM7) {
+ throw new IllegalArgumentException();
}
-
- /**
- * Visit the main class of the current module.
- *
- * @param mainClass the internal name of the main class of the current module.
- */
- public void visitMainClass(String mainClass) {
- if (mv != null) {
- mv.visitMainClass(mainClass);
- }
+ this.api = api;
+ this.mv = moduleVisitor;
+ }
+
+ /**
+ * Visit the main class of the current module.
+ *
+ * @param mainClass the internal name of the main class of the current module.
+ */
+ public void visitMainClass(final String mainClass) {
+ if (mv != null) {
+ mv.visitMainClass(mainClass);
}
-
- /**
- * Visit a package of the current module.
- *
- * @param packaze the qualified name of a package.
- */
- public void visitPackage(String packaze) {
- if (mv != null) {
- mv.visitPackage(packaze);
- }
+ }
+
+ /**
+ * Visit a package of the current module.
+ *
+ * @param packaze the internal name of a package.
+ */
+ public void visitPackage(final String packaze) {
+ if (mv != null) {
+ mv.visitPackage(packaze);
}
-
- /**
- * Visits a dependence of the current module.
- *
- * @param module the qualified name of the dependence.
- * @param access the access flag of the dependence among
- * ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC
- * and ACC_MANDATED.
- * @param version the module version at compile time or null.
- */
- public void visitRequire(String module, int access, String version) {
- if (mv != null) {
- mv.visitRequire(module, access, version);
- }
+ }
+
+ /**
+ * Visits a dependence of the current module.
+ *
+ * @param module the fully qualified name (using dots) of the dependence.
+ * @param access the access flag of the dependence among {@code ACC_TRANSITIVE}, {@code
+ * ACC_STATIC_PHASE}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ * @param version the module version at compile time, or {@literal null}.
+ */
+ public void visitRequire(final String module, final int access, final String version) {
+ if (mv != null) {
+ mv.visitRequire(module, access, version);
}
-
- /**
- * Visit an exported package of the current module.
- *
- * @param packaze the qualified name of the exported package.
- * @param access the access flag of the exported package,
- * valid values are among {@code ACC_SYNTHETIC} and
- * {@code ACC_MANDATED}.
- * @param modules the qualified names of the modules that can access to
- * the public classes of the exported package or
- * <tt>null</tt>.
- */
- public void visitExport(String packaze, int access, String... modules) {
- if (mv != null) {
- mv.visitExport(packaze, access, modules);
- }
+ }
+
+ /**
+ * Visit an exported package of the current module.
+ *
+ * @param packaze the internal name of the exported package.
+ * @param access the access flag of the exported package, valid values are among {@code
+ * ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ * @param modules the fully qualified names (using dots) of the modules that can access the public
+ * classes of the exported package, or {@literal null}.
+ */
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ if (mv != null) {
+ mv.visitExport(packaze, access, modules);
}
-
- /**
- * Visit an open package of the current module.
- *
- * @param packaze the qualified name of the opened package.
- * @param access the access flag of the opened package,
- * valid values are among {@code ACC_SYNTHETIC} and
- * {@code ACC_MANDATED}.
- * @param modules the qualified names of the modules that can use deep
- * reflection to the classes of the open package or
- * <tt>null</tt>.
- */
- public void visitOpen(String packaze, int access, String... modules) {
- if (mv != null) {
- mv.visitOpen(packaze, access, modules);
- }
+ }
+
+ /**
+ * Visit an open package of the current module.
+ *
+ * @param packaze the internal name of the opened package.
+ * @param access the access flag of the opened package, valid values are among {@code
+ * ACC_SYNTHETIC} and {@code ACC_MANDATED}.
+ * @param modules the fully qualified names (using dots) of the modules that can use deep
+ * reflection to the classes of the open package, or {@literal null}.
+ */
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ if (mv != null) {
+ mv.visitOpen(packaze, access, modules);
}
-
- /**
- * Visit a service used by the current module.
- * The name must be the internal name of an interface or a class.
- *
- * @param service the internal name of the service.
- */
- public void visitUse(String service) {
- if (mv != null) {
- mv.visitUse(service);
- }
+ }
+
+ /**
+ * Visit a service used by the current module. The name must be the internal name of an interface
+ * or a class.
+ *
+ * @param service the internal name of the service.
+ */
+ public void visitUse(final String service) {
+ if (mv != null) {
+ mv.visitUse(service);
}
-
- /**
- * Visit an implementation of a service.
- *
- * @param service the internal name of the service
- * @param providers the internal names of the implementations
- * of the service (there is at least one provider).
- */
- public void visitProvide(String service, String... providers) {
- if (mv != null) {
- mv.visitProvide(service, providers);
- }
+ }
+
+ /**
+ * Visit an implementation of a service.
+ *
+ * @param service the internal name of the service.
+ * @param providers the internal names of the implementations of the service (there is at least
+ * one provider).
+ */
+ public void visitProvide(final String service, final String... providers) {
+ if (mv != null) {
+ mv.visitProvide(service, providers);
}
-
- /**
- * Visits the end of the module. This method, which is the last one to be
- * called, is used to inform the visitor that everything have been visited.
- */
- public void visitEnd() {
- if (mv != null) {
- mv.visitEnd();
- }
+ }
+
+ /**
+ * Visits the end of the module. This method, which is the last one to be called, is used to
+ * inform the visitor that everything have been visited.
+ */
+ public void visitEnd() {
+ if (mv != null) {
+ mv.visitEnd();
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleWriter.java
old mode 100644
new mode 100755
index 5ab0b3c..1a8f355
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ModuleWriter.java
@@ -1,293 +1,253 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
+ * A {@link ModuleVisitor} that generates the corresponding Module, ModulePackages and
+ * ModuleMainClass attributes, as defined in the Java Virtual Machine Specification (JVMS).
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.25">JVMS
+ * 4.7.25</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.26">JVMS
+ * 4.7.26</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.27">JVMS
+ * 4.7.27</a>
* @author Remi Forax
+ * @author Eric Bruneton
*/
final class ModuleWriter extends ModuleVisitor {
- /**
- * The class writer to which this Module attribute must be added.
- */
- private final ClassWriter cw;
-
- /**
- * size in byte of the Module attribute.
- */
- int size;
-
- /**
- * Number of attributes associated with the current module
- * (Version, ConcealPackages, etc)
- */
- int attributeCount;
-
- /**
- * Size in bytes of the attributes associated with the current module
- */
- int attributesSize;
-
- /**
- * module name index in the constant pool
- */
- private final int name;
-
- /**
- * module access flags
- */
- private final int access;
-
- /**
- * module version index in the constant pool or 0
- */
- private final int version;
-
- /**
- * module main class index in the constant pool or 0
- */
- private int mainClass;
-
- /**
- * number of packages
- */
- private int packageCount;
-
- /**
- * The packages in bytecode form. This byte vector only contains
- * the items themselves, the number of items is store in packageCount
- */
- private ByteVector packages;
-
- /**
- * number of requires items
- */
- private int requireCount;
-
- /**
- * The requires items in bytecode form. This byte vector only contains
- * the items themselves, the number of items is store in requireCount
- */
- private ByteVector requires;
-
- /**
- * number of exports items
- */
- private int exportCount;
-
- /**
- * The exports items in bytecode form. This byte vector only contains
- * the items themselves, the number of items is store in exportCount
- */
- private ByteVector exports;
-
- /**
- * number of opens items
- */
- private int openCount;
-
- /**
- * The opens items in bytecode form. This byte vector only contains
- * the items themselves, the number of items is store in openCount
- */
- private ByteVector opens;
-
- /**
- * number of uses items
- */
- private int useCount;
-
- /**
- * The uses items in bytecode form. This byte vector only contains
- * the items themselves, the number of items is store in useCount
- */
- private ByteVector uses;
-
- /**
- * number of provides items
- */
- private int provideCount;
-
- /**
- * The uses provides in bytecode form. This byte vector only contains
- * the items themselves, the number of items is store in provideCount
- */
- private ByteVector provides;
-
- ModuleWriter(final ClassWriter cw, final int name,
- final int access, final int version) {
- super(Opcodes.ASM6);
- this.cw = cw;
- this.size = 16; // name + access + version + 5 counts
- this.name = name;
- this.access = access;
- this.version = version;
- }
-
- @Override
- public void visitMainClass(String mainClass) {
- if (this.mainClass == 0) { // protect against several calls to visitMainClass
- cw.newUTF8("ModuleMainClass");
- attributeCount++;
- attributesSize += 8;
- }
- this.mainClass = cw.newClass(mainClass);
- }
-
- @Override
- public void visitPackage(String packaze) {
- if (packages == null) {
- // protect against several calls to visitPackage
- cw.newUTF8("ModulePackages");
- packages = new ByteVector();
- attributeCount++;
- attributesSize += 8;
- }
- packages.putShort(cw.newPackage(packaze));
- packageCount++;
- attributesSize += 2;
- }
-
- @Override
- public void visitRequire(String module, int access, String version) {
- if (requires == null) {
- requires = new ByteVector();
- }
- requires.putShort(cw.newModule(module))
- .putShort(access)
- .putShort(version == null? 0: cw.newUTF8(version));
- requireCount++;
- size += 6;
- }
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- if (exports == null) {
- exports = new ByteVector();
- }
- exports.putShort(cw.newPackage(packaze)).putShort(access);
- if (modules == null) {
- exports.putShort(0);
- size += 6;
- } else {
- exports.putShort(modules.length);
- for(String module: modules) {
- exports.putShort(cw.newModule(module));
- }
- size += 6 + 2 * modules.length;
- }
- exportCount++;
+
+ /** Where the constants used in this AnnotationWriter must be stored. */
+ private final SymbolTable symbolTable;
+
+ /** The module_name_index field of the JVMS Module attribute. */
+ private final int moduleNameIndex;
+
+ /** The module_flags field of the JVMS Module attribute. */
+ private final int moduleFlags;
+
+ /** The module_version_index field of the JVMS Module attribute. */
+ private final int moduleVersionIndex;
+
+ /** The requires_count field of the JVMS Module attribute. */
+ private int requiresCount;
+
+ /** The binary content of the 'requires' array of the JVMS Module attribute. */
+ private final ByteVector requires;
+
+ /** The exports_count field of the JVMS Module attribute. */
+ private int exportsCount;
+
+ /** The binary content of the 'exports' array of the JVMS Module attribute. */
+ private final ByteVector exports;
+
+ /** The opens_count field of the JVMS Module attribute. */
+ private int opensCount;
+
+ /** The binary content of the 'opens' array of the JVMS Module attribute. */
+ private final ByteVector opens;
+
+ /** The uses_count field of the JVMS Module attribute. */
+ private int usesCount;
+
+ /** The binary content of the 'uses_index' array of the JVMS Module attribute. */
+ private final ByteVector usesIndex;
+
+ /** The provides_count field of the JVMS Module attribute. */
+ private int providesCount;
+
+ /** The binary content of the 'provides' array of the JVMS Module attribute. */
+ private final ByteVector provides;
+
+ /** The provides_count field of the JVMS ModulePackages attribute. */
+ private int packageCount;
+
+ /** The binary content of the 'package_index' array of the JVMS ModulePackages attribute. */
+ private final ByteVector packageIndex;
+
+ /** The main_class_index field of the JVMS ModuleMainClass attribute, or 0. */
+ private int mainClassIndex;
+
+ ModuleWriter(final SymbolTable symbolTable, final int name, final int access, final int version) {
+ super(Opcodes.ASM7);
+ this.symbolTable = symbolTable;
+ this.moduleNameIndex = name;
+ this.moduleFlags = access;
+ this.moduleVersionIndex = version;
+ this.requires = new ByteVector();
+ this.exports = new ByteVector();
+ this.opens = new ByteVector();
+ this.usesIndex = new ByteVector();
+ this.provides = new ByteVector();
+ this.packageIndex = new ByteVector();
+ }
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ this.mainClassIndex = symbolTable.addConstantClass(mainClass).index;
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ packageIndex.putShort(symbolTable.addConstantPackage(packaze).index);
+ packageCount++;
+ }
+
+ @Override
+ public void visitRequire(final String module, final int access, final String version) {
+ requires
+ .putShort(symbolTable.addConstantModule(module).index)
+ .putShort(access)
+ .putShort(version == null ? 0 : symbolTable.addConstantUtf8(version));
+ requiresCount++;
+ }
+
+ @Override
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ exports.putShort(symbolTable.addConstantPackage(packaze).index).putShort(access);
+ if (modules == null) {
+ exports.putShort(0);
+ } else {
+ exports.putShort(modules.length);
+ for (String module : modules) {
+ exports.putShort(symbolTable.addConstantModule(module).index);
+ }
}
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- if (opens == null) {
- opens = new ByteVector();
- }
- opens.putShort(cw.newPackage(packaze)).putShort(access);
- if (modules == null) {
- opens.putShort(0);
- size += 6;
- } else {
- opens.putShort(modules.length);
- for(String module: modules) {
- opens.putShort(cw.newModule(module));
- }
- size += 6 + 2 * modules.length;
- }
- openCount++;
+ exportsCount++;
+ }
+
+ @Override
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ opens.putShort(symbolTable.addConstantPackage(packaze).index).putShort(access);
+ if (modules == null) {
+ opens.putShort(0);
+ } else {
+ opens.putShort(modules.length);
+ for (String module : modules) {
+ opens.putShort(symbolTable.addConstantModule(module).index);
+ }
}
-
- @Override
- public void visitUse(String service) {
- if (uses == null) {
- uses = new ByteVector();
- }
- uses.putShort(cw.newClass(service));
- useCount++;
- size += 2;
+ opensCount++;
+ }
+
+ @Override
+ public void visitUse(final String service) {
+ usesIndex.putShort(symbolTable.addConstantClass(service).index);
+ usesCount++;
+ }
+
+ @Override
+ public void visitProvide(final String service, final String... providers) {
+ provides.putShort(symbolTable.addConstantClass(service).index);
+ provides.putShort(providers.length);
+ for (String provider : providers) {
+ provides.putShort(symbolTable.addConstantClass(provider).index);
}
-
- @Override
- public void visitProvide(String service, String... providers) {
- if (provides == null) {
- provides = new ByteVector();
- }
- provides.putShort(cw.newClass(service));
- provides.putShort(providers.length);
- for(String provider: providers) {
- provides.putShort(cw.newClass(provider));
- }
- provideCount++;
- size += 4 + 2 * providers.length;
+ providesCount++;
+ }
+
+ @Override
+ public void visitEnd() {
+ // Nothing to do.
+ }
+
+ /**
+ * Returns the number of Module, ModulePackages and ModuleMainClass attributes generated by this
+ * ModuleWriter.
+ *
+ * @return the number of Module, ModulePackages and ModuleMainClass attributes (between 1 and 3).
+ */
+ int getAttributeCount() {
+ return 1 + (packageCount > 0 ? 1 : 0) + (mainClassIndex > 0 ? 1 : 0);
+ }
+
+ /**
+ * Returns the size of the Module, ModulePackages and ModuleMainClass attributes generated by this
+ * ModuleWriter. Also add the names of these attributes in the constant pool.
+ *
+ * @return the size in bytes of the Module, ModulePackages and ModuleMainClass attributes.
+ */
+ int computeAttributesSize() {
+ symbolTable.addConstantUtf8(Constants.MODULE);
+ // 6 attribute header bytes, 6 bytes for name, flags and version, and 5 * 2 bytes for counts.
+ int size =
+ 22 + requires.length + exports.length + opens.length + usesIndex.length + provides.length;
+ if (packageCount > 0) {
+ symbolTable.addConstantUtf8(Constants.MODULE_PACKAGES);
+ // 6 attribute header bytes, and 2 bytes for package_count.
+ size += 8 + packageIndex.length;
}
-
- @Override
- public void visitEnd() {
- // empty
+ if (mainClassIndex > 0) {
+ symbolTable.addConstantUtf8(Constants.MODULE_MAIN_CLASS);
+ // 6 attribute header bytes, and 2 bytes for main_class_index.
+ size += 8;
}
+ return size;
+ }
- void putAttributes(ByteVector out) {
- if (mainClass != 0) {
- out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
- }
- if (packages != null) {
- out.putShort(cw.newUTF8("ModulePackages"))
- .putInt(2 + 2 * packageCount)
- .putShort(packageCount)
- .putByteArray(packages.data, 0, packages.length);
- }
+ /**
+ * Puts the Module, ModulePackages and ModuleMainClass attributes generated by this ModuleWriter
+ * in the given ByteVector.
+ *
+ * @param output where the attributes must be put.
+ */
+ void putAttributes(final ByteVector output) {
+ // 6 bytes for name, flags and version, and 5 * 2 bytes for counts.
+ int moduleAttributeLength =
+ 16 + requires.length + exports.length + opens.length + usesIndex.length + provides.length;
+ output
+ .putShort(symbolTable.addConstantUtf8(Constants.MODULE))
+ .putInt(moduleAttributeLength)
+ .putShort(moduleNameIndex)
+ .putShort(moduleFlags)
+ .putShort(moduleVersionIndex)
+ .putShort(requiresCount)
+ .putByteArray(requires.data, 0, requires.length)
+ .putShort(exportsCount)
+ .putByteArray(exports.data, 0, exports.length)
+ .putShort(opensCount)
+ .putByteArray(opens.data, 0, opens.length)
+ .putShort(usesCount)
+ .putByteArray(usesIndex.data, 0, usesIndex.length)
+ .putShort(providesCount)
+ .putByteArray(provides.data, 0, provides.length);
+ if (packageCount > 0) {
+ output
+ .putShort(symbolTable.addConstantUtf8(Constants.MODULE_PACKAGES))
+ .putInt(2 + packageIndex.length)
+ .putShort(packageCount)
+ .putByteArray(packageIndex.data, 0, packageIndex.length);
}
-
- void put(ByteVector out) {
- out.putInt(size);
- out.putShort(name).putShort(access).putShort(version);
- out.putShort(requireCount);
- if (requires != null) {
- out.putByteArray(requires.data, 0, requires.length);
- }
- out.putShort(exportCount);
- if (exports != null) {
- out.putByteArray(exports.data, 0, exports.length);
- }
- out.putShort(openCount);
- if (opens != null) {
- out.putByteArray(opens.data, 0, opens.length);
- }
- out.putShort(useCount);
- if (uses != null) {
- out.putByteArray(uses.data, 0, uses.length);
- }
- out.putShort(provideCount);
- if (provides != null) {
- out.putByteArray(provides.data, 0, provides.length);
- }
- }
+ if (mainClassIndex > 0) {
+ output
+ .putShort(symbolTable.addConstantUtf8(Constants.MODULE_MAIN_CLASS))
+ .putInt(2)
+ .putShort(mainClassIndex);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
old mode 100644
new mode 100755
index c710ad8..94b98f9
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
@@ -1,372 +1,340 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * Defines the JVM opcodes, access flags and array type codes. This interface
- * does not define all the JVM opcodes because some opcodes are automatically
- * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
- * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
- * opcodes are therefore not defined in this interface. Likewise for LDC,
- * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
- * JSR_W.
- *
+ * The JVM opcodes, access flags and array type codes. This interface does not define all the JVM
+ * opcodes because some opcodes are automatically handled. For example, the xLOAD and xSTORE opcodes
+ * are automatically replaced by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and
+ * xSTORE_n opcodes are therefore not defined in this interface. Likewise for LDC, automatically
+ * replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and JSR_W.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
+// DontCheck(InterfaceIsType): can't be fixed (for backward binary compatibility).
public interface Opcodes {
- // ASM API versions
+ // ASM API versions.
+
+ int ASM4 = 4 << 16 | 0 << 8;
+ int ASM5 = 5 << 16 | 0 << 8;
+ int ASM6 = 6 << 16 | 0 << 8;
+ int ASM7 = 7 << 16 | 0 << 8;
+
+ // Java ClassFile versions (the minor version is stored in the 16 most
+ // significant bits, and the
+ // major version in the 16 least significant bits).
- int ASM4 = 4 << 16 | 0 << 8 | 0;
- int ASM5 = 5 << 16 | 0 << 8 | 0;
- int ASM6 = 6 << 16 | 0 << 8 | 0;
+ int V1_1 = 3 << 16 | 45;
+ int V1_2 = 0 << 16 | 46;
+ int V1_3 = 0 << 16 | 47;
+ int V1_4 = 0 << 16 | 48;
+ int V1_5 = 0 << 16 | 49;
+ int V1_6 = 0 << 16 | 50;
+ int V1_7 = 0 << 16 | 51;
+ int V1_8 = 0 << 16 | 52;
+ int V9 = 0 << 16 | 53;
+ int V10 = 0 << 16 | 54;
+ int V11 = 0 << 16 | 55;
+ int V12 = 0 << 16 | 56;
- // versions
+ /**
+ * Version flag indicating that the class is using 'preview' features.
+ *
+ * <p>{@code version & V_PREVIEW == V_PREVIEW} tests if a version is flagged with {@code
+ * V_PREVIEW}.
+ */
+ int V_PREVIEW = 0xFFFF0000;
- int V1_1 = 3 << 16 | 45;
- int V1_2 = 0 << 16 | 46;
- int V1_3 = 0 << 16 | 47;
- int V1_4 = 0 << 16 | 48;
- int V1_5 = 0 << 16 | 49;
- int V1_6 = 0 << 16 | 50;
- int V1_7 = 0 << 16 | 51;
- int V1_8 = 0 << 16 | 52;
- int V9 = 0 << 16 | 53;
+ // Access flags values, defined in
+ // - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1
+ // - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.5-200-A.1
+ // - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.6-200-A.1
+ // - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.25
- // access flags
+ int ACC_PUBLIC = 0x0001; // class, field, method
+ int ACC_PRIVATE = 0x0002; // class, field, method
+ int ACC_PROTECTED = 0x0004; // class, field, method
+ int ACC_STATIC = 0x0008; // field, method
+ int ACC_FINAL = 0x0010; // class, field, method, parameter
+ int ACC_SUPER = 0x0020; // class
+ int ACC_SYNCHRONIZED = 0x0020; // method
+ int ACC_OPEN = 0x0020; // module
+ int ACC_TRANSITIVE = 0x0020; // module requires
+ int ACC_VOLATILE = 0x0040; // field
+ int ACC_BRIDGE = 0x0040; // method
+ int ACC_STATIC_PHASE = 0x0040; // module requires
+ int ACC_VARARGS = 0x0080; // method
+ int ACC_TRANSIENT = 0x0080; // field
+ int ACC_NATIVE = 0x0100; // method
+ int ACC_INTERFACE = 0x0200; // class
+ int ACC_ABSTRACT = 0x0400; // class, method
+ int ACC_STRICT = 0x0800; // method
+ int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
+ int ACC_ANNOTATION = 0x2000; // class
+ int ACC_ENUM = 0x4000; // class(?) field inner
+ int ACC_MANDATED = 0x8000; // parameter, module, module *
+ int ACC_MODULE = 0x8000; // class
- int ACC_PUBLIC = 0x0001; // class, field, method
- int ACC_PRIVATE = 0x0002; // class, field, method
- int ACC_PROTECTED = 0x0004; // class, field, method
- int ACC_STATIC = 0x0008; // field, method
- int ACC_FINAL = 0x0010; // class, field, method, parameter
- int ACC_SUPER = 0x0020; // class
- int ACC_SYNCHRONIZED = 0x0020; // method
- int ACC_OPEN = 0x0020; // module
- int ACC_TRANSITIVE = 0x0020; // module requires
- int ACC_VOLATILE = 0x0040; // field
- int ACC_BRIDGE = 0x0040; // method
- int ACC_STATIC_PHASE = 0x0040; // module requires
- int ACC_VARARGS = 0x0080; // method
- int ACC_TRANSIENT = 0x0080; // field
- int ACC_NATIVE = 0x0100; // method
- int ACC_INTERFACE = 0x0200; // class
- int ACC_ABSTRACT = 0x0400; // class, method
- int ACC_STRICT = 0x0800; // method
- int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
- int ACC_ANNOTATION = 0x2000; // class
- int ACC_ENUM = 0x4000; // class(?) field inner
- int ACC_MANDATED = 0x8000; // parameter, module, module *
- int ACC_MODULE = 0x8000; // class
-
+ // ASM specific access flags.
+ // WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
+ // access flags, and also to make sure that these flags are automatically filtered out when
+ // written in class files (because access flags are stored using 16 bits only).
- // ASM specific pseudo access flags
+ int ACC_DEPRECATED = 0x20000; // class, field, method
- int ACC_DEPRECATED = 0x20000; // class, field, method
+ // Possible values for the type operand of the NEWARRAY instruction.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html#jvms-6.5.newarray.
- // types for NEWARRAY
+ int T_BOOLEAN = 4;
+ int T_CHAR = 5;
+ int T_FLOAT = 6;
+ int T_DOUBLE = 7;
+ int T_BYTE = 8;
+ int T_SHORT = 9;
+ int T_INT = 10;
+ int T_LONG = 11;
- int T_BOOLEAN = 4;
- int T_CHAR = 5;
- int T_FLOAT = 6;
- int T_DOUBLE = 7;
- int T_BYTE = 8;
- int T_SHORT = 9;
- int T_INT = 10;
- int T_LONG = 11;
+ // Possible values for the reference_kind field of CONSTANT_MethodHandle_info structures.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.8.
- // tags for Handle
+ int H_GETFIELD = 1;
+ int H_GETSTATIC = 2;
+ int H_PUTFIELD = 3;
+ int H_PUTSTATIC = 4;
+ int H_INVOKEVIRTUAL = 5;
+ int H_INVOKESTATIC = 6;
+ int H_INVOKESPECIAL = 7;
+ int H_NEWINVOKESPECIAL = 8;
+ int H_INVOKEINTERFACE = 9;
- int H_GETFIELD = 1;
- int H_GETSTATIC = 2;
- int H_PUTFIELD = 3;
- int H_PUTSTATIC = 4;
- int H_INVOKEVIRTUAL = 5;
- int H_INVOKESTATIC = 6;
- int H_INVOKESPECIAL = 7;
- int H_NEWINVOKESPECIAL = 8;
- int H_INVOKEINTERFACE = 9;
+ // ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.
- // stack map frame types
+ /** An expanded frame. See {@link ClassReader#EXPAND_FRAMES}. */
+ int F_NEW = -1;
- /**
- * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
- */
- int F_NEW = -1;
+ /** A compressed frame with complete frame data. */
+ int F_FULL = 0;
- /**
- * Represents a compressed frame with complete frame data.
- */
- int F_FULL = 0;
+ /**
+ * A compressed frame where locals are the same as the locals in the previous frame, except that
+ * additional 1-3 locals are defined, and with an empty stack.
+ */
+ int F_APPEND = 1;
- /**
- * Represents a compressed frame where locals are the same as the locals in
- * the previous frame, except that additional 1-3 locals are defined, and
- * with an empty stack.
- */
- int F_APPEND = 1;
+ /**
+ * A compressed frame where locals are the same as the locals in the previous frame, except that
+ * the last 1-3 locals are absent and with an empty stack.
+ */
+ int F_CHOP = 2;
- /**
- * Represents a compressed frame where locals are the same as the locals in
- * the previous frame, except that the last 1-3 locals are absent and with
- * an empty stack.
- */
- int F_CHOP = 2;
+ /**
+ * A compressed frame with exactly the same locals as the previous frame and with an empty stack.
+ */
+ int F_SAME = 3;
- /**
- * Represents a compressed frame with exactly the same locals as the
- * previous frame and with an empty stack.
- */
- int F_SAME = 3;
+ /**
+ * A compressed frame with exactly the same locals as the previous frame and with a single value
+ * on the stack.
+ */
+ int F_SAME1 = 4;
- /**
- * Represents a compressed frame with exactly the same locals as the
- * previous frame and with a single value on the stack.
- */
- int F_SAME1 = 4;
+ // Standard stack map frame element types, used in {@link ClassVisitor#visitFrame}.
- // Do not try to change the following code to use auto-boxing,
- // these values are compared by reference and not by value
- // The constructor of Integer was deprecated in 9
- // but we are stuck with it by backward compatibility
- @SuppressWarnings("deprecation") Integer TOP = new Integer(0);
- @SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);
- @SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);
- @SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);
- @SuppressWarnings("deprecation") Integer LONG = new Integer(4);
- @SuppressWarnings("deprecation") Integer NULL = new Integer(5);
- @SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);
+ Integer TOP = Frame.ITEM_TOP;
+ Integer INTEGER = Frame.ITEM_INTEGER;
+ Integer FLOAT = Frame.ITEM_FLOAT;
+ Integer DOUBLE = Frame.ITEM_DOUBLE;
+ Integer LONG = Frame.ITEM_LONG;
+ Integer NULL = Frame.ITEM_NULL;
+ Integer UNINITIALIZED_THIS = Frame.ITEM_UNINITIALIZED_THIS;
- // opcodes // visit method (- = idem)
+ // The JVM opcode values (with the MethodVisitor method name used to visit them in comment, and
+ // where '-' means 'same method name as on the previous line').
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
- int NOP = 0; // visitInsn
- int ACONST_NULL = 1; // -
- int ICONST_M1 = 2; // -
- int ICONST_0 = 3; // -
- int ICONST_1 = 4; // -
- int ICONST_2 = 5; // -
- int ICONST_3 = 6; // -
- int ICONST_4 = 7; // -
- int ICONST_5 = 8; // -
- int LCONST_0 = 9; // -
- int LCONST_1 = 10; // -
- int FCONST_0 = 11; // -
- int FCONST_1 = 12; // -
- int FCONST_2 = 13; // -
- int DCONST_0 = 14; // -
- int DCONST_1 = 15; // -
- int BIPUSH = 16; // visitIntInsn
- int SIPUSH = 17; // -
- int LDC = 18; // visitLdcInsn
- // int LDC_W = 19; // -
- // int LDC2_W = 20; // -
- int ILOAD = 21; // visitVarInsn
- int LLOAD = 22; // -
- int FLOAD = 23; // -
- int DLOAD = 24; // -
- int ALOAD = 25; // -
- // int ILOAD_0 = 26; // -
- // int ILOAD_1 = 27; // -
- // int ILOAD_2 = 28; // -
- // int ILOAD_3 = 29; // -
- // int LLOAD_0 = 30; // -
- // int LLOAD_1 = 31; // -
- // int LLOAD_2 = 32; // -
- // int LLOAD_3 = 33; // -
- // int FLOAD_0 = 34; // -
- // int FLOAD_1 = 35; // -
- // int FLOAD_2 = 36; // -
- // int FLOAD_3 = 37; // -
- // int DLOAD_0 = 38; // -
- // int DLOAD_1 = 39; // -
- // int DLOAD_2 = 40; // -
- // int DLOAD_3 = 41; // -
- // int ALOAD_0 = 42; // -
- // int ALOAD_1 = 43; // -
- // int ALOAD_2 = 44; // -
- // int ALOAD_3 = 45; // -
- int IALOAD = 46; // visitInsn
- int LALOAD = 47; // -
- int FALOAD = 48; // -
- int DALOAD = 49; // -
- int AALOAD = 50; // -
- int BALOAD = 51; // -
- int CALOAD = 52; // -
- int SALOAD = 53; // -
- int ISTORE = 54; // visitVarInsn
- int LSTORE = 55; // -
- int FSTORE = 56; // -
- int DSTORE = 57; // -
- int ASTORE = 58; // -
- // int ISTORE_0 = 59; // -
- // int ISTORE_1 = 60; // -
- // int ISTORE_2 = 61; // -
- // int ISTORE_3 = 62; // -
- // int LSTORE_0 = 63; // -
- // int LSTORE_1 = 64; // -
- // int LSTORE_2 = 65; // -
- // int LSTORE_3 = 66; // -
- // int FSTORE_0 = 67; // -
- // int FSTORE_1 = 68; // -
- // int FSTORE_2 = 69; // -
- // int FSTORE_3 = 70; // -
- // int DSTORE_0 = 71; // -
- // int DSTORE_1 = 72; // -
- // int DSTORE_2 = 73; // -
- // int DSTORE_3 = 74; // -
- // int ASTORE_0 = 75; // -
- // int ASTORE_1 = 76; // -
- // int ASTORE_2 = 77; // -
- // int ASTORE_3 = 78; // -
- int IASTORE = 79; // visitInsn
- int LASTORE = 80; // -
- int FASTORE = 81; // -
- int DASTORE = 82; // -
- int AASTORE = 83; // -
- int BASTORE = 84; // -
- int CASTORE = 85; // -
- int SASTORE = 86; // -
- int POP = 87; // -
- int POP2 = 88; // -
- int DUP = 89; // -
- int DUP_X1 = 90; // -
- int DUP_X2 = 91; // -
- int DUP2 = 92; // -
- int DUP2_X1 = 93; // -
- int DUP2_X2 = 94; // -
- int SWAP = 95; // -
- int IADD = 96; // -
- int LADD = 97; // -
- int FADD = 98; // -
- int DADD = 99; // -
- int ISUB = 100; // -
- int LSUB = 101; // -
- int FSUB = 102; // -
- int DSUB = 103; // -
- int IMUL = 104; // -
- int LMUL = 105; // -
- int FMUL = 106; // -
- int DMUL = 107; // -
- int IDIV = 108; // -
- int LDIV = 109; // -
- int FDIV = 110; // -
- int DDIV = 111; // -
- int IREM = 112; // -
- int LREM = 113; // -
- int FREM = 114; // -
- int DREM = 115; // -
- int INEG = 116; // -
- int LNEG = 117; // -
- int FNEG = 118; // -
- int DNEG = 119; // -
- int ISHL = 120; // -
- int LSHL = 121; // -
- int ISHR = 122; // -
- int LSHR = 123; // -
- int IUSHR = 124; // -
- int LUSHR = 125; // -
- int IAND = 126; // -
- int LAND = 127; // -
- int IOR = 128; // -
- int LOR = 129; // -
- int IXOR = 130; // -
- int LXOR = 131; // -
- int IINC = 132; // visitIincInsn
- int I2L = 133; // visitInsn
- int I2F = 134; // -
- int I2D = 135; // -
- int L2I = 136; // -
- int L2F = 137; // -
- int L2D = 138; // -
- int F2I = 139; // -
- int F2L = 140; // -
- int F2D = 141; // -
- int D2I = 142; // -
- int D2L = 143; // -
- int D2F = 144; // -
- int I2B = 145; // -
- int I2C = 146; // -
- int I2S = 147; // -
- int LCMP = 148; // -
- int FCMPL = 149; // -
- int FCMPG = 150; // -
- int DCMPL = 151; // -
- int DCMPG = 152; // -
- int IFEQ = 153; // visitJumpInsn
- int IFNE = 154; // -
- int IFLT = 155; // -
- int IFGE = 156; // -
- int IFGT = 157; // -
- int IFLE = 158; // -
- int IF_ICMPEQ = 159; // -
- int IF_ICMPNE = 160; // -
- int IF_ICMPLT = 161; // -
- int IF_ICMPGE = 162; // -
- int IF_ICMPGT = 163; // -
- int IF_ICMPLE = 164; // -
- int IF_ACMPEQ = 165; // -
- int IF_ACMPNE = 166; // -
- int GOTO = 167; // -
- int JSR = 168; // -
- int RET = 169; // visitVarInsn
- int TABLESWITCH = 170; // visiTableSwitchInsn
- int LOOKUPSWITCH = 171; // visitLookupSwitch
- int IRETURN = 172; // visitInsn
- int LRETURN = 173; // -
- int FRETURN = 174; // -
- int DRETURN = 175; // -
- int ARETURN = 176; // -
- int RETURN = 177; // -
- int GETSTATIC = 178; // visitFieldInsn
- int PUTSTATIC = 179; // -
- int GETFIELD = 180; // -
- int PUTFIELD = 181; // -
- int INVOKEVIRTUAL = 182; // visitMethodInsn
- int INVOKESPECIAL = 183; // -
- int INVOKESTATIC = 184; // -
- int INVOKEINTERFACE = 185; // -
- int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
- int NEW = 187; // visitTypeInsn
- int NEWARRAY = 188; // visitIntInsn
- int ANEWARRAY = 189; // visitTypeInsn
- int ARRAYLENGTH = 190; // visitInsn
- int ATHROW = 191; // -
- int CHECKCAST = 192; // visitTypeInsn
- int INSTANCEOF = 193; // -
- int MONITORENTER = 194; // visitInsn
- int MONITOREXIT = 195; // -
- // int WIDE = 196; // NOT VISITED
- int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
- int IFNULL = 198; // visitJumpInsn
- int IFNONNULL = 199; // -
- // int GOTO_W = 200; // -
- // int JSR_W = 201; // -
+ int NOP = 0; // visitInsn
+ int ACONST_NULL = 1; // -
+ int ICONST_M1 = 2; // -
+ int ICONST_0 = 3; // -
+ int ICONST_1 = 4; // -
+ int ICONST_2 = 5; // -
+ int ICONST_3 = 6; // -
+ int ICONST_4 = 7; // -
+ int ICONST_5 = 8; // -
+ int LCONST_0 = 9; // -
+ int LCONST_1 = 10; // -
+ int FCONST_0 = 11; // -
+ int FCONST_1 = 12; // -
+ int FCONST_2 = 13; // -
+ int DCONST_0 = 14; // -
+ int DCONST_1 = 15; // -
+ int BIPUSH = 16; // visitIntInsn
+ int SIPUSH = 17; // -
+ int LDC = 18; // visitLdcInsn
+ int ILOAD = 21; // visitVarInsn
+ int LLOAD = 22; // -
+ int FLOAD = 23; // -
+ int DLOAD = 24; // -
+ int ALOAD = 25; // -
+ int IALOAD = 46; // visitInsn
+ int LALOAD = 47; // -
+ int FALOAD = 48; // -
+ int DALOAD = 49; // -
+ int AALOAD = 50; // -
+ int BALOAD = 51; // -
+ int CALOAD = 52; // -
+ int SALOAD = 53; // -
+ int ISTORE = 54; // visitVarInsn
+ int LSTORE = 55; // -
+ int FSTORE = 56; // -
+ int DSTORE = 57; // -
+ int ASTORE = 58; // -
+ int IASTORE = 79; // visitInsn
+ int LASTORE = 80; // -
+ int FASTORE = 81; // -
+ int DASTORE = 82; // -
+ int AASTORE = 83; // -
+ int BASTORE = 84; // -
+ int CASTORE = 85; // -
+ int SASTORE = 86; // -
+ int POP = 87; // -
+ int POP2 = 88; // -
+ int DUP = 89; // -
+ int DUP_X1 = 90; // -
+ int DUP_X2 = 91; // -
+ int DUP2 = 92; // -
+ int DUP2_X1 = 93; // -
+ int DUP2_X2 = 94; // -
+ int SWAP = 95; // -
+ int IADD = 96; // -
+ int LADD = 97; // -
+ int FADD = 98; // -
+ int DADD = 99; // -
+ int ISUB = 100; // -
+ int LSUB = 101; // -
+ int FSUB = 102; // -
+ int DSUB = 103; // -
+ int IMUL = 104; // -
+ int LMUL = 105; // -
+ int FMUL = 106; // -
+ int DMUL = 107; // -
+ int IDIV = 108; // -
+ int LDIV = 109; // -
+ int FDIV = 110; // -
+ int DDIV = 111; // -
+ int IREM = 112; // -
+ int LREM = 113; // -
+ int FREM = 114; // -
+ int DREM = 115; // -
+ int INEG = 116; // -
+ int LNEG = 117; // -
+ int FNEG = 118; // -
+ int DNEG = 119; // -
+ int ISHL = 120; // -
+ int LSHL = 121; // -
+ int ISHR = 122; // -
+ int LSHR = 123; // -
+ int IUSHR = 124; // -
+ int LUSHR = 125; // -
+ int IAND = 126; // -
+ int LAND = 127; // -
+ int IOR = 128; // -
+ int LOR = 129; // -
+ int IXOR = 130; // -
+ int LXOR = 131; // -
+ int IINC = 132; // visitIincInsn
+ int I2L = 133; // visitInsn
+ int I2F = 134; // -
+ int I2D = 135; // -
+ int L2I = 136; // -
+ int L2F = 137; // -
+ int L2D = 138; // -
+ int F2I = 139; // -
+ int F2L = 140; // -
+ int F2D = 141; // -
+ int D2I = 142; // -
+ int D2L = 143; // -
+ int D2F = 144; // -
+ int I2B = 145; // -
+ int I2C = 146; // -
+ int I2S = 147; // -
+ int LCMP = 148; // -
+ int FCMPL = 149; // -
+ int FCMPG = 150; // -
+ int DCMPL = 151; // -
+ int DCMPG = 152; // -
+ int IFEQ = 153; // visitJumpInsn
+ int IFNE = 154; // -
+ int IFLT = 155; // -
+ int IFGE = 156; // -
+ int IFGT = 157; // -
+ int IFLE = 158; // -
+ int IF_ICMPEQ = 159; // -
+ int IF_ICMPNE = 160; // -
+ int IF_ICMPLT = 161; // -
+ int IF_ICMPGE = 162; // -
+ int IF_ICMPGT = 163; // -
+ int IF_ICMPLE = 164; // -
+ int IF_ACMPEQ = 165; // -
+ int IF_ACMPNE = 166; // -
+ int GOTO = 167; // -
+ int JSR = 168; // -
+ int RET = 169; // visitVarInsn
+ int TABLESWITCH = 170; // visiTableSwitchInsn
+ int LOOKUPSWITCH = 171; // visitLookupSwitch
+ int IRETURN = 172; // visitInsn
+ int LRETURN = 173; // -
+ int FRETURN = 174; // -
+ int DRETURN = 175; // -
+ int ARETURN = 176; // -
+ int RETURN = 177; // -
+ int GETSTATIC = 178; // visitFieldInsn
+ int PUTSTATIC = 179; // -
+ int GETFIELD = 180; // -
+ int PUTFIELD = 181; // -
+ int INVOKEVIRTUAL = 182; // visitMethodInsn
+ int INVOKESPECIAL = 183; // -
+ int INVOKESTATIC = 184; // -
+ int INVOKEINTERFACE = 185; // -
+ int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
+ int NEW = 187; // visitTypeInsn
+ int NEWARRAY = 188; // visitIntInsn
+ int ANEWARRAY = 189; // visitTypeInsn
+ int ARRAYLENGTH = 190; // visitInsn
+ int ATHROW = 191; // -
+ int CHECKCAST = 192; // visitTypeInsn
+ int INSTANCEOF = 193; // -
+ int MONITORENTER = 194; // visitInsn
+ int MONITOREXIT = 195; // -
+ int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
+ int IFNULL = 198; // visitJumpInsn
+ int IFNONNULL = 199; // -
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Symbol.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Symbol.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Symbol.java
new file mode 100755
index 0000000..e1a5aa1
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Symbol.java
@@ -0,0 +1,243 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.apache.tapestry5.internal.plastic.asm;
+
+/**
+ * An entry of the constant pool, of the BootstrapMethods attribute, or of the (ASM specific) type
+ * table of a class.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4">JVMS
+ * 4.4</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
+ * 4.7.23</a>
+ * @author Eric Bruneton
+ */
+abstract class Symbol {
+
+ // Tag values for the constant pool entries (using the same order as in the JVMS).
+
+ /** The tag value of CONSTANT_Class_info JVMS structures. */
+ static final int CONSTANT_CLASS_TAG = 7;
+
+ /** The tag value of CONSTANT_Fieldref_info JVMS structures. */
+ static final int CONSTANT_FIELDREF_TAG = 9;
+
+ /** The tag value of CONSTANT_Methodref_info JVMS structures. */
+ static final int CONSTANT_METHODREF_TAG = 10;
+
+ /** The tag value of CONSTANT_InterfaceMethodref_info JVMS structures. */
+ static final int CONSTANT_INTERFACE_METHODREF_TAG = 11;
+
+ /** The tag value of CONSTANT_String_info JVMS structures. */
+ static final int CONSTANT_STRING_TAG = 8;
+
+ /** The tag value of CONSTANT_Integer_info JVMS structures. */
+ static final int CONSTANT_INTEGER_TAG = 3;
+
+ /** The tag value of CONSTANT_Float_info JVMS structures. */
+ static final int CONSTANT_FLOAT_TAG = 4;
+
+ /** The tag value of CONSTANT_Long_info JVMS structures. */
+ static final int CONSTANT_LONG_TAG = 5;
+
+ /** The tag value of CONSTANT_Double_info JVMS structures. */
+ static final int CONSTANT_DOUBLE_TAG = 6;
+
+ /** The tag value of CONSTANT_NameAndType_info JVMS structures. */
+ static final int CONSTANT_NAME_AND_TYPE_TAG = 12;
+
+ /** The tag value of CONSTANT_Utf8_info JVMS structures. */
+ static final int CONSTANT_UTF8_TAG = 1;
+
+ /** The tag value of CONSTANT_MethodHandle_info JVMS structures. */
+ static final int CONSTANT_METHOD_HANDLE_TAG = 15;
+
+ /** The tag value of CONSTANT_MethodType_info JVMS structures. */
+ static final int CONSTANT_METHOD_TYPE_TAG = 16;
+
+ /** The tag value of CONSTANT_Dynamic_info JVMS structures. */
+ static final int CONSTANT_DYNAMIC_TAG = 17;
+
+ /** The tag value of CONSTANT_InvokeDynamic_info JVMS structures. */
+ static final int CONSTANT_INVOKE_DYNAMIC_TAG = 18;
+
+ /** The tag value of CONSTANT_Module_info JVMS structures. */
+ static final int CONSTANT_MODULE_TAG = 19;
+
+ /** The tag value of CONSTANT_Package_info JVMS structures. */
+ static final int CONSTANT_PACKAGE_TAG = 20;
+
+ // Tag values for the BootstrapMethods attribute entries (ASM specific tag).
+
+ /** The tag value of the BootstrapMethods attribute entries. */
+ static final int BOOTSTRAP_METHOD_TAG = 64;
+
+ // Tag values for the type table entries (ASM specific tags).
+
+ /** The tag value of a normal type entry in the (ASM specific) type table of a class. */
+ static final int TYPE_TAG = 128;
+
+ /**
+ * The tag value of an {@link Frame#ITEM_UNINITIALIZED} type entry in the type table of a class.
+ */
+ static final int UNINITIALIZED_TYPE_TAG = 129;
+
+ /** The tag value of a merged type entry in the (ASM specific) type table of a class. */
+ static final int MERGED_TYPE_TAG = 130;
+
+ // Instance fields.
+
+ /**
+ * The index of this symbol in the constant pool, in the BootstrapMethods attribute, or in the
+ * (ASM specific) type table of a class (depending on the {@link #tag} value).
+ */
+ final int index;
+
+ /**
+ * A tag indicating the type of this symbol. Must be one of the static tag values defined in this
+ * class.
+ */
+ final int tag;
+
+ /**
+ * The internal name of the owner class of this symbol. Only used for {@link
+ * #CONSTANT_FIELDREF_TAG}, {@link #CONSTANT_METHODREF_TAG}, {@link
+ * #CONSTANT_INTERFACE_METHODREF_TAG}, and {@link #CONSTANT_METHOD_HANDLE_TAG} symbols.
+ */
+ final String owner;
+
+ /**
+ * The name of the class field or method corresponding to this symbol. Only used for {@link
+ * #CONSTANT_FIELDREF_TAG}, {@link #CONSTANT_METHODREF_TAG}, {@link
+ * #CONSTANT_INTERFACE_METHODREF_TAG}, {@link #CONSTANT_NAME_AND_TYPE_TAG}, {@link
+ * #CONSTANT_METHOD_HANDLE_TAG}, {@link #CONSTANT_DYNAMIC_TAG} and {@link
+ * #CONSTANT_INVOKE_DYNAMIC_TAG} symbols.
+ */
+ final String name;
+
+ /**
+ * The string value of this symbol. This is:
+ *
+ * <ul>
+ * <li>a field or method descriptor for {@link #CONSTANT_FIELDREF_TAG}, {@link
+ * #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG}, {@link
+ * #CONSTANT_NAME_AND_TYPE_TAG}, {@link #CONSTANT_METHOD_HANDLE_TAG}, {@link
+ * #CONSTANT_METHOD_TYPE_TAG}, {@link #CONSTANT_DYNAMIC_TAG} and {@link
+ * #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
+ * <li>an arbitrary string for {@link #CONSTANT_UTF8_TAG} and {@link #CONSTANT_STRING_TAG}
+ * symbols,
+ * <li>an internal class name for {@link #CONSTANT_CLASS_TAG}, {@link #TYPE_TAG} and {@link
+ * #UNINITIALIZED_TYPE_TAG} symbols,
+ * <li>{@literal null} for the other types of symbol.
+ * </ul>
+ */
+ final String value;
+
+ /**
+ * The numeric value of this symbol. This is:
+ *
+ * <ul>
+ * <li>the symbol's value for {@link #CONSTANT_INTEGER_TAG},{@link #CONSTANT_FLOAT_TAG}, {@link
+ * #CONSTANT_LONG_TAG}, {@link #CONSTANT_DOUBLE_TAG},
+ * <li>the CONSTANT_MethodHandle_info reference_kind field value for {@link
+ * #CONSTANT_METHOD_HANDLE_TAG} symbols,
+ * <li>the CONSTANT_InvokeDynamic_info bootstrap_method_attr_index field value for {@link
+ * #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
+ * <li>the offset of a bootstrap method in the BootstrapMethods boostrap_methods array, for
+ * {@link #CONSTANT_DYNAMIC_TAG} or {@link #BOOTSTRAP_METHOD_TAG} symbols,
+ * <li>the bytecode offset of the NEW instruction that created an {@link
+ * Frame#ITEM_UNINITIALIZED} type for {@link #UNINITIALIZED_TYPE_TAG} symbols,
+ * <li>the indices (in the class' type table) of two {@link #TYPE_TAG} source types for {@link
+ * #MERGED_TYPE_TAG} symbols,
+ * <li>0 for the other types of symbol.
+ * </ul>
+ */
+ final long data;
+
+ /**
+ * Additional information about this symbol, generally computed lazily. <i>Warning: the value of
+ * this field is ignored when comparing Symbol instances</i> (to avoid duplicate entries in a
+ * SymbolTable). Therefore, this field should only contain data that can be computed from the
+ * other fields of this class. It contains:
+ *
+ * <ul>
+ * <li>the {@link Type#getArgumentsAndReturnSizes} of the symbol's method descriptor for {@link
+ * #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link
+ * #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
+ * <li>the index in the InnerClasses_attribute 'classes' array (plus one) corresponding to this
+ * class, for {@link #CONSTANT_CLASS_TAG} symbols,
+ * <li>the index (in the class' type table) of the merged type of the two source types for
+ * {@link #MERGED_TYPE_TAG} symbols,
+ * <li>0 for the other types of symbol, or if this field has not been computed yet.
+ * </ul>
+ */
+ int info;
+
+ /**
+ * Constructs a new Symbol. This constructor can't be used directly because the Symbol class is
+ * abstract. Instead, use the factory methods of the {@link SymbolTable} class.
+ *
+ * @param index the symbol index in the constant pool, in the BootstrapMethods attribute, or in
+ * the (ASM specific) type table of a class (depending on 'tag').
+ * @param tag the symbol type. Must be one of the static tag values defined in this class.
+ * @param owner The internal name of the symbol's owner class. Maybe {@literal null}.
+ * @param name The name of the symbol's corresponding class field or method. Maybe {@literal
+ * null}.
+ * @param value The string value of this symbol. Maybe {@literal null}.
+ * @param data The numeric value of this symbol.
+ */
+ Symbol(
+ final int index,
+ final int tag,
+ final String owner,
+ final String name,
+ final String value,
+ final long data) {
+ this.index = index;
+ this.tag = tag;
+ this.owner = owner;
+ this.name = name;
+ this.value = value;
+ this.data = data;
+ }
+
+ /**
+ * Returns the result {@link Type#getArgumentsAndReturnSizes} on {@link #value}.
+ *
+ * @return the result {@link Type#getArgumentsAndReturnSizes} on {@link #value} (memoized in
+ * {@link #info} for efficiency). This should only be used for {@link
+ * #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link
+ * #CONSTANT_INVOKE_DYNAMIC_TAG} symbols.
+ */
+ int getArgumentsAndReturnSizes() {
+ if (info == 0) {
+ info = Type.getArgumentsAndReturnSizes(value);
+ }
+ return info;
+ }
+}
[13/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
old mode 100644
new mode 100755
index b71c186..8ddee8d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
@@ -1,41 +1,38 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
-import java.io.FileInputStream;
-import java.io.PrintWriter;
+import java.io.IOException;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Attribute;
-import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
@@ -44,1397 +41,1534 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A {@link Printer} that prints the ASM code to generate the classes if visits.
- *
+ *
* @author Eric Bruneton
*/
+// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public class ASMifier extends Printer {
- /**
- * The name of the visitor variable in the produced code.
- */
- protected final String name;
-
- /**
- * Identifier of the annotation visitor variable in the produced code.
- */
- protected final int id;
-
- /**
- * The label names. This map associates String values to Label keys. It is
- * used only in ASMifierMethodVisitor.
- */
- protected Map<Label, String> labelNames;
-
- /**
- * Pseudo access flag used to distinguish class access flags.
- */
- private static final int ACCESS_CLASS = 262144;
-
- /**
- * Pseudo access flag used to distinguish field access flags.
- */
- private static final int ACCESS_FIELD = 524288;
-
- /**
- * Pseudo access flag used to distinguish inner class flags.
- */
- private static final int ACCESS_INNER = 1048576;
-
- /**
- * Pseudo access flag used to distinguish module requires/exports flags.
- */
- private static final int ACCESS_MODULE = 2097152;
-
- /**
- * Constructs a new {@link ASMifier}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #ASMifier(int, String, int)} version.
- *
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public ASMifier() {
- this(Opcodes.ASM6, "cw", 0);
- if (getClass() != ASMifier.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Constructs a new {@link ASMifier}.
- *
- * @param api
- * the ASM API version implemented by this class. Must be one of
- * {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param name
- * the name of the visitor variable in the produced code.
- * @param id
- * identifier of the annotation visitor variable in the produced
- * code.
- */
- protected ASMifier(final int api, final String name, final int id) {
- super(api);
- this.name = name;
- this.id = id;
- }
-
- /**
- * Prints the ASM source code to generate the given class to the standard
- * output.
- * <p>
- * Usage: ASMifier [-debug] <binary class name or class file name>
- *
- * @param args
- * the command line arguments.
- *
- * @throws Exception
- * if the class cannot be found, or if an IO exception occurs.
- */
- public static void main(final String[] args) throws Exception {
- int i = 0;
- int flags = ClassReader.SKIP_DEBUG;
-
- boolean ok = true;
- if (args.length < 1 || args.length > 2) {
- ok = false;
- }
- if (ok && "-debug".equals(args[0])) {
- i = 1;
- flags = 0;
- if (args.length != 2) {
- ok = false;
- }
- }
- if (!ok) {
- System.err
- .println("Prints the ASM code to generate the given class.");
- System.err.println("Usage: ASMifier [-debug] "
- + "<fully qualified class name or class file name>");
- return;
- }
- ClassReader cr;
- if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
- || args[i].indexOf('/') > -1) {
- cr = new ClassReader(new FileInputStream(args[i]));
+ /** A pseudo access flag used to distinguish class access flags. */
+ private static final int ACCESS_CLASS = 0x40000;
+
+ /** A pseudo access flag used to distinguish field access flags. */
+ private static final int ACCESS_FIELD = 0x80000;
+
+ /** A pseudo access flag used to distinguish inner class flags. */
+ private static final int ACCESS_INNER = 0x100000;
+
+ /** A pseudo access flag used to distinguish module requires / exports flags. */
+ private static final int ACCESS_MODULE = 0x200000;
+
+ private static final String ANNOTATION_VISITOR = "annotationVisitor";
+ private static final String ANNOTATION_VISITOR0 = "annotationVisitor0 = ";
+ private static final String NEW_OBJECT_ARRAY = ", new Object[] {";
+ private static final String END_ARRAY = " });\n";
+ private static final String END_PARAMETERS = ");\n\n";
+ private static final String VISIT_END = ".visitEnd();\n";
+
+ private static final Map<Integer, String> CLASS_VERSIONS;
+
+ static {
+ HashMap<Integer, String> classVersions = new HashMap<Integer, String>();
+ classVersions.put(Opcodes.V1_1, "V1_1");
+ classVersions.put(Opcodes.V1_2, "V1_2");
+ classVersions.put(Opcodes.V1_3, "V1_3");
+ classVersions.put(Opcodes.V1_4, "V1_4");
+ classVersions.put(Opcodes.V1_5, "V1_5");
+ classVersions.put(Opcodes.V1_6, "V1_6");
+ classVersions.put(Opcodes.V1_7, "V1_7");
+ classVersions.put(Opcodes.V1_8, "V1_8");
+ classVersions.put(Opcodes.V9, "V9");
+ classVersions.put(Opcodes.V10, "V10");
+ classVersions.put(Opcodes.V11, "V11");
+ classVersions.put(Opcodes.V12, "V12");
+ CLASS_VERSIONS = Collections.unmodifiableMap(classVersions);
+ }
+
+ /** The name of the visitor variable in the produced code. */
+ protected final String name;
+
+ /** The identifier of the annotation visitor variable in the produced code. */
+ protected final int id;
+
+ /** The name of the Label variables in the produced code. */
+ protected Map<Label, String> labelNames;
+
+ /**
+ * Constructs a new {@link ASMifier}. <i>Subclasses must not use this constructor</i>. Instead,
+ * they must use the {@link #ASMifier(int, String, int)} version.
+ *
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public ASMifier() {
+ this(Opcodes.ASM7, "classWriter", 0);
+ if (getClass() != ASMifier.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link ASMifier}.
+ *
+ * @param api the ASM API version implemented by this class. Must be one of {@link Opcodes#ASM4},
+ * {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param visitorVariableName the name of the visitor variable in the produced code.
+ * @param annotationVisitorId identifier of the annotation visitor variable in the produced code.
+ */
+ protected ASMifier(
+ final int api, final String visitorVariableName, final int annotationVisitorId) {
+ super(api);
+ this.name = visitorVariableName;
+ this.id = annotationVisitorId;
+ }
+
+ /**
+ * Prints the ASM source code to generate the given class to the standard output.
+ *
+ * <p>Usage: ASMifier [-debug] <binary class name or class file name>
+ *
+ * @param args the command line arguments.
+ * @throws IOException if the class cannot be found, or if an IOException occurs.
+ */
+ public static void main(final String[] args) throws IOException {
+ String usage =
+ "Prints the ASM code to generate the given class.\n"
+ + "Usage: ASMifier [-debug] <fully qualified class name or class file name>";
+ main(usage, new ASMifier(), args);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Classes
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ String simpleName;
+ if (name == null) {
+ simpleName = "module-info";
+ } else {
+ int lastSlashIndex = name.lastIndexOf('/');
+ if (lastSlashIndex == -1) {
+ simpleName = name;
+ } else {
+ text.add("package asm." + name.substring(0, lastSlashIndex).replace('/', '.') + ";\n");
+ simpleName = name.substring(lastSlashIndex + 1).replace('-', '_');
+ }
+ }
+ text.add("import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Attribute;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.ClassReader;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.ClassWriter;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Handle;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Label;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Opcodes;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Type;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.TypePath;\n");
+ text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
+ text.add("public static byte[] dump () throws Exception {\n\n");
+ text.add("ClassWriter classWriter = new ClassWriter(0);\n");
+ text.add("FieldVisitor fieldVisitor;\n");
+ text.add("MethodVisitor methodVisitor;\n");
+ text.add("AnnotationVisitor annotationVisitor0;\n\n");
+
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visit(");
+ String versionString = CLASS_VERSIONS.get(version);
+ if (versionString != null) {
+ stringBuilder.append(versionString);
+ } else {
+ stringBuilder.append(version);
+ }
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_CLASS);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(signature);
+ stringBuilder.append(", ");
+ appendConstant(superName);
+ stringBuilder.append(", ");
+ if (interfaces != null && interfaces.length > 0) {
+ stringBuilder.append("new String[] {");
+ for (int i = 0; i < interfaces.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(interfaces[i]);
+ }
+ stringBuilder.append(" }");
+ } else {
+ stringBuilder.append("null");
+ }
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitSource(");
+ appendConstant(file);
+ stringBuilder.append(", ");
+ appendConstant(debug);
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Printer visitModule(final String name, final int flags, final String version) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("ModuleVisitor moduleVisitor = classWriter.visitModule(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendAccessFlags(flags | ACCESS_MODULE);
+ stringBuilder.append(", ");
+ appendConstant(version);
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier("moduleVisitor", 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitNestHost(final String nestHost) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitNestHost(");
+ appendConstant(nestHost);
+ stringBuilder.append(");\n\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitOuterClass(");
+ appendConstant(owner);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitClassAnnotation(final String descriptor, final boolean visible) {
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public ASMifier visitClassTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitClassAttribute(final Attribute attribute) {
+ visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitNestMember(final String nestMember) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitNestMember(");
+ appendConstant(nestMember);
+ stringBuilder.append(");\n\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitInnerClass(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(outerName);
+ stringBuilder.append(", ");
+ appendConstant(innerName);
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_INNER);
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("{\n");
+ stringBuilder.append("fieldVisitor = classWriter.visitField(");
+ appendAccessFlags(access | ACCESS_FIELD);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(signature);
+ stringBuilder.append(", ");
+ appendConstant(value);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier("fieldVisitor", 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public ASMifier visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("{\n");
+ stringBuilder.append("methodVisitor = classWriter.visitMethod(");
+ appendAccessFlags(access);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(signature);
+ stringBuilder.append(", ");
+ if (exceptions != null && exceptions.length > 0) {
+ stringBuilder.append("new String[] {");
+ for (int i = 0; i < exceptions.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(exceptions[i]);
+ }
+ stringBuilder.append(" }");
+ } else {
+ stringBuilder.append("null");
+ }
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier("methodVisitor", 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitClassEnd() {
+ text.add("classWriter.visitEnd();\n\n");
+ text.add("return classWriter.toByteArray();\n");
+ text.add("}\n");
+ text.add("}\n");
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Modules
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitMainClass(");
+ appendConstant(mainClass);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitPackage(");
+ appendConstant(packaze);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitRequire(final String module, final int access, final String version) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitRequire(");
+ appendConstant(module);
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_MODULE);
+ stringBuilder.append(", ");
+ appendConstant(version);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitExport(");
+ appendConstant(packaze);
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_MODULE);
+ if (modules != null && modules.length > 0) {
+ stringBuilder.append(", new String[] {");
+ for (int i = 0; i < modules.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(modules[i]);
+ }
+ stringBuilder.append(" }");
+ }
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitOpen(");
+ appendConstant(packaze);
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_MODULE);
+ if (modules != null && modules.length > 0) {
+ stringBuilder.append(", new String[] {");
+ for (int i = 0; i < modules.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(modules[i]);
+ }
+ stringBuilder.append(" }");
+ }
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitUse(final String service) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitUse(");
+ appendConstant(service);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitProvide(final String service, final String... providers) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitProvide(");
+ appendConstant(service);
+ stringBuilder.append(", new String[] {");
+ for (int i = 0; i < providers.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(providers[i]);
+ }
+ stringBuilder.append(END_ARRAY);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitModuleEnd() {
+ text.add("moduleVisitor.visitEnd();\n");
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Annotations
+ // -----------------------------------------------------------------------------------------------
+
+ // DontCheck(OverloadMethodsDeclarationOrder): overloads are semantically different.
+ @Override
+ public void visit(final String name, final Object value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(ANNOTATION_VISITOR).append(id).append(".visit(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(value);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(ANNOTATION_VISITOR).append(id).append(".visitEnum(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(value);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitAnnotation(final String name, final String descriptor) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append("AnnotationVisitor annotationVisitor")
+ .append(id + 1)
+ .append(" = annotationVisitor");
+ stringBuilder.append(id).append(".visitAnnotation(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, id + 1);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public ASMifier visitArray(final String name) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("{\n");
+ stringBuilder
+ .append("AnnotationVisitor annotationVisitor")
+ .append(id + 1)
+ .append(" = annotationVisitor");
+ stringBuilder.append(id).append(".visitArray(");
+ appendConstant(name);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, id + 1);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitAnnotationEnd() {
+ stringBuilder.setLength(0);
+ stringBuilder.append(ANNOTATION_VISITOR).append(id).append(VISIT_END);
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Fields
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public ASMifier visitFieldAnnotation(final String descriptor, final boolean visible) {
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public ASMifier visitFieldTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitFieldAttribute(final Attribute attribute) {
+ visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitFieldEnd() {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(VISIT_END);
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visitParameter(final String parameterName, final int access) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitParameter(");
+ appendString(stringBuilder, parameterName);
+ stringBuilder.append(", ");
+ appendAccessFlags(access);
+ text.add(stringBuilder.append(");\n").toString());
+ }
+
+ @Override
+ public ASMifier visitAnnotationDefault() {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".visitAnnotationDefault();\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public ASMifier visitMethodAnnotation(final String descriptor, final boolean visible) {
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public ASMifier visitMethodTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public ASMifier visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitAnnotableParameterCount(")
+ .append(parameterCount)
+ .append(", ")
+ .append(visible)
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ return this;
+ }
+
+ @Override
+ public ASMifier visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".visitParameterAnnotation(")
+ .append(parameter)
+ .append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(visible).append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitMethodAttribute(final Attribute attribute) {
+ visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitCode() {
+ text.add(name + ".visitCode();\n");
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ stringBuilder.setLength(0);
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ declareFrameTypes(numLocal, local);
+ declareFrameTypes(numStack, stack);
+ if (type == Opcodes.F_NEW) {
+ stringBuilder.append(name).append(".visitFrame(Opcodes.F_NEW, ");
} else {
- cr = new ClassReader(args[i]);
+ stringBuilder.append(name).append(".visitFrame(Opcodes.F_FULL, ");
}
- cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(
- System.out)), flags);
- }
-
- // ------------------------------------------------------------------------
- // Classes
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- String simpleName;
- if (name == null) {
- simpleName = "module-info";
+ stringBuilder.append(numLocal).append(NEW_OBJECT_ARRAY);
+ appendFrameTypes(numLocal, local);
+ stringBuilder.append("}, ").append(numStack).append(NEW_OBJECT_ARRAY);
+ appendFrameTypes(numStack, stack);
+ stringBuilder.append('}');
+ break;
+ case Opcodes.F_APPEND:
+ declareFrameTypes(numLocal, local);
+ stringBuilder
+ .append(name)
+ .append(".visitFrame(Opcodes.F_APPEND,")
+ .append(numLocal)
+ .append(NEW_OBJECT_ARRAY);
+ appendFrameTypes(numLocal, local);
+ stringBuilder.append("}, 0, null");
+ break;
+ case Opcodes.F_CHOP:
+ stringBuilder
+ .append(name)
+ .append(".visitFrame(Opcodes.F_CHOP,")
+ .append(numLocal)
+ .append(", null, 0, null");
+ break;
+ case Opcodes.F_SAME:
+ stringBuilder.append(name).append(".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+ break;
+ case Opcodes.F_SAME1:
+ declareFrameTypes(1, stack);
+ stringBuilder
+ .append(name)
+ .append(".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
+ appendFrameTypes(1, stack);
+ stringBuilder.append('}');
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitInsn(").append(OPCODES[opcode]).append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitIntInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer.toString(operand))
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitVarInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(var)
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitTypeInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(type);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(this.name).append(".visitFieldInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(owner);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(this.name)
+ .append(".visitMethodInsn(")
+ .append(OPCODES[opcode])
+ .append(", ");
+ appendConstant(owner);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ stringBuilder.append(isInterface ? "true" : "false");
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(this.name).append(".visitInvokeDynamicInsn(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(bootstrapMethodHandle);
+ stringBuilder.append(", new Object[]{");
+ for (int i = 0; i < bootstrapMethodArguments.length; ++i) {
+ appendConstant(bootstrapMethodArguments[i]);
+ if (i != bootstrapMethodArguments.length - 1) {
+ stringBuilder.append(", ");
+ }
+ }
+ stringBuilder.append("});\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ stringBuilder.setLength(0);
+ declareLabel(label);
+ stringBuilder.append(name).append(".visitJumpInsn(").append(OPCODES[opcode]).append(", ");
+ appendLabel(label);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ stringBuilder.setLength(0);
+ declareLabel(label);
+ stringBuilder.append(name).append(".visitLabel(");
+ appendLabel(label);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitLdcInsn(");
+ appendConstant(value);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitIincInsn(")
+ .append(var)
+ .append(", ")
+ .append(increment)
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ stringBuilder.setLength(0);
+ for (Label label : labels) {
+ declareLabel(label);
+ }
+ declareLabel(dflt);
+
+ stringBuilder
+ .append(name)
+ .append(".visitTableSwitchInsn(")
+ .append(min)
+ .append(", ")
+ .append(max)
+ .append(", ");
+ appendLabel(dflt);
+ stringBuilder.append(", new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ stringBuilder.append(END_ARRAY);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ stringBuilder.setLength(0);
+ for (Label label : labels) {
+ declareLabel(label);
+ }
+ declareLabel(dflt);
+
+ stringBuilder.append(name).append(".visitLookupSwitchInsn(");
+ appendLabel(dflt);
+ stringBuilder.append(", new int[] {");
+ for (int i = 0; i < keys.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ").append(keys[i]);
+ }
+ stringBuilder.append(" }, new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ stringBuilder.append(END_ARRAY);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitMultiANewArrayInsn(");
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(numDimensions).append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ stringBuilder.setLength(0);
+ declareLabel(start);
+ declareLabel(end);
+ declareLabel(handler);
+ stringBuilder.append(name).append(".visitTryCatchBlock(");
+ appendLabel(start);
+ stringBuilder.append(", ");
+ appendLabel(end);
+ stringBuilder.append(", ");
+ appendLabel(handler);
+ stringBuilder.append(", ");
+ appendConstant(type);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation("visitTryCatchAnnotation", typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(this.name).append(".visitLocalVariable(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(signature);
+ stringBuilder.append(", ");
+ appendLabel(start);
+ stringBuilder.append(", ");
+ appendLabel(end);
+ stringBuilder.append(", ").append(index).append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Printer visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".visitLocalVariableAnnotation(")
+ .append(typeRef);
+ if (typePath == null) {
+ stringBuilder.append(", null, ");
+ } else {
+ stringBuilder.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+ }
+ stringBuilder.append("new Label[] {");
+ for (int i = 0; i < start.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendLabel(start[i]);
+ }
+ stringBuilder.append(" }, new Label[] {");
+ for (int i = 0; i < end.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendLabel(end[i]);
+ }
+ stringBuilder.append(" }, new int[] {");
+ for (int i = 0; i < index.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ").append(index[i]);
+ }
+ stringBuilder.append(" }, ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(visible).append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitLineNumber(").append(line).append(", ");
+ appendLabel(start);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitMaxs(")
+ .append(maxStack)
+ .append(", ")
+ .append(maxLocals)
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMethodEnd() {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(VISIT_END);
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Common methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Visits a class, field or method annotation.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a new {@link ASMifier} to visit the annotation values.
+ */
+ // DontCheck(OverloadMethodsDeclarationOrder): overloads are semantically different.
+ public ASMifier visitAnnotation(final String descriptor, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".visitAnnotation(");
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(visible).append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ /**
+ * Visits a class, field or method type annotation.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#FIELD}. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a new {@link ASMifier} to visit the annotation values.
+ */
+ public ASMifier visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation("visitTypeAnnotation", typeRef, typePath, descriptor, visible);
+ }
+
+ /**
+ * Visits a class, field, method, instruction or try catch block type annotation.
+ *
+ * @param method the name of the visit method for this type of annotation.
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#FIELD}. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a new {@link ASMifier} to visit the annotation values.
+ */
+ public ASMifier visitTypeAnnotation(
+ final String method,
+ final int typeRef,
+ final TypePath typePath,
+ final String descriptor,
+ final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".")
+ .append(method)
+ .append("(")
+ .append(typeRef);
+ if (typePath == null) {
+ stringBuilder.append(", null, ");
+ } else {
+ stringBuilder.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+ }
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(visible).append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ /**
+ * Visit a class, field or method attribute.
+ *
+ * @param attribute an attribute.
+ */
+ public void visitAttribute(final Attribute attribute) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("// ATTRIBUTE ").append(attribute.type).append('\n');
+ if (attribute instanceof ASMifiable) {
+ if (labelNames == null) {
+ labelNames = new HashMap<Label, String>();
+ }
+ stringBuilder.append("{\n");
+ StringBuffer stringBuffer = new StringBuffer();
+ ((ASMifiable) attribute).asmify(stringBuffer, "attribute", labelNames);
+ stringBuilder.append(stringBuffer.toString());
+ stringBuilder.append(name).append(".visitAttribute(attribute);\n");
+ stringBuilder.append("}\n");
+ }
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ASMifier}.
+ *
+ * @param visitorVariableName the name of the visitor variable in the produced code.
+ * @param annotationVisitorId identifier of the annotation visitor variable in the produced code.
+ * @return a new {@link ASMifier}.
+ */
+ // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
+ protected ASMifier createASMifier(
+ final String visitorVariableName, final int annotationVisitorId) {
+ return new ASMifier(Opcodes.ASM7, visitorVariableName, annotationVisitorId);
+ }
+
+ /**
+ * Appends a string representation of the given access flags to {@link #stringBuilder}.
+ *
+ * @param accessFlags some access flags.
+ */
+ private void appendAccessFlags(final int accessFlags) {
+ boolean isEmpty = true;
+ if ((accessFlags & Opcodes.ACC_PUBLIC) != 0) {
+ stringBuilder.append("ACC_PUBLIC");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_PRIVATE) != 0) {
+ stringBuilder.append("ACC_PRIVATE");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_PROTECTED) != 0) {
+ stringBuilder.append("ACC_PROTECTED");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_FINAL) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ if ((accessFlags & ACCESS_MODULE) == 0) {
+ stringBuilder.append("ACC_FINAL");
+ } else {
+ stringBuilder.append("ACC_TRANSITIVE");
+ }
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_STATIC) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_STATIC");
+ isEmpty = false;
+ }
+ if ((accessFlags & (Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_SUPER | Opcodes.ACC_TRANSITIVE))
+ != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ if ((accessFlags & ACCESS_CLASS) == 0) {
+ if ((accessFlags & ACCESS_MODULE) == 0) {
+ stringBuilder.append("ACC_SYNCHRONIZED");
} else {
- int n = name.lastIndexOf('/');
- if (n == -1) {
- simpleName = name;
- } else {
- text.add("package asm." + name.substring(0, n).replace('/', '.')
- + ";\n");
- simpleName = name.substring(n + 1).replace('-', '_');
- }
+ stringBuilder.append("ACC_TRANSITIVE");
}
- text.add("import java.util.*;\n");
- text.add("import org.apache.tapestry5.internal.plastic.asm.*;\n");
- text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
- text.add("public static byte[] dump () throws Exception {\n\n");
- text.add("ClassWriter cw = new ClassWriter(0);\n");
- text.add("FieldVisitor fv;\n");
- text.add("MethodVisitor mv;\n");
- text.add("AnnotationVisitor av0;\n\n");
-
- buf.setLength(0);
- buf.append("cw.visit(");
- switch (version) {
- case Opcodes.V1_1:
- buf.append("V1_1");
- break;
- case Opcodes.V1_2:
- buf.append("V1_2");
- break;
- case Opcodes.V1_3:
- buf.append("V1_3");
- break;
- case Opcodes.V1_4:
- buf.append("V1_4");
- break;
- case Opcodes.V1_5:
- buf.append("V1_5");
- break;
- case Opcodes.V1_6:
- buf.append("V1_6");
- break;
- case Opcodes.V1_7:
- buf.append("V1_7");
- break;
- case Opcodes.V1_8:
- buf.append("V1_8");
- break;
- case Opcodes.V9:
- buf.append("V9");
- break;
- default:
- buf.append(version);
- break;
- }
- buf.append(", ");
- appendAccess(access | ACCESS_CLASS);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(signature);
- buf.append(", ");
- appendConstant(superName);
- buf.append(", ");
- if (interfaces != null && interfaces.length > 0) {
- buf.append("new String[] {");
- for (int i = 0; i < interfaces.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(interfaces[i]);
- }
- buf.append(" }");
+ } else {
+ stringBuilder.append("ACC_SUPER");
+ }
+ isEmpty = false;
+ }
+ if ((accessFlags & (Opcodes.ACC_VOLATILE | Opcodes.ACC_BRIDGE | Opcodes.ACC_STATIC_PHASE))
+ != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ if ((accessFlags & ACCESS_FIELD) == 0) {
+ if ((accessFlags & ACCESS_MODULE) == 0) {
+ stringBuilder.append("ACC_BRIDGE");
} else {
- buf.append("null");
+ stringBuilder.append("ACC_STATIC_PHASE");
}
- buf.append(");\n\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitSource(final String file, final String debug) {
- buf.setLength(0);
- buf.append("cw.visitSource(");
- appendConstant(file);
- buf.append(", ");
- appendConstant(debug);
- buf.append(");\n\n");
- text.add(buf.toString());
- }
-
- @Override
- public Printer visitModule(final String name, final int flags,
- final String version) {
- buf.setLength(0);
- buf.append("ModuleVisitor mdv = cw.visitModule(");
- appendConstant(name);
- buf.append(", ");
- appendAccess(flags | ACCESS_MODULE);
- buf.append(", ");
- appendConstant(version);
- buf.append(");\n\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("mdv", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitOuterClass(final String owner, final String name,
- final String desc) {
- buf.setLength(0);
- buf.append("cw.visitOuterClass(");
- appendConstant(owner);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(");\n\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitClassAnnotation(final String desc,
- final boolean visible) {
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public ASMifier visitClassTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public void visitClassAttribute(final Attribute attr) {
- visitAttribute(attr);
- }
-
- @Override
- public void visitInnerClass(final String name, final String outerName,
- final String innerName, final int access) {
- buf.setLength(0);
- buf.append("cw.visitInnerClass(");
- appendConstant(name);
- buf.append(", ");
- appendConstant(outerName);
- buf.append(", ");
- appendConstant(innerName);
- buf.append(", ");
- appendAccess(access | ACCESS_INNER);
- buf.append(");\n\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- buf.setLength(0);
- buf.append("{\n");
- buf.append("fv = cw.visitField(");
- appendAccess(access | ACCESS_FIELD);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- appendConstant(signature);
- buf.append(", ");
- appendConstant(value);
- buf.append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("fv", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public ASMifier visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- buf.setLength(0);
- buf.append("{\n");
- buf.append("mv = cw.visitMethod(");
- appendAccess(access);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- appendConstant(signature);
- buf.append(", ");
- if (exceptions != null && exceptions.length > 0) {
- buf.append("new String[] {");
- for (int i = 0; i < exceptions.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(exceptions[i]);
- }
- buf.append(" }");
- } else {
- buf.append("null");
+ } else {
+ stringBuilder.append("ACC_VOLATILE");
+ }
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_VARARGS) != 0
+ && (accessFlags & (ACCESS_CLASS | ACCESS_FIELD)) == 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_VARARGS");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_TRANSIENT) != 0 && (accessFlags & ACCESS_FIELD) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_TRANSIENT");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_NATIVE) != 0
+ && (accessFlags & (ACCESS_CLASS | ACCESS_FIELD)) == 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_NATIVE");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_ENUM) != 0
+ && (accessFlags & (ACCESS_CLASS | ACCESS_FIELD | ACCESS_INNER)) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_ENUM");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_ANNOTATION) != 0
+ && (accessFlags & (ACCESS_CLASS | ACCESS_INNER)) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_ANNOTATION");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_ABSTRACT) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_ABSTRACT");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_INTERFACE) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_INTERFACE");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_STRICT) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_STRICT");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_SYNTHETIC");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_DEPRECATED");
+ isEmpty = false;
+ }
+ if ((accessFlags & (Opcodes.ACC_MANDATED | Opcodes.ACC_MODULE)) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ if ((accessFlags & ACCESS_CLASS) == 0) {
+ stringBuilder.append("ACC_MANDATED");
+ } else {
+ stringBuilder.append("ACC_MODULE");
+ }
+ isEmpty = false;
+ }
+ if (isEmpty) {
+ stringBuilder.append('0');
+ }
+ }
+
+ /**
+ * Appends a string representation of the given constant to {@link #stringBuilder}.
+ *
+ * @param value a {@link String}, {@link Type}, {@link Handle}, {@link Byte}, {@link Short},
+ * {@link Character}, {@link Integer}, {@link Float}, {@link Long} or {@link Double} object,
+ * or an array of primitive values. May be {@literal null}.
+ */
+ protected void appendConstant(final Object value) {
+ if (value == null) {
+ stringBuilder.append("null");
+ } else if (value instanceof String) {
+ appendString(stringBuilder, (String) value);
+ } else if (value instanceof Type) {
+ stringBuilder.append("Type.getType(\"");
+ stringBuilder.append(((Type) value).getDescriptor());
+ stringBuilder.append("\")");
+ } else if (value instanceof Handle) {
+ stringBuilder.append("new Handle(");
+ Handle handle = (Handle) value;
+ stringBuilder.append("Opcodes.").append(HANDLE_TAG[handle.getTag()]).append(", \"");
+ stringBuilder.append(handle.getOwner()).append("\", \"");
+ stringBuilder.append(handle.getName()).append("\", \"");
+ stringBuilder.append(handle.getDesc()).append("\", ");
+ stringBuilder.append(handle.isInterface()).append(")");
+ } else if (value instanceof ConstantDynamic) {
+ stringBuilder.append("new ConstantDynamic(\"");
+ ConstantDynamic constantDynamic = (ConstantDynamic) value;
+ stringBuilder.append(constantDynamic.getName()).append("\", \"");
+ stringBuilder.append(constantDynamic.getDescriptor()).append("\", ");
+ appendConstant(constantDynamic.getBootstrapMethod());
+ stringBuilder.append(", new Object[] {");
+ int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
+ for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
+ appendConstant(constantDynamic.getBootstrapMethodArgument(i));
+ if (i != bootstrapMethodArgumentCount - 1) {
+ stringBuilder.append(", ");
}
- buf.append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("mv", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitClassEnd() {
- text.add("cw.visitEnd();\n\n");
- text.add("return cw.toByteArray();\n");
- text.add("}\n");
- text.add("}\n");
- }
-
- // ------------------------------------------------------------------------
- // Module
- // ------------------------------------------------------------------------
-
- @Override
- public void visitMainClass(String mainClass) {
- buf.setLength(0);
- buf.append("mdv.visitMainClass(");
- appendConstant(buf, mainClass);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitPackage(String packaze) {
- buf.setLength(0);
- buf.append("mdv.visitPackage(");
- appendConstant(buf, packaze);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitRequire(String module, int access, String version) {
- buf.setLength(0);
- buf.append("mdv.visitRequire(");
- appendConstant(buf, module);
- buf.append(", ");
- appendAccess(access | ACCESS_MODULE);
- buf.append(", ");
- appendConstant(buf, version);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- buf.setLength(0);
- buf.append("mdv.visitExport(");
- appendConstant(buf, packaze);
- buf.append(", ");
- appendAccess(access | ACCESS_MODULE);
- if (modules != null && modules.length > 0) {
- buf.append(", new String[] {");
- for (int i = 0; i < modules.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(modules[i]);
- }
- buf.append(" }");
- }
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- buf.setLength(0);
- buf.append("mdv.visitOpen(");
- appendConstant(buf, packaze);
- buf.append(", ");
- appendAccess(access | ACCESS_MODULE);
- if (modules != null && modules.length > 0) {
- buf.append(", new String[] {");
- for (int i = 0; i < modules.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(modules[i]);
- }
- buf.append(" }");
- }
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitUse(String service) {
- buf.setLength(0);
- buf.append("mdv.visitUse(");
- appendConstant(buf, service);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitProvide(String service, String... providers) {
- buf.setLength(0);
- buf.append("mdv.visitProvide(");
- appendConstant(buf, service);
- buf.append(", new String[] {");
- for (int i = 0; i < providers.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(providers[i]);
- }
- buf.append(" });\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitModuleEnd() {
- text.add("mdv.visitEnd();\n");
- }
-
-
- // ------------------------------------------------------------------------
- // Annotations
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final String name, final Object value) {
- buf.setLength(0);
- buf.append("av").append(id).append(".visit(");
- appendConstant(buf, name);
- buf.append(", ");
- appendConstant(buf, value);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- buf.setLength(0);
- buf.append("av").append(id).append(".visitEnum(");
- appendConstant(buf, name);
- buf.append(", ");
- appendConstant(buf, desc);
- buf.append(", ");
- appendConstant(buf, value);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitAnnotation(final String name, final String desc) {
- buf.setLength(0);
- buf.append("{\n");
- buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
- buf.append(id).append(".visitAnnotation(");
- appendConstant(buf, name);
- buf.append(", ");
- appendConstant(buf, desc);
- buf.append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", id + 1);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public ASMifier visitArray(final String name) {
- buf.setLength(0);
- buf.append("{\n");
- buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
- buf.append(id).append(".visitArray(");
- appendConstant(buf, name);
- buf.append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", id + 1);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitAnnotationEnd() {
- buf.setLength(0);
- buf.append("av").append(id).append(".visitEnd();\n");
- text.add(buf.toString());
- }
-
- // ------------------------------------------------------------------------
- // Fields
- // ------------------------------------------------------------------------
-
- @Override
- public ASMifier visitFieldAnnotation(final String desc,
- final boolean visible) {
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public ASMifier visitFieldTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public void visitFieldAttribute(final Attribute attr) {
- visitAttribute(attr);
- }
-
- @Override
- public void visitFieldEnd() {
- buf.setLength(0);
- buf.append(name).append(".visitEnd();\n");
- text.add(buf.toString());
- }
-
- // ------------------------------------------------------------------------
- // Methods
- // ------------------------------------------------------------------------
-
- @Override
- public void visitParameter(String parameterName, int access) {
- buf.setLength(0);
- buf.append(name).append(".visitParameter(");
- appendString(buf, parameterName);
- buf.append(", ");
- appendAccess(access);
- text.add(buf.append(");\n").toString());
- }
-
- @Override
- public ASMifier visitAnnotationDefault() {
- buf.setLength(0);
- buf.append("{\n").append("av0 = ").append(name)
- .append(".visitAnnotationDefault();\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public ASMifier visitMethodAnnotation(final String desc,
- final boolean visible) {
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public ASMifier visitMethodTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public ASMifier visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- buf.setLength(0);
- buf.append("{\n").append("av0 = ").append(name)
- .append(".visitParameterAnnotation(").append(parameter)
- .append(", ");
- appendConstant(desc);
- buf.append(", ").append(visible).append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitMethodAttribute(final Attribute attr) {
- visitAttribute(attr);
- }
-
- @Override
- public void visitCode() {
- text.add(name + ".visitCode();\n");
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- buf.setLength(0);
- switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- declareFrameTypes(nLocal, local);
- declareFrameTypes(nStack, stack);
- if (type == Opcodes.F_NEW) {
- buf.append(name).append(".visitFrame(Opcodes.F_NEW, ");
- } else {
- buf.append(name).append(".visitFrame(Opcodes.F_FULL, ");
- }
- buf.append(nLocal).append(", new Object[] {");
- appendFrameTypes(nLocal, local);
- buf.append("}, ").append(nStack).append(", new Object[] {");
- appendFrameTypes(nStack, stack);
- buf.append('}');
+ }
+ stringBuilder.append("})");
+ } else if (value instanceof Byte) {
+ stringBuilder.append("new Byte((byte)").append(value).append(')');
+ } else if (value instanceof Boolean) {
+ stringBuilder.append(((Boolean) value).booleanValue() ? "Boolean.TRUE" : "Boolean.FALSE");
+ } else if (value instanceof Short) {
+ stringBuilder.append("new Short((short)").append(value).append(')');
+ } else if (value instanceof Character) {
+ stringBuilder
+ .append("new Character((char)")
+ .append((int) ((Character) value).charValue())
+ .append(')');
+ } else if (value instanceof Integer) {
+ stringBuilder.append("new Integer(").append(value).append(')');
+ } else if (value instanceof Float) {
+ stringBuilder.append("new Float(\"").append(value).append("\")");
+ } else if (value instanceof Long) {
+ stringBuilder.append("new Long(").append(value).append("L)");
+ } else if (value instanceof Double) {
+ stringBuilder.append("new Double(\"").append(value).append("\")");
+ } else if (value instanceof byte[]) {
+ byte[] byteArray = (byte[]) value;
+ stringBuilder.append("new byte[] {");
+ for (int i = 0; i < byteArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(byteArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof boolean[]) {
+ boolean[] booleanArray = (boolean[]) value;
+ stringBuilder.append("new boolean[] {");
+ for (int i = 0; i < booleanArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(booleanArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof short[]) {
+ short[] shortArray = (short[]) value;
+ stringBuilder.append("new short[] {");
+ for (int i = 0; i < shortArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append("(short)").append(shortArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof char[]) {
+ char[] charArray = (char[]) value;
+ stringBuilder.append("new char[] {");
+ for (int i = 0; i < charArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append("(char)").append((int) charArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof int[]) {
+ int[] intArray = (int[]) value;
+ stringBuilder.append("new int[] {");
+ for (int i = 0; i < intArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(intArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof long[]) {
+ long[] longArray = (long[]) value;
+ stringBuilder.append("new long[] {");
+ for (int i = 0; i < longArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(longArray[i]).append('L');
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof float[]) {
+ float[] floatArray = (float[]) value;
+ stringBuilder.append("new float[] {");
+ for (int i = 0; i < floatArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(floatArray[i]).append('f');
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof double[]) {
+ double[] doubleArray = (double[]) value;
+ stringBuilder.append("new double[] {");
+ for (int i = 0; i < doubleArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(doubleArray[i]).append('d');
+ }
+ stringBuilder.append('}');
+ }
+ }
+
+ /**
+ * Calls {@link #declareLabel} for each label in the given stack map frame types.
+ *
+ * @param numTypes the number of stack map frame types in 'frameTypes'.
+ * @param frameTypes an array of stack map frame types, in the format described in {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+ */
+ private void declareFrameTypes(final int numTypes, final Object[] frameTypes) {
+ for (int i = 0; i < numTypes; ++i) {
+ if (frameTypes[i] instanceof Label) {
+ declareLabel((Label) frameTypes[i]);
+ }
+ }
+ }
+
+ /**
+ * Appends the given stack map frame types to {@link #stringBuilder}.
+ *
+ * @param numTypes the number of stack map frame types in 'frameTypes'.
+ * @param frameTypes an array of stack map frame types, in the format described in {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+ */
+ private void appendFrameTypes(final int numTypes, final Object[] frameTypes) {
+ for (int i = 0; i < numTypes; ++i) {
+ if (i > 0) {
+ stringBuilder.append(", ");
+ }
+ if (frameTypes[i] instanceof String) {
+ appendConstant(frameTypes[i]);
+ } else if (frameTypes[i] instanceof Integer) {
+ switch (((Integer) frameTypes[i]).intValue()) {
+ case 0:
+ stringBuilder.append("Opcodes.TOP");
break;
- case Opcodes.F_APPEND:
- declareFrameTypes(nLocal, local);
- buf.append(name).append(".visitFrame(Opcodes.F_APPEND,")
- .append(nLocal).append(", new Object[] {");
- appendFrameTypes(nLocal, local);
- buf.append("}, 0, null");
+ case 1:
+ stringBuilder.append("Opcodes.INTEGER");
break;
- case Opcodes.F_CHOP:
- buf.append(name).append(".visitFrame(Opcodes.F_CHOP,")
- .append(nLocal).append(", null, 0, null");
+ case 2:
+ stringBuilder.append("Opcodes.FLOAT");
break;
- case Opcodes.F_SAME:
- buf.append(name).append(
- ".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+ case 3:
+ stringBuilder.append("Opcodes.DOUBLE");
break;
- case Opcodes.F_SAME1:
- declareFrameTypes(1, stack);
- buf.append(name).append(
- ".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
- appendFrameTypes(1, stack);
- buf.append('}');
+ case 4:
+ stringBuilder.append("Opcodes.LONG");
break;
+ case 5:
+ stringBuilder.append("Opcodes.NULL");
+ break;
+ case 6:
+ stringBuilder.append("Opcodes.UNINITIALIZED_THIS");
+ break;
+ default:
+ throw new IllegalArgumentException();
}
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitInsn(final int opcode) {
- buf.setLength(0);
- buf.append(name).append(".visitInsn(").append(OPCODES[opcode])
- .append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- buf.setLength(0);
- buf.append(name)
- .append(".visitIntInsn(")
- .append(OPCODES[opcode])
- .append(", ")
- .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
- .toString(operand)).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- buf.setLength(0);
- buf.append(name).append(".visitVarInsn(").append(OPCODES[opcode])
- .append(", ").append(var).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- buf.setLength(0);
- buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode])
- .append(", ");
- appendConstant(type);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- buf.setLength(0);
- buf.append(this.name).append(".visitFieldInsn(")
- .append(OPCODES[opcode]).append(", ");
- appendConstant(owner);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
- }
-
- private void doVisitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- buf.setLength(0);
- buf.append(this.name).append(".visitMethodInsn(")
- .append(OPCODES[opcode]).append(", ");
- appendConstant(owner);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- buf.append(itf ? "true" : "false");
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- buf.setLength(0);
- buf.append(this.name).append(".visitInvokeDynamicInsn(");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- appendConstant(bsm);
- buf.append(", new Object[]{");
- for (int i = 0; i < bsmArgs.length; ++i) {
- appendConstant(bsmArgs[i]);
- if (i != bsmArgs.length - 1) {
- buf.append(", ");
- }
- }
- buf.append("});\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- buf.setLength(0);
- declareLabel(label);
- buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode])
- .append(", ");
- appendLabel(label);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitLabel(final Label label) {
- buf.setLength(0);
- declareLabel(label);
- buf.append(name).append(".visitLabel(");
- appendLabel(label);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- buf.setLength(0);
- buf.append(name).append(".visitLdcInsn(");
- appendConstant(cst);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- buf.setLength(0);
- buf.append(name).append(".visitIincInsn(").append(var).append(", ")
- .append(increment).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- buf.setLength(0);
- for (int i = 0; i < labels.length; ++i) {
- declareLabel(labels[i]);
- }
- declareLabel(dflt);
-
- buf.append(name).append(".visitTableSwitchInsn(").append(min)
- .append(", ").append(max).append(", ");
- appendLabel(dflt);
- buf.append(", new Label[] {");
- for (int i = 0; i < labels.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendLabel(labels[i]);
- }
- buf.append(" });\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- buf.setLength(0);
- for (int i = 0; i < labels.length; ++i) {
- declareLabel(labels[i]);
- }
- declareLabel(dflt);
-
- buf.append(name).append(".visitLookupSwitchInsn(");
- appendLabel(dflt);
- buf.append(", new int[] {");
- for (int i = 0; i < keys.length; ++i) {
- buf.append(i == 0 ? " " : ", ").append(keys[i]);
- }
- buf.append(" }, new Label[] {");
- for (int i = 0; i < labels.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendLabel(labels[i]);
- }
- buf.append(" });\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- buf.setLength(0);
- buf.append(name).append(".visitMultiANewArrayInsn(");
- appendConstant(desc);
- buf.append(", ").append(dims).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitInsnAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath,
- desc, visible);
- }
-
- @Override
- public void visitTryCatchBlock(final Label start, final Label end,
- final Label handler, final String type) {
- buf.setLength(0);
- declareLabel(start);
- declareLabel(end);
- declareLabel(handler);
- buf.append(name).append(".visitTryCatchBlock(");
- appendLabel(start);
- buf.append(", ");
- appendLabel(end);
- buf.append(", ");
- appendLabel(handler);
- buf.append(", ");
- appendConstant(type);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitTryCatchAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation("visitTryCatchAnnotation", typeRef,
- typePath, desc, visible);
- }
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- buf.setLength(0);
- buf.append(this.name).append(".visitLocalVariable(");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- appendConstant(signature);
- buf.append(", ");
- appendLabel(start);
- buf.append(", ");
- appendLabel(end);
- buf.append(", ").append(index).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath,
- Label[] start, Label[] end, int[] index, String desc,
- boolean visible) {
- buf.setLength(0);
- buf.append("{\n").append("av0 = ").append(name)
- .append(".visitLocalVariableAnnotation(");
- buf.append(typeRef);
- if (typePath == null) {
- buf.append(", null, ");
- } else {
- buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
- }
- buf.append("new Label[] {");
- for (int i = 0; i < start.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendLabel(start[i]);
- }
- buf.append(" }, new Label[] {");
- for (int i = 0; i < end.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendLabel(end[i]);
- }
- buf.append(" }, new int[] {");
- for (int i = 0; i < index.length; ++i) {
- buf.append(i == 0 ? " " : ", ").append(index[i]);
- }
- buf.append(" }, ");
- appendConstant(desc);
- buf.append(", ").append(visible).append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitLineNumber(final int line, final Label start) {
- buf.setLength(0);
- buf.append(name).append(".visitLineNumber(").append(line).append(", ");
- appendLabel(
<TRUNCATED>
[21/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
old mode 100644
new mode 100755
index 8600566..a71d05d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
@@ -1,210 +1,188 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * A node that represents a stack map frame. These nodes are pseudo instruction
- * nodes in order to be inserted in an instruction list. In fact these nodes
- * must(*) be inserted <i>just before</i> any instruction node <b>i</b> that
- * follows an unconditionnal branch instruction such as GOTO or THROW, that is
- * the target of a jump instruction, or that starts an exception handler block.
- * The stack map frame types must describe the values of the local variables and
- * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
+ * A node that represents a stack map frame. These nodes are pseudo instruction nodes in order to be
+ * inserted in an instruction list. In fact these nodes must(*) be inserted <i>just before</i> any
+ * instruction node <b>i</b> that follows an unconditionnal branch instruction such as GOTO or
+ * THROW, that is the target of a jump instruction, or that starts an exception handler block. The
+ * stack map frame types must describe the values of the local variables and of the operand stack
+ * elements <i>just before</i> <b>i</b> is executed. <br>
* <br>
- * (*) this is mandatory only for classes whose version is greater than or equal
- * to {@link Opcodes#V1_6 V1_6}.
- *
+ * (*) this is mandatory only for classes whose version is greater than or equal to {@link
+ * Opcodes#V1_6}.
+ *
* @author Eric Bruneton
*/
public class FrameNode extends AbstractInsnNode {
- /**
- * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
- * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
- * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
- * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
- */
- public int type;
+ /**
+ * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or {@link
+ * Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
+ */
+ public int type;
- /**
- * The types of the local variables of this stack map frame. Elements of
- * this list can be Integer, String or LabelNode objects (for primitive,
- * reference and uninitialized types respectively - see
- * {@link MethodVisitor}).
- */
- public List<Object> local;
+ /**
+ * The types of the local variables of this stack map frame. Elements of this list can be Integer,
+ * String or LabelNode objects (for primitive, reference and uninitialized types respectively -
+ * see {@link MethodVisitor}).
+ */
+ public List<Object> local;
- /**
- * The types of the operand stack elements of this stack map frame. Elements
- * of this list can be Integer, String or LabelNode objects (for primitive,
- * reference and uninitialized types respectively - see
- * {@link MethodVisitor}).
- */
- public List<Object> stack;
+ /**
+ * The types of the operand stack elements of this stack map frame. Elements of this list can be
+ * Integer, String or LabelNode objects (for primitive, reference and uninitialized types
+ * respectively - see {@link MethodVisitor}).
+ */
+ public List<Object> stack;
- private FrameNode() {
- super(-1);
- }
+ private FrameNode() {
+ super(-1);
+ }
- /**
- * Constructs a new {@link FrameNode}.
- *
- * @param type
- * the type of this frame. Must be {@link Opcodes#F_NEW} for
- * expanded frames, or {@link Opcodes#F_FULL},
- * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
- * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
- * {@link Opcodes#F_SAME1} for compressed frames.
- * @param nLocal
- * number of local variables of this stack map frame.
- * @param local
- * the types of the local variables of this stack map frame.
- * Elements of this list can be Integer, String or LabelNode
- * objects (for primitive, reference and uninitialized types
- * respectively - see {@link MethodVisitor}).
- * @param nStack
- * number of operand stack elements of this stack map frame.
- * @param stack
- * the types of the operand stack elements of this stack map
- * frame. Elements of this list can be Integer, String or
- * LabelNode objects (for primitive, reference and uninitialized
- * types respectively - see {@link MethodVisitor}).
- */
- public FrameNode(final int type, final int nLocal, final Object[] local,
- final int nStack, final Object[] stack) {
- super(-1);
- this.type = type;
- switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- this.local = asList(nLocal, local);
- this.stack = asList(nStack, stack);
- break;
- case Opcodes.F_APPEND:
- this.local = asList(nLocal, local);
- break;
- case Opcodes.F_CHOP:
- this.local = Arrays.asList(new Object[nLocal]);
- break;
- case Opcodes.F_SAME:
- break;
- case Opcodes.F_SAME1:
- this.stack = asList(1, stack);
- break;
- }
+ /**
+ * Constructs a new {@link FrameNode}.
+ *
+ * @param type the type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or
+ * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
+ * Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
+ * @param numLocal number of local variables of this stack map frame.
+ * @param local the types of the local variables of this stack map frame. Elements of this list
+ * can be Integer, String or LabelNode objects (for primitive, reference and uninitialized
+ * types respectively - see {@link MethodVisitor}).
+ * @param numStack number of operand stack elements of this stack map frame.
+ * @param stack the types of the operand stack elements of this stack map frame. Elements of this
+ * list can be Integer, String or LabelNode objects (for primitive, reference and
+ * uninitialized types respectively - see {@link MethodVisitor}).
+ */
+ public FrameNode(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ super(-1);
+ this.type = type;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ this.local = Util.asArrayList(numLocal, local);
+ this.stack = Util.asArrayList(numStack, stack);
+ break;
+ case Opcodes.F_APPEND:
+ this.local = Util.asArrayList(numLocal, local);
+ break;
+ case Opcodes.F_CHOP:
+ this.local = Util.asArrayList(numLocal);
+ break;
+ case Opcodes.F_SAME:
+ break;
+ case Opcodes.F_SAME1:
+ this.stack = Util.asArrayList(1, stack);
+ break;
+ default:
+ throw new IllegalArgumentException();
}
+ }
- @Override
- public int getType() {
- return FRAME;
- }
+ @Override
+ public int getType() {
+ return FRAME;
+ }
- /**
- * Makes the given visitor visit this stack map frame.
- *
- * @param mv
- * a method visitor.
- */
- @Override
- public void accept(final MethodVisitor mv) {
- switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- mv.visitFrame(type, local.size(), asArray(local), stack.size(),
- asArray(stack));
- break;
- case Opcodes.F_APPEND:
- mv.visitFrame(type, local.size(), asArray(local), 0, null);
- break;
- case Opcodes.F_CHOP:
- mv.visitFrame(type, local.size(), null, 0, null);
- break;
- case Opcodes.F_SAME:
- mv.visitFrame(type, 0, null, 0, null);
- break;
- case Opcodes.F_SAME1:
- mv.visitFrame(type, 0, null, 1, asArray(stack));
- break;
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ methodVisitor.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack));
+ break;
+ case Opcodes.F_APPEND:
+ methodVisitor.visitFrame(type, local.size(), asArray(local), 0, null);
+ break;
+ case Opcodes.F_CHOP:
+ methodVisitor.visitFrame(type, local.size(), null, 0, null);
+ break;
+ case Opcodes.F_SAME:
+ methodVisitor.visitFrame(type, 0, null, 0, null);
+ break;
+ case Opcodes.F_SAME1:
+ methodVisitor.visitFrame(type, 0, null, 1, asArray(stack));
+ break;
+ default:
+ throw new IllegalArgumentException();
}
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- FrameNode clone = new FrameNode();
- clone.type = type;
- if (local != null) {
- clone.local = new ArrayList<Object>();
- for (int i = 0; i < local.size(); ++i) {
- Object l = local.get(i);
- if (l instanceof LabelNode) {
- l = labels.get(l);
- }
- clone.local.add(l);
- }
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ FrameNode clone = new FrameNode();
+ clone.type = type;
+ if (local != null) {
+ clone.local = new ArrayList<Object>();
+ for (int i = 0, n = local.size(); i < n; ++i) {
+ Object localElement = local.get(i);
+ if (localElement instanceof LabelNode) {
+ localElement = clonedLabels.get(localElement);
}
- if (stack != null) {
- clone.stack = new ArrayList<Object>();
- for (int i = 0; i < stack.size(); ++i) {
- Object s = stack.get(i);
- if (s instanceof LabelNode) {
- s = labels.get(s);
- }
- clone.stack.add(s);
- }
- }
- return clone;
+ clone.local.add(localElement);
+ }
}
-
- // ------------------------------------------------------------------------
-
- private static List<Object> asList(final int n, final Object[] o) {
- return Arrays.asList(o).subList(0, n);
+ if (stack != null) {
+ clone.stack = new ArrayList<Object>();
+ for (int i = 0, n = stack.size(); i < n; ++i) {
+ Object stackElement = stack.get(i);
+ if (stackElement instanceof LabelNode) {
+ stackElement = clonedLabels.get(stackElement);
+ }
+ clone.stack.add(stackElement);
+ }
}
+ return clone;
+ }
- private static Object[] asArray(final List<Object> l) {
- Object[] objs = new Object[l.size()];
- for (int i = 0; i < objs.length; ++i) {
- Object o = l.get(i);
- if (o instanceof LabelNode) {
- o = ((LabelNode) o).getLabel();
- }
- objs[i] = o;
- }
- return objs;
+ private static Object[] asArray(final List<Object> list) {
+ Object[] array = new Object[list.size()];
+ for (int i = 0, n = array.length; i < n; ++i) {
+ Object o = list.get(i);
+ if (o instanceof LabelNode) {
+ o = ((LabelNode) o).getLabel();
+ }
+ array[i] = o;
}
+ return array;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
old mode 100644
new mode 100755
index 729dd3e..2b53001
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
@@ -1,83 +1,74 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A node that represents an IINC instruction.
- *
+ *
* @author Eric Bruneton
*/
public class IincInsnNode extends AbstractInsnNode {
- /**
- * Index of the local variable to be incremented.
- */
- public int var;
+ /** Index of the local variable to be incremented. */
+ public int var;
- /**
- * Amount to increment the local variable by.
- */
- public int incr;
+ /** Amount to increment the local variable by. */
+ public int incr;
- /**
- * Constructs a new {@link IincInsnNode}.
- *
- * @param var
- * index of the local variable to be incremented.
- * @param incr
- * increment amount to increment the local variable by.
- */
- public IincInsnNode(final int var, final int incr) {
- super(Opcodes.IINC);
- this.var = var;
- this.incr = incr;
- }
+ /**
+ * Constructs a new {@link IincInsnNode}.
+ *
+ * @param var index of the local variable to be incremented.
+ * @param incr increment amount to increment the local variable by.
+ */
+ public IincInsnNode(final int var, final int incr) {
+ super(Opcodes.IINC);
+ this.var = var;
+ this.incr = incr;
+ }
- @Override
- public int getType() {
- return IINC_INSN;
- }
+ @Override
+ public int getType() {
+ return IINC_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitIincInsn(var, incr);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitIincInsn(var, incr);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new IincInsnNode(var, incr).cloneAnnotations(this);
- }
-}
\ No newline at end of file
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new IincInsnNode(var, incr).cloneAnnotations(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
old mode 100644
new mode 100755
index e3eb5db..6ec3a3c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
@@ -1,101 +1,85 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
/**
* A node that represents an inner class.
- *
+ *
* @author Eric Bruneton
*/
public class InnerClassNode {
- /**
- * The internal name of an inner class (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
- */
- public String name;
+ /** The internal name of an inner class (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}). */
+ public String name;
- /**
- * The internal name of the class to which the inner class belongs (see
- * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
- */
- public String outerName;
+ /**
+ * The internal name of the class to which the inner class belongs (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}). May be {@literal null}.
+ */
+ public String outerName;
- /**
- * The (simple) name of the inner class inside its enclosing class. May be
- * <tt>null</tt> for anonymous inner classes.
- */
- public String innerName;
+ /**
+ * The (simple) name of the inner class inside its enclosing class. May be {@literal null} for
+ * anonymous inner classes.
+ */
+ public String innerName;
- /**
- * The access flags of the inner class as originally declared in the
- * enclosing class.
- */
- public int access;
+ /** The access flags of the inner class as originally declared in the enclosing class. */
+ public int access;
- /**
- * Constructs a new {@link InnerClassNode}.
- *
- * @param name
- * the internal name of an inner class (see
- * {@link org.objectweb.asm.Type#getInternalName()
- * getInternalName}).
- * @param outerName
- * the internal name of the class to which the inner class
- * belongs (see {@link org.objectweb.asm.Type#getInternalName()
- * getInternalName}). May be <tt>null</tt>.
- * @param innerName
- * the (simple) name of the inner class inside its enclosing
- * class. May be <tt>null</tt> for anonymous inner classes.
- * @param access
- * the access flags of the inner class as originally declared in
- * the enclosing class.
- */
- public InnerClassNode(final String name, final String outerName,
- final String innerName, final int access) {
- this.name = name;
- this.outerName = outerName;
- this.innerName = innerName;
- this.access = access;
- }
+ /**
+ * Constructs a new {@link InnerClassNode}.
+ *
+ * @param name the internal name of an inner class (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}).
+ * @param outerName the internal name of the class to which the inner class belongs (see {@link
+ * org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()}). May be {@literal null}.
+ * @param innerName the (simple) name of the inner class inside its enclosing class. May be
+ * {@literal null} for anonymous inner classes.
+ * @param access the access flags of the inner class as originally declared in the enclosing
+ * class.
+ */
+ public InnerClassNode(
+ final String name, final String outerName, final String innerName, final int access) {
+ this.name = name;
+ this.outerName = outerName;
+ this.innerName = innerName;
+ this.access = access;
+ }
- /**
- * Makes the given class visitor visit this inner class.
- *
- * @param cv
- * a class visitor.
- */
- public void accept(final ClassVisitor cv) {
- cv.visitInnerClass(name, outerName, innerName, access);
- }
+ /**
+ * Makes the given class visitor visit this inner class.
+ *
+ * @param classVisitor a class visitor.
+ */
+ public void accept(final ClassVisitor classVisitor) {
+ classVisitor.visitInnerClass(name, outerName, innerName, access);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
old mode 100644
new mode 100755
index f7e4925..23d4c9f
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
@@ -1,632 +1,594 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
import java.util.ListIterator;
import java.util.NoSuchElementException;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
/**
- * A doubly linked list of {@link AbstractInsnNode} objects. <i>This
- * implementation is not thread safe</i>.
+ * A doubly linked list of {@link AbstractInsnNode} objects. <i>This implementation is not thread
+ * safe</i>.
*/
public class InsnList {
- /**
- * The number of instructions in this list.
- */
- private int size;
-
- /**
- * The first instruction in this list. May be <tt>null</tt>.
- */
- private AbstractInsnNode first;
-
- /**
- * The last instruction in this list. May be <tt>null</tt>.
- */
- private AbstractInsnNode last;
-
- /**
- * A cache of the instructions of this list. This cache is used to improve
- * the performance of the {@link #get} method.
- */
- AbstractInsnNode[] cache;
-
- /**
- * Returns the number of instructions in this list.
- *
- * @return the number of instructions in this list.
- */
- public int size() {
- return size;
- }
-
- /**
- * Returns the first instruction in this list.
- *
- * @return the first instruction in this list, or <tt>null</tt> if the list
- * is empty.
- */
- public AbstractInsnNode getFirst() {
- return first;
- }
-
- /**
- * Returns the last instruction in this list.
- *
- * @return the last instruction in this list, or <tt>null</tt> if the list
- * is empty.
- */
- public AbstractInsnNode getLast() {
- return last;
- }
-
- /**
- * Returns the instruction whose index is given. This method builds a cache
- * of the instructions in this list to avoid scanning the whole list each
- * time it is called. Once the cache is built, this method run in constant
- * time. This cache is invalidated by all the methods that modify the list.
- *
- * @param index
- * the index of the instruction that must be returned.
- * @return the instruction whose index is given.
- * @throws IndexOutOfBoundsException
- * if (index < 0 || index >= size()).
- */
- public AbstractInsnNode get(final int index) {
- if (index < 0 || index >= size) {
- throw new IndexOutOfBoundsException();
- }
- if (cache == null) {
- cache = toArray();
- }
- return cache[index];
- }
-
- /**
- * Returns <tt>true</tt> if the given instruction belongs to this list. This
- * method always scans the instructions of this list until it finds the
- * given instruction or reaches the end of the list.
- *
- * @param insn
- * an instruction.
- * @return <tt>true</tt> if the given instruction belongs to this list.
- */
- public boolean contains(final AbstractInsnNode insn) {
- AbstractInsnNode i = first;
- while (i != null && i != insn) {
- i = i.next;
- }
- return i != null;
- }
-
- /**
- * Returns the index of the given instruction in this list. This method
- * builds a cache of the instruction indexes to avoid scanning the whole
- * list each time it is called. Once the cache is built, this method run in
- * constant time. The cache is invalidated by all the methods that modify
- * the list.
- *
- * @param insn
- * an instruction <i>of this list</i>.
- * @return the index of the given instruction in this list. <i>The result of
- * this method is undefined if the given instruction does not belong
- * to this list</i>. Use {@link #contains contains} to test if an
- * instruction belongs to an instruction list or not.
- */
- public int indexOf(final AbstractInsnNode insn) {
- if (cache == null) {
- cache = toArray();
- }
- return insn.index;
- }
-
- /**
- * Makes the given visitor visit all of the instructions in this list.
- *
- * @param mv
- * the method visitor that must visit the instructions.
- */
- public void accept(final MethodVisitor mv) {
- AbstractInsnNode insn = first;
- while (insn != null) {
- insn.accept(mv);
- insn = insn.next;
- }
+ /** The number of instructions in this list. */
+ private int size;
+
+ /** The first instruction in this list. May be {@literal null}. */
+ private AbstractInsnNode firstInsn;
+
+ /** The last instruction in this list. May be {@literal null}. */
+ private AbstractInsnNode lastInsn;
+
+ /**
+ * A cache of the instructions of this list. This cache is used to improve the performance of the
+ * {@link #get} method.
+ */
+ AbstractInsnNode[] cache;
+
+ /**
+ * Returns the number of instructions in this list.
+ *
+ * @return the number of instructions in this list.
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Returns the first instruction in this list.
+ *
+ * @return the first instruction in this list, or {@literal null} if the list is empty.
+ */
+ public AbstractInsnNode getFirst() {
+ return firstInsn;
+ }
+
+ /**
+ * Returns the last instruction in this list.
+ *
+ * @return the last instruction in this list, or {@literal null} if the list is empty.
+ */
+ public AbstractInsnNode getLast() {
+ return lastInsn;
+ }
+
+ /**
+ * Returns the instruction whose index is given. This method builds a cache of the instructions in
+ * this list to avoid scanning the whole list each time it is called. Once the cache is built,
+ * this method runs in constant time. This cache is invalidated by all the methods that modify the
+ * list.
+ *
+ * @param index the index of the instruction that must be returned.
+ * @return the instruction whose index is given.
+ * @throws IndexOutOfBoundsException if (index < 0 || index >= size()).
+ */
+ public AbstractInsnNode get(final int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException();
}
-
- /**
- * Returns an iterator over the instructions in this list.
- *
- * @return an iterator over the instructions in this list.
- */
- public ListIterator<AbstractInsnNode> iterator() {
- return iterator(0);
- }
-
- /**
- * Returns an iterator over the instructions in this list.
- *
- * @param index
- * index of instruction for the iterator to start at
- *
- * @return an iterator over the instructions in this list.
- */
- @SuppressWarnings("unchecked")
- public ListIterator<AbstractInsnNode> iterator(int index) {
- return new InsnListIterator(index);
- }
-
- /**
- * Returns an array containing all of the instructions in this list.
- *
- * @return an array containing all of the instructions in this list.
- */
- public AbstractInsnNode[] toArray() {
- int i = 0;
- AbstractInsnNode elem = first;
- AbstractInsnNode[] insns = new AbstractInsnNode[size];
- while (elem != null) {
- insns[i] = elem;
- elem.index = i++;
- elem = elem.next;
- }
- return insns;
- }
-
- /**
- * Replaces an instruction of this list with another instruction.
- *
- * @param location
- * an instruction <i>of this list</i>.
- * @param insn
- * another instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
- */
- public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
- AbstractInsnNode next = location.next;
- insn.next = next;
- if (next != null) {
- next.prev = insn;
- } else {
- last = insn;
- }
- AbstractInsnNode prev = location.prev;
- insn.prev = prev;
- if (prev != null) {
- prev.next = insn;
- } else {
- first = insn;
- }
- if (cache != null) {
- int index = location.index;
- cache[index] = insn;
- insn.index = index;
- } else {
- insn.index = 0; // insn now belongs to an InsnList
- }
- location.index = -1; // i no longer belongs to an InsnList
- location.prev = null;
- location.next = null;
- }
-
- /**
- * Adds the given instruction to the end of this list.
- *
- * @param insn
- * an instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
- */
- public void add(final AbstractInsnNode insn) {
- ++size;
- if (last == null) {
- first = insn;
- last = insn;
- } else {
- last.next = insn;
- insn.prev = last;
- }
- last = insn;
- cache = null;
- insn.index = 0; // insn now belongs to an InsnList
- }
-
- /**
- * Adds the given instructions to the end of this list.
- *
- * @param insns
- * an instruction list, which is cleared during the process. This
- * list must be different from 'this'.
- */
- public void add(final InsnList insns) {
- if (insns.size == 0) {
- return;
- }
- size += insns.size;
- if (last == null) {
- first = insns.first;
- last = insns.last;
- } else {
- AbstractInsnNode elem = insns.first;
- last.next = elem;
- elem.prev = last;
- last = insns.last;
- }
- cache = null;
- insns.removeAll(false);
- }
-
- /**
- * Inserts the given instruction at the begining of this list.
- *
- * @param insn
- * an instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
- */
- public void insert(final AbstractInsnNode insn) {
- ++size;
- if (first == null) {
- first = insn;
- last = insn;
- } else {
- first.prev = insn;
- insn.next = first;
- }
- first = insn;
- cache = null;
- insn.index = 0; // insn now belongs to an InsnList
- }
-
- /**
- * Inserts the given instructions at the begining of this list.
- *
- * @param insns
- * an instruction list, which is cleared during the process. This
- * list must be different from 'this'.
- */
- public void insert(final InsnList insns) {
- if (insns.size == 0) {
- return;
- }
- size += insns.size;
- if (first == null) {
- first = insns.first;
- last = insns.last;
- } else {
- AbstractInsnNode elem = insns.last;
- first.prev = elem;
- elem.next = first;
- first = insns.first;
- }
- cache = null;
- insns.removeAll(false);
- }
-
- /**
- * Inserts the given instruction after the specified instruction.
- *
- * @param location
- * an instruction <i>of this list</i> after which insn must be
- * inserted.
- * @param insn
- * the instruction to be inserted, <i>which must not belong to
- * any {@link InsnList}</i>.
- */
- public void insert(final AbstractInsnNode location,
- final AbstractInsnNode insn) {
- ++size;
- AbstractInsnNode next = location.next;
- if (next == null) {
- last = insn;
- } else {
- next.prev = insn;
- }
- location.next = insn;
- insn.next = next;
- insn.prev = location;
- cache = null;
- insn.index = 0; // insn now belongs to an InsnList
- }
-
- /**
- * Inserts the given instructions after the specified instruction.
- *
- * @param location
- * an instruction <i>of this list</i> after which the
- * instructions must be inserted.
- * @param insns
- * the instruction list to be inserted, which is cleared during
- * the process. This list must be different from 'this'.
- */
- public void insert(final AbstractInsnNode location, final InsnList insns) {
- if (insns.size == 0) {
- return;
- }
- size += insns.size;
- AbstractInsnNode ifirst = insns.first;
- AbstractInsnNode ilast = insns.last;
- AbstractInsnNode next = location.next;
- if (next == null) {
- last = ilast;
- } else {
- next.prev = ilast;
- }
- location.next = ifirst;
- ilast.next = next;
- ifirst.prev = location;
- cache = null;
- insns.removeAll(false);
- }
-
- /**
- * Inserts the given instruction before the specified instruction.
- *
- * @param location
- * an instruction <i>of this list</i> before which insn must be
- * inserted.
- * @param insn
- * the instruction to be inserted, <i>which must not belong to
- * any {@link InsnList}</i>.
- */
- public void insertBefore(final AbstractInsnNode location,
- final AbstractInsnNode insn) {
- ++size;
- AbstractInsnNode prev = location.prev;
- if (prev == null) {
- first = insn;
- } else {
- prev.next = insn;
- }
- location.prev = insn;
- insn.next = location;
- insn.prev = prev;
- cache = null;
- insn.index = 0; // insn now belongs to an InsnList
- }
-
- /**
- * Inserts the given instructions before the specified instruction.
- *
- * @param location
- * an instruction <i>of this list</i> before which the
- * instructions must be inserted.
- * @param insns
- * the instruction list to be inserted, which is cleared during
- * the process. This list must be different from 'this'.
- */
- public void insertBefore(final AbstractInsnNode location,
- final InsnList insns) {
- if (insns.size == 0) {
- return;
- }
- size += insns.size;
- AbstractInsnNode ifirst = insns.first;
- AbstractInsnNode ilast = insns.last;
- AbstractInsnNode prev = location.prev;
- if (prev == null) {
- first = ifirst;
- } else {
- prev.next = ifirst;
- }
- location.prev = ilast;
- ilast.next = location;
- ifirst.prev = prev;
- cache = null;
- insns.removeAll(false);
- }
-
- /**
- * Removes the given instruction from this list.
- *
- * @param insn
- * the instruction <i>of this list</i> that must be removed.
- */
- public void remove(final AbstractInsnNode insn) {
- --size;
- AbstractInsnNode next = insn.next;
- AbstractInsnNode prev = insn.prev;
- if (next == null) {
- if (prev == null) {
- first = null;
- last = null;
- } else {
- prev.next = null;
- last = prev;
- }
- } else {
- if (prev == null) {
- first = next;
- next.prev = null;
- } else {
- prev.next = next;
- next.prev = prev;
- }
- }
- cache = null;
- insn.index = -1; // insn no longer belongs to an InsnList
- insn.prev = null;
- insn.next = null;
- }
-
- /**
- * Removes all of the instructions of this list.
- *
- * @param mark
- * if the instructions must be marked as no longer belonging to
- * any {@link InsnList}.
- */
- void removeAll(final boolean mark) {
- if (mark) {
- AbstractInsnNode insn = first;
- while (insn != null) {
- AbstractInsnNode next = insn.next;
- insn.index = -1; // insn no longer belongs to an InsnList
- insn.prev = null;
- insn.next = null;
- insn = next;
- }
- }
- size = 0;
- first = null;
- last = null;
- cache = null;
- }
-
- /**
- * Removes all of the instructions of this list.
- */
- public void clear() {
- removeAll(false);
- }
-
- /**
- * Reset all labels in the instruction list. This method should be called
- * before reusing same instructions list between several
- * <code>ClassWriter</code>s.
- */
- public void resetLabels() {
- AbstractInsnNode insn = first;
- while (insn != null) {
- if (insn instanceof LabelNode) {
- ((LabelNode) insn).resetLabel();
- }
- insn = insn.next;
- }
+ if (cache == null) {
+ cache = toArray();
}
+ return cache[index];
+ }
+
+ /**
+ * Returns {@literal true} if the given instruction belongs to this list. This method always scans
+ * the instructions of this list until it finds the given instruction or reaches the end of the
+ * list.
+ *
+ * @param insnNode an instruction.
+ * @return {@literal true} if the given instruction belongs to this list.
+ */
+ public boolean contains(final AbstractInsnNode insnNode) {
+ AbstractInsnNode currentInsn = firstInsn;
+ while (currentInsn != null && currentInsn != insnNode) {
+ currentInsn = currentInsn.nextInsn;
+ }
+ return currentInsn != null;
+ }
+
+ /**
+ * Returns the index of the given instruction in this list. This method builds a cache of the
+ * instruction indexes to avoid scanning the whole list each time it is called. Once the cache is
+ * built, this method run in constant time. The cache is invalidated by all the methods that
+ * modify the list.
+ *
+ * @param insnNode an instruction <i>of this list</i>.
+ * @return the index of the given instruction in this list. <i>The result of this method is
+ * undefined if the given instruction does not belong to this list</i>. Use {@link #contains }
+ * to test if an instruction belongs to an instruction list or not.
+ */
+ public int indexOf(final AbstractInsnNode insnNode) {
+ if (cache == null) {
+ cache = toArray();
+ }
+ return insnNode.index;
+ }
+
+ /**
+ * Makes the given visitor visit all the instructions in this list.
+ *
+ * @param methodVisitor the method visitor that must visit the instructions.
+ */
+ public void accept(final MethodVisitor methodVisitor) {
+ AbstractInsnNode currentInsn = firstInsn;
+ while (currentInsn != null) {
+ currentInsn.accept(methodVisitor);
+ currentInsn = currentInsn.nextInsn;
+ }
+ }
+
+ /**
+ * Returns an iterator over the instructions in this list.
+ *
+ * @return an iterator over the instructions in this list.
+ */
+ public ListIterator<AbstractInsnNode> iterator() {
+ return iterator(0);
+ }
+
+ /**
+ * Returns an iterator over the instructions in this list.
+ *
+ * @param index index of instruction for the iterator to start at.
+ * @return an iterator over the instructions in this list.
+ */
+ @SuppressWarnings("unchecked")
+ public ListIterator<AbstractInsnNode> iterator(final int index) {
+ return new InsnListIterator(index);
+ }
+
+ /**
+ * Returns an array containing all the instructions in this list.
+ *
+ * @return an array containing all the instructions in this list.
+ */
+ public AbstractInsnNode[] toArray() {
+ int currentInsnIndex = 0;
+ AbstractInsnNode currentInsn = firstInsn;
+ AbstractInsnNode[] insnNodeArray = new AbstractInsnNode[size];
+ while (currentInsn != null) {
+ insnNodeArray[currentInsnIndex] = currentInsn;
+ currentInsn.index = currentInsnIndex++;
+ currentInsn = currentInsn.nextInsn;
+ }
+ return insnNodeArray;
+ }
+
+ /**
+ * Replaces an instruction of this list with another instruction.
+ *
+ * @param oldInsnNode an instruction <i>of this list</i>.
+ * @param newInsnNode another instruction, <i>which must not belong to any {@link InsnList}</i>.
+ */
+ public void set(final AbstractInsnNode oldInsnNode, final AbstractInsnNode newInsnNode) {
+ AbstractInsnNode nextInsn = oldInsnNode.nextInsn;
+ newInsnNode.nextInsn = nextInsn;
+ if (nextInsn != null) {
+ nextInsn.previousInsn = newInsnNode;
+ } else {
+ lastInsn = newInsnNode;
+ }
+ AbstractInsnNode previousInsn = oldInsnNode.previousInsn;
+ newInsnNode.previousInsn = previousInsn;
+ if (previousInsn != null) {
+ previousInsn.nextInsn = newInsnNode;
+ } else {
+ firstInsn = newInsnNode;
+ }
+ if (cache != null) {
+ int index = oldInsnNode.index;
+ cache[index] = newInsnNode;
+ newInsnNode.index = index;
+ } else {
+ newInsnNode.index = 0; // newInnsnNode now belongs to an InsnList.
+ }
+ oldInsnNode.index = -1; // oldInsnNode no longer belongs to an InsnList.
+ oldInsnNode.previousInsn = null;
+ oldInsnNode.nextInsn = null;
+ }
+
+ /**
+ * Adds the given instruction to the end of this list.
+ *
+ * @param insnNode an instruction, <i>which must not belong to any {@link InsnList}</i>.
+ */
+ public void add(final AbstractInsnNode insnNode) {
+ ++size;
+ if (lastInsn == null) {
+ firstInsn = insnNode;
+ lastInsn = insnNode;
+ } else {
+ lastInsn.nextInsn = insnNode;
+ insnNode.previousInsn = lastInsn;
+ }
+ lastInsn = insnNode;
+ cache = null;
+ insnNode.index = 0; // insnNode now belongs to an InsnList.
+ }
+
+ /**
+ * Adds the given instructions to the end of this list.
+ *
+ * @param insnList an instruction list, which is cleared during the process. This list must be
+ * different from 'this'.
+ */
+ public void add(final InsnList insnList) {
+ if (insnList.size == 0) {
+ return;
+ }
+ size += insnList.size;
+ if (lastInsn == null) {
+ firstInsn = insnList.firstInsn;
+ lastInsn = insnList.lastInsn;
+ } else {
+ AbstractInsnNode firstInsnListElement = insnList.firstInsn;
+ lastInsn.nextInsn = firstInsnListElement;
+ firstInsnListElement.previousInsn = lastInsn;
+ lastInsn = insnList.lastInsn;
+ }
+ cache = null;
+ insnList.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction at the beginning of this list.
+ *
+ * @param insnNode an instruction, <i>which must not belong to any {@link InsnList}</i>.
+ */
+ public void insert(final AbstractInsnNode insnNode) {
+ ++size;
+ if (firstInsn == null) {
+ firstInsn = insnNode;
+ lastInsn = insnNode;
+ } else {
+ firstInsn.previousInsn = insnNode;
+ insnNode.nextInsn = firstInsn;
+ }
+ firstInsn = insnNode;
+ cache = null;
+ insnNode.index = 0; // insnNode now belongs to an InsnList.
+ }
+
+ /**
+ * Inserts the given instructions at the beginning of this list.
+ *
+ * @param insnList an instruction list, which is cleared during the process. This list must be
+ * different from 'this'.
+ */
+ public void insert(final InsnList insnList) {
+ if (insnList.size == 0) {
+ return;
+ }
+ size += insnList.size;
+ if (firstInsn == null) {
+ firstInsn = insnList.firstInsn;
+ lastInsn = insnList.lastInsn;
+ } else {
+ AbstractInsnNode lastInsnListElement = insnList.lastInsn;
+ firstInsn.previousInsn = lastInsnListElement;
+ lastInsnListElement.nextInsn = firstInsn;
+ firstInsn = insnList.firstInsn;
+ }
+ cache = null;
+ insnList.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction after the specified instruction.
+ *
+ * @param previousInsn an instruction <i>of this list</i> after which insnNode must be inserted.
+ * @param insnNode the instruction to be inserted, <i>which must not belong to any {@link
+ * InsnList}</i>.
+ */
+ public void insert(final AbstractInsnNode previousInsn, final AbstractInsnNode insnNode) {
+ ++size;
+ AbstractInsnNode nextInsn = previousInsn.nextInsn;
+ if (nextInsn == null) {
+ lastInsn = insnNode;
+ } else {
+ nextInsn.previousInsn = insnNode;
+ }
+ previousInsn.nextInsn = insnNode;
+ insnNode.nextInsn = nextInsn;
+ insnNode.previousInsn = previousInsn;
+ cache = null;
+ insnNode.index = 0; // insnNode now belongs to an InsnList.
+ }
+
+ /**
+ * Inserts the given instructions after the specified instruction.
+ *
+ * @param previousInsn an instruction <i>of this list</i> after which the instructions must be
+ * inserted.
+ * @param insnList the instruction list to be inserted, which is cleared during the process. This
+ * list must be different from 'this'.
+ */
+ public void insert(final AbstractInsnNode previousInsn, final InsnList insnList) {
+ if (insnList.size == 0) {
+ return;
+ }
+ size += insnList.size;
+ AbstractInsnNode firstInsnListElement = insnList.firstInsn;
+ AbstractInsnNode lastInsnListElement = insnList.lastInsn;
+ AbstractInsnNode nextInsn = previousInsn.nextInsn;
+ if (nextInsn == null) {
+ lastInsn = lastInsnListElement;
+ } else {
+ nextInsn.previousInsn = lastInsnListElement;
+ }
+ previousInsn.nextInsn = firstInsnListElement;
+ lastInsnListElement.nextInsn = nextInsn;
+ firstInsnListElement.previousInsn = previousInsn;
+ cache = null;
+ insnList.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction before the specified instruction.
+ *
+ * @param nextInsn an instruction <i>of this list</i> before which insnNode must be inserted.
+ * @param insnNode the instruction to be inserted, <i>which must not belong to any {@link
+ * InsnList}</i>.
+ */
+ public void insertBefore(final AbstractInsnNode nextInsn, final AbstractInsnNode insnNode) {
+ ++size;
+ AbstractInsnNode previousInsn = nextInsn.previousInsn;
+ if (previousInsn == null) {
+ firstInsn = insnNode;
+ } else {
+ previousInsn.nextInsn = insnNode;
+ }
+ nextInsn.previousInsn = insnNode;
+ insnNode.nextInsn = nextInsn;
+ insnNode.previousInsn = previousInsn;
+ cache = null;
+ insnNode.index = 0; // insnNode now belongs to an InsnList.
+ }
+
+ /**
+ * Inserts the given instructions before the specified instruction.
+ *
+ * @param nextInsn an instruction <i>of this list</i> before which the instructions must be
+ * inserted.
+ * @param insnList the instruction list to be inserted, which is cleared during the process. This
+ * list must be different from 'this'.
+ */
+ public void insertBefore(final AbstractInsnNode nextInsn, final InsnList insnList) {
+ if (insnList.size == 0) {
+ return;
+ }
+ size += insnList.size;
+ AbstractInsnNode firstInsnListElement = insnList.firstInsn;
+ AbstractInsnNode lastInsnListElement = insnList.lastInsn;
+ AbstractInsnNode previousInsn = nextInsn.previousInsn;
+ if (previousInsn == null) {
+ firstInsn = firstInsnListElement;
+ } else {
+ previousInsn.nextInsn = firstInsnListElement;
+ }
+ nextInsn.previousInsn = lastInsnListElement;
+ lastInsnListElement.nextInsn = nextInsn;
+ firstInsnListElement.previousInsn = previousInsn;
+ cache = null;
+ insnList.removeAll(false);
+ }
+
+ /**
+ * Removes the given instruction from this list.
+ *
+ * @param insnNode the instruction <i>of this list</i> that must be removed.
+ */
+ public void remove(final AbstractInsnNode insnNode) {
+ --size;
+ AbstractInsnNode nextInsn = insnNode.nextInsn;
+ AbstractInsnNode previousInsn = insnNode.previousInsn;
+ if (nextInsn == null) {
+ if (previousInsn == null) {
+ firstInsn = null;
+ lastInsn = null;
+ } else {
+ previousInsn.nextInsn = null;
+ lastInsn = previousInsn;
+ }
+ } else {
+ if (previousInsn == null) {
+ firstInsn = nextInsn;
+ nextInsn.previousInsn = null;
+ } else {
+ previousInsn.nextInsn = nextInsn;
+ nextInsn.previousInsn = previousInsn;
+ }
+ }
+ cache = null;
+ insnNode.index = -1; // insnNode no longer belongs to an InsnList.
+ insnNode.previousInsn = null;
+ insnNode.nextInsn = null;
+ }
+
+ /**
+ * Removes all the instructions of this list.
+ *
+ * @param mark if the instructions must be marked as no longer belonging to any {@link InsnList}.
+ */
+ void removeAll(final boolean mark) {
+ if (mark) {
+ AbstractInsnNode currentInsn = firstInsn;
+ while (currentInsn != null) {
+ AbstractInsnNode next = currentInsn.nextInsn;
+ currentInsn.index = -1; // currentInsn no longer belongs to an InsnList.
+ currentInsn.previousInsn = null;
+ currentInsn.nextInsn = null;
+ currentInsn = next;
+ }
+ }
+ size = 0;
+ firstInsn = null;
+ lastInsn = null;
+ cache = null;
+ }
+
+ /** Removes all the instructions of this list. */
+ public void clear() {
+ removeAll(false);
+ }
+
+ /**
+ * Resets all the labels in the instruction list. This method should be called before reusing an
+ * instruction list between several <code>ClassWriter</code>s.
+ */
+ public void resetLabels() {
+ AbstractInsnNode currentInsn = firstInsn;
+ while (currentInsn != null) {
+ if (currentInsn instanceof LabelNode) {
+ ((LabelNode) currentInsn).resetLabel();
+ }
+ currentInsn = currentInsn.nextInsn;
+ }
+ }
- // this class is not generified because it will create bridges
- @SuppressWarnings("rawtypes")
- private final class InsnListIterator implements ListIterator {
+ // Note: this class is not generified because it would create bridges.
+ @SuppressWarnings("rawtypes")
+ private final class InsnListIterator implements ListIterator {
- AbstractInsnNode next;
+ AbstractInsnNode nextInsn;
- AbstractInsnNode prev;
+ AbstractInsnNode previousInsn;
- AbstractInsnNode remove;
+ AbstractInsnNode remove;
- InsnListIterator(int index) {
- if (index == size()) {
- next = null;
- prev = getLast();
- } else {
- next = get(index);
- prev = next.prev;
- }
- }
+ InsnListIterator(final int index) {
+ if (index == size()) {
+ nextInsn = null;
+ previousInsn = getLast();
+ } else {
+ nextInsn = get(index);
+ previousInsn = nextInsn.previousInsn;
+ }
+ }
- public boolean hasNext() {
- return next != null;
- }
+ @Override
+ public boolean hasNext() {
+ return nextInsn != null;
+ }
- public Object next() {
- if (next == null) {
- throw new NoSuchElementException();
- }
- AbstractInsnNode result = next;
- prev = result;
- next = result.next;
- remove = result;
- return result;
- }
+ @Override
+ public Object next() {
+ if (nextInsn == null) {
+ throw new NoSuchElementException();
+ }
+ AbstractInsnNode result = nextInsn;
+ previousInsn = result;
+ nextInsn = result.nextInsn;
+ remove = result;
+ return result;
+ }
- public void remove() {
- if (remove != null) {
- if (remove == next) {
- next = next.next;
- } else {
- prev = prev.prev;
- }
- InsnList.this.remove(remove);
- remove = null;
- } else {
- throw new IllegalStateException();
- }
+ @Override
+ public void remove() {
+ if (remove != null) {
+ if (remove == nextInsn) {
+ nextInsn = nextInsn.nextInsn;
+ } else {
+ previousInsn = previousInsn.previousInsn;
}
+ InsnList.this.remove(remove);
+ remove = null;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
- public boolean hasPrevious() {
- return prev != null;
- }
+ @Override
+ public boolean hasPrevious() {
+ return previousInsn != null;
+ }
- public Object previous() {
- AbstractInsnNode result = prev;
- next = result;
- prev = result.prev;
- remove = result;
- return result;
- }
+ @Override
+ public Object previous() {
+ AbstractInsnNode result = previousInsn;
+ nextInsn = result;
+ previousInsn = result.previousInsn;
+ remove = result;
+ return result;
+ }
- public int nextIndex() {
- if (next == null) {
- return size();
- }
- if (cache == null) {
- cache = toArray();
- }
- return next.index;
- }
+ @Override
+ public int nextIndex() {
+ if (nextInsn == null) {
+ return size();
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return nextInsn.index;
+ }
- public int previousIndex() {
- if (prev == null) {
- return -1;
- }
- if (cache == null) {
- cache = toArray();
- }
- return prev.index;
- }
+ @Override
+ public int previousIndex() {
+ if (previousInsn == null) {
+ return -1;
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return previousInsn.index;
+ }
- public void add(Object o) {
- if (next != null) {
- InsnList.this.insertBefore(next, (AbstractInsnNode) o);
- } else if (prev != null) {
- InsnList.this.insert(prev, (AbstractInsnNode) o);
- } else {
- InsnList.this.add((AbstractInsnNode) o);
- }
- prev = (AbstractInsnNode) o;
- remove = null;
- }
+ @Override
+ public void add(final Object o) {
+ if (nextInsn != null) {
+ InsnList.this.insertBefore(nextInsn, (AbstractInsnNode) o);
+ } else if (previousInsn != null) {
+ InsnList.this.insert(previousInsn, (AbstractInsnNode) o);
+ } else {
+ InsnList.this.add((AbstractInsnNode) o);
+ }
+ previousInsn = (AbstractInsnNode) o;
+ remove = null;
+ }
- public void set(Object o) {
- if (remove != null) {
- InsnList.this.set(remove, (AbstractInsnNode) o);
- if (remove == prev) {
- prev = (AbstractInsnNode) o;
- } else {
- next = (AbstractInsnNode) o;
- }
- } else {
- throw new IllegalStateException();
- }
+ @Override
+ public void set(final Object o) {
+ if (remove != null) {
+ InsnList.this.set(remove, (AbstractInsnNode) o);
+ if (remove == previousInsn) {
+ previousInsn = (AbstractInsnNode) o;
+ } else {
+ nextInsn = (AbstractInsnNode) o;
}
+ } else {
+ throw new IllegalStateException();
+ }
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
old mode 100644
new mode 100755
index 7eb2359..2e0ea1b
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
@@ -1,88 +1,73 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents a zero operand instruction.
- *
+ *
* @author Eric Bruneton
*/
public class InsnNode extends AbstractInsnNode {
- /**
- * Constructs a new {@link InsnNode}.
- *
- * @param opcode
- * the opcode of the instruction to be constructed. This opcode
- * must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
- * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
- * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
- * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
- * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
- * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
- * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
- * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
- * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
- * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
- * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
- * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
- * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
- * or MONITOREXIT.
- */
- public InsnNode(final int opcode) {
- super(opcode);
- }
+ /**
+ * Constructs a new {@link InsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed. This opcode must be NOP,
+ * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5,
+ * LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,
+ * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE, DASTORE,
+ * AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2,
+ * SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
+ * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR,
+ * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I,
+ * D2L, D2F, I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+ * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, or MONITOREXIT.
+ */
+ public InsnNode(final int opcode) {
+ super(opcode);
+ }
- @Override
- public int getType() {
- return INSN;
- }
+ @Override
+ public int getType() {
+ return INSN;
+ }
- /**
- * Makes the given visitor visit this instruction.
- *
- * @param mv
- * a method visitor.
- */
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitInsn(opcode);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitInsn(opcode);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new InsnNode(opcode).cloneAnnotations(this);
- }
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new InsnNode(opcode).cloneAnnotations(this);
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
old mode 100644
new mode 100755
index 5b0c351..e0b091c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
@@ -1,88 +1,79 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.tree;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents an instruction with a single int operand.
- *
+ *
* @author Eric Bruneton
*/
public class IntInsnNode extends AbstractInsnNode {
- /**
- * The operand of this instruction.
- */
- public int operand;
+ /** The operand of this instruction. */
+ public int operand;
- /**
- * Constructs a new {@link IntInsnNode}.
- *
- * @param opcode
- * the opcode of the instruction to be constructed. This opcode
- * must be BIPUSH, SIPUSH or NEWARRAY.
- * @param operand
- * the operand of the instruction to be constructed.
- */
- public IntInsnNode(final int opcode, final int operand) {
- super(opcode);
- this.operand = operand;
- }
+ /**
+ * Constructs a new {@link IntInsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed. This opcode must be BIPUSH,
+ * SIPUSH or NEWARRAY.
+ * @param operand the operand of the instruction to be constructed.
+ */
+ public IntInsnNode(final int opcode, final int operand) {
+ super(opcode);
+ this.operand = operand;
+ }
- /**
- * Sets the opcode of this instruction.
- *
- * @param opcode
- * the new instruction opcode. This opcode must be BIPUSH, SIPUSH
- * or NEWARRAY.
- */
- public void setOpcode(final int opcode) {
- this.opcode = opcode;
- }
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be BIPUSH, SIPUSH or NEWARRAY.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
- @Override
- public int getType() {
- return INT_INSN;
- }
+ @Override
+ public int getType() {
+ return INT_INSN;
+ }
- @Override
- public void accept(final MethodVisitor mv) {
- mv.visitIntInsn(opcode, operand);
- acceptAnnotations(mv);
- }
+ @Override
+ public void accept(final MethodVisitor methodVisitor) {
+ methodVisitor.visitIntInsn(opcode, operand);
+ acceptAnnotations(methodVisitor);
+ }
- @Override
- public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new IntInsnNode(opcode, operand).cloneAnnotations(this);
- }
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
+ return new IntInsnNode(opcode, operand).cloneAnnotations(this);
+ }
}
[04/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
old mode 100644
new mode 100755
index dbccd3c..e991756
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
@@ -1,89 +1,93 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * An {@link AnnotationVisitor} that prints the annotations it visits with a
- * {@link Printer}.
- *
+ * An {@link AnnotationVisitor} that prints the annotations it visits with a {@link Printer}.
+ *
* @author Eric Bruneton
*/
public final class TraceAnnotationVisitor extends AnnotationVisitor {
- private final Printer p;
+ /** The printer to convert the visited annotation into text. */
+ private final Printer printer;
- public TraceAnnotationVisitor(final Printer p) {
- this(null, p);
- }
+ /**
+ * Constructs a new {@link TraceAnnotationVisitor}.
+ *
+ * @param printer the printer to convert the visited annotation into text.
+ */
+ public TraceAnnotationVisitor(final Printer printer) {
+ this(null, printer);
+ }
- public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) {
- super(Opcodes.ASM6, av);
- this.p = p;
- }
+ /**
+ * Constructs a new {@link TraceAnnotationVisitor}.
+ *
+ * @param annotationVisitor the annotation visitor to which to delegate calls. May be {@literal
+ * null}.
+ * @param printer the printer to convert the visited annotation into text.
+ */
+ public TraceAnnotationVisitor(final AnnotationVisitor annotationVisitor, final Printer printer) {
+ super(Opcodes.ASM7, annotationVisitor);
+ this.printer = printer;
+ }
- @Override
- public void visit(final String name, final Object value) {
- p.visit(name, value);
- super.visit(name, value);
- }
+ @Override
+ public void visit(final String name, final Object value) {
+ printer.visit(name, value);
+ super.visit(name, value);
+ }
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- p.visitEnum(name, desc, value);
- super.visitEnum(name, desc, value);
- }
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ printer.visitEnum(name, descriptor, value);
+ super.visitEnum(name, descriptor, value);
+ }
- @Override
- public AnnotationVisitor visitAnnotation(final String name,
- final String desc) {
- Printer p = this.p.visitAnnotation(name, desc);
- AnnotationVisitor av = this.av == null ? null : this.av
- .visitAnnotation(name, desc);
- return new TraceAnnotationVisitor(av, p);
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ Printer annotationPrinter = printer.visitAnnotation(name, descriptor);
+ return new TraceAnnotationVisitor(super.visitAnnotation(name, descriptor), annotationPrinter);
+ }
- @Override
- public AnnotationVisitor visitArray(final String name) {
- Printer p = this.p.visitArray(name);
- AnnotationVisitor av = this.av == null ? null : this.av
- .visitArray(name);
- return new TraceAnnotationVisitor(av, p);
- }
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ Printer arrayPrinter = printer.visitArray(name);
+ return new TraceAnnotationVisitor(super.visitArray(name), arrayPrinter);
+ }
- @Override
- public void visitEnd() {
- p.visitAnnotationEnd();
- super.visitEnd();
- }
+ @Override
+ public void visitEnd() {
+ printer.visitAnnotationEnd();
+ super.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
old mode 100644
new mode 100755
index 95435fe..4dc095a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
@@ -1,36 +1,33 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import java.io.PrintWriter;
-
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
@@ -41,189 +38,192 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link ClassVisitor} that prints the classes it visits with a
- * {@link Printer}. This class visitor can be used in the middle of a class
- * visitor chain to trace the class that is visited at a given point in this
- * chain. This may be useful for debugging purposes.
- * <p>
- * The trace printed when visiting the <tt>Hello</tt> class is the following:
- * <p>
- * <blockquote>
- *
+ * A {@link ClassVisitor} that prints the classes it visits with a {@link Printer}. This class
+ * visitor can be used in the middle of a class visitor chain to trace the class that is visited at
+ * a given point in this chain. This may be useful for debugging purposes.
+ *
+ * <p>When used with a {@link Textifier}, the trace printed when visiting the {@code Hello} class is
+ * the following:
+ *
* <pre>
* // class version 49.0 (49) // access flags 0x21 public class Hello {
- *
+ *
* // compiled from: Hello.java
- *
- * // access flags 0x1 public <init> ()V ALOAD 0 INVOKESPECIAL
- * java/lang/Object <init> ()V RETURN MAXSTACK = 1 MAXLOCALS = 1
- *
- * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
- * java/lang/System out Ljava/io/PrintStream; LDC "hello"
- * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
- * MAXSTACK = 2 MAXLOCALS = 1 }
+ *
+ * // access flags 0x1
+ * public <init> ()V
+ * ALOAD 0
+ * INVOKESPECIAL java/lang/Object <init> ()V
+ * RETURN
+ * MAXSTACK = 1 MAXLOCALS = 1
+ *
+ * // access flags 0x9
+ * public static main ([Ljava/lang/String;)V
+ * GETSTATIC java/lang/System out Ljava/io/PrintStream;
+ * LDC "hello"
+ * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V
+ * RETURN
+ * MAXSTACK = 2 MAXLOCALS = 1
+ * }
* </pre>
- *
- * </blockquote> where <tt>Hello</tt> is defined by:
- * <p>
- * <blockquote>
- *
+ *
+ * <p>where {@code Hello} is defined by:
+ *
* <pre>
* public class Hello {
- *
- * public static void main(String[] args) {
- * System.out.println("hello");
- * }
+ *
+ * public static void main(String[] args) {
+ * System.out.println("hello");
+ * }
* }
* </pre>
- *
- * </blockquote>
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
public final class TraceClassVisitor extends ClassVisitor {
- /**
- * The print writer to be used to print the class. May be null.
- */
- private final PrintWriter pw;
-
- /**
- * The object that actually converts visit events into text.
- */
- public final Printer p;
-
- /**
- * Constructs a new {@link TraceClassVisitor}.
- *
- * @param pw
- * the print writer to be used to print the class.
- */
- public TraceClassVisitor(final PrintWriter pw) {
- this(null, pw);
- }
-
- /**
- * Constructs a new {@link TraceClassVisitor}.
- *
- * @param cv
- * the {@link ClassVisitor} to which this visitor delegates
- * calls. May be <tt>null</tt>.
- * @param pw
- * the print writer to be used to print the class.
- */
- public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
- this(cv, new Textifier(), pw);
- }
-
- /**
- * Constructs a new {@link TraceClassVisitor}.
- *
- * @param cv
- * the {@link ClassVisitor} to which this visitor delegates
- * calls. May be <tt>null</tt>.
- * @param p
- * the object that actually converts visit events into text.
- * @param pw
- * the print writer to be used to print the class. May be null if
- * you simply want to use the result via
- * {@link Printer#getText()}, instead of printing it.
- */
- public TraceClassVisitor(final ClassVisitor cv, final Printer p,
- final PrintWriter pw) {
- super(Opcodes.ASM6, cv);
- this.pw = pw;
- this.p = p;
- }
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- p.visit(version, access, name, signature, superName, interfaces);
- super.visit(version, access, name, signature, superName, interfaces);
- }
-
- @Override
- public void visitSource(final String file, final String debug) {
- p.visitSource(file, debug);
- super.visitSource(file, debug);
- }
-
- @Override
- public ModuleVisitor visitModule(String name, int flags,
- String version) {
- Printer p = this.p.visitModule(name, flags, version);
- ModuleVisitor mv = super.visitModule(name, flags, version);
- return new TraceModuleVisitor(mv, p);
- }
-
- @Override
- public void visitOuterClass(final String owner, final String name,
- final String desc) {
- p.visitOuterClass(owner, name, desc);
- super.visitOuterClass(owner, name, desc);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- Printer p = this.p.visitClassAnnotation(desc, visible);
- AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc,
- visible);
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- Printer p = this.p.visitClassTypeAnnotation(typeRef, typePath, desc,
- visible);
- AnnotationVisitor av = cv == null ? null : cv.visitTypeAnnotation(
- typeRef, typePath, desc, visible);
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public void visitAttribute(final Attribute attr) {
- p.visitClassAttribute(attr);
- super.visitAttribute(attr);
- }
-
- @Override
- public void visitInnerClass(final String name, final String outerName,
- final String innerName, final int access) {
- p.visitInnerClass(name, outerName, innerName, access);
- super.visitInnerClass(name, outerName, innerName, access);
- }
-
- @Override
- public FieldVisitor visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- Printer p = this.p.visitField(access, name, desc, signature, value);
- FieldVisitor fv = cv == null ? null : cv.visitField(access, name, desc,
- signature, value);
- return new TraceFieldVisitor(fv, p);
- }
-
- @Override
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- Printer p = this.p.visitMethod(access, name, desc, signature,
- exceptions);
- MethodVisitor mv = cv == null ? null : cv.visitMethod(access, name,
- desc, signature, exceptions);
- return new TraceMethodVisitor(mv, p);
- }
-
- @Override
- public void visitEnd() {
- p.visitClassEnd();
- if (pw != null) {
- p.print(pw);
- pw.flush();
- }
- super.visitEnd();
+ /** The print writer to be used to print the class. May be {@literal null}. */
+ private final PrintWriter printWriter;
+
+ /** The printer to convert the visited class into text. */
+ // DontCheck(MemberName): can't be renamed (for backward binary compatibility).
+ public final Printer p;
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param printWriter the print writer to be used to print the class. May be {@literal null}.
+ */
+ public TraceClassVisitor(final PrintWriter printWriter) {
+ this(null, printWriter);
+ }
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param classVisitor the class visitor to which to delegate calls. May be {@literal null}.
+ * @param printWriter the print writer to be used to print the class. May be {@literal null}.
+ */
+ public TraceClassVisitor(final ClassVisitor classVisitor, final PrintWriter printWriter) {
+ this(classVisitor, new Textifier(), printWriter);
+ }
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param classVisitor the class visitor to which to delegate calls. May be {@literal null}.
+ * @param printer the printer to convert the visited class into text.
+ * @param printWriter the print writer to be used to print the class. May be {@literal null}.
+ */
+ public TraceClassVisitor(
+ final ClassVisitor classVisitor, final Printer printer, final PrintWriter printWriter) {
+ super(Opcodes.ASM7, classVisitor);
+ this.printWriter = printWriter;
+ this.p = printer;
+ }
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ p.visit(version, access, name, signature, superName, interfaces);
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ p.visitSource(file, debug);
+ super.visitSource(file, debug);
+ }
+
+ @Override
+ public ModuleVisitor visitModule(final String name, final int flags, final String version) {
+ Printer modulePrinter = p.visitModule(name, flags, version);
+ return new TraceModuleVisitor(super.visitModule(name, flags, version), modulePrinter);
+ }
+
+ @Override
+ public void visitNestHost(final String nestHost) {
+ p.visitNestHost(nestHost);
+ super.visitNestHost(nestHost);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ p.visitOuterClass(owner, name, descriptor);
+ super.visitOuterClass(owner, name, descriptor);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitClassAnnotation(descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitAnnotation(descriptor, visible), annotationPrinter);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitClassTypeAnnotation(typeRef, typePath, descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ p.visitClassAttribute(attribute);
+ super.visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitNestMember(final String nestMember) {
+ p.visitNestMember(nestMember);
+ super.visitNestMember(nestMember);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ p.visitInnerClass(name, outerName, innerName, access);
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ Printer fieldPrinter = p.visitField(access, name, descriptor, signature, value);
+ return new TraceFieldVisitor(
+ super.visitField(access, name, descriptor, signature, value), fieldPrinter);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ Printer methodPrinter = p.visitMethod(access, name, descriptor, signature, exceptions);
+ return new TraceMethodVisitor(
+ super.visitMethod(access, name, descriptor, signature, exceptions), methodPrinter);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitClassEnd();
+ if (printWriter != null) {
+ p.print(printWriter);
+ printWriter.flush();
}
+ super.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
old mode 100644
new mode 100755
index 29b60b2..c01176c
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
@@ -36,52 +34,60 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link FieldVisitor} that prints the fields it visits with a
- * {@link Printer}.
- *
+ * A {@link FieldVisitor} that prints the fields it visits with a {@link Printer}.
+ *
* @author Eric Bruneton
*/
public final class TraceFieldVisitor extends FieldVisitor {
- public final Printer p;
+ /** The printer to convert the visited field into text. */
+ // DontCheck(MemberName): can't be renamed (for backward binary compatibility).
+ public final Printer p;
- public TraceFieldVisitor(final Printer p) {
- this(null, p);
- }
+ /**
+ * Constructs a new {@link TraceFieldVisitor}.
+ *
+ * @param printer the printer to convert the visited field into text.
+ */
+ public TraceFieldVisitor(final Printer printer) {
+ this(null, printer);
+ }
- public TraceFieldVisitor(final FieldVisitor fv, final Printer p) {
- super(Opcodes.ASM6, fv);
- this.p = p;
- }
+ /**
+ * Constructs a new {@link TraceFieldVisitor}.
+ *
+ * @param fieldVisitor the field visitor to which to delegate calls. May be {@literal null}.
+ * @param printer the printer to convert the visited field into text.
+ */
+ public TraceFieldVisitor(final FieldVisitor fieldVisitor, final Printer printer) {
+ super(Opcodes.ASM7, fieldVisitor);
+ this.p = printer;
+ }
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- Printer p = this.p.visitFieldAnnotation(desc, visible);
- AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc,
- visible);
- return new TraceAnnotationVisitor(av, p);
- }
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitFieldAnnotation(descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitAnnotation(descriptor, visible), annotationPrinter);
+ }
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- Printer p = this.p.visitFieldTypeAnnotation(typeRef, typePath, desc,
- visible);
- AnnotationVisitor av = fv == null ? null : fv.visitTypeAnnotation(
- typeRef, typePath, desc, visible);
- return new TraceAnnotationVisitor(av, p);
- }
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitFieldTypeAnnotation(typeRef, typePath, descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter);
+ }
- @Override
- public void visitAttribute(final Attribute attr) {
- p.visitFieldAttribute(attr);
- super.visitAttribute(attr);
- }
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ p.visitFieldAttribute(attribute);
+ super.visitAttribute(attribute);
+ }
- @Override
- public void visitEnd() {
- p.visitFieldEnd();
- super.visitEnd();
- }
+ @Override
+ public void visitEnd() {
+ p.visitFieldEnd();
+ super.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
old mode 100644
new mode 100755
index 053ff33..b152c48
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
@@ -1,32 +1,30 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
@@ -38,255 +36,287 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link MethodVisitor} that prints the methods it visits with a
- * {@link Printer}.
- *
+ * A {@link MethodVisitor} that prints the methods it visits with a {@link Printer}.
+ *
* @author Eric Bruneton
*/
public final class TraceMethodVisitor extends MethodVisitor {
- public final Printer p;
-
- public TraceMethodVisitor(final Printer p) {
- this(null, p);
- }
-
- public TraceMethodVisitor(final MethodVisitor mv, final Printer p) {
- super(Opcodes.ASM6, mv);
- this.p = p;
- }
-
- @Override
- public void visitParameter(String name, int access) {
- p.visitParameter(name, access);
- super.visitParameter(name, access);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc,
- final boolean visible) {
- Printer p = this.p.visitMethodAnnotation(desc, visible);
- AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc,
- visible);
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- Printer p = this.p.visitMethodTypeAnnotation(typeRef, typePath, desc,
- visible);
- AnnotationVisitor av = mv == null ? null : mv.visitTypeAnnotation(
- typeRef, typePath, desc, visible);
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public void visitAttribute(final Attribute attr) {
- p.visitMethodAttribute(attr);
- super.visitAttribute(attr);
- }
-
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- Printer p = this.p.visitAnnotationDefault();
- AnnotationVisitor av = mv == null ? null : mv.visitAnnotationDefault();
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- Printer p = this.p.visitParameterAnnotation(parameter, desc, visible);
- AnnotationVisitor av = mv == null ? null : mv.visitParameterAnnotation(
- parameter, desc, visible);
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public void visitCode() {
- p.visitCode();
- super.visitCode();
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- p.visitFrame(type, nLocal, local, nStack, stack);
- super.visitFrame(type, nLocal, local, nStack, stack);
- }
-
- @Override
- public void visitInsn(final int opcode) {
- p.visitInsn(opcode);
- super.visitInsn(opcode);
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- p.visitIntInsn(opcode, operand);
- super.visitIntInsn(opcode, operand);
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- p.visitVarInsn(opcode, var);
- super.visitVarInsn(opcode, var);
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- p.visitTypeInsn(opcode, type);
- super.visitTypeInsn(opcode, type);
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- p.visitFieldInsn(opcode, owner, name, desc);
- super.visitFieldInsn(opcode, owner, name, desc);
- }
-
- @Deprecated
- @Override
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- p.visitMethodInsn(opcode, owner, name, desc);
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc);
- }
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc, boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- p.visitMethodInsn(opcode, owner, name, desc, itf);
- if (mv != null) {
- mv.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- p.visitJumpInsn(opcode, label);
- super.visitJumpInsn(opcode, label);
- }
-
- @Override
- public void visitLabel(final Label label) {
- p.visitLabel(label);
- super.visitLabel(label);
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- p.visitLdcInsn(cst);
- super.visitLdcInsn(cst);
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- p.visitIincInsn(var, increment);
- super.visitIincInsn(var, increment);
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- p.visitTableSwitchInsn(min, max, dflt, labels);
- super.visitTableSwitchInsn(min, max, dflt, labels);
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- p.visitLookupSwitchInsn(dflt, keys, labels);
- super.visitLookupSwitchInsn(dflt, keys, labels);
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- p.visitMultiANewArrayInsn(desc, dims);
- super.visitMultiANewArrayInsn(desc, dims);
- }
-
- @Override
- public AnnotationVisitor visitInsnAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- Printer p = this.p
- .visitInsnAnnotation(typeRef, typePath, desc, visible);
- AnnotationVisitor av = mv == null ? null : mv.visitInsnAnnotation(
- typeRef, typePath, desc, visible);
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public void visitTryCatchBlock(final Label start, final Label end,
- final Label handler, final String type) {
- p.visitTryCatchBlock(start, end, handler, type);
- super.visitTryCatchBlock(start, end, handler, type);
- }
-
- @Override
- public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
- TypePath typePath, String desc, boolean visible) {
- Printer p = this.p.visitTryCatchAnnotation(typeRef, typePath, desc,
- visible);
- AnnotationVisitor av = mv == null ? null : mv.visitTryCatchAnnotation(
- typeRef, typePath, desc, visible);
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- p.visitLocalVariable(name, desc, signature, start, end, index);
- super.visitLocalVariable(name, desc, signature, start, end, index);
- }
-
- @Override
- public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
- TypePath typePath, Label[] start, Label[] end, int[] index,
- String desc, boolean visible) {
- Printer p = this.p.visitLocalVariableAnnotation(typeRef, typePath,
- start, end, index, desc, visible);
- AnnotationVisitor av = mv == null ? null : mv
- .visitLocalVariableAnnotation(typeRef, typePath, start, end,
- index, desc, visible);
- return new TraceAnnotationVisitor(av, p);
- }
-
- @Override
- public void visitLineNumber(final int line, final Label start) {
- p.visitLineNumber(line, start);
- super.visitLineNumber(line, start);
- }
-
- @Override
- public void visitMaxs(final int maxStack, final int maxLocals) {
- p.visitMaxs(maxStack, maxLocals);
- super.visitMaxs(maxStack, maxLocals);
- }
-
- @Override
- public void visitEnd() {
- p.visitMethodEnd();
- super.visitEnd();
- }
+ /** The printer to convert the visited method into text. */
+ // DontCheck(MemberName): can't be renamed (for backward binary compatibility).
+ public final Printer p;
+
+ /**
+ * Constructs a new {@link TraceMethodVisitor}.
+ *
+ * @param printer the printer to convert the visited method into text.
+ */
+ public TraceMethodVisitor(final Printer printer) {
+ this(null, printer);
+ }
+
+ /**
+ * Constructs a new {@link TraceMethodVisitor}.
+ *
+ * @param methodVisitor the method visitor to which to delegate calls. May be {@literal null}.
+ * @param printer the printer to convert the visited method into text.
+ */
+ public TraceMethodVisitor(final MethodVisitor methodVisitor, final Printer printer) {
+ super(Opcodes.ASM7, methodVisitor);
+ this.p = printer;
+ }
+
+ @Override
+ public void visitParameter(final String name, final int access) {
+ p.visitParameter(name, access);
+ super.visitParameter(name, access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitMethodAnnotation(descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitAnnotation(descriptor, visible), annotationPrinter);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitMethodTypeAnnotation(typeRef, typePath, descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attribute) {
+ p.visitMethodAttribute(attribute);
+ super.visitAttribute(attribute);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ Printer annotationPrinter = p.visitAnnotationDefault();
+ return new TraceAnnotationVisitor(super.visitAnnotationDefault(), annotationPrinter);
+ }
+
+ @Override
+ public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ p.visitAnnotableParameterCount(parameterCount, visible);
+ super.visitAnnotableParameterCount(parameterCount, visible);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitParameterAnnotation(parameter, descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitParameterAnnotation(parameter, descriptor, visible), annotationPrinter);
+ }
+
+ @Override
+ public void visitCode() {
+ p.visitCode();
+ super.visitCode();
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ p.visitFrame(type, numLocal, local, numStack, stack);
+ super.visitFrame(type, numLocal, local, numStack, stack);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ p.visitInsn(opcode);
+ super.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ p.visitIntInsn(opcode, operand);
+ super.visitIntInsn(opcode, operand);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ p.visitVarInsn(opcode, var);
+ super.visitVarInsn(opcode, var);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ p.visitTypeInsn(opcode, type);
+ super.visitTypeInsn(opcode, type);
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ p.visitFieldInsn(opcode, owner, name, descriptor);
+ super.visitFieldInsn(opcode, owner, name, descriptor);
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
+ }
+ p.visitMethodInsn(opcode, owner, name, descriptor);
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, descriptor);
+ }
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
+ }
+ p.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ p.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ p.visitJumpInsn(opcode, label);
+ super.visitJumpInsn(opcode, label);
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ p.visitLabel(label);
+ super.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ p.visitLdcInsn(value);
+ super.visitLdcInsn(value);
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ p.visitIincInsn(var, increment);
+ super.visitIincInsn(var, increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ p.visitTableSwitchInsn(min, max, dflt, labels);
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ p.visitLookupSwitchInsn(dflt, keys, labels);
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ p.visitMultiANewArrayInsn(descriptor, numDimensions);
+ super.visitMultiANewArrayInsn(descriptor, numDimensions);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitInsnAnnotation(typeRef, typePath, descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitInsnAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter);
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ p.visitTryCatchBlock(start, end, handler, type);
+ super.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ Printer annotationPrinter = p.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter);
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ p.visitLocalVariable(name, descriptor, signature, start, end, index);
+ super.visitLocalVariable(name, descriptor, signature, start, end, index);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ Printer annotationPrinter =
+ p.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible);
+ return new TraceAnnotationVisitor(
+ super.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, index, descriptor, visible),
+ annotationPrinter);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ p.visitLineNumber(line, start);
+ super.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ p.visitMaxs(maxStack, maxLocals);
+ super.visitMaxs(maxStack, maxLocals);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitMethodEnd();
+ super.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceModuleVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceModuleVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceModuleVisitor.java
old mode 100644
new mode 100755
index 94dc498..610ff75
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceModuleVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceModuleVisitor.java
@@ -1,101 +1,111 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * A {@link ModuleVisitor} that prints the fields it visits with a
- * {@link Printer}.
- *
+ * A {@link ModuleVisitor} that prints the fields it visits with a {@link Printer}.
+ *
* @author Remi Forax
*/
public final class TraceModuleVisitor extends ModuleVisitor {
-
- public final Printer p;
- public TraceModuleVisitor(final Printer p) {
- this(null, p);
- }
+ /** The printer to convert the visited module into text. */
+ // DontCheck(MemberName): can't be renamed (for backward binary compatibility).
+ public final Printer p;
+
+ /**
+ * Constructs a new {@link TraceModuleVisitor}.
+ *
+ * @param printer the printer to convert the visited module into text.
+ */
+ public TraceModuleVisitor(final Printer printer) {
+ this(null, printer);
+ }
+
+ /**
+ * Constructs a new {@link TraceModuleVisitor}.
+ *
+ * @param moduleVisitor the module visitor to which to delegate calls. May be {@literal null}.
+ * @param printer the printer to convert the visited module into text.
+ */
+ public TraceModuleVisitor(final ModuleVisitor moduleVisitor, final Printer printer) {
+ super(Opcodes.ASM7, moduleVisitor);
+ this.p = printer;
+ }
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ p.visitMainClass(mainClass);
+ super.visitMainClass(mainClass);
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ p.visitPackage(packaze);
+ super.visitPackage(packaze);
+ }
+
+ @Override
+ public void visitRequire(final String module, final int access, final String version) {
+ p.visitRequire(module, access, version);
+ super.visitRequire(module, access, version);
+ }
+
+ @Override
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ p.visitExport(packaze, access, modules);
+ super.visitExport(packaze, access, modules);
+ }
+
+ @Override
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ p.visitOpen(packaze, access, modules);
+ super.visitOpen(packaze, access, modules);
+ }
- public TraceModuleVisitor(final ModuleVisitor mv, final Printer p) {
- super(Opcodes.ASM6, mv);
- this.p = p;
- }
+ @Override
+ public void visitUse(final String use) {
+ p.visitUse(use);
+ super.visitUse(use);
+ }
- @Override
- public void visitMainClass(String mainClass) {
- p.visitMainClass(mainClass);
- super.visitMainClass(mainClass);
- }
-
- @Override
- public void visitPackage(String packaze) {
- p.visitPackage(packaze);
- super.visitPackage(packaze);
- }
-
- @Override
- public void visitRequire(String module, int access, String version) {
- p.visitRequire(module, access, version);
- super.visitRequire(module, access, version);
- }
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- p.visitExport(packaze, access, modules);
- super.visitExport(packaze, access, modules);
- }
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- p.visitOpen(packaze, access, modules);
- super.visitOpen(packaze, access, modules);
- }
-
- @Override
- public void visitUse(String use) {
- p.visitUse(use);
- super.visitUse(use);
- }
-
- @Override
- public void visitProvide(String service, String... providers) {
- p.visitProvide(service, providers);
- super.visitProvide(service, providers);
- }
+ @Override
+ public void visitProvide(final String service, final String... providers) {
+ p.visitProvide(service, providers);
+ super.visitProvide(service, providers);
+ }
- @Override
- public void visitEnd() {
- p.visitModuleEnd();
- super.visitEnd();
- }
+ @Override
+ public void visitEnd() {
+ p.visitModuleEnd();
+ super.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
old mode 100644
new mode 100755
index 2125130..fe1908a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
@@ -1,317 +1,351 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
/**
- * A {@link SignatureVisitor} that prints a disassembled view of the signature
- * it visits.
- *
+ * A {@link SignatureVisitor} that builds the Java generic type declaration corresponding to the
+ * signature it visits.
+ *
* @author Eugene Kuleshov
* @author Eric Bruneton
*/
public final class TraceSignatureVisitor extends SignatureVisitor {
- private final StringBuilder declaration;
-
- private boolean isInterface;
-
- private boolean seenFormalParameter;
-
- private boolean seenInterfaceBound;
-
- private boolean seenParameter;
-
- private boolean seenInterface;
-
- private StringBuilder returnType;
-
- private StringBuilder exceptions;
-
- /**
- * Stack used to keep track of class types that have arguments. Each element
- * of this stack is a boolean encoded in one bit. The top of the stack is
- * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
- * /2.
- */
- private int argumentStack;
-
- /**
- * Stack used to keep track of array class types. Each element of this stack
- * is a boolean encoded in one bit. The top of the stack is the lowest order
- * bit. Pushing false = *2, pushing true = *2+1, popping = /2.
- */
- private int arrayStack;
-
- private String separator = "";
-
- public TraceSignatureVisitor(final int access) {
- super(Opcodes.ASM6);
- isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
- this.declaration = new StringBuilder();
- }
-
- private TraceSignatureVisitor(final StringBuilder buf) {
- super(Opcodes.ASM6);
- this.declaration = buf;
- }
-
- @Override
- public void visitFormalTypeParameter(final String name) {
- declaration.append(seenFormalParameter ? ", " : "<").append(name);
- seenFormalParameter = true;
- seenInterfaceBound = false;
+ private static final String COMMA_SEPARATOR = ", ";
+ private static final String EXTENDS_SEPARATOR = " extends ";
+ private static final String IMPLEMENTS_SEPARATOR = " implements ";
+
+ /** Whether the visited signature is a class signature of a Java interface. */
+ private final boolean isInterface;
+
+ /** The Java generic type declaration corresponding to the visited signature. */
+ private final StringBuilder declaration;
+
+ /** The Java generic method return type declaration corresponding to the visited signature. */
+ private StringBuilder returnType;
+
+ /** The Java generic exception types declaration corresponding to the visited signature. */
+ private StringBuilder exceptions;
+
+ /** Whether {@link #visitFormalTypeParameter} has been called. */
+ private boolean formalTypeParameterVisited;
+
+ /** Whether {@link #visitInterfaceBound} has been called. */
+ private boolean interfaceBoundVisited;
+
+ /** Whether {@link #visitParameterType} has been called. */
+ private boolean parameterTypeVisited;
+
+ /** Whether {@link #visitInterface} has been called. */
+ private boolean interfaceVisited;
+
+ /**
+ * The stack used to keep track of class types that have arguments. Each element of this stack is
+ * a boolean encoded in one bit. The top of the stack is the least significant bit. Pushing false
+ * = *2, pushing true = *2+1, popping = /2.
+ */
+ private int argumentStack;
+
+ /**
+ * The stack used to keep track of array class types. Each element of this stack is a boolean
+ * encoded in one bit. The top of the stack is the lowest order bit. Pushing false = *2, pushing
+ * true = *2+1, popping = /2.
+ */
+ private int arrayStack;
+
+ /** The separator to append before the next visited class or inner class type. */
+ private String separator = "";
+
+ /**
+ * Constructs a new {@link TraceSignatureVisitor}.
+ *
+ * @param accessFlags for class type signatures, the access flags of the class.
+ */
+ public TraceSignatureVisitor(final int accessFlags) {
+ super(Opcodes.ASM7);
+ this.isInterface = (accessFlags & Opcodes.ACC_INTERFACE) != 0;
+ this.declaration = new StringBuilder();
+ }
+
+ private TraceSignatureVisitor(final StringBuilder stringBuilder) {
+ super(Opcodes.ASM7);
+ this.isInterface = false;
+ this.declaration = stringBuilder;
+ }
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ declaration.append(formalTypeParameterVisited ? COMMA_SEPARATOR : "<").append(name);
+ formalTypeParameterVisited = true;
+ interfaceBoundVisited = false;
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ separator = EXTENDS_SEPARATOR;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ separator = interfaceBoundVisited ? COMMA_SEPARATOR : EXTENDS_SEPARATOR;
+ interfaceBoundVisited = true;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ endFormals();
+ separator = EXTENDS_SEPARATOR;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ if (interfaceVisited) {
+ separator = COMMA_SEPARATOR;
+ } else {
+ separator = isInterface ? EXTENDS_SEPARATOR : IMPLEMENTS_SEPARATOR;
+ interfaceVisited = true;
}
-
- @Override
- public SignatureVisitor visitClassBound() {
- separator = " extends ";
- startType();
- return this;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ endFormals();
+ if (parameterTypeVisited) {
+ declaration.append(COMMA_SEPARATOR);
+ } else {
+ declaration.append('(');
+ parameterTypeVisited = true;
}
-
- @Override
- public SignatureVisitor visitInterfaceBound() {
- separator = seenInterfaceBound ? ", " : " extends ";
- seenInterfaceBound = true;
- startType();
- return this;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ endFormals();
+ if (parameterTypeVisited) {
+ parameterTypeVisited = false;
+ } else {
+ declaration.append('(');
}
-
- @Override
- public SignatureVisitor visitSuperclass() {
- endFormals();
- separator = " extends ";
- startType();
- return this;
+ declaration.append(')');
+ returnType = new StringBuilder();
+ return new TraceSignatureVisitor(returnType);
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (exceptions == null) {
+ exceptions = new StringBuilder();
+ } else {
+ exceptions.append(COMMA_SEPARATOR);
}
-
- @Override
- public SignatureVisitor visitInterface() {
- separator = seenInterface ? ", " : isInterface ? " extends "
- : " implements ";
- seenInterface = true;
- startType();
- return this;
+ return new TraceSignatureVisitor(exceptions);
+ }
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ switch (descriptor) {
+ case 'V':
+ declaration.append("void");
+ break;
+ case 'B':
+ declaration.append("byte");
+ break;
+ case 'J':
+ declaration.append("long");
+ break;
+ case 'Z':
+ declaration.append("boolean");
+ break;
+ case 'I':
+ declaration.append("int");
+ break;
+ case 'S':
+ declaration.append("short");
+ break;
+ case 'C':
+ declaration.append("char");
+ break;
+ case 'F':
+ declaration.append("float");
+ break;
+ case 'D':
+ declaration.append("double");
+ break;
+ default:
+ throw new IllegalArgumentException();
}
-
- @Override
- public SignatureVisitor visitParameterType() {
- endFormals();
- if (seenParameter) {
- declaration.append(", ");
- } else {
- seenParameter = true;
- declaration.append('(');
- }
- startType();
- return this;
- }
-
- @Override
- public SignatureVisitor visitReturnType() {
- endFormals();
- if (seenParameter) {
- seenParameter = false;
- } else {
- declaration.append('(');
- }
- declaration.append(')');
- returnType = new StringBuilder();
- return new TraceSignatureVisitor(returnType);
- }
-
- @Override
- public SignatureVisitor visitExceptionType() {
- if (exceptions == null) {
- exceptions = new StringBuilder();
- } else {
- exceptions.append(", ");
- }
- // startType();
- return new TraceSignatureVisitor(exceptions);
- }
-
- @Override
- public void visitBaseType(final char descriptor) {
- switch (descriptor) {
- case 'V':
- declaration.append("void");
- break;
- case 'B':
- declaration.append("byte");
- break;
- case 'J':
- declaration.append("long");
- break;
- case 'Z':
- declaration.append("boolean");
- break;
- case 'I':
- declaration.append("int");
- break;
- case 'S':
- declaration.append("short");
- break;
- case 'C':
- declaration.append("char");
- break;
- case 'F':
- declaration.append("float");
- break;
- // case 'D':
- default:
- declaration.append("double");
- break;
- }
- endType();
- }
-
- @Override
- public void visitTypeVariable(final String name) {
- declaration.append(name);
- endType();
- }
-
- @Override
- public SignatureVisitor visitArrayType() {
- startType();
- arrayStack |= 1;
- return this;
- }
-
- @Override
- public void visitClassType(final String name) {
- if ("java/lang/Object".equals(name)) {
- // Map<java.lang.Object,java.util.List>
- // or
- // abstract public V get(Object key); (seen in Dictionary.class)
- // should have Object
- // but java.lang.String extends java.lang.Object is unnecessary
- boolean needObjectClass = argumentStack % 2 != 0 || seenParameter;
- if (needObjectClass) {
- declaration.append(separator).append(name.replace('/', '.'));
- }
- } else {
- declaration.append(separator).append(name.replace('/', '.'));
- }
- separator = "";
- argumentStack *= 2;
- }
-
- @Override
- public void visitInnerClassType(final String name) {
- if (argumentStack % 2 != 0) {
- declaration.append('>');
- }
- argumentStack /= 2;
- declaration.append('.');
+ endType();
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ declaration.append(separator).append(name);
+ separator = "";
+ endType();
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ startType();
+ arrayStack |= 1;
+ return this;
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if ("java/lang/Object".equals(name)) {
+ // 'Map<java.lang.Object,java.util.List>' or 'abstract public V get(Object key);' should have
+ // Object 'but java.lang.String extends java.lang.Object' is unnecessary.
+ boolean needObjectClass = argumentStack % 2 != 0 || parameterTypeVisited;
+ if (needObjectClass) {
declaration.append(separator).append(name.replace('/', '.'));
- separator = "";
- argumentStack *= 2;
+ }
+ } else {
+ declaration.append(separator).append(name.replace('/', '.'));
}
-
- @Override
- public void visitTypeArgument() {
- if (argumentStack % 2 == 0) {
- ++argumentStack;
- declaration.append('<');
- } else {
- declaration.append(", ");
- }
- declaration.append('?');
+ separator = "";
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (argumentStack % 2 != 0) {
+ declaration.append('>');
}
-
- @Override
- public SignatureVisitor visitTypeArgument(final char tag) {
- if (argumentStack % 2 == 0) {
- ++argumentStack;
- declaration.append('<');
- } else {
- declaration.append(", ");
- }
-
- if (tag == EXTENDS) {
- declaration.append("? extends ");
- } else if (tag == SUPER) {
- declaration.append("? super ");
- }
-
- startType();
- return this;
+ argumentStack /= 2;
+ declaration.append('.');
+ declaration.append(separator).append(name.replace('/', '.'));
+ separator = "";
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ declaration.append('<');
+ } else {
+ declaration.append(COMMA_SEPARATOR);
}
-
- @Override
- public void visitEnd() {
- if (argumentStack % 2 != 0) {
- declaration.append('>');
- }
- argumentStack /= 2;
- endType();
+ declaration.append('?');
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char tag) {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ declaration.append('<');
+ } else {
+ declaration.append(COMMA_SEPARATOR);
}
- public String getDeclaration() {
- return declaration.toString();
+ if (tag == EXTENDS) {
+ declaration.append("? extends ");
+ } else if (tag == SUPER) {
+ declaration.append("? super ");
}
- public String getReturnType() {
- return returnType == null ? null : returnType.toString();
- }
+ startType();
+ return this;
+ }
- public String getExceptions() {
- return exceptions == null ? null : exceptions.toString();
+ @Override
+ public void visitEnd() {
+ if (argumentStack % 2 != 0) {
+ declaration.append('>');
}
-
- // -----------------------------------------------
-
- private void endFormals() {
- if (seenFormalParameter) {
- declaration.append('>');
- seenFormalParameter = false;
- }
+ argumentStack /= 2;
+ endType();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the Java generic type declaration corresponding to the visited signature.
+ *
+ * @return the Java generic type declaration corresponding to the visited signature.
+ */
+ public String getDeclaration() {
+ return declaration.toString();
+ }
+
+ /**
+ * Returns the Java generic method return type declaration corresponding to the visited signature.
+ *
+ * @return the Java generic method return type declaration corresponding to the visited signature.
+ */
+ public String getReturnType() {
+ return returnType == null ? null : returnType.toString();
+ }
+
+ /**
+ * Returns the Java generic exception types declaration corresponding to the visited signature.
+ *
+ * @return the Java generic exception types declaration corresponding to the visited signature.
+ */
+ public String getExceptions() {
+ return exceptions == null ? null : exceptions.toString();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+
+ private void endFormals() {
+ if (formalTypeParameterVisited) {
+ declaration.append('>');
+ formalTypeParameterVisited = false;
}
-
- private void startType() {
- arrayStack *= 2;
- }
-
- private void endType() {
- if (arrayStack % 2 == 0) {
- arrayStack /= 2;
- } else {
- while (arrayStack % 2 != 0) {
- arrayStack /= 2;
- declaration.append("[]");
- }
- }
+ }
+
+ private void startType() {
+ arrayStack *= 2;
+ }
+
+ private void endType() {
+ if (arrayStack % 2 == 0) {
+ arrayStack /= 2;
+ } else {
+ while (arrayStack % 2 != 0) {
+ arrayStack /= 2;
+ declaration.append("[]");
+ }
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/package.html
old mode 100644
new mode 100755
index 91d7420..91fb0db
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/package.html
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/package.html
@@ -31,8 +31,8 @@
<body>
Provides ASM visitors that can be useful for programming and
debugging purposes. These class visitors are normally not used by applications
-at runtime. This is why they are bundled in an optional <tt>asm-util.jar</tt>
-library that is separated from (but requires) the <tt>asm.jar</tt> library,
+at runtime. This is why they are bundled in an optional <code>asm-util.jar</code>
+library that is separated from (but requires) the <code>asm.jar</code> library,
which contains the core ASM framework.
@since ASM 1.3.2
[46/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
TAP5-2588: upgrading from ASM 6 to 7 for Java 9+ support
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/1c71aec7
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/1c71aec7
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/1c71aec7
Branch: refs/heads/master
Commit: 1c71aec760797c7dc595351639767ae4974b1b82
Parents: cb3b34d
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
Authored: Wed Nov 28 22:33:25 2018 -0200
Committer: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
Committed: Wed Nov 28 22:33:25 2018 -0200
----------------------------------------------------------------------
gradle/wrapper/gradle-wrapper.properties | 2 +-
plastic/LICENSE-ASM-5_0.txt | 29 -
plastic/LICENSE-ASM-7_0.txt | 28 +
plastic/build.gradle | 2 +-
.../internal/plastic/asm/AnnotationVisitor.java | 268 +-
.../internal/plastic/asm/AnnotationWriter.java | 713 +-
.../internal/plastic/asm/Attribute.java | 530 +-
.../internal/plastic/asm/ByteVector.java | 636 +-
.../internal/plastic/asm/ClassReader.java | 6213 ++++++++++--------
.../plastic/asm/ClassTooLargeException.java | 71 +
.../internal/plastic/asm/ClassVisitor.java | 603 +-
.../internal/plastic/asm/ClassWriter.java | 2820 +++-----
.../internal/plastic/asm/ConstantDynamic.java | 178 +
.../internal/plastic/asm/Constants.java | 177 +
.../tapestry5/internal/plastic/asm/Context.java | 282 +-
.../internal/plastic/asm/CurrentFrame.java | 112 +-
.../tapestry5/internal/plastic/asm/Edge.java | 144 +-
.../internal/plastic/asm/FieldVisitor.java | 243 +-
.../internal/plastic/asm/FieldWriter.java | 603 +-
.../tapestry5/internal/plastic/asm/Frame.java | 2812 ++++----
.../tapestry5/internal/plastic/asm/Handle.java | 373 +-
.../tapestry5/internal/plastic/asm/Handler.java | 291 +-
.../tapestry5/internal/plastic/asm/Item.java | 318 -
.../tapestry5/internal/plastic/asm/Label.java | 1141 ++--
.../plastic/asm/MethodTooLargeException.java | 99 +
.../internal/plastic/asm/MethodVisitor.java | 1646 +++--
.../internal/plastic/asm/MethodWriter.java | 4710 ++++++-------
.../internal/plastic/asm/ModuleVisitor.java | 330 +-
.../internal/plastic/asm/ModuleWriter.java | 518 +-
.../tapestry5/internal/plastic/asm/Opcodes.java | 652 +-
.../tapestry5/internal/plastic/asm/Symbol.java | 243 +
.../internal/plastic/asm/SymbolTable.java | 1318 ++++
.../tapestry5/internal/plastic/asm/Type.java | 1734 +++--
.../internal/plastic/asm/TypePath.java | 397 +-
.../internal/plastic/asm/TypeReference.java | 888 ++-
.../plastic/asm/commons/AdviceAdapter.java | 1217 ++--
.../plastic/asm/commons/AnalyzerAdapter.java | 1770 +++--
.../plastic/asm/commons/AnnotationRemapper.java | 142 +-
.../plastic/asm/commons/ClassRemapper.java | 354 +-
.../plastic/asm/commons/CodeSizeEvaluator.java | 443 +-
.../plastic/asm/commons/FieldRemapper.java | 124 +-
.../plastic/asm/commons/GeneratorAdapter.java | 2868 ++++----
.../plastic/asm/commons/InstructionAdapter.java | 2471 +++----
.../plastic/asm/commons/JSRInlinerAdapter.java | 1173 ++--
.../asm/commons/LocalVariablesSorter.java | 650 +-
.../internal/plastic/asm/commons/Method.java | 470 +-
.../plastic/asm/commons/MethodRemapper.java | 432 +-
.../asm/commons/ModuleHashesAttribute.java | 223 +-
.../plastic/asm/commons/ModuleRemapper.java | 194 +-
.../asm/commons/ModuleResolutionAttribute.java | 191 +-
.../asm/commons/ModuleTargetAttribute.java | 140 +-
.../internal/plastic/asm/commons/Remapper.java | 516 +-
.../asm/commons/RemappingAnnotationAdapter.java | 124 +-
.../asm/commons/RemappingClassAdapter.java | 270 +-
.../asm/commons/RemappingFieldAdapter.java | 105 +-
.../asm/commons/RemappingMethodAdapter.java | 415 +-
.../asm/commons/RemappingSignatureAdapter.java | 284 +-
.../asm/commons/SerialVersionUIDAdder.java | 934 ++-
.../plastic/asm/commons/SignatureRemapper.java | 309 +-
.../plastic/asm/commons/SimpleRemapper.java | 131 +-
.../plastic/asm/commons/StaticInitMerger.java | 175 +-
.../asm/commons/TableSwitchGenerator.java | 80 +-
.../asm/commons/TryCatchBlockSorter.java | 171 +-
.../internal/plastic/asm/commons/package.html | 0
.../tapestry5/internal/plastic/asm/package.html | 19 +-
.../plastic/asm/signature/SignatureReader.java | 438 +-
.../plastic/asm/signature/SignatureVisitor.java | 415 +-
.../plastic/asm/signature/SignatureWriter.java | 447 +-
.../internal/plastic/asm/signature/package.html | 0
.../plastic/asm/tree/AbstractInsnNode.java | 553 +-
.../plastic/asm/tree/AnnotationNode.java | 463 +-
.../internal/plastic/asm/tree/ClassNode.java | 813 ++-
.../plastic/asm/tree/FieldInsnNode.java | 170 +-
.../internal/plastic/asm/tree/FieldNode.java | 481 +-
.../internal/plastic/asm/tree/FrameNode.java | 340 +-
.../internal/plastic/asm/tree/IincInsnNode.java | 123 +-
.../plastic/asm/tree/InnerClassNode.java | 154 +-
.../internal/plastic/asm/tree/InsnList.java | 1168 ++--
.../internal/plastic/asm/tree/InsnNode.java | 131 +-
.../internal/plastic/asm/tree/IntInsnNode.java | 133 +-
.../plastic/asm/tree/InvokeDynamicInsnNode.java | 154 +-
.../internal/plastic/asm/tree/JumpInsnNode.java | 152 +-
.../internal/plastic/asm/tree/LabelNode.java | 125 +-
.../internal/plastic/asm/tree/LdcInsnNode.java | 121 +-
.../plastic/asm/tree/LineNumberNode.java | 126 +-
.../asm/tree/LocalVariableAnnotationNode.java | 297 +-
.../plastic/asm/tree/LocalVariableNode.java | 168 +-
.../plastic/asm/tree/LookupSwitchInsnNode.java | 167 +-
.../plastic/asm/tree/MethodInsnNode.java | 229 +-
.../internal/plastic/asm/tree/MethodNode.java | 1579 +++--
.../plastic/asm/tree/ModuleExportNode.java | 133 +-
.../internal/plastic/asm/tree/ModuleNode.java | 420 +-
.../plastic/asm/tree/ModuleOpenNode.java | 135 +-
.../plastic/asm/tree/ModuleProvideNode.java | 112 +-
.../plastic/asm/tree/ModuleRequireNode.java | 134 +-
.../asm/tree/MultiANewArrayInsnNode.java | 124 +-
.../plastic/asm/tree/ParameterNode.java | 120 +-
.../plastic/asm/tree/TableSwitchInsnNode.java | 163 +-
.../plastic/asm/tree/TryCatchBlockNode.java | 235 +-
.../plastic/asm/tree/TypeAnnotationNode.java | 185 +-
.../internal/plastic/asm/tree/TypeInsnNode.java | 146 +-
.../tree/UnsupportedClassVersionException.java | 14 +
.../internal/plastic/asm/tree/Util.java | 157 +
.../internal/plastic/asm/tree/VarInsnNode.java | 146 +-
.../plastic/asm/tree/analysis/Analyzer.java | 1047 +--
.../asm/tree/analysis/AnalyzerException.java | 123 +-
.../asm/tree/analysis/BasicInterpreter.java | 650 +-
.../plastic/asm/tree/analysis/BasicValue.java | 216 +-
.../asm/tree/analysis/BasicVerifier.java | 795 +--
.../plastic/asm/tree/analysis/Frame.java | 1333 ++--
.../plastic/asm/tree/analysis/Interpreter.java | 470 +-
.../asm/tree/analysis/SimpleVerifier.java | 600 +-
.../plastic/asm/tree/analysis/SmallSet.java | 266 +-
.../asm/tree/analysis/SourceInterpreter.java | 345 +-
.../plastic/asm/tree/analysis/SourceValue.java | 178 +-
.../plastic/asm/tree/analysis/Subroutine.java | 157 +-
.../plastic/asm/tree/analysis/Value.java | 73 +-
.../plastic/asm/tree/analysis/package.html | 30 +-
.../internal/plastic/asm/tree/package.html | 71 +-
.../internal/plastic/asm/util/ASMifiable.java | 70 +-
.../internal/plastic/asm/util/ASMifier.java | 2952 +++++----
.../asm/util/CheckAnnotationAdapter.java | 217 +-
.../plastic/asm/util/CheckClassAdapter.java | 1967 +++---
.../plastic/asm/util/CheckFieldAdapter.java | 186 +-
.../plastic/asm/util/CheckMethodAdapter.java | 2870 ++++----
.../plastic/asm/util/CheckModuleAdapter.java | 323 +-
.../plastic/asm/util/CheckSignatureAdapter.java | 627 +-
.../internal/plastic/asm/util/Printer.java | 2457 ++++---
.../internal/plastic/asm/util/Textifiable.java | 67 +-
.../internal/plastic/asm/util/Textifier.java | 3143 ++++-----
.../asm/util/TraceAnnotationVisitor.java | 146 +-
.../plastic/asm/util/TraceClassVisitor.java | 402 +-
.../plastic/asm/util/TraceFieldVisitor.java | 140 +-
.../plastic/asm/util/TraceMethodVisitor.java | 582 +-
.../plastic/asm/util/TraceModuleVisitor.java | 184 +-
.../plastic/asm/util/TraceSignatureVisitor.java | 610 +-
.../internal/plastic/asm/util/package.html | 4 +-
.../plastic/asm/xml/ASMContentHandler.java | 1569 -----
.../internal/plastic/asm/xml/Processor.java | 1044 ---
.../internal/plastic/asm/xml/SAXAdapter.java | 89 -
.../plastic/asm/xml/SAXAnnotationAdapter.java | 242 -
.../plastic/asm/xml/SAXClassAdapter.java | 381 --
.../plastic/asm/xml/SAXCodeAdapter.java | 415 --
.../plastic/asm/xml/SAXFieldAdapter.java | 71 -
.../plastic/asm/xml/SAXModuleAdapter.java | 137 -
.../internal/plastic/asm/xml/asm-xml.dtd | 363 -
.../internal/plastic/asm/xml/package.html | 96 -
.../plastic/InstructionBuilderImpl.java | 84 +-
.../internal/plastic/PlasticClassImpl.java | 174 +-
.../internal/plastic/PlasticClassPool.java | 2 +-
.../org/apache/tapestry5/ioc/internal/Main.java | 38 +
.../src/test/resources/hibernate.cfg.xml | 42 +
152 files changed, 42157 insertions(+), 44581 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/gradle/wrapper/gradle-wrapper.properties
----------------------------------------------------------------------
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0e680f3..fb7ef98 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/LICENSE-ASM-5_0.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-5_0.txt b/plastic/LICENSE-ASM-5_0.txt
deleted file mode 100644
index c5aba7b..0000000
--- a/plastic/LICENSE-ASM-5_0.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-Copyright (c) 2000-2011 INRIA, France Telecom
-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.
-
-3. Neither the name of the copyright holders nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-THE POSSIBILITY OF SUCH DAMAGE.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/LICENSE-ASM-7_0.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-7_0.txt b/plastic/LICENSE-ASM-7_0.txt
new file mode 100755
index 0000000..4d19185
--- /dev/null
+++ b/plastic/LICENSE-ASM-7_0.txt
@@ -0,0 +1,28 @@
+
+ ASM: a very small and fast Java bytecode manipulation framework
+ Copyright (c) 2000-2011 INRIA, France Telecom
+ 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.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/build.gradle
----------------------------------------------------------------------
diff --git a/plastic/build.gradle b/plastic/build.gradle
index 25a53f9..d292efa 100644
--- a/plastic/build.gradle
+++ b/plastic/build.gradle
@@ -9,7 +9,7 @@ test {
useJUnit()
}
-// Add the source directory for the imported/repackaged ASM 3.3.1 code
+// Add the source directory for the imported/repackaged ASM 7.0.1 code
sourceSets.main.java.srcDir "src/external/java"
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
old mode 100644
new mode 100755
index a3df31b..a0c6726
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
@@ -1,169 +1,145 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java annotation. The methods of this class must be
- * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
- * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
- *
+ * A visitor to visit a Java annotation. The methods of this class must be called in the following
+ * order: ( {@code visit} | {@code visitEnum} | {@code visitAnnotation} | {@code visitArray} )*
+ * {@code visitEnd}.
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
public abstract class AnnotationVisitor {
- /**
- * The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- protected final int api;
+ /**
+ * The ASM API version implemented by this visitor. The value of this field must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ protected final int api;
- /**
- * The annotation visitor to which this visitor must delegate method calls.
- * May be null.
- */
- protected AnnotationVisitor av;
+ /** The annotation visitor to which this visitor must delegate method calls. May be null. */
+ protected AnnotationVisitor av;
- /**
- * Constructs a new {@link AnnotationVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- */
- public AnnotationVisitor(final int api) {
- this(api, null);
- }
+ /**
+ * Constructs a new {@link AnnotationVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ */
+ public AnnotationVisitor(final int api) {
+ this(api, null);
+ }
- /**
- * Constructs a new {@link AnnotationVisitor}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param av
- * the annotation visitor to which this visitor must delegate
- * method calls. May be null.
- */
- public AnnotationVisitor(final int api, final AnnotationVisitor av) {
- if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
- throw new IllegalArgumentException();
- }
- this.api = api;
- this.av = av;
+ /**
+ * Constructs a new {@link AnnotationVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param annotationVisitor the annotation visitor to which this visitor must delegate method
+ * calls. May be null.
+ */
+ public AnnotationVisitor(final int api, final AnnotationVisitor annotationVisitor) {
+ if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
+ throw new IllegalArgumentException();
}
+ this.api = api;
+ this.av = annotationVisitor;
+ }
- /**
- * Visits a primitive value of the annotation.
- *
- * @param name
- * the value name.
- * @param value
- * the actual value, whose type must be {@link Byte},
- * {@link Boolean}, {@link Character}, {@link Short},
- * {@link Integer} , {@link Long}, {@link Float}, {@link Double},
- * {@link String} or {@link Type} of OBJECT or ARRAY sort. This
- * value can also be an array of byte, boolean, short, char, int,
- * long, float or double values (this is equivalent to using
- * {@link #visitArray visitArray} and visiting each array element
- * in turn, but is more convenient).
- */
- public void visit(String name, Object value) {
- if (av != null) {
- av.visit(name, value);
- }
+ /**
+ * Visits a primitive value of the annotation.
+ *
+ * @param name the value name.
+ * @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link
+ * Character}, {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+ * {@link String} or {@link Type} of {@link Type#OBJECT} or {@link Type#ARRAY} sort. This
+ * value can also be an array of byte, boolean, short, char, int, long, float or double values
+ * (this is equivalent to using {@link #visitArray} and visiting each array element in turn,
+ * but is more convenient).
+ */
+ public void visit(final String name, final Object value) {
+ if (av != null) {
+ av.visit(name, value);
}
+ }
- /**
- * Visits an enumeration value of the annotation.
- *
- * @param name
- * the value name.
- * @param desc
- * the class descriptor of the enumeration class.
- * @param value
- * the actual enumeration value.
- */
- public void visitEnum(String name, String desc, String value) {
- if (av != null) {
- av.visitEnum(name, desc, value);
- }
+ /**
+ * Visits an enumeration value of the annotation.
+ *
+ * @param name the value name.
+ * @param descriptor the class descriptor of the enumeration class.
+ * @param value the actual enumeration value.
+ */
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ if (av != null) {
+ av.visitEnum(name, descriptor, value);
}
+ }
- /**
- * Visits a nested annotation value of the annotation.
- *
- * @param name
- * the value name.
- * @param desc
- * the class descriptor of the nested annotation class.
- * @return a visitor to visit the actual nested annotation value, or
- * <tt>null</tt> if this visitor is not interested in visiting this
- * nested annotation. <i>The nested annotation value must be fully
- * visited before calling other methods on this annotation
- * visitor</i>.
- */
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- if (av != null) {
- return av.visitAnnotation(name, desc);
- }
- return null;
+ /**
+ * Visits a nested annotation value of the annotation.
+ *
+ * @param name the value name.
+ * @param descriptor the class descriptor of the nested annotation class.
+ * @return a visitor to visit the actual nested annotation value, or {@literal null} if this
+ * visitor is not interested in visiting this nested annotation. <i>The nested annotation
+ * value must be fully visited before calling other methods on this annotation visitor</i>.
+ */
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ if (av != null) {
+ return av.visitAnnotation(name, descriptor);
}
+ return null;
+ }
- /**
- * Visits an array value of the annotation. Note that arrays of primitive
- * types (such as byte, boolean, short, char, int, long, float or double)
- * can be passed as value to {@link #visit visit}. This is what
- * {@link ClassReader} does.
- *
- * @param name
- * the value name.
- * @return a visitor to visit the actual array value elements, or
- * <tt>null</tt> if this visitor is not interested in visiting these
- * values. The 'name' parameters passed to the methods of this
- * visitor are ignored. <i>All the array values must be visited
- * before calling other methods on this annotation visitor</i>.
- */
- public AnnotationVisitor visitArray(String name) {
- if (av != null) {
- return av.visitArray(name);
- }
- return null;
+ /**
+ * Visits an array value of the annotation. Note that arrays of primitive types (such as byte,
+ * boolean, short, char, int, long, float or double) can be passed as value to {@link #visit
+ * visit}. This is what {@link ClassReader} does.
+ *
+ * @param name the value name.
+ * @return a visitor to visit the actual array value elements, or {@literal null} if this visitor
+ * is not interested in visiting these values. The 'name' parameters passed to the methods of
+ * this visitor are ignored. <i>All the array values must be visited before calling other
+ * methods on this annotation visitor</i>.
+ */
+ public AnnotationVisitor visitArray(final String name) {
+ if (av != null) {
+ return av.visitArray(name);
}
+ return null;
+ }
- /**
- * Visits the end of the annotation.
- */
- public void visitEnd() {
- if (av != null) {
- av.visitEnd();
- }
+ /** Visits the end of the annotation. */
+ public void visitEnd() {
+ if (av != null) {
+ av.visitEnd();
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
old mode 100644
new mode 100755
index d0d2d4a..c55f36a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
@@ -1,371 +1,418 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * An {@link AnnotationVisitor} that generates annotations in bytecode form.
- *
+ * An {@link AnnotationVisitor} that generates a corresponding 'annotation' or 'type_annotation'
+ * structure, as defined in the Java Virtual Machine Specification (JVMS). AnnotationWriter
+ * instances can be chained in a doubly linked list, from which Runtime[In]Visible[Type]Annotations
+ * attributes can be generated with the {@link #putAnnotations} method. Similarly, arrays of such
+ * lists can be used to generate Runtime[In]VisibleParameterAnnotations attributes.
+ *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16">JVMS
+ * 4.7.16</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS
+ * 4.7.20</a>
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
final class AnnotationWriter extends AnnotationVisitor {
- /**
- * The class writer to which this annotation must be added.
- */
- private final ClassWriter cw;
-
- /**
- * The number of values in this annotation.
- */
- private int size;
+ /** Where the constants used in this AnnotationWriter must be stored. */
+ private final SymbolTable symbolTable;
- /**
- * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
- * writers used for annotation default and annotation arrays use unnamed
- * values.
- */
- private final boolean named;
+ /**
+ * Whether values are named or not. AnnotationWriter instances used for annotation default and
+ * annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each
+ * value, instead of an element_name_index followed by an element_value).
+ */
+ private final boolean useNamedValues;
- /**
- * The annotation values in bytecode form. This byte vector only contains
- * the values themselves, i.e. the number of values must be stored as a
- * unsigned short just before these bytes.
- */
- private final ByteVector bv;
+ /**
+ * The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values
+ * visited so far. All the fields of these structures, except the last one - the
+ * element_value_pairs array, must be set before this ByteVector is passed to the constructor
+ * (num_element_value_pairs can be set to 0, it is reset to the correct value in {@link
+ * #visitEnd()}). The element_value_pairs array is filled incrementally in the various visit()
+ * methods.
+ *
+ * <p>Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a
+ * single element_value by definition), this ByteVector is initially empty when passed to the
+ * constructor, and {@link #numElementValuePairsOffset} is set to -1.
+ */
+ private final ByteVector annotation;
- /**
- * The byte vector to be used to store the number of values of this
- * annotation. See {@link #bv}.
- */
- private final ByteVector parent;
+ /**
+ * The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for
+ * the case of AnnotationDefault attributes).
+ */
+ private final int numElementValuePairsOffset;
- /**
- * Where the number of values of this annotation must be stored in
- * {@link #parent}.
- */
- private final int offset;
+ /** The number of element value pairs visited so far. */
+ private int numElementValuePairs;
- /**
- * Next annotation writer. This field is used to store annotation lists.
- */
- AnnotationWriter next;
+ /**
+ * The previous AnnotationWriter. This field is used to store the list of annotations of a
+ * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
+ * (annotation values of annotation type), or for AnnotationDefault attributes.
+ */
+ private final AnnotationWriter previousAnnotation;
- /**
- * Previous annotation writer. This field is used to store annotation lists.
- */
- AnnotationWriter prev;
+ /**
+ * The next AnnotationWriter. This field is used to store the list of annotations of a
+ * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
+ * (annotation values of annotation type), or for AnnotationDefault attributes.
+ */
+ private AnnotationWriter nextAnnotation;
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // Constructors
+ // -----------------------------------------------------------------------------------------------
- /**
- * Constructs a new {@link AnnotationWriter}.
- *
- * @param cw
- * the class writer to which this annotation must be added.
- * @param named
- * <tt>true<tt> if values are named, <tt>false</tt> otherwise.
- * @param bv
- * where the annotation values must be stored.
- * @param parent
- * where the number of annotation values must be stored.
- * @param offset
- * where in <tt>parent</tt> the number of annotation values must
- * be stored.
- */
- AnnotationWriter(final ClassWriter cw, final boolean named,
- final ByteVector bv, final ByteVector parent, final int offset) {
- super(Opcodes.ASM6);
- this.cw = cw;
- this.named = named;
- this.bv = bv;
- this.parent = parent;
- this.offset = offset;
+ /**
+ * Constructs a new {@link AnnotationWriter}.
+ *
+ * @param symbolTable where the constants used in this AnnotationWriter must be stored.
+ * @param useNamedValues whether values are named or not. AnnotationDefault and annotation arrays
+ * use unnamed values.
+ * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
+ * the visited content must be stored. This ByteVector must already contain all the fields of
+ * the structure except the last one (the element_value_pairs array).
+ * @param previousAnnotation the previously visited annotation of the
+ * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
+ * other cases (e.g. nested or array annotations).
+ */
+ AnnotationWriter(
+ final SymbolTable symbolTable,
+ final boolean useNamedValues,
+ final ByteVector annotation,
+ final AnnotationWriter previousAnnotation) {
+ super(Opcodes.ASM7);
+ this.symbolTable = symbolTable;
+ this.useNamedValues = useNamedValues;
+ this.annotation = annotation;
+ // By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'.
+ this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2;
+ this.previousAnnotation = previousAnnotation;
+ if (previousAnnotation != null) {
+ previousAnnotation.nextAnnotation = this;
}
+ }
- // ------------------------------------------------------------------------
- // Implementation of the AnnotationVisitor abstract class
- // ------------------------------------------------------------------------
+ /**
+ * Constructs a new {@link AnnotationWriter} using named values.
+ *
+ * @param symbolTable where the constants used in this AnnotationWriter must be stored.
+ * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
+ * the visited content must be stored. This ByteVector must already contain all the fields of
+ * the structure except the last one (the element_value_pairs array).
+ * @param previousAnnotation the previously visited annotation of the
+ * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
+ * other cases (e.g. nested or array annotations).
+ */
+ AnnotationWriter(
+ final SymbolTable symbolTable,
+ final ByteVector annotation,
+ final AnnotationWriter previousAnnotation) {
+ this(symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation);
+ }
- @Override
- public void visit(final String name, final Object value) {
- ++size;
- if (named) {
- bv.putShort(cw.newUTF8(name));
- }
- if (value instanceof String) {
- bv.put12('s', cw.newUTF8((String) value));
- } else if (value instanceof Byte) {
- bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
- } else if (value instanceof Boolean) {
- int v = ((Boolean) value).booleanValue() ? 1 : 0;
- bv.put12('Z', cw.newInteger(v).index);
- } else if (value instanceof Character) {
- bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
- } else if (value instanceof Short) {
- bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
- } else if (value instanceof Type) {
- bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
- } else if (value instanceof byte[]) {
- byte[] v = (byte[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('B', cw.newInteger(v[i]).index);
- }
- } else if (value instanceof boolean[]) {
- boolean[] v = (boolean[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
- }
- } else if (value instanceof short[]) {
- short[] v = (short[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('S', cw.newInteger(v[i]).index);
- }
- } else if (value instanceof char[]) {
- char[] v = (char[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('C', cw.newInteger(v[i]).index);
- }
- } else if (value instanceof int[]) {
- int[] v = (int[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('I', cw.newInteger(v[i]).index);
- }
- } else if (value instanceof long[]) {
- long[] v = (long[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('J', cw.newLong(v[i]).index);
- }
- } else if (value instanceof float[]) {
- float[] v = (float[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('F', cw.newFloat(v[i]).index);
- }
- } else if (value instanceof double[]) {
- double[] v = (double[]) value;
- bv.put12('[', v.length);
- for (int i = 0; i < v.length; i++) {
- bv.put12('D', cw.newDouble(v[i]).index);
- }
- } else {
- Item i = cw.newConstItem(value);
- bv.put12(".s.IFJDCS".charAt(i.type), i.index);
- }
+ // -----------------------------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor abstract class
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ // Case of an element_value with a const_value_index, class_info_index or array_index field.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+ ++numElementValuePairs;
+ if (useNamedValues) {
+ annotation.putShort(symbolTable.addConstantUtf8(name));
+ }
+ if (value instanceof String) {
+ annotation.put12('s', symbolTable.addConstantUtf8((String) value));
+ } else if (value instanceof Byte) {
+ annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index);
+ } else if (value instanceof Boolean) {
+ int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0;
+ annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index);
+ } else if (value instanceof Character) {
+ annotation.put12('C', symbolTable.addConstantInteger(((Character) value).charValue()).index);
+ } else if (value instanceof Short) {
+ annotation.put12('S', symbolTable.addConstantInteger(((Short) value).shortValue()).index);
+ } else if (value instanceof Type) {
+ annotation.put12('c', symbolTable.addConstantUtf8(((Type) value).getDescriptor()));
+ } else if (value instanceof byte[]) {
+ byte[] byteArray = (byte[]) value;
+ annotation.put12('[', byteArray.length);
+ for (byte byteValue : byteArray) {
+ annotation.put12('B', symbolTable.addConstantInteger(byteValue).index);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] booleanArray = (boolean[]) value;
+ annotation.put12('[', booleanArray.length);
+ for (boolean booleanValue : booleanArray) {
+ annotation.put12('Z', symbolTable.addConstantInteger(booleanValue ? 1 : 0).index);
+ }
+ } else if (value instanceof short[]) {
+ short[] shortArray = (short[]) value;
+ annotation.put12('[', shortArray.length);
+ for (short shortValue : shortArray) {
+ annotation.put12('S', symbolTable.addConstantInteger(shortValue).index);
+ }
+ } else if (value instanceof char[]) {
+ char[] charArray = (char[]) value;
+ annotation.put12('[', charArray.length);
+ for (char charValue : charArray) {
+ annotation.put12('C', symbolTable.addConstantInteger(charValue).index);
+ }
+ } else if (value instanceof int[]) {
+ int[] intArray = (int[]) value;
+ annotation.put12('[', intArray.length);
+ for (int intValue : intArray) {
+ annotation.put12('I', symbolTable.addConstantInteger(intValue).index);
+ }
+ } else if (value instanceof long[]) {
+ long[] longArray = (long[]) value;
+ annotation.put12('[', longArray.length);
+ for (long longValue : longArray) {
+ annotation.put12('J', symbolTable.addConstantLong(longValue).index);
+ }
+ } else if (value instanceof float[]) {
+ float[] floatArray = (float[]) value;
+ annotation.put12('[', floatArray.length);
+ for (float floatValue : floatArray) {
+ annotation.put12('F', symbolTable.addConstantFloat(floatValue).index);
+ }
+ } else if (value instanceof double[]) {
+ double[] doubleArray = (double[]) value;
+ annotation.put12('[', doubleArray.length);
+ for (double doubleValue : doubleArray) {
+ annotation.put12('D', symbolTable.addConstantDouble(doubleValue).index);
+ }
+ } else {
+ Symbol symbol = symbolTable.addConstant(value);
+ annotation.put12(".s.IFJDCS".charAt(symbol.tag), symbol.index);
}
+ }
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- ++size;
- if (named) {
- bv.putShort(cw.newUTF8(name));
- }
- bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ // Case of an element_value with an enum_const_value field.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+ ++numElementValuePairs;
+ if (useNamedValues) {
+ annotation.putShort(symbolTable.addConstantUtf8(name));
}
+ annotation
+ .put12('e', symbolTable.addConstantUtf8(descriptor))
+ .putShort(symbolTable.addConstantUtf8(value));
+ }
- @Override
- public AnnotationVisitor visitAnnotation(final String name,
- final String desc) {
- ++size;
- if (named) {
- bv.putShort(cw.newUTF8(name));
- }
- // write tag and type, and reserve space for values count
- bv.put12('@', cw.newUTF8(desc)).putShort(0);
- return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ // Case of an element_value with an annotation_value field.
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+ ++numElementValuePairs;
+ if (useNamedValues) {
+ annotation.putShort(symbolTable.addConstantUtf8(name));
}
+ // Write tag and type_index, and reserve 2 bytes for num_element_value_pairs.
+ annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0);
+ return new AnnotationWriter(symbolTable, annotation, null);
+ }
- @Override
- public AnnotationVisitor visitArray(final String name) {
- ++size;
- if (named) {
- bv.putShort(cw.newUTF8(name));
- }
- // write tag, and reserve space for array size
- bv.put12('[', 0);
- return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ // Case of an element_value with an array_value field.
+ // https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1
+ ++numElementValuePairs;
+ if (useNamedValues) {
+ annotation.putShort(symbolTable.addConstantUtf8(name));
}
+ // Write tag, and reserve 2 bytes for num_values. Here we take advantage of the fact that the
+ // end of an element_value of array type is similar to the end of an 'annotation' structure: an
+ // unsigned short num_values followed by num_values element_value, versus an unsigned short
+ // num_element_value_pairs, followed by num_element_value_pairs { element_name_index,
+ // element_value } tuples. This allows us to use an AnnotationWriter with unnamed values to
+ // visit the array elements. Its num_element_value_pairs will correspond to the number of array
+ // elements and will be stored in what is in fact num_values.
+ annotation.put12('[', 0);
+ return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null);
+ }
- @Override
- public void visitEnd() {
- if (parent != null) {
- byte[] data = parent.data;
- data[offset] = (byte) (size >>> 8);
- data[offset + 1] = (byte) size;
- }
+ @Override
+ public void visitEnd() {
+ if (numElementValuePairsOffset != -1) {
+ byte[] data = annotation.data;
+ data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8);
+ data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs;
}
+ }
- // ------------------------------------------------------------------------
- // Utility methods
- // ------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
- /**
- * Returns the size of this annotation writer list.
- *
- * @return the size of this annotation writer list.
- */
- int getSize() {
- int size = 0;
- AnnotationWriter aw = this;
- while (aw != null) {
- size += aw.bv.length;
- aw = aw.next;
- }
- return size;
+ /**
+ * Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation
+ * and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name
+ * to the constant pool of the class (if not null).
+ *
+ * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or null.
+ * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this
+ * annotation and all its predecessors. This includes the size of the attribute_name_index and
+ * attribute_length fields.
+ */
+ int computeAnnotationsSize(final String attributeName) {
+ if (attributeName != null) {
+ symbolTable.addConstantUtf8(attributeName);
+ }
+ // The attribute_name_index, attribute_length and num_annotations fields use 8 bytes.
+ int attributeSize = 8;
+ AnnotationWriter annotationWriter = this;
+ while (annotationWriter != null) {
+ attributeSize += annotationWriter.annotation.length;
+ annotationWriter = annotationWriter.previousAnnotation;
}
+ return attributeSize;
+ }
- /**
- * Puts the annotations of this annotation writer list into the given byte
- * vector.
- *
- * @param out
- * where the annotations must be put.
- */
- void put(final ByteVector out) {
- int n = 0;
- int size = 2;
- AnnotationWriter aw = this;
- AnnotationWriter last = null;
- while (aw != null) {
- ++n;
- size += aw.bv.length;
- aw.visitEnd(); // in case user forgot to call visitEnd
- aw.prev = last;
- last = aw;
- aw = aw.next;
- }
- out.putInt(size);
- out.putShort(n);
- aw = last;
- while (aw != null) {
- out.putByteArray(aw.bv.data, 0, aw.bv.length);
- aw = aw.prev;
- }
+ /**
+ * Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its
+ * <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are
+ * put in the same order they have been visited.
+ *
+ * @param attributeNameIndex the constant pool index of the attribute name (one of
+ * "Runtime[In]Visible[Type]Annotations").
+ * @param output where the attribute must be put.
+ */
+ void putAnnotations(final int attributeNameIndex, final ByteVector output) {
+ int attributeLength = 2; // For num_annotations.
+ int numAnnotations = 0;
+ AnnotationWriter annotationWriter = this;
+ AnnotationWriter firstAnnotation = null;
+ while (annotationWriter != null) {
+ // In case the user forgot to call visitEnd().
+ annotationWriter.visitEnd();
+ attributeLength += annotationWriter.annotation.length;
+ numAnnotations++;
+ firstAnnotation = annotationWriter;
+ annotationWriter = annotationWriter.previousAnnotation;
}
+ output.putShort(attributeNameIndex);
+ output.putInt(attributeLength);
+ output.putShort(numAnnotations);
+ annotationWriter = firstAnnotation;
+ while (annotationWriter != null) {
+ output.putByteArray(annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
+ annotationWriter = annotationWriter.nextAnnotation;
+ }
+ }
- /**
- * Puts the given annotation lists into the given byte vector.
- *
- * @param panns
- * an array of annotation writer lists.
- * @param off
- * index of the first annotation to be written.
- * @param out
- * where the annotations must be put.
- */
- static void put(final AnnotationWriter[] panns, final int off,
- final ByteVector out) {
- int size = 1 + 2 * (panns.length - off);
- for (int i = off; i < panns.length; ++i) {
- size += panns[i] == null ? 0 : panns[i].getSize();
- }
- out.putInt(size).putByte(panns.length - off);
- for (int i = off; i < panns.length; ++i) {
- AnnotationWriter aw = panns[i];
- AnnotationWriter last = null;
- int n = 0;
- while (aw != null) {
- ++n;
- aw.visitEnd(); // in case user forgot to call visitEnd
- aw.prev = last;
- last = aw;
- aw = aw.next;
- }
- out.putShort(n);
- aw = last;
- while (aw != null) {
- out.putByteArray(aw.bv.data, 0, aw.bv.length);
- aw = aw.prev;
- }
- }
+ /**
+ * Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the
+ * annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the
+ * constant pool of the class.
+ *
+ * @param attributeName one of "Runtime[In]VisibleParameterAnnotations".
+ * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i>
+ * element).
+ * @param annotableParameterCount the number of elements in annotationWriters to take into account
+ * (elements [0..annotableParameterCount[ are taken into account).
+ * @return the size in bytes of a Runtime[In]VisibleParameterAnnotations attribute corresponding
+ * to the given sub-array of AnnotationWriter lists. This includes the size of the
+ * attribute_name_index and attribute_length fields.
+ */
+ static int computeParameterAnnotationsSize(
+ final String attributeName,
+ final AnnotationWriter[] annotationWriters,
+ final int annotableParameterCount) {
+ // Note: attributeName is added to the constant pool by the call to computeAnnotationsSize
+ // below. This assumes that there is at least one non-null element in the annotationWriters
+ // sub-array (which is ensured by the lazy instantiation of this array in MethodWriter).
+ // The attribute_name_index, attribute_length and num_parameters fields use 7 bytes, and each
+ // element of the parameter_annotations array uses 2 bytes for its num_annotations field.
+ int attributeSize = 7 + 2 * annotableParameterCount;
+ for (int i = 0; i < annotableParameterCount; ++i) {
+ AnnotationWriter annotationWriter = annotationWriters[i];
+ attributeSize +=
+ annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(attributeName) - 8;
}
+ return attributeSize;
+ }
- /**
- * Puts the given type reference and type path into the given bytevector.
- * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
- *
- * @param typeRef
- * a reference to the annotated type. See {@link TypeReference}.
- * @param typePath
- * the path to the annotated type argument, wildcard bound, array
- * element type, or static inner type within 'typeRef'. May be
- * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
- * @param out
- * where the type reference and type path must be put.
- */
- static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
- switch (typeRef >>> 24) {
- case 0x00: // CLASS_TYPE_PARAMETER
- case 0x01: // METHOD_TYPE_PARAMETER
- case 0x16: // METHOD_FORMAL_PARAMETER
- out.putShort(typeRef >>> 16);
- break;
- case 0x13: // FIELD
- case 0x14: // METHOD_RETURN
- case 0x15: // METHOD_RECEIVER
- out.putByte(typeRef >>> 24);
- break;
- case 0x47: // CAST
- case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
- case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
- case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
- case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
- out.putInt(typeRef);
- break;
- // case 0x10: // CLASS_EXTENDS
- // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
- // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
- // case 0x17: // THROWS
- // case 0x42: // EXCEPTION_PARAMETER
- // case 0x43: // INSTANCEOF
- // case 0x44: // NEW
- // case 0x45: // CONSTRUCTOR_REFERENCE
- // case 0x46: // METHOD_REFERENCE
- default:
- out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
- break;
- }
- if (typePath == null) {
- out.putByte(0);
- } else {
- int length = typePath.b[typePath.offset] * 2 + 1;
- out.putByteArray(typePath.b, typePath.offset, length);
- }
+ /**
+ * Puts a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists
+ * from the given AnnotationWriter sub-array in the given ByteVector.
+ *
+ * @param attributeNameIndex constant pool index of the attribute name (one of
+ * Runtime[In]VisibleParameterAnnotations).
+ * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i>
+ * element).
+ * @param annotableParameterCount the number of elements in annotationWriters to put (elements
+ * [0..annotableParameterCount[ are put).
+ * @param output where the attribute must be put.
+ */
+ static void putParameterAnnotations(
+ final int attributeNameIndex,
+ final AnnotationWriter[] annotationWriters,
+ final int annotableParameterCount,
+ final ByteVector output) {
+ // The num_parameters field uses 1 byte, and each element of the parameter_annotations array
+ // uses 2 bytes for its num_annotations field.
+ int attributeLength = 1 + 2 * annotableParameterCount;
+ for (int i = 0; i < annotableParameterCount; ++i) {
+ AnnotationWriter annotationWriter = annotationWriters[i];
+ attributeLength +=
+ annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(null) - 8;
+ }
+ output.putShort(attributeNameIndex);
+ output.putInt(attributeLength);
+ output.putByte(annotableParameterCount);
+ for (int i = 0; i < annotableParameterCount; ++i) {
+ AnnotationWriter annotationWriter = annotationWriters[i];
+ AnnotationWriter firstAnnotation = null;
+ int numAnnotations = 0;
+ while (annotationWriter != null) {
+ // In case user the forgot to call visitEnd().
+ annotationWriter.visitEnd();
+ numAnnotations++;
+ firstAnnotation = annotationWriter;
+ annotationWriter = annotationWriter.previousAnnotation;
+ }
+ output.putShort(numAnnotations);
+ annotationWriter = firstAnnotation;
+ while (annotationWriter != null) {
+ output.putByteArray(
+ annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
+ annotationWriter = annotationWriter.nextAnnotation;
+ }
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
old mode 100644
new mode 100755
index fae580f..c062ade
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
@@ -1,255 +1,325 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A non standard class, field, method or code attribute.
- *
+ * A non standard class, field, method or code attribute, as defined in the Java Virtual Machine
+ * Specification (JVMS).
+ *
+ * @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7">JVMS
+ * 4.7</a>
+ * @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS
+ * 4.7.3</a>
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
public class Attribute {
- /**
- * The type of this attribute.
- */
- public final String type;
-
- /**
- * The raw value of this attribute, used only for unknown attributes.
- */
- byte[] value;
-
- /**
- * The next attribute in this attribute list. May be <tt>null</tt>.
- */
- Attribute next;
-
- /**
- * Constructs a new empty attribute.
- *
- * @param type
- * the type of the attribute.
- */
- protected Attribute(final String type) {
- this.type = type;
- }
+ /** The type of this attribute, also called its name in the JVMS. */
+ public final String type;
- /**
- * Returns <tt>true</tt> if this type of attribute is unknown. The default
- * implementation of this method always returns <tt>true</tt>.
- *
- * @return <tt>true</tt> if this type of attribute is unknown.
- */
- public boolean isUnknown() {
- return true;
- }
+ /**
+ * The raw content of this attribute, only used for unknown attributes (see {@link #isUnknown()}).
+ * The 6 header bytes of the attribute (attribute_name_index and attribute_length) are <i>not</i>
+ * included.
+ */
+ private byte[] content;
- /**
- * Returns <tt>true</tt> if this type of attribute is a code attribute.
- *
- * @return <tt>true</tt> if this type of attribute is a code attribute.
- */
- public boolean isCodeAttribute() {
- return false;
- }
+ /**
+ * The next attribute in this attribute list (Attribute instances can be linked via this field to
+ * store a list of class, field, method or code attributes). May be {@literal null}.
+ */
+ Attribute nextAttribute;
+
+ /**
+ * Constructs a new empty attribute.
+ *
+ * @param type the type of the attribute.
+ */
+ protected Attribute(final String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns {@literal true} if this type of attribute is unknown. This means that the attribute
+ * content can't be parsed to extract constant pool references, labels, etc. Instead, the
+ * attribute content is read as an opaque byte array, and written back as is. This can lead to
+ * invalid attributes, if the content actually contains constant pool references, labels, or other
+ * symbolic references that need to be updated when there are changes to the constant pool, the
+ * method bytecode, etc. The default implementation of this method always returns {@literal true}.
+ *
+ * @return {@literal true} if this type of attribute is unknown.
+ */
+ public boolean isUnknown() {
+ return true;
+ }
+
+ /**
+ * Returns {@literal true} if this type of attribute is a code attribute.
+ *
+ * @return {@literal true} if this type of attribute is a code attribute.
+ */
+ public boolean isCodeAttribute() {
+ return false;
+ }
+
+ /**
+ * Returns the labels corresponding to this attribute.
+ *
+ * @return the labels corresponding to this attribute, or {@literal null} if this attribute is not
+ * a code attribute that contains labels.
+ */
+ protected Label[] getLabels() {
+ return new Label[0];
+ }
- /**
- * Returns the labels corresponding to this attribute.
- *
- * @return the labels corresponding to this attribute, or <tt>null</tt> if
- * this attribute is not a code attribute that contains labels.
- */
- protected Label[] getLabels() {
- return null;
+ /**
+ * Reads a {@link #type} attribute. This method must return a <i>new</i> {@link Attribute} object,
+ * of type {@link #type}, corresponding to the 'length' bytes starting at 'offset', in the given
+ * ClassReader.
+ *
+ * @param classReader the class that contains the attribute to be read.
+ * @param offset index of the first byte of the attribute's content in {@link ClassReader#b}. The
+ * 6 attribute header bytes (attribute_name_index and attribute_length) are not taken into
+ * account here.
+ * @param length the length of the attribute's content (excluding the 6 attribute header bytes).
+ * @param charBuffer the buffer to be used to call the ClassReader methods requiring a
+ * 'charBuffer' parameter.
+ * @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute
+ * in {@link ClassReader#b}, or -1 if the attribute to be read is not a code attribute. The 6
+ * attribute header bytes (attribute_name_index and attribute_length) are not taken into
+ * account here.
+ * @param labels the labels of the method's code, or {@literal null} if the attribute to be read
+ * is not a code attribute.
+ * @return a <i>new</i> {@link Attribute} object corresponding to the specified bytes.
+ */
+ protected Attribute read(
+ final ClassReader classReader,
+ final int offset,
+ final int length,
+ final char[] charBuffer,
+ final int codeAttributeOffset,
+ final Label[] labels) {
+ Attribute attribute = new Attribute(type);
+ attribute.content = new byte[length];
+ System.arraycopy(classReader.b, offset, attribute.content, 0, length);
+ return attribute;
+ }
+
+ /**
+ * Returns the byte array form of the content of this attribute. The 6 header bytes
+ * (attribute_name_index and attribute_length) must <i>not</i> be added in the returned
+ * ByteVector.
+ *
+ * @param classWriter the class to which this attribute must be added. This parameter can be used
+ * to add the items that corresponds to this attribute to the constant pool of this class.
+ * @param code the bytecode of the method corresponding to this code attribute, or {@literal null}
+ * if this attribute is not a code attribute. Corresponds to the 'code' field of the Code
+ * attribute.
+ * @param codeLength the length of the bytecode of the method corresponding to this code
+ * attribute, or 0 if this attribute is not a code attribute. Corresponds to the 'code_length'
+ * field of the Code attribute.
+ * @param maxStack the maximum stack size of the method corresponding to this code attribute, or
+ * -1 if this attribute is not a code attribute.
+ * @param maxLocals the maximum number of local variables of the method corresponding to this code
+ * attribute, or -1 if this attribute is not a code attribute.
+ * @return the byte array form of this attribute.
+ */
+ protected ByteVector write(
+ final ClassWriter classWriter,
+ final byte[] code,
+ final int codeLength,
+ final int maxStack,
+ final int maxLocals) {
+ return new ByteVector(content);
+ }
+
+ /**
+ * Returns the number of attributes of the attribute list that begins with this attribute.
+ *
+ * @return the number of attributes of the attribute list that begins with this attribute.
+ */
+ final int getAttributeCount() {
+ int count = 0;
+ Attribute attribute = this;
+ while (attribute != null) {
+ count += 1;
+ attribute = attribute.nextAttribute;
}
+ return count;
+ }
+
+ /**
+ * Returns the total size in bytes of all the attributes in the attribute list that begins with
+ * this attribute. This size includes the 6 header bytes (attribute_name_index and
+ * attribute_length) per attribute. Also adds the attribute type names to the constant pool.
+ *
+ * @param symbolTable where the constants used in the attributes must be stored.
+ * @return the size of all the attributes in this attribute list. This size includes the size of
+ * the attribute headers.
+ */
+ final int computeAttributesSize(final SymbolTable symbolTable) {
+ final byte[] code = null;
+ final int codeLength = 0;
+ final int maxStack = -1;
+ final int maxLocals = -1;
+ return computeAttributesSize(symbolTable, code, codeLength, maxStack, maxLocals);
+ }
- /**
- * Reads a {@link #type type} attribute. This method must return a
- * <i>new</i> {@link Attribute} object, of type {@link #type type},
- * corresponding to the <tt>len</tt> bytes starting at the given offset, in
- * the given class reader.
- *
- * @param cr
- * the class that contains the attribute to be read.
- * @param off
- * index of the first byte of the attribute's content in
- * {@link ClassReader#b cr.b}. The 6 attribute header bytes,
- * containing the type and the length of the attribute, are not
- * taken into account here.
- * @param len
- * the length of the attribute's content.
- * @param buf
- * buffer to be used to call {@link ClassReader#readUTF8
- * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
- * or {@link ClassReader#readConst readConst}.
- * @param codeOff
- * index of the first byte of code's attribute content in
- * {@link ClassReader#b cr.b}, or -1 if the attribute to be read
- * is not a code attribute. The 6 attribute header bytes,
- * containing the type and the length of the attribute, are not
- * taken into account here.
- * @param labels
- * the labels of the method's code, or <tt>null</tt> if the
- * attribute to be read is not a code attribute.
- * @return a <i>new</i> {@link Attribute} object corresponding to the given
- * bytes.
- */
- protected Attribute read(final ClassReader cr, final int off,
- final int len, final char[] buf, final int codeOff,
- final Label[] labels) {
- Attribute attr = new Attribute(type);
- attr.value = new byte[len];
- System.arraycopy(cr.b, off, attr.value, 0, len);
- return attr;
+ /**
+ * Returns the total size in bytes of all the attributes in the attribute list that begins with
+ * this attribute. This size includes the 6 header bytes (attribute_name_index and
+ * attribute_length) per attribute. Also adds the attribute type names to the constant pool.
+ *
+ * @param symbolTable where the constants used in the attributes must be stored.
+ * @param code the bytecode of the method corresponding to these code attributes, or {@literal
+ * null} if they are not code attributes. Corresponds to the 'code' field of the Code
+ * attribute.
+ * @param codeLength the length of the bytecode of the method corresponding to these code
+ * attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
+ * the Code attribute.
+ * @param maxStack the maximum stack size of the method corresponding to these code attributes, or
+ * -1 if they are not code attributes.
+ * @param maxLocals the maximum number of local variables of the method corresponding to these
+ * code attributes, or -1 if they are not code attribute.
+ * @return the size of all the attributes in this attribute list. This size includes the size of
+ * the attribute headers.
+ */
+ final int computeAttributesSize(
+ final SymbolTable symbolTable,
+ final byte[] code,
+ final int codeLength,
+ final int maxStack,
+ final int maxLocals) {
+ final ClassWriter classWriter = symbolTable.classWriter;
+ int size = 0;
+ Attribute attribute = this;
+ while (attribute != null) {
+ symbolTable.addConstantUtf8(attribute.type);
+ size += 6 + attribute.write(classWriter, code, codeLength, maxStack, maxLocals).length;
+ attribute = attribute.nextAttribute;
}
+ return size;
+ }
- /**
- * Returns the byte array form of this attribute.
- *
- * @param cw
- * the class to which this attribute must be added. This
- * parameter can be used to add to the constant pool of this
- * class the items that corresponds to this attribute.
- * @param code
- * the bytecode of the method corresponding to this code
- * attribute, or <tt>null</tt> if this attribute is not a code
- * attributes.
- * @param len
- * the length of the bytecode of the method corresponding to this
- * code attribute, or <tt>null</tt> if this attribute is not a
- * code attribute.
- * @param maxStack
- * the maximum stack size of the method corresponding to this
- * code attribute, or -1 if this attribute is not a code
- * attribute.
- * @param maxLocals
- * the maximum number of local variables of the method
- * corresponding to this code attribute, or -1 if this attribute
- * is not a code attribute.
- * @return the byte array form of this attribute.
- */
- protected ByteVector write(final ClassWriter cw, final byte[] code,
- final int len, final int maxStack, final int maxLocals) {
- ByteVector v = new ByteVector();
- v.data = value;
- v.length = value.length;
- return v;
+ /**
+ * Puts all the attributes of the attribute list that begins with this attribute, in the given
+ * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
+ * attribute.
+ *
+ * @param symbolTable where the constants used in the attributes must be stored.
+ * @param output where the attributes must be written.
+ */
+ final void putAttributes(final SymbolTable symbolTable, final ByteVector output) {
+ final byte[] code = null;
+ final int codeLength = 0;
+ final int maxStack = -1;
+ final int maxLocals = -1;
+ putAttributes(symbolTable, code, codeLength, maxStack, maxLocals, output);
+ }
+
+ /**
+ * Puts all the attributes of the attribute list that begins with this attribute, in the given
+ * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
+ * attribute.
+ *
+ * @param symbolTable where the constants used in the attributes must be stored.
+ * @param code the bytecode of the method corresponding to these code attributes, or {@literal
+ * null} if they are not code attributes. Corresponds to the 'code' field of the Code
+ * attribute.
+ * @param codeLength the length of the bytecode of the method corresponding to these code
+ * attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
+ * the Code attribute.
+ * @param maxStack the maximum stack size of the method corresponding to these code attributes, or
+ * -1 if they are not code attributes.
+ * @param maxLocals the maximum number of local variables of the method corresponding to these
+ * code attributes, or -1 if they are not code attribute.
+ * @param output where the attributes must be written.
+ */
+ final void putAttributes(
+ final SymbolTable symbolTable,
+ final byte[] code,
+ final int codeLength,
+ final int maxStack,
+ final int maxLocals,
+ final ByteVector output) {
+ final ClassWriter classWriter = symbolTable.classWriter;
+ Attribute attribute = this;
+ while (attribute != null) {
+ ByteVector attributeContent =
+ attribute.write(classWriter, code, codeLength, maxStack, maxLocals);
+ // Put attribute_name_index and attribute_length.
+ output.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(attributeContent.length);
+ output.putByteArray(attributeContent.data, 0, attributeContent.length);
+ attribute = attribute.nextAttribute;
}
+ }
+
+ /** A set of attribute prototypes (attributes with the same type are considered equal). */
+ static final class Set {
- /**
- * Returns the length of the attribute list that begins with this attribute.
- *
- * @return the length of the attribute list that begins with this attribute.
- */
- final int getCount() {
- int count = 0;
- Attribute attr = this;
- while (attr != null) {
- count += 1;
- attr = attr.next;
+ private static final int SIZE_INCREMENT = 6;
+
+ private int size;
+ private Attribute[] data = new Attribute[SIZE_INCREMENT];
+
+ void addAttributes(final Attribute attributeList) {
+ Attribute attribute = attributeList;
+ while (attribute != null) {
+ if (!contains(attribute)) {
+ add(attribute);
}
- return count;
+ attribute = attribute.nextAttribute;
+ }
}
- /**
- * Returns the size of all the attributes in this attribute list.
- *
- * @param cw
- * the class writer to be used to convert the attributes into
- * byte arrays, with the {@link #write write} method.
- * @param code
- * the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len
- * the length of the bytecode of the method corresponding to
- * these code attributes, or <tt>null</tt> if these attributes
- * are not code attributes.
- * @param maxStack
- * the maximum stack size of the method corresponding to these
- * code attributes, or -1 if these attributes are not code
- * attributes.
- * @param maxLocals
- * the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these
- * attributes are not code attributes.
- * @return the size of all the attributes in this attribute list. This size
- * includes the size of the attribute headers.
- */
- final int getSize(final ClassWriter cw, final byte[] code, final int len,
- final int maxStack, final int maxLocals) {
- Attribute attr = this;
- int size = 0;
- while (attr != null) {
- cw.newUTF8(attr.type);
- size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
- attr = attr.next;
- }
- return size;
+ Attribute[] toArray() {
+ Attribute[] result = new Attribute[size];
+ System.arraycopy(data, 0, result, 0, size);
+ return result;
}
- /**
- * Writes all the attributes of this attribute list in the given byte
- * vector.
- *
- * @param cw
- * the class writer to be used to convert the attributes into
- * byte arrays, with the {@link #write write} method.
- * @param code
- * the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len
- * the length of the bytecode of the method corresponding to
- * these code attributes, or <tt>null</tt> if these attributes
- * are not code attributes.
- * @param maxStack
- * the maximum stack size of the method corresponding to these
- * code attributes, or -1 if these attributes are not code
- * attributes.
- * @param maxLocals
- * the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these
- * attributes are not code attributes.
- * @param out
- * where the attributes must be written.
- */
- final void put(final ClassWriter cw, final byte[] code, final int len,
- final int maxStack, final int maxLocals, final ByteVector out) {
- Attribute attr = this;
- while (attr != null) {
- ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
- out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
- out.putByteArray(b.data, 0, b.length);
- attr = attr.next;
+ private boolean contains(final Attribute attribute) {
+ for (int i = 0; i < size; ++i) {
+ if (data[i].type.equals(attribute.type)) {
+ return true;
}
+ }
+ return false;
+ }
+
+ private void add(final Attribute attribute) {
+ if (size >= data.length) {
+ Attribute[] newData = new Attribute[data.length + SIZE_INCREMENT];
+ System.arraycopy(data, 0, newData, 0, size);
+ data = newData;
+ }
+ data[size++] = attribute;
}
+ }
}
[29/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
Posted by th...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
old mode 100644
new mode 100755
index 45319c6..96d850a
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
@@ -1,39 +1,37 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * 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.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// 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.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.commons;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
@@ -41,30 +39,30 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
/**
- * A {@link org.objectweb.asm.MethodVisitor} with convenient methods to generate
- * code. For example, using this adapter, the class below
- *
+ * A {@link MethodVisitor} with convenient methods to generate code. For example, using this
+ * adapter, the class below
+ *
* <pre>
* public class Example {
- * public static void main(String[] args) {
- * System.out.println("Hello world!");
- * }
+ * public static void main(String[] args) {
+ * System.out.println("Hello world!");
+ * }
* }
* </pre>
- *
- * can be generated as follows:
- *
+ *
+ * <p>can be generated as follows:
+ *
* <pre>
- * ClassWriter cw = new ClassWriter(true);
+ * ClassWriter cw = new ClassWriter(0);
* cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
- *
+ *
* Method m = Method.getMethod("void <init> ()");
* GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
* mg.loadThis();
* mg.invokeConstructor(Type.getType(Object.class), m);
* mg.returnValue();
* mg.endMethod();
- *
+ *
* m = Method.getMethod("void main (String[])");
* mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
* mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
@@ -73,10 +71,10 @@ import org.apache.tapestry5.internal.plastic.asm.Type;
* Method.getMethod("void println (String)"));
* mg.returnValue();
* mg.endMethod();
- *
+ *
* cw.visitEnd();
* </pre>
- *
+ *
* @author Juozas Baliuka
* @author Chris Nokleberg
* @author Eric Bruneton
@@ -84,1547 +82,1361 @@ import org.apache.tapestry5.internal.plastic.asm.Type;
*/
public class GeneratorAdapter extends LocalVariablesSorter {
- private static final String CLDESC = "Ljava/lang/Class;";
-
- private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
-
- private static final Type BOOLEAN_TYPE = Type
- .getObjectType("java/lang/Boolean");
-
- private static final Type SHORT_TYPE = Type
- .getObjectType("java/lang/Short");
-
- private static final Type CHARACTER_TYPE = Type
- .getObjectType("java/lang/Character");
+ private static final String CLASS_DESCRIPTOR = "Ljava/lang/Class;";
- private static final Type INTEGER_TYPE = Type
- .getObjectType("java/lang/Integer");
+ private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
- private static final Type FLOAT_TYPE = Type
- .getObjectType("java/lang/Float");
+ private static final Type BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean");
- private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
+ private static final Type SHORT_TYPE = Type.getObjectType("java/lang/Short");
- private static final Type DOUBLE_TYPE = Type
- .getObjectType("java/lang/Double");
+ private static final Type CHARACTER_TYPE = Type.getObjectType("java/lang/Character");
- private static final Type NUMBER_TYPE = Type
- .getObjectType("java/lang/Number");
+ private static final Type INTEGER_TYPE = Type.getObjectType("java/lang/Integer");
- private static final Type OBJECT_TYPE = Type
- .getObjectType("java/lang/Object");
+ private static final Type FLOAT_TYPE = Type.getObjectType("java/lang/Float");
- private static final Method BOOLEAN_VALUE = Method
- .getMethod("boolean booleanValue()");
+ private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
- private static final Method CHAR_VALUE = Method
- .getMethod("char charValue()");
+ private static final Type DOUBLE_TYPE = Type.getObjectType("java/lang/Double");
- private static final Method INT_VALUE = Method.getMethod("int intValue()");
+ private static final Type NUMBER_TYPE = Type.getObjectType("java/lang/Number");
- private static final Method FLOAT_VALUE = Method
- .getMethod("float floatValue()");
+ private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object");
- private static final Method LONG_VALUE = Method
- .getMethod("long longValue()");
+ private static final Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()");
- private static final Method DOUBLE_VALUE = Method
- .getMethod("double doubleValue()");
+ private static final Method CHAR_VALUE = Method.getMethod("char charValue()");
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int ADD = Opcodes.IADD;
+ private static final Method INT_VALUE = Method.getMethod("int intValue()");
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int SUB = Opcodes.ISUB;
+ private static final Method FLOAT_VALUE = Method.getMethod("float floatValue()");
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int MUL = Opcodes.IMUL;
+ private static final Method LONG_VALUE = Method.getMethod("long longValue()");
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int DIV = Opcodes.IDIV;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int REM = Opcodes.IREM;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int NEG = Opcodes.INEG;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int SHL = Opcodes.ISHL;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int SHR = Opcodes.ISHR;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int USHR = Opcodes.IUSHR;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int AND = Opcodes.IAND;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int OR = Opcodes.IOR;
-
- /**
- * Constant for the {@link #math math} method.
- */
- public static final int XOR = Opcodes.IXOR;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int EQ = Opcodes.IFEQ;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int NE = Opcodes.IFNE;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int LT = Opcodes.IFLT;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int GE = Opcodes.IFGE;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int GT = Opcodes.IFGT;
-
- /**
- * Constant for the {@link #ifCmp ifCmp} method.
- */
- public static final int LE = Opcodes.IFLE;
-
- /**
- * Access flags of the method visited by this adapter.
- */
- private final int access;
-
- /**
- * Return type of the method visited by this adapter.
- */
- private final Type returnType;
-
- /**
- * Argument types of the method visited by this adapter.
- */
- private final Type[] argumentTypes;
-
- /**
- * Types of the local variables of the method visited by this adapter.
- */
- private final List<Type> localTypes = new ArrayList<Type>();
-
- /**
- * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
- * version.
- *
- * @param mv
- * the method visitor to which this adapter delegates calls.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public GeneratorAdapter(final MethodVisitor mv, final int access,
- final String name, final String desc) {
- this(Opcodes.ASM6, mv, access, name, desc);
- if (getClass() != GeneratorAdapter.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Creates a new {@link GeneratorAdapter}.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param mv
- * the method visitor to which this adapter delegates calls.
- * @param access
- * the method's access flags (see {@link Opcodes}).
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- */
- protected GeneratorAdapter(final int api, final MethodVisitor mv,
- final int access, final String name, final String desc) {
- super(api, access, desc, mv);
- this.access = access;
- this.returnType = Type.getReturnType(desc);
- this.argumentTypes = Type.getArgumentTypes(desc);
- }
+ private static final Method DOUBLE_VALUE = Method.getMethod("double doubleValue()");
- /**
- * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
- * version.
- *
- * @param access
- * access flags of the adapted method.
- * @param method
- * the adapted method.
- * @param mv
- * the method visitor to which this adapter delegates calls.
- */
- public GeneratorAdapter(final int access, final Method method,
- final MethodVisitor mv) {
- this(mv, access, null, method.getDescriptor());
- }
-
- /**
- * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
- * version.
- *
- * @param access
- * access flags of the adapted method.
- * @param method
- * the adapted method.
- * @param signature
- * the signature of the adapted method (may be <tt>null</tt>).
- * @param exceptions
- * the exceptions thrown by the adapted method (may be
- * <tt>null</tt>).
- * @param cv
- * the class visitor to which this adapter delegates calls.
- */
- public GeneratorAdapter(final int access, final Method method,
- final String signature, final Type[] exceptions,
- final ClassVisitor cv) {
- this(access, method, cv
- .visitMethod(access, method.getName(), method.getDescriptor(),
- signature, getInternalNames(exceptions)));
- }
+ /** Constant for the {@link #math} method. */
+ public static final int ADD = Opcodes.IADD;
- /**
- * Returns the internal names of the given types.
- *
- * @param types
- * a set of types.
- * @return the internal names of the given types.
- */
- private static String[] getInternalNames(final Type[] types) {
- if (types == null) {
- return null;
- }
- String[] names = new String[types.length];
- for (int i = 0; i < names.length; ++i) {
- names[i] = types[i].getInternalName();
- }
- return names;
- }
-
- // ------------------------------------------------------------------------
- // Instructions to push constants on the stack
- // ------------------------------------------------------------------------
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final boolean value) {
- push(value ? 1 : 0);
- }
-
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final int value) {
- if (value >= -1 && value <= 5) {
- mv.visitInsn(Opcodes.ICONST_0 + value);
- } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
- mv.visitIntInsn(Opcodes.BIPUSH, value);
- } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
- mv.visitIntInsn(Opcodes.SIPUSH, value);
- } else {
- mv.visitLdcInsn(value);
- }
- }
+ /** Constant for the {@link #math} method. */
+ public static final int SUB = Opcodes.ISUB;
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final long value) {
- if (value == 0L || value == 1L) {
- mv.visitInsn(Opcodes.LCONST_0 + (int) value);
- } else {
- mv.visitLdcInsn(value);
- }
- }
+ /** Constant for the {@link #math} method. */
+ public static final int MUL = Opcodes.IMUL;
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final float value) {
- int bits = Float.floatToIntBits(value);
- if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
- mv.visitInsn(Opcodes.FCONST_0 + (int) value);
- } else {
- mv.visitLdcInsn(value);
- }
- }
+ /** Constant for the {@link #math} method. */
+ public static final int DIV = Opcodes.IDIV;
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final double value) {
- long bits = Double.doubleToLongBits(value);
- if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
- mv.visitInsn(Opcodes.DCONST_0 + (int) value);
- } else {
- mv.visitLdcInsn(value);
- }
- }
+ /** Constant for the {@link #math} method. */
+ public static final int REM = Opcodes.IREM;
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack. May be <tt>null</tt>.
- */
- public void push(final String value) {
- if (value == null) {
- mv.visitInsn(Opcodes.ACONST_NULL);
- } else {
- mv.visitLdcInsn(value);
- }
- }
+ /** Constant for the {@link #math} method. */
+ public static final int NEG = Opcodes.INEG;
- /**
- * Generates the instruction to push the given value on the stack.
- *
- * @param value
- * the value to be pushed on the stack.
- */
- public void push(final Type value) {
- if (value == null) {
- mv.visitInsn(Opcodes.ACONST_NULL);
- } else {
- switch (value.getSort()) {
- case Type.BOOLEAN:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean",
- "TYPE", CLDESC);
- break;
- case Type.CHAR:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character",
- "TYPE", CLDESC);
- break;
- case Type.BYTE:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE",
- CLDESC);
- break;
- case Type.SHORT:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE",
- CLDESC);
- break;
- case Type.INT:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer",
- "TYPE", CLDESC);
- break;
- case Type.FLOAT:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE",
- CLDESC);
- break;
- case Type.LONG:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE",
- CLDESC);
- break;
- case Type.DOUBLE:
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double",
- "TYPE", CLDESC);
- break;
- default:
- mv.visitLdcInsn(value);
- }
- }
- }
+ /** Constant for the {@link #math} method. */
+ public static final int SHL = Opcodes.ISHL;
- /**
- * Generates the instruction to push a handle on the stack.
- *
- * @param handle
- * the handle to be pushed on the stack.
- */
- public void push(final Handle handle) {
- mv.visitLdcInsn(handle);
- }
+ /** Constant for the {@link #math} method. */
+ public static final int SHR = Opcodes.ISHR;
- // ------------------------------------------------------------------------
- // Instructions to load and store method arguments
- // ------------------------------------------------------------------------
-
- /**
- * Returns the index of the given method argument in the frame's local
- * variables array.
- *
- * @param arg
- * the index of a method argument.
- * @return the index of the given method argument in the frame's local
- * variables array.
- */
- private int getArgIndex(final int arg) {
- int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
- for (int i = 0; i < arg; i++) {
- index += argumentTypes[i].getSize();
- }
- return index;
- }
+ /** Constant for the {@link #math} method. */
+ public static final int USHR = Opcodes.IUSHR;
- /**
- * Generates the instruction to push a local variable on the stack.
- *
- * @param type
- * the type of the local variable to be loaded.
- * @param index
- * an index in the frame's local variables array.
- */
- private void loadInsn(final Type type, final int index) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
- }
+ /** Constant for the {@link #math} method. */
+ public static final int AND = Opcodes.IAND;
- /**
- * Generates the instruction to store the top stack value in a local
- * variable.
- *
- * @param type
- * the type of the local variable to be stored.
- * @param index
- * an index in the frame's local variables array.
- */
- private void storeInsn(final Type type, final int index) {
- mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
- }
+ /** Constant for the {@link #math} method. */
+ public static final int OR = Opcodes.IOR;
- /**
- * Generates the instruction to load 'this' on the stack.
- */
- public void loadThis() {
- if ((access & Opcodes.ACC_STATIC) != 0) {
- throw new IllegalStateException(
- "no 'this' pointer within static method");
- }
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- }
+ /** Constant for the {@link #math} method. */
+ public static final int XOR = Opcodes.IXOR;
- /**
- * Generates the instruction to load the given method argument on the stack.
- *
- * @param arg
- * the index of a method argument.
- */
- public void loadArg(final int arg) {
- loadInsn(argumentTypes[arg], getArgIndex(arg));
- }
+ /** Constant for the {@link #ifCmp} method. */
+ public static final int EQ = Opcodes.IFEQ;
- /**
- * Generates the instructions to load the given method arguments on the
- * stack.
- *
- * @param arg
- * the index of the first method argument to be loaded.
- * @param count
- * the number of method arguments to be loaded.
- */
- public void loadArgs(final int arg, final int count) {
- int index = getArgIndex(arg);
- for (int i = 0; i < count; ++i) {
- Type t = argumentTypes[arg + i];
- loadInsn(t, index);
- index += t.getSize();
- }
- }
+ /** Constant for the {@link #ifCmp} method. */
+ public static final int NE = Opcodes.IFNE;
- /**
- * Generates the instructions to load all the method arguments on the stack.
- */
- public void loadArgs() {
- loadArgs(0, argumentTypes.length);
- }
+ /** Constant for the {@link #ifCmp} method. */
+ public static final int LT = Opcodes.IFLT;
- /**
- * Generates the instructions to load all the method arguments on the stack,
- * as a single object array.
- */
- public void loadArgArray() {
- push(argumentTypes.length);
- newArray(OBJECT_TYPE);
- for (int i = 0; i < argumentTypes.length; i++) {
- dup();
- push(i);
- loadArg(i);
- box(argumentTypes[i]);
- arrayStore(OBJECT_TYPE);
- }
- }
+ /** Constant for the {@link #ifCmp} method. */
+ public static final int GE = Opcodes.IFGE;
- /**
- * Generates the instruction to store the top stack value in the given
- * method argument.
- *
- * @param arg
- * the index of a method argument.
- */
- public void storeArg(final int arg) {
- storeInsn(argumentTypes[arg], getArgIndex(arg));
- }
-
- // ------------------------------------------------------------------------
- // Instructions to load and store local variables
- // ------------------------------------------------------------------------
-
- /**
- * Returns the type of the given local variable.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- * @return the type of the given local variable.
- */
- public Type getLocalType(final int local) {
- return localTypes.get(local - firstLocal);
- }
-
- @Override
- protected void setLocalType(final int local, final Type type) {
- int index = local - firstLocal;
- while (localTypes.size() < index + 1) {
- localTypes.add(null);
- }
- localTypes.set(index, type);
- }
-
- /**
- * Generates the instruction to load the given local variable on the stack.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- */
- public void loadLocal(final int local) {
- loadInsn(getLocalType(local), local);
- }
-
- /**
- * Generates the instruction to load the given local variable on the stack.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- * @param type
- * the type of this local variable.
- */
- public void loadLocal(final int local, final Type type) {
- setLocalType(local, type);
- loadInsn(type, local);
- }
-
- /**
- * Generates the instruction to store the top stack value in the given local
- * variable.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- */
- public void storeLocal(final int local) {
- storeInsn(getLocalType(local), local);
- }
-
- /**
- * Generates the instruction to store the top stack value in the given local
- * variable.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- * @param type
- * the type of this local variable.
- */
- public void storeLocal(final int local, final Type type) {
- setLocalType(local, type);
- storeInsn(type, local);
- }
-
- /**
- * Generates the instruction to load an element from an array.
- *
- * @param type
- * the type of the array element to be loaded.
- */
- public void arrayLoad(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
- }
-
- /**
- * Generates the instruction to store an element in an array.
- *
- * @param type
- * the type of the array element to be stored.
- */
- public void arrayStore(final Type type) {
- mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
- }
-
- // ------------------------------------------------------------------------
- // Instructions to manage the stack
- // ------------------------------------------------------------------------
-
- /**
- * Generates a POP instruction.
- */
- public void pop() {
- mv.visitInsn(Opcodes.POP);
- }
-
- /**
- * Generates a POP2 instruction.
- */
- public void pop2() {
- mv.visitInsn(Opcodes.POP2);
- }
-
- /**
- * Generates a DUP instruction.
- */
- public void dup() {
- mv.visitInsn(Opcodes.DUP);
- }
-
- /**
- * Generates a DUP2 instruction.
- */
- public void dup2() {
- mv.visitInsn(Opcodes.DUP2);
- }
-
- /**
- * Generates a DUP_X1 instruction.
- */
- public void dupX1() {
- mv.visitInsn(Opcodes.DUP_X1);
- }
-
- /**
- * Generates a DUP_X2 instruction.
- */
- public void dupX2() {
- mv.visitInsn(Opcodes.DUP_X2);
- }
-
- /**
- * Generates a DUP2_X1 instruction.
- */
- public void dup2X1() {
- mv.visitInsn(Opcodes.DUP2_X1);
- }
-
- /**
- * Generates a DUP2_X2 instruction.
- */
- public void dup2X2() {
- mv.visitInsn(Opcodes.DUP2_X2);
- }
-
- /**
- * Generates a SWAP instruction.
- */
- public void swap() {
- mv.visitInsn(Opcodes.SWAP);
- }
-
- /**
- * Generates the instructions to swap the top two stack values.
- *
- * @param prev
- * type of the top - 1 stack value.
- * @param type
- * type of the top stack value.
- */
- public void swap(final Type prev, final Type type) {
- if (type.getSize() == 1) {
- if (prev.getSize() == 1) {
- swap(); // same as dupX1(), pop();
- } else {
- dupX2();
- pop();
- }
- } else {
- if (prev.getSize() == 1) {
- dup2X1();
- pop2();
- } else {
- dup2X2();
- pop2();
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Instructions to do mathematical and logical operations
- // ------------------------------------------------------------------------
-
- /**
- * Generates the instruction to do the specified mathematical or logical
- * operation.
- *
- * @param op
- * a mathematical or logical operation. Must be one of ADD, SUB,
- * MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR.
- * @param type
- * the type of the operand(s) for this operation.
- */
- public void math(final int op, final Type type) {
- mv.visitInsn(type.getOpcode(op));
- }
-
- /**
- * Generates the instructions to compute the bitwise negation of the top
- * stack value.
- */
- public void not() {
- mv.visitInsn(Opcodes.ICONST_1);
- mv.visitInsn(Opcodes.IXOR);
- }
-
- /**
- * Generates the instruction to increment the given local variable.
- *
- * @param local
- * the local variable to be incremented.
- * @param amount
- * the amount by which the local variable must be incremented.
- */
- public void iinc(final int local, final int amount) {
- mv.visitIincInsn(local, amount);
- }
-
- /**
- * Generates the instructions to cast a numerical value from one type to
- * another.
- *
- * @param from
- * the type of the top stack value
- * @param to
- * the type into which this value must be cast.
- */
- public void cast(final Type from, final Type to) {
- if (from != to) {
- if (from == Type.DOUBLE_TYPE) {
- if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.D2F);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.D2L);
- } else {
- mv.visitInsn(Opcodes.D2I);
- cast(Type.INT_TYPE, to);
- }
- } else if (from == Type.FLOAT_TYPE) {
- if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.F2D);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.F2L);
- } else {
- mv.visitInsn(Opcodes.F2I);
- cast(Type.INT_TYPE, to);
- }
- } else if (from == Type.LONG_TYPE) {
- if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.L2D);
- } else if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.L2F);
- } else {
- mv.visitInsn(Opcodes.L2I);
- cast(Type.INT_TYPE, to);
- }
- } else {
- if (to == Type.BYTE_TYPE) {
- mv.visitInsn(Opcodes.I2B);
- } else if (to == Type.CHAR_TYPE) {
- mv.visitInsn(Opcodes.I2C);
- } else if (to == Type.DOUBLE_TYPE) {
- mv.visitInsn(Opcodes.I2D);
- } else if (to == Type.FLOAT_TYPE) {
- mv.visitInsn(Opcodes.I2F);
- } else if (to == Type.LONG_TYPE) {
- mv.visitInsn(Opcodes.I2L);
- } else if (to == Type.SHORT_TYPE) {
- mv.visitInsn(Opcodes.I2S);
- }
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Instructions to do boxing and unboxing operations
- // ------------------------------------------------------------------------
-
- private static Type getBoxedType(final Type type) {
- switch (type.getSort()) {
- case Type.BYTE:
- return BYTE_TYPE;
+ /** Constant for the {@link #ifCmp} method. */
+ public static final int GT = Opcodes.IFGT;
+
+ /** Constant for the {@link #ifCmp} method. */
+ public static final int LE = Opcodes.IFLE;
+
+ /** The access flags of the visited method. */
+ private final int access;
+
+ /** The name of the visited method. */
+ private final String name;
+
+ /** The return type of the visited method. */
+ private final Type returnType;
+
+ /** The argument types of the visited method. */
+ private final Type[] argumentTypes;
+
+ /** The types of the local variables of the visited method. */
+ private final List<Type> localTypes = new ArrayList<Type>();
+
+ /**
+ * Constructs a new {@link GeneratorAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param methodVisitor the method visitor to which this adapter delegates calls.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ * @throws IllegalStateException if a subclass calls this constructor.
+ */
+ public GeneratorAdapter(
+ final MethodVisitor methodVisitor,
+ final int access,
+ final String name,
+ final String descriptor) {
+ this(Opcodes.ASM7, methodVisitor, access, name, descriptor);
+ if (getClass() != GeneratorAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link GeneratorAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param methodVisitor the method visitor to which this adapter delegates calls.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param descriptor the method's descriptor (see {@link Type}).
+ */
+ protected GeneratorAdapter(
+ final int api,
+ final MethodVisitor methodVisitor,
+ final int access,
+ final String name,
+ final String descriptor) {
+ super(api, access, descriptor, methodVisitor);
+ this.access = access;
+ this.name = name;
+ this.returnType = Type.getReturnType(descriptor);
+ this.argumentTypes = Type.getArgumentTypes(descriptor);
+ }
+
+ /**
+ * Constructs a new {@link GeneratorAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param access access flags of the adapted method.
+ * @param method the adapted method.
+ * @param methodVisitor the method visitor to which this adapter delegates calls.
+ */
+ public GeneratorAdapter(
+ final int access, final Method method, final MethodVisitor methodVisitor) {
+ this(methodVisitor, access, method.getName(), method.getDescriptor());
+ }
+
+ /**
+ * Constructs a new {@link GeneratorAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param access access flags of the adapted method.
+ * @param method the adapted method.
+ * @param signature the signature of the adapted method (may be {@literal null}).
+ * @param exceptions the exceptions thrown by the adapted method (may be {@literal null}).
+ * @param classVisitor the class visitor to which this adapter delegates calls.
+ */
+ public GeneratorAdapter(
+ final int access,
+ final Method method,
+ final String signature,
+ final Type[] exceptions,
+ final ClassVisitor classVisitor) {
+ this(
+ access,
+ method,
+ classVisitor.visitMethod(
+ access,
+ method.getName(),
+ method.getDescriptor(),
+ signature,
+ getInternalNames(exceptions)));
+ }
+
+ /**
+ * Returns the internal names of the given types.
+ *
+ * @param types a set of types.
+ * @return the internal names of the given types.
+ */
+ private static String[] getInternalNames(final Type[] types) {
+ if (types == null) {
+ return null;
+ }
+ String[] names = new String[types.length];
+ for (int i = 0; i < names.length; ++i) {
+ names[i] = types[i].getInternalName();
+ }
+ return names;
+ }
+
+ public int getAccess() {
+ return access;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Type getReturnType() {
+ return returnType;
+ }
+
+ public Type[] getArgumentTypes() {
+ return argumentTypes.clone();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Instructions to push constants on the stack
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value the value to be pushed on the stack.
+ */
+ public void push(final boolean value) {
+ push(value ? 1 : 0);
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value the value to be pushed on the stack.
+ */
+ public void push(final int value) {
+ if (value >= -1 && value <= 5) {
+ mv.visitInsn(Opcodes.ICONST_0 + value);
+ } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.BIPUSH, value);
+ } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.SIPUSH, value);
+ } else {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value the value to be pushed on the stack.
+ */
+ public void push(final long value) {
+ if (value == 0L || value == 1L) {
+ mv.visitInsn(Opcodes.LCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value the value to be pushed on the stack.
+ */
+ public void push(final float value) {
+ int bits = Float.floatToIntBits(value);
+ if (bits == 0L || bits == 0x3F800000 || bits == 0x40000000) { // 0..2
+ mv.visitInsn(Opcodes.FCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value the value to be pushed on the stack.
+ */
+ public void push(final double value) {
+ long bits = Double.doubleToLongBits(value);
+ if (bits == 0L || bits == 0x3FF0000000000000L) { // +0.0d and 1.0d
+ mv.visitInsn(Opcodes.DCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value the value to be pushed on the stack. May be {@literal null}.
+ */
+ public void push(final String value) {
+ if (value == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value the value to be pushed on the stack.
+ */
+ public void push(final Type value) {
+ if (value == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ switch (value.getSort()) {
case Type.BOOLEAN:
- return BOOLEAN_TYPE;
- case Type.SHORT:
- return SHORT_TYPE;
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", CLASS_DESCRIPTOR);
+ break;
case Type.CHAR:
- return CHARACTER_TYPE;
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character", "TYPE", CLASS_DESCRIPTOR);
+ break;
+ case Type.BYTE:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE", CLASS_DESCRIPTOR);
+ break;
+ case Type.SHORT:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE", CLASS_DESCRIPTOR);
+ break;
case Type.INT:
- return INTEGER_TYPE;
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", CLASS_DESCRIPTOR);
+ break;
case Type.FLOAT:
- return FLOAT_TYPE;
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE", CLASS_DESCRIPTOR);
+ break;
case Type.LONG:
- return LONG_TYPE;
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE", CLASS_DESCRIPTOR);
+ break;
case Type.DOUBLE:
- return DOUBLE_TYPE;
- }
- return type;
- }
-
- /**
- * Generates the instructions to box the top stack value. This value is
- * replaced by its boxed equivalent on top of the stack.
- *
- * @param type
- * the type of the top stack value.
- */
- public void box(final Type type) {
- if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
- return;
- }
- if (type == Type.VOID_TYPE) {
- push((String) null);
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double", "TYPE", CLASS_DESCRIPTOR);
+ break;
+ default:
+ mv.visitLdcInsn(value);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Generates the instruction to push a handle on the stack.
+ *
+ * @param handle the handle to be pushed on the stack.
+ */
+ public void push(final Handle handle) {
+ if (handle == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitLdcInsn(handle);
+ }
+ }
+
+ /**
+ * Generates the instruction to push a constant dynamic on the stack.
+ *
+ * @param constantDynamic the constant dynamic to be pushed on the stack.
+ */
+ public void push(final ConstantDynamic constantDynamic) {
+ if (constantDynamic == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitLdcInsn(constantDynamic);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Instructions to load and store method arguments
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the index of the given method argument in the frame's local variables array.
+ *
+ * @param arg the index of a method argument.
+ * @return the index of the given method argument in the frame's local variables array.
+ */
+ private int getArgIndex(final int arg) {
+ int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
+ for (int i = 0; i < arg; i++) {
+ index += argumentTypes[i].getSize();
+ }
+ return index;
+ }
+
+ /**
+ * Generates the instruction to push a local variable on the stack.
+ *
+ * @param type the type of the local variable to be loaded.
+ * @param index an index in the frame's local variables array.
+ */
+ private void loadInsn(final Type type, final int index) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in a local variable.
+ *
+ * @param type the type of the local variable to be stored.
+ * @param index an index in the frame's local variables array.
+ */
+ private void storeInsn(final Type type, final int index) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
+ }
+
+ /** Generates the instruction to load 'this' on the stack. */
+ public void loadThis() {
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ throw new IllegalStateException("no 'this' pointer within static method");
+ }
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ }
+
+ /**
+ * Generates the instruction to load the given method argument on the stack.
+ *
+ * @param arg the index of a method argument.
+ */
+ public void loadArg(final int arg) {
+ loadInsn(argumentTypes[arg], getArgIndex(arg));
+ }
+
+ /**
+ * Generates the instructions to load the given method arguments on the stack.
+ *
+ * @param arg the index of the first method argument to be loaded.
+ * @param count the number of method arguments to be loaded.
+ */
+ public void loadArgs(final int arg, final int count) {
+ int index = getArgIndex(arg);
+ for (int i = 0; i < count; ++i) {
+ Type argumentType = argumentTypes[arg + i];
+ loadInsn(argumentType, index);
+ index += argumentType.getSize();
+ }
+ }
+
+ /** Generates the instructions to load all the method arguments on the stack. */
+ public void loadArgs() {
+ loadArgs(0, argumentTypes.length);
+ }
+
+ /**
+ * Generates the instructions to load all the method arguments on the stack, as a single object
+ * array.
+ */
+ public void loadArgArray() {
+ push(argumentTypes.length);
+ newArray(OBJECT_TYPE);
+ for (int i = 0; i < argumentTypes.length; i++) {
+ dup();
+ push(i);
+ loadArg(i);
+ box(argumentTypes[i]);
+ arrayStore(OBJECT_TYPE);
+ }
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given method argument.
+ *
+ * @param arg the index of a method argument.
+ */
+ public void storeArg(final int arg) {
+ storeInsn(argumentTypes[arg], getArgIndex(arg));
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Instructions to load and store local variables
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the type of the given local variable.
+ *
+ * @param local a local variable identifier, as returned by {@link
+ * LocalVariablesSorter#newLocal(Type)}.
+ * @return the type of the given local variable.
+ */
+ public Type getLocalType(final int local) {
+ return localTypes.get(local - firstLocal);
+ }
+
+ @Override
+ protected void setLocalType(final int local, final Type type) {
+ int index = local - firstLocal;
+ while (localTypes.size() < index + 1) {
+ localTypes.add(null);
+ }
+ localTypes.set(index, type);
+ }
+
+ /**
+ * Generates the instruction to load the given local variable on the stack.
+ *
+ * @param local a local variable identifier, as returned by {@link
+ * LocalVariablesSorter#newLocal(Type)}.
+ */
+ public void loadLocal(final int local) {
+ loadInsn(getLocalType(local), local);
+ }
+
+ /**
+ * Generates the instruction to load the given local variable on the stack.
+ *
+ * @param local a local variable identifier, as returned by {@link
+ * LocalVariablesSorter#newLocal(Type)}.
+ * @param type the type of this local variable.
+ */
+ public void loadLocal(final int local, final Type type) {
+ setLocalType(local, type);
+ loadInsn(type, local);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given local variable.
+ *
+ * @param local a local variable identifier, as returned by {@link
+ * LocalVariablesSorter#newLocal(Type)}.
+ */
+ public void storeLocal(final int local) {
+ storeInsn(getLocalType(local), local);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given local variable.
+ *
+ * @param local a local variable identifier, as returned by {@link
+ * LocalVariablesSorter#newLocal(Type)}.
+ * @param type the type of this local variable.
+ */
+ public void storeLocal(final int local, final Type type) {
+ setLocalType(local, type);
+ storeInsn(type, local);
+ }
+
+ /**
+ * Generates the instruction to load an element from an array.
+ *
+ * @param type the type of the array element to be loaded.
+ */
+ public void arrayLoad(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+ }
+
+ /**
+ * Generates the instruction to store an element in an array.
+ *
+ * @param type the type of the array element to be stored.
+ */
+ public void arrayStore(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Instructions to manage the stack
+ // -----------------------------------------------------------------------------------------------
+
+ /** Generates a POP instruction. */
+ public void pop() {
+ mv.visitInsn(Opcodes.POP);
+ }
+
+ /** Generates a POP2 instruction. */
+ public void pop2() {
+ mv.visitInsn(Opcodes.POP2);
+ }
+
+ /** Generates a DUP instruction. */
+ public void dup() {
+ mv.visitInsn(Opcodes.DUP);
+ }
+
+ /** Generates a DUP2 instruction. */
+ public void dup2() {
+ mv.visitInsn(Opcodes.DUP2);
+ }
+
+ /** Generates a DUP_X1 instruction. */
+ public void dupX1() {
+ mv.visitInsn(Opcodes.DUP_X1);
+ }
+
+ /** Generates a DUP_X2 instruction. */
+ public void dupX2() {
+ mv.visitInsn(Opcodes.DUP_X2);
+ }
+
+ /** Generates a DUP2_X1 instruction. */
+ public void dup2X1() {
+ mv.visitInsn(Opcodes.DUP2_X1);
+ }
+
+ /** Generates a DUP2_X2 instruction. */
+ public void dup2X2() {
+ mv.visitInsn(Opcodes.DUP2_X2);
+ }
+
+ /** Generates a SWAP instruction. */
+ public void swap() {
+ mv.visitInsn(Opcodes.SWAP);
+ }
+
+ /**
+ * Generates the instructions to swap the top two stack values.
+ *
+ * @param prev type of the top - 1 stack value.
+ * @param type type of the top stack value.
+ */
+ public void swap(final Type prev, final Type type) {
+ if (type.getSize() == 1) {
+ if (prev.getSize() == 1) {
+ swap(); // Same as dupX1 pop.
+ } else {
+ dupX2();
+ pop();
+ }
+ } else {
+ if (prev.getSize() == 1) {
+ dup2X1();
+ pop2();
+ } else {
+ dup2X2();
+ pop2();
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Instructions to do mathematical and logical operations
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Generates the instruction to do the specified mathematical or logical operation.
+ *
+ * @param op a mathematical or logical operation. Must be one of ADD, SUB, MUL, DIV, REM, NEG,
+ * SHL, SHR, USHR, AND, OR, XOR.
+ * @param type the type of the operand(s) for this operation.
+ */
+ public void math(final int op, final Type type) {
+ mv.visitInsn(type.getOpcode(op));
+ }
+
+ /** Generates the instructions to compute the bitwise negation of the top stack value. */
+ public void not() {
+ mv.visitInsn(Opcodes.ICONST_1);
+ mv.visitInsn(Opcodes.IXOR);
+ }
+
+ /**
+ * Generates the instruction to increment the given local variable.
+ *
+ * @param local the local variable to be incremented.
+ * @param amount the amount by which the local variable must be incremented.
+ */
+ public void iinc(final int local, final int amount) {
+ mv.visitIincInsn(local, amount);
+ }
+
+ /**
+ * Generates the instructions to cast a numerical value from one type to another.
+ *
+ * @param from the type of the top stack value
+ * @param to the type into which this value must be cast.
+ */
+ public void cast(final Type from, final Type to) {
+ if (from != to) {
+ if (from.getSort() < Type.BOOLEAN
+ || from.getSort() > Type.DOUBLE
+ || to.getSort() < Type.BOOLEAN
+ || to.getSort() > Type.DOUBLE) {
+ throw new IllegalArgumentException("Cannot cast from " + from + " to " + to);
+ }
+ if (from == Type.DOUBLE_TYPE) {
+ if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.D2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.D2L);
} else {
- Type boxed = getBoxedType(type);
- newInstance(boxed);
- if (type.getSize() == 2) {
- // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
- dupX2();
- dupX2();
- pop();
- } else {
- // p -> po -> opo -> oop -> o
- dupX1();
- swap();
- }
- invokeConstructor(boxed, new Method("<init>", Type.VOID_TYPE,
- new Type[] { type }));
- }
- }
-
- /**
- * Generates the instructions to box the top stack value using Java 5's
- * valueOf() method. This value is replaced by its boxed equivalent on top
- * of the stack.
- *
- * @param type
- * the type of the top stack value.
- */
- public void valueOf(final Type type) {
- if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
- return;
+ mv.visitInsn(Opcodes.D2I);
+ cast(Type.INT_TYPE, to);
}
- if (type == Type.VOID_TYPE) {
- push((String) null);
+ } else if (from == Type.FLOAT_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.F2D);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.F2L);
} else {
- Type boxed = getBoxedType(type);
- invokeStatic(boxed, new Method("valueOf", boxed,
- new Type[] { type }));
- }
- }
-
- /**
- * Generates the instructions to unbox the top stack value. This value is
- * replaced by its unboxed equivalent on top of the stack.
- *
- * @param type
- * the type of the top stack value.
- */
- public void unbox(final Type type) {
- Type t = NUMBER_TYPE;
- Method sig = null;
- switch (type.getSort()) {
- case Type.VOID:
- return;
- case Type.CHAR:
- t = CHARACTER_TYPE;
- sig = CHAR_VALUE;
- break;
- case Type.BOOLEAN:
- t = BOOLEAN_TYPE;
- sig = BOOLEAN_VALUE;
- break;
- case Type.DOUBLE:
- sig = DOUBLE_VALUE;
- break;
- case Type.FLOAT:
- sig = FLOAT_VALUE;
- break;
- case Type.LONG:
- sig = LONG_VALUE;
- break;
- case Type.INT:
- case Type.SHORT:
- case Type.BYTE:
- sig = INT_VALUE;
+ mv.visitInsn(Opcodes.F2I);
+ cast(Type.INT_TYPE, to);
}
- if (sig == null) {
- checkCast(type);
+ } else if (from == Type.LONG_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.L2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.L2F);
} else {
- checkCast(t);
- invokeVirtual(t, sig);
+ mv.visitInsn(Opcodes.L2I);
+ cast(Type.INT_TYPE, to);
}
- }
-
- // ------------------------------------------------------------------------
- // Instructions to jump to other instructions
- // ------------------------------------------------------------------------
-
- /**
- * Creates a new {@link Label}.
- *
- * @return a new {@link Label}.
- */
- public Label newLabel() {
- return new Label();
- }
-
- /**
- * Marks the current code position with the given label.
- *
- * @param label
- * a label.
- */
- public void mark(final Label label) {
- mv.visitLabel(label);
- }
-
- /**
- * Marks the current code position with a new label.
- *
- * @return the label that was created to mark the current code position.
- */
- public Label mark() {
- Label label = new Label();
- mv.visitLabel(label);
- return label;
- }
-
- /**
- * Generates the instructions to jump to a label based on the comparison of
- * the top two stack values.
- *
- * @param type
- * the type of the top two stack values.
- * @param mode
- * how these values must be compared. One of EQ, NE, LT, GE, GT,
- * LE.
- * @param label
- * where to jump if the comparison result is <tt>true</tt>.
- */
- public void ifCmp(final Type type, final int mode, final Label label) {
- switch (type.getSort()) {
- case Type.LONG:
- mv.visitInsn(Opcodes.LCMP);
- break;
- case Type.DOUBLE:
- mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL
- : Opcodes.DCMPG);
- break;
- case Type.FLOAT:
- mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL
- : Opcodes.FCMPG);
- break;
- case Type.ARRAY:
- case Type.OBJECT:
- switch (mode) {
- case EQ:
- mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
- return;
- case NE:
- mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
- return;
- }
- throw new IllegalArgumentException("Bad comparison for type "
- + type);
- default:
- int intOp = -1;
- switch (mode) {
- case EQ:
- intOp = Opcodes.IF_ICMPEQ;
- break;
- case NE:
- intOp = Opcodes.IF_ICMPNE;
- break;
- case GE:
- intOp = Opcodes.IF_ICMPGE;
- break;
- case LT:
- intOp = Opcodes.IF_ICMPLT;
- break;
- case LE:
- intOp = Opcodes.IF_ICMPLE;
- break;
- case GT:
- intOp = Opcodes.IF_ICMPGT;
- break;
- }
- mv.visitJumpInsn(intOp, label);
- return;
+ } else {
+ if (to == Type.BYTE_TYPE) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (to == Type.CHAR_TYPE) {
+ mv.visitInsn(Opcodes.I2C);
+ } else if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.I2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.I2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.I2L);
+ } else if (to == Type.SHORT_TYPE) {
+ mv.visitInsn(Opcodes.I2S);
}
- mv.visitJumpInsn(mode, label);
- }
-
- /**
- * Generates the instructions to jump to a label based on the comparison of
- * the top two integer stack values.
- *
- * @param mode
- * how these values must be compared. One of EQ, NE, LT, GE, GT,
- * LE.
- * @param label
- * where to jump if the comparison result is <tt>true</tt>.
- */
- public void ifICmp(final int mode, final Label label) {
- ifCmp(Type.INT_TYPE, mode, label);
- }
-
- /**
- * Generates the instructions to jump to a label based on the comparison of
- * the top integer stack value with zero.
- *
- * @param mode
- * how these values must be compared. One of EQ, NE, LT, GE, GT,
- * LE.
- * @param label
- * where to jump if the comparison result is <tt>true</tt>.
- */
- public void ifZCmp(final int mode, final Label label) {
- mv.visitJumpInsn(mode, label);
- }
-
- /**
- * Generates the instruction to jump to the given label if the top stack
- * value is null.
- *
- * @param label
- * where to jump if the condition is <tt>true</tt>.
- */
- public void ifNull(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNULL, label);
- }
-
- /**
- * Generates the instruction to jump to the given label if the top stack
- * value is not null.
- *
- * @param label
- * where to jump if the condition is <tt>true</tt>.
- */
- public void ifNonNull(final Label label) {
- mv.visitJumpInsn(Opcodes.IFNONNULL, label);
- }
-
- /**
- * Generates the instruction to jump to the given label.
- *
- * @param label
- * where to jump if the condition is <tt>true</tt>.
- */
- public void goTo(final Label label) {
- mv.visitJumpInsn(Opcodes.GOTO, label);
- }
-
- /**
- * Generates a RET instruction.
- *
- * @param local
- * a local variable identifier, as returned by
- * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
- */
- public void ret(final int local) {
- mv.visitVarInsn(Opcodes.RET, local);
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Instructions to do boxing and unboxing operations
+ // -----------------------------------------------------------------------------------------------
+
+ private static Type getBoxedType(final Type type) {
+ switch (type.getSort()) {
+ case Type.BYTE:
+ return BYTE_TYPE;
+ case Type.BOOLEAN:
+ return BOOLEAN_TYPE;
+ case Type.SHORT:
+ return SHORT_TYPE;
+ case Type.CHAR:
+ return CHARACTER_TYPE;
+ case Type.INT:
+ return INTEGER_TYPE;
+ case Type.FLOAT:
+ return FLOAT_TYPE;
+ case Type.LONG:
+ return LONG_TYPE;
+ case Type.DOUBLE:
+ return DOUBLE_TYPE;
+ default:
+ return type;
}
-
- /**
- * Generates the instructions for a switch statement.
- *
- * @param keys
- * the switch case keys.
- * @param generator
- * a generator to generate the code for the switch cases.
- */
- public void tableSwitch(final int[] keys,
- final TableSwitchGenerator generator) {
- float density;
- if (keys.length == 0) {
- density = 0;
+ }
+
+ /**
+ * Generates the instructions to box the top stack value. This value is replaced by its boxed
+ * equivalent on top of the stack.
+ *
+ * @param type the type of the top stack value.
+ */
+ public void box(final Type type) {
+ if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+ return;
+ }
+ if (type == Type.VOID_TYPE) {
+ push((String) null);
+ } else {
+ Type boxedType = getBoxedType(type);
+ newInstance(boxedType);
+ if (type.getSize() == 2) {
+ // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
+ dupX2();
+ dupX2();
+ pop();
+ } else {
+ // p -> po -> opo -> oop -> o
+ dupX1();
+ swap();
+ }
+ invokeConstructor(boxedType, new Method("<init>", Type.VOID_TYPE, new Type[] {type}));
+ }
+ }
+
+ /**
+ * Generates the instructions to box the top stack value using Java 5's valueOf() method. This
+ * value is replaced by its boxed equivalent on top of the stack.
+ *
+ * @param type the type of the top stack value.
+ */
+ public void valueOf(final Type type) {
+ if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+ return;
+ }
+ if (type == Type.VOID_TYPE) {
+ push((String) null);
+ } else {
+ Type boxedType = getBoxedType(type);
+ invokeStatic(boxedType, new Method("valueOf", boxedType, new Type[] {type}));
+ }
+ }
+
+ /**
+ * Generates the instructions to unbox the top stack value. This value is replaced by its unboxed
+ * equivalent on top of the stack.
+ *
+ * @param type the type of the top stack value.
+ */
+ public void unbox(final Type type) {
+ Type boxedType = NUMBER_TYPE;
+ Method unboxMethod;
+ switch (type.getSort()) {
+ case Type.VOID:
+ return;
+ case Type.CHAR:
+ boxedType = CHARACTER_TYPE;
+ unboxMethod = CHAR_VALUE;
+ break;
+ case Type.BOOLEAN:
+ boxedType = BOOLEAN_TYPE;
+ unboxMethod = BOOLEAN_VALUE;
+ break;
+ case Type.DOUBLE:
+ unboxMethod = DOUBLE_VALUE;
+ break;
+ case Type.FLOAT:
+ unboxMethod = FLOAT_VALUE;
+ break;
+ case Type.LONG:
+ unboxMethod = LONG_VALUE;
+ break;
+ case Type.INT:
+ case Type.SHORT:
+ case Type.BYTE:
+ unboxMethod = INT_VALUE;
+ break;
+ default:
+ unboxMethod = null;
+ break;
+ }
+ if (unboxMethod == null) {
+ checkCast(type);
+ } else {
+ checkCast(boxedType);
+ invokeVirtual(boxedType, unboxMethod);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Instructions to jump to other instructions
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link Label}.
+ *
+ * @return a new {@link Label}.
+ */
+ public Label newLabel() {
+ return new Label();
+ }
+
+ /**
+ * Marks the current code position with the given label.
+ *
+ * @param label a label.
+ */
+ public void mark(final Label label) {
+ mv.visitLabel(label);
+ }
+
+ /**
+ * Marks the current code position with a new label.
+ *
+ * @return the label that was created to mark the current code position.
+ */
+ public Label mark() {
+ Label label = new Label();
+ mv.visitLabel(label);
+ return label;
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of the top two stack
+ * values.
+ *
+ * @param type the type of the top two stack values.
+ * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT, LE.
+ * @param label where to jump if the comparison result is {@literal true}.
+ */
+ public void ifCmp(final Type type, final int mode, final Label label) {
+ switch (type.getSort()) {
+ case Type.LONG:
+ mv.visitInsn(Opcodes.LCMP);
+ break;
+ case Type.DOUBLE:
+ mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL : Opcodes.DCMPG);
+ break;
+ case Type.FLOAT:
+ mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL : Opcodes.FCMPG);
+ break;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ if (mode == EQ) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+ return;
+ } else if (mode == NE) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+ return;
} else {
- density = (float) keys.length
- / (keys[keys.length - 1] - keys[0] + 1);
- }
- tableSwitch(keys, generator, density >= 0.5f);
- }
-
- /**
- * Generates the instructions for a switch statement.
- *
- * @param keys
- * the switch case keys.
- * @param generator
- * a generator to generate the code for the switch cases.
- * @param useTable
- * <tt>true</tt> to use a TABLESWITCH instruction, or
- * <tt>false</tt> to use a LOOKUPSWITCH instruction.
- */
- public void tableSwitch(final int[] keys,
- final TableSwitchGenerator generator, final boolean useTable) {
- for (int i = 1; i < keys.length; ++i) {
- if (keys[i] < keys[i - 1]) {
- throw new IllegalArgumentException(
- "keys must be sorted ascending");
- }
- }
- Label def = newLabel();
- Label end = newLabel();
- if (keys.length > 0) {
- int len = keys.length;
- int min = keys[0];
- int max = keys[len - 1];
- int range = max - min + 1;
- if (useTable) {
- Label[] labels = new Label[range];
- Arrays.fill(labels, def);
- for (int i = 0; i < len; ++i) {
- labels[keys[i] - min] = newLabel();
- }
- mv.visitTableSwitchInsn(min, max, def, labels);
- for (int i = 0; i < range; ++i) {
- Label label = labels[i];
- if (label != def) {
- mark(label);
- generator.generateCase(i + min, end);
- }
- }
- } else {
- Label[] labels = new Label[len];
- for (int i = 0; i < len; ++i) {
- labels[i] = newLabel();
- }
- mv.visitLookupSwitchInsn(def, keys, labels);
- for (int i = 0; i < len; ++i) {
- mark(labels[i]);
- generator.generateCase(keys[i], end);
- }
- }
+ throw new IllegalArgumentException("Bad comparison for type " + type);
}
- mark(def);
- generator.generateDefault();
- mark(end);
- }
-
- /**
- * Generates the instruction to return the top stack value to the caller.
- */
- public void returnValue() {
- mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
- }
-
- // ------------------------------------------------------------------------
- // Instructions to load and store fields
- // ------------------------------------------------------------------------
-
- /**
- * Generates a get field or set field instruction.
- *
- * @param opcode
- * the instruction's opcode.
- * @param ownerType
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param fieldType
- * the type of the field.
- */
- private void fieldInsn(final int opcode, final Type ownerType,
- final String name, final Type fieldType) {
- mv.visitFieldInsn(opcode, ownerType.getInternalName(), name,
- fieldType.getDescriptor());
- }
-
- /**
- * Generates the instruction to push the value of a static field on the
- * stack.
- *
- * @param owner
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param type
- * the type of the field.
- */
- public void getStatic(final Type owner, final String name, final Type type) {
- fieldInsn(Opcodes.GETSTATIC, owner, name, type);
- }
-
- /**
- * Generates the instruction to store the top stack value in a static field.
- *
- * @param owner
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param type
- * the type of the field.
- */
- public void putStatic(final Type owner, final String name, final Type type) {
- fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
- }
-
- /**
- * Generates the instruction to push the value of a non static field on the
- * stack.
- *
- * @param owner
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param type
- * the type of the field.
- */
- public void getField(final Type owner, final String name, final Type type) {
- fieldInsn(Opcodes.GETFIELD, owner, name, type);
- }
-
- /**
- * Generates the instruction to store the top stack value in a non static
- * field.
- *
- * @param owner
- * the class in which the field is defined.
- * @param name
- * the name of the field.
- * @param type
- * the type of the field.
- */
- public void putField(final Type owner, final String name, final Type type) {
- fieldInsn(Opcodes.PUTFIELD, owner, name, type);
- }
-
- // ------------------------------------------------------------------------
- // Instructions to invoke methods
- // ------------------------------------------------------------------------
-
- /**
- * Generates an invoke method instruction.
- *
- * @param opcode
- * the instruction's opcode.
- * @param type
- * the class in which the method is defined.
- * @param method
- * the method to be invoked.
- */
- private void invokeInsn(final int opcode, final Type type,
- final Method method, final boolean itf) {
- String owner = type.getSort() == Type.ARRAY ? type.getDescriptor()
- : type.getInternalName();
- mv.visitMethodInsn(opcode, owner, method.getName(),
- method.getDescriptor(), itf);
- }
-
- /**
- * Generates the instruction to invoke a normal method.
- *
- * @param owner
- * the class in which the method is defined.
- * @param method
- * the method to be invoked.
- */
- public void invokeVirtual(final Type owner, final Method method) {
- invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method, false);
- }
-
- /**
- * Generates the instruction to invoke a constructor.
- *
- * @param type
- * the class in which the constructor is defined.
- * @param method
- * the constructor to be invoked.
- */
- public void invokeConstructor(final Type type, final Method method) {
- invokeInsn(Opcodes.INVOKESPECIAL, type, method, false);
- }
-
- /**
- * Generates the instruction to invoke a static method.
- *
- * @param owner
- * the class in which the method is defined.
- * @param method
- * the method to be invoked.
- */
- public void invokeStatic(final Type owner, final Method method) {
- invokeInsn(Opcodes.INVOKESTATIC, owner, method, false);
- }
-
- /**
- * Generates the instruction to invoke an interface method.
- *
- * @param owner
- * the class in which the method is defined.
- * @param method
- * the method to be invoked.
- */
- public void invokeInterface(final Type owner, final Method method) {
- invokeInsn(Opcodes.INVOKEINTERFACE, owner, method, true);
- }
-
- /**
- * Generates an invokedynamic instruction.
- *
- * @param name
- * the method's name.
- * @param desc
- * the method's descriptor (see {@link Type Type}).
- * @param bsm
- * the bootstrap method.
- * @param bsmArgs
- * the bootstrap method constant arguments. Each argument must be
- * an {@link Integer}, {@link Float}, {@link Long},
- * {@link Double}, {@link String}, {@link Type} or {@link Handle}
- * value. This method is allowed to modify the content of the
- * array so a caller should expect that this array may change.
- */
- public void invokeDynamic(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
-
- // ------------------------------------------------------------------------
- // Instructions to create objects and arrays
- // ------------------------------------------------------------------------
-
- /**
- * Generates a type dependent instruction.
- *
- * @param opcode
- * the instruction's opcode.
- * @param type
- * the instruction's operand.
- */
- private void typeInsn(final int opcode, final Type type) {
- mv.visitTypeInsn(opcode, type.getInternalName());
- }
-
- /**
- * Generates the instruction to create a new object.
- *
- * @param type
- * the class of the object to be created.
- */
- public void newInstance(final Type type) {
- typeInsn(Opcodes.NEW, type);
- }
-
- /**
- * Generates the instruction to create a new array.
- *
- * @param type
- * the type of the array elements.
- */
- public void newArray(final Type type) {
- int typ;
- switch (type.getSort()) {
- case Type.BOOLEAN:
- typ = Opcodes.T_BOOLEAN;
+ default:
+ int intOp = -1;
+ switch (mode) {
+ case EQ:
+ intOp = Opcodes.IF_ICMPEQ;
break;
- case Type.CHAR:
- typ = Opcodes.T_CHAR;
+ case NE:
+ intOp = Opcodes.IF_ICMPNE;
break;
- case Type.BYTE:
- typ = Opcodes.T_BYTE;
+ case GE:
+ intOp = Opcodes.IF_ICMPGE;
break;
- case Type.SHORT:
- typ = Opcodes.T_SHORT;
+ case LT:
+ intOp = Opcodes.IF_ICMPLT;
break;
- case Type.INT:
- typ = Opcodes.T_INT;
+ case LE:
+ intOp = Opcodes.IF_ICMPLE;
break;
- case Type.FLOAT:
- typ = Opcodes.T_FLOAT;
- break;
- case Type.LONG:
- typ = Opcodes.T_LONG;
- break;
- case Type.DOUBLE:
- typ = Opcodes.T_DOUBLE;
+ case GT:
+ intOp = Opcodes.IF_ICMPGT;
break;
- default:
- typeInsn(Opcodes.ANEWARRAY, type);
- return;
+ default:
+ throw new IllegalArgumentException("Bad comparison mode " + mode);
}
- mv.visitIntInsn(Opcodes.NEWARRAY, typ);
- }
-
- // ------------------------------------------------------------------------
- // Miscelaneous instructions
- // ------------------------------------------------------------------------
-
- /**
- * Generates the instruction to compute the length of an array.
- */
- public void arrayLength() {
- mv.visitInsn(Opcodes.ARRAYLENGTH);
- }
-
- /**
- * Generates the instruction to throw an exception.
- */
- public void throwException() {
- mv.visitInsn(Opcodes.ATHROW);
- }
-
- /**
- * Generates the instructions to create and throw an exception. The
- * exception class must have a constructor with a single String argument.
- *
- * @param type
- * the class of the exception to be thrown.
- * @param msg
- * the detailed message of the exception.
- */
- public void throwException(final Type type, final String msg) {
- newInstance(type);
- dup();
- push(msg);
- invokeConstructor(type, Method.getMethod("void <init> (String)"));
- throwException();
- }
-
- /**
- * Generates the instruction to check that the top stack value is of the
- * given type.
- *
- * @param type
- * a class or interface type.
- */
- public void checkCast(final Type type) {
- if (!type.equals(OBJECT_TYPE)) {
- typeInsn(Opcodes.CHECKCAST, type);
+ mv.visitJumpInsn(intOp, label);
+ return;
+ }
+ mv.visitJumpInsn(mode, label);
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of the top two integer
+ * stack values.
+ *
+ * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT, LE.
+ * @param label where to jump if the comparison result is {@literal true}.
+ */
+ public void ifICmp(final int mode, final Label label) {
+ ifCmp(Type.INT_TYPE, mode, label);
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of the top integer stack
+ * value with zero.
+ *
+ * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT, LE.
+ * @param label where to jump if the comparison result is {@literal true}.
+ */
+ public void ifZCmp(final int mode, final Label label) {
+ mv.visitJumpInsn(mode, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label if the top stack value is null.
+ *
+ * @param label where to jump if the condition is {@literal true}.
+ */
+ public void ifNull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNULL, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label if the top stack value is not null.
+ *
+ * @param label where to jump if the condition is {@literal true}.
+ */
+ public void ifNonNull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label.
+ *
+ * @param label where to jump if the condition is {@literal true}.
+ */
+ public void goTo(final Label label) {
+ mv.visitJumpInsn(Opcodes.GOTO, label);
+ }
+
+ /**
+ * Generates a RET instruction.
+ *
+ * @param local a local variable identifier, as returned by {@link
+ * LocalVariablesSorter#newLocal(Type)}.
+ */
+ public void ret(final int local) {
+ mv.visitVarInsn(Opcodes.RET, local);
+ }
+
+ /**
+ * Generates the instructions for a switch statement.
+ *
+ * @param keys the switch case keys.
+ * @param generator a generator to generate the code for the switch cases.
+ */
+ public void tableSwitch(final int[] keys, final TableSwitchGenerator generator) {
+ float density;
+ if (keys.length == 0) {
+ density = 0;
+ } else {
+ density = (float) keys.length / (keys[keys.length - 1] - keys[0] + 1);
+ }
+ tableSwitch(keys, generator, density >= 0.5f);
+ }
+
+ /**
+ * Generates the instructions for a switch statement.
+ *
+ * @param keys the switch case keys.
+ * @param generator a generator to generate the code for the switch cases.
+ * @param useTable {@literal true} to use a TABLESWITCH instruction, or {@literal false} to use a
+ * LOOKUPSWITCH instruction.
+ */
+ public void tableSwitch(
+ final int[] keys, final TableSwitchGenerator generator, final boolean useTable) {
+ for (int i = 1; i < keys.length; ++i) {
+ if (keys[i] < keys[i - 1]) {
+ throw new IllegalArgumentException("keys must be sorted in ascending order");
+ }
+ }
+ Label defaultLabel = newLabel();
+ Label endLabel = newLabel();
+ if (keys.length > 0) {
+ int numKeys = keys.length;
+ if (useTable) {
+ int min = keys[0];
+ int max = keys[numKeys - 1];
+ int range = max - min + 1;
+ Label[] labels = new Label[range];
+ Arrays.fill(labels, defaultLabel);
+ for (int i = 0; i < numKeys; ++i) {
+ labels[keys[i] - min] = newLabel();
}
- }
-
- /**
- * Generates the instruction to test if the top stack value is of the given
- * type.
- *
- * @param type
- * a class or interface type.
- */
- public void instanceOf(final Type type) {
- typeInsn(Opcodes.INSTANCEOF, type);
- }
-
- /**
- * Generates the instruction to get the monitor of the top stack value.
- */
- public void monitorEnter() {
- mv.visitInsn(Opcodes.MONITORENTER);
- }
-
- /**
- * Generates the instruction to release the monitor of the top stack value.
- */
- public void monitorExit() {
- mv.visitInsn(Opcodes.MONITOREXIT);
- }
-
- // ------------------------------------------------------------------------
- // Non instructions
- // ------------------------------------------------------------------------
-
- /**
- * Marks the end of the visited method.
- */
- public void endMethod() {
- if ((access & Opcodes.ACC_ABSTRACT) == 0) {
- mv.visitMaxs(0, 0);
+ mv.visitTableSwitchInsn(min, max, defaultLabel, labels);
+ for (int i = 0; i < range; ++i) {
+ Label label = labels[i];
+ if (label != defaultLabel) {
+ mark(label);
+ generator.generateCase(i + min, endLabel);
+ }
}
- mv.visitEnd();
- }
-
- /**
- * Marks the start of an exception handler.
- *
- * @param start
- * beginning of the exception handler's scope (inclusive).
- * @param end
- * end of the exception handler's scope (exclusive).
- * @param exception
- * internal name of the type of exceptions handled by the
- * handler.
- */
- public void catchException(final Label start, final Label end,
- final Type exception) {
- Label doCatch = new Label();
- if (exception == null) {
- mv.visitTryCatchBlock(start, end, doCatch, null);
- } else {
- mv.visitTryCatchBlock(start, end, doCatch,
- exception.getInternalName());
+ } else {
+ Label[] labels = new Label[numKeys];
+ for (int i = 0; i < numKeys; ++i) {
+ labels[i] = newLabel();
}
- mark(doCatch);
- }
+ mv.visitLookupSwitchInsn(defaultLabel, keys, labels);
+ for (int i = 0; i < numKeys; ++i) {
+ mark(labels[i]);
+ generator.generateCase(keys[i], endLabel);
+ }
+ }
+ }
+ mark(defaultLabel);
+ generator.generateDefault();
+ mark(endLabel);
+ }
+
+ /** Generates the instruction to return the top stack value to the caller. */
+ public void returnValue() {
+ mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Instructions to load and store fields
+ // -----------------------------------------------------------------------------------------------
+
+
<TRUNCATED>