Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / services / bytecode / BCClass.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java
new file mode 100644 (file)
index 0000000..4aa130d
--- /dev/null
@@ -0,0 +1,465 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.services.bytecode.BCClass\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.services.bytecode;\r
+\r
+import org.apache.derby.iapi.services.compiler.ClassBuilder;\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.compiler.LocalField;\r
+\r
+import org.apache.derby.iapi.services.classfile.ClassHolder;\r
+import org.apache.derby.iapi.services.classfile.ClassMember;\r
+import org.apache.derby.iapi.services.classfile.ClassFormatOutput;\r
+import org.apache.derby.iapi.services.loader.ClassFactory;\r
+\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.Property;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.util.ByteArray;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.lang.reflect.Modifier;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.services.classfile.VMDescriptor;\r
+\r
+import org.apache.derby.impl.services.bytecode.GClass;\r
+\r
+import java.io.IOException;\r
+\r
+/**\r
+ * ClassBuilder is used to construct a java class's byte array\r
+ * representation.\r
+ *\r
+ * Limitations:\r
+ *   No checking for language use violations such as invalid modifiers\r
+ *     or duplicate field names.\r
+ *   All classes must have a superclass; java.lang.Object must be\r
+ *      supplied if there is no superclass.\r
+ *\r
+ * <p>\r
+ * When a class is first created, it has:\r
+ * <ul>\r
+ * <li> a superclass\r
+ * <li> modifiers\r
+ * <li> a name\r
+ * <li> a package\r
+ * <li> no superinterfaces, methods, fields, or constructors\r
+ * <li> an empty static initializer\r
+ * <li> an empty initializer\r
+ * </ul>\r
+ * <p>\r
+ * MethodBuilder implementations are required to supply a way for\r
+ * Generators to give them code.  Most typically, they may have\r
+ * a stream to which the Generator writes the code that is of\r
+ * the type to satisfy what the Generator is writing.\r
+ * <p>\r
+ * BCClass is a ClassBuilder implementation for generating java bytecode\r
+ * directly.\r
+ *\r
+ */\r
+class BCClass extends GClass {\r
+       \r
+       /**\r
+        * Simple text indicating any limits execeeded while generating\r
+        * the class file.\r
+        */\r
+       String limitMsg;\r
+       \r
+       //\r
+       // ClassBuilder interface\r
+       //\r
+       /**\r
+        * add a field to this class. Fields cannot\r
+        * be initialized here, they must be initialized\r
+        * in the static initializer code (static fields)\r
+        * or in the constructors.\r
+        * <p>\r
+        * static fields also added to this list,\r
+        * with the modifier set appropriately.\r
+        */\r
+       public LocalField addField(String javaType, String name, int modifiers) {\r
+\r
+               Type type = factory.type(javaType);\r
+               // put it into the class holder right away.\r
+               ClassMember field = classHold.addMember(name, type.vmName(), modifiers);\r
+               int cpi = classHold.addFieldReference(field);\r
+\r
+               return new BCLocalField(type, cpi);\r
+       }\r
+\r
+       /**\r
+        * At the time the class is completed and bytecode\r
+        * generated, if there are no constructors then\r
+        * the default no-arg constructor will be defined.\r
+        */\r
+       public ByteArray getClassBytecode() throws StandardException {\r
+\r
+               // return if already done\r
+               if (bytecode != null) return bytecode;\r
+               \r
+               try {\r
+\r
+                       if (SanityManager.DEBUG) {\r
+                               if (SanityManager.DEBUG_ON("ClassLineNumbers")) {\r
+\r
+                                       ClassFormatOutput sout = new ClassFormatOutput(2);\r
+\r
+                                       int cpiUTF = classHold.addUtf8("GC.java");\r
+\r
+                                       sout.putU2(cpiUTF);\r
+\r
+                                       classHold.addAttribute("SourceFile", sout);\r
+                               }\r
+                       }\r
+\r
+                       // the class is now complete, get its bytecode.\r
+                       bytecode = classHold.getFileFormat();\r
+                       \r
+               } catch (IOException ioe) {\r
+                       throw StandardException.newException(\r
+                                       SQLState.GENERATED_CLASS_LINKAGE_ERROR, ioe, getFullName());\r
+               }\r
+\r
+               // release resources, we have the code now.\r
+               // name is not released, it may still be accessed.\r
+               classHold = null;\r
+\r
+               if (SanityManager.DEBUG) {\r
+                       if (SanityManager.DEBUG_ON("DumpClassFile")) {\r
+                               /* Dump the file in derby.system.home */\r
+                               String systemHome = System.getProperty(Property.SYSTEM_HOME_PROPERTY,".");\r
+                               writeClassFile(systemHome,false,null);\r
+                       }\r
+               }\r
+\r
+               if (SanityManager.DEBUG) {\r
+                 if (SanityManager.DEBUG_ON("ByteCodeGenInstr")) {\r
+                       SanityManager.DEBUG("ByteCodeGenInstr",\r
+                               "GEN complete for class "+name);\r
+                 }\r
+               }\r
+               \r
+               if (limitMsg != null)\r
+                       throw StandardException.newException(\r
+                                       SQLState.GENERATED_CLASS_LIMIT_EXCEEDED, getFullName(), limitMsg);\r
+               return bytecode;\r
+       }\r
+\r
+\r
+       /**\r
+        * the class's unqualified name\r
+        */\r
+       public String getName() {\r
+               return name;\r
+       }\r
\r
+       /**\r
+        * a method. Once it is created, thrown\r
+        * exceptions, statements, and local variable declarations\r
+        * must be added to it. It is put into its defining class\r
+        * when it is created.\r
+        * <verbatim>\r
+          Java: #modifiers #returnType #methodName() {}\r
+                       // modifiers is the | of the JVM constants for\r
+                       // the modifiers such as static, public, etc.\r
+          </verbatim>\r
+        * <p>\r
+        * This is used to start a constructor as well; pass in\r
+        * null for the returnType when used in that manner.\r
+        *\r
+        * See java.lang.reflect.Modifiers\r
+        * @param modifiers the | of the Modifiers\r
+        *      constants representing the visibility and control of this\r
+        *      method.\r
+        * @param returnType the return type of the method as its\r
+        *      Java language type name.\r
+        * @param methodName the name of the method.\r
+        *\r
+        * @return the method builder.\r
+        */\r
+       public MethodBuilder newMethodBuilder(int modifiers, String returnType,\r
+               String methodName) {\r
+\r
+               return newMethodBuilder(modifiers, returnType,\r
+                       methodName, (String[]) null);\r
+\r
+       }\r
+\r
+\r
+       /**\r
+        * a method with parameters. Once it is created, thrown\r
+        * exceptions, statements, and local variable declarations\r
+        * must be added to it. It is put into its defining class\r
+        * when it is created.\r
+        * <verbatim>\r
+          Java: #modifiers #returnType #methodName() {}\r
+                       // modifiers is the | of the JVM constants for\r
+                       // the modifiers such as static, public, etc.\r
+          </verbatim>\r
+        * <p>\r
+        * This is used to start a constructor as well; pass in\r
+        * null for the returnType when used in that manner.\r
+        *\r
+        * See java.lang.reflect.Modifiers\r
+        * @param modifiers the | of the Modifiers\r
+        *      constants representing the visibility and control of this\r
+        *      method.\r
+        * @param returnType the return type of the method as its\r
+        *      Java language type name.\r
+        * @param methodName the name of the method.\r
+        * @param parms an array of ParameterDeclarations representing the\r
+        *                              method's parameters\r
+        *\r
+        * @return the method builder.\r
+        */\r
+       public MethodBuilder newMethodBuilder(int modifiers, String returnType,\r
+               String methodName, String[] parms) {\r
+\r
+               if (SanityManager.DEBUG) {\r
+                       SanityManager.ASSERT(returnType!=null);\r
+               }\r
+\r
+               BCMethod m = new BCMethod(this,\r
+                                                                       returnType,\r
+                                                                       methodName,\r
+                                                                       modifiers,\r
+                                                                       parms,\r
+                                                                       factory);\r
+\r
+               return m;\r
+               \r
+       }\r
+\r
+\r
+       /**\r
+        * a constructor. Once it is created, thrown\r
+        * exceptions, statements, and local variable declarations\r
+        * must be added to it. It is put into its defining class\r
+        * when it is created.\r
+        * <verbatim>\r
+          Java: #modifiers #className() {}\r
+                       // modifiers is the | of the JVM constants for\r
+                       // the modifiers such as static, public, etc.\r
+                       // className is taken from definingClass.getName()\r
+          </verbatim>\r
+        * <p>\r
+        * This is used to start a constructor as well; pass in\r
+        * null for the returnType when used in that manner.\r
+        *\r
+        * See Modifiers\r
+        * @param modifiers the | of the Modifiers\r
+        *      constants representing the visibility and control of this\r
+        *      method.\r
+        *\r
+        * @return the method builder for the constructor.\r
+        */\r
+       public MethodBuilder newConstructorBuilder(int modifiers) {\r
+\r
+               BCMethod m = new BCMethod(this, "void", "<init>", \r
+                                                                       modifiers,\r
+                                                                       (String []) null,\r
+                                                                       factory);\r
+\r
+               return m;\r
+       }\r
+       //\r
+       // class interface\r
+       //\r
+\r
+       String getSuperClassName() {\r
+               return superClassName;\r
+       }\r
+\r
+       /**\r
+        * Let those that need to get to the\r
+        * classModify tool to alter the class definition.\r
+        */\r
+       ClassHolder modify() {\r
+               return classHold;\r
+       }\r
+\r
+       /*\r
+       ** Method descriptor caching\r
+       */\r
+\r
+       BCClass(ClassFactory cf, String packageName, int classModifiers,\r
+                       String className, String superClassName,\r
+                       BCJava factory) {\r
+\r
+               super(cf, packageName.concat(className));\r
+\r
+               if (SanityManager.DEBUG) {\r
+                 if (SanityManager.DEBUG_ON("ByteCodeGenInstr")) {\r
+                       SanityManager.DEBUG("ByteCodeGenInstr",\r
+                               "GEN starting for class "+className);\r
+                 }\r
+               }\r
+\r
+               // by the time the constructor is done, we have:\r
+               //\r
+               // package #packageName;\r
+               // #classModifiers class #className extends #superClassName\r
+               // { }\r
+               //\r
+\r
+               name = className;\r
+               if (superClassName == null)\r
+                       superClassName = "java.lang.Object";\r
+               this.superClassName = superClassName;\r
+\r
+               classType = factory.type(getFullName());\r
+\r
+               classHold = new ClassHolder(qualifiedName, factory.type(superClassName).vmNameSimple, classModifiers);\r
+\r
+               this.factory = factory;\r
+       }\r
+\r
+       protected ClassHolder classHold;\r
+\r
+       protected String superClassName;\r
+       protected String name;\r
+\r
+       BCJava factory;\r
+       final Type classType;\r
+\r
+       ClassFactory getClassFactory() {\r
+               return cf;\r
+       }\r
+\r
+       public void newFieldWithAccessors(String getter, String setter,\r
+               int methodModifers,\r
+               boolean staticField, String type) {\r
+\r
+               String vmType = factory.type(type).vmName();\r
+               methodModifers |= Modifier.FINAL;\r
+\r
+\r
+               // add a field, field has same name as get method\r
+               int fieldModifiers = Modifier.PRIVATE;\r
+               if (staticField)\r
+                       fieldModifiers |= Modifier.STATIC;\r
+\r
+               ClassMember field = classHold.addMember(getter, vmType, fieldModifiers);\r
+               int cpi = classHold.addFieldReference(field);\r
+\r
+               /*\r
+               ** add the get method\r
+               */\r
+\r
+               String sig = BCMethodDescriptor.get(BCMethodDescriptor.EMPTY, vmType, factory);\r
+\r
+               ClassMember method = classHold.addMember(getter, sig, methodModifers);\r
+\r
+               CodeChunk chunk = new CodeChunk(this);\r
+\r
+               // load 'this' if required\r
+               if (!staticField)\r
+                       chunk.addInstr(VMOpcode.ALOAD_0); // this\r
+               \r
+               // get the field value\r
+               chunk.addInstrU2((staticField ? VMOpcode.GETSTATIC : VMOpcode.GETFIELD), cpi);\r
+\r
+               // and return it\r
+               short vmTypeId = BCJava.vmTypeId(vmType);\r
+\r
+               chunk.addInstr(CodeChunk.RETURN_OPCODE[vmTypeId]);\r
+\r
+               int typeWidth = Type.width(vmTypeId);\r
+               chunk.complete(null, classHold, method, typeWidth, 1);\r
+\r
+               /*\r
+               ** add the set method\r
+               */\r
+               String[] pda = new String[1];\r
+               pda[0] = vmType;\r
+               sig = new BCMethodDescriptor(pda, VMDescriptor.VOID, factory).toString();\r
+               method = classHold.addMember(setter, sig, methodModifers);\r
+               chunk = new CodeChunk(this);\r
+\r
+               // load 'this' if required\r
+               if (!staticField)\r
+                       chunk.addInstr(VMOpcode.ALOAD_0); // this\r
+               // push the only parameter\r
+               chunk.addInstr((short) (CodeChunk.LOAD_VARIABLE_FAST[vmTypeId] + 1));\r
+               \r
+               // and set the field\r
+               chunk.addInstrU2((staticField ? VMOpcode.PUTSTATIC : VMOpcode.PUTFIELD), cpi);\r
+\r
+               chunk.addInstr(VMOpcode.RETURN);\r
+\r
+               chunk.complete(null, classHold, method, typeWidth + (staticField ? 0 : 1), 1 + typeWidth);\r
+       }\r
+       \r
+       /**\r
+        * Add the fact that some class limit was exceeded while generating\r
+        * the class. We create a set of them and report at the end, this\r
+        * allows the generated class file to still be dumped.\r
+        * @param mb\r
+        * @param limitName\r
+        * @param limit\r
+        * @param value\r
+        */\r
+       void addLimitExceeded(BCMethod mb, String limitName, int limit, int value)\r
+       {\r
+               StringBuffer sb = new StringBuffer();\r
+               if (limitMsg != null)\r
+               {\r
+                       sb.append(limitMsg);\r
+                       sb.append(", ");\r
+               }\r
+               \r
+               sb.append("method:");\r
+               sb.append(mb.getName());\r
+               sb.append(" ");\r
+               sb.append(limitName);\r
+               sb.append(" (");\r
+               sb.append(value);\r
+               sb.append(" > ");\r
+               sb.append(limit);\r
+               sb.append(")");\r
+               \r
+               limitMsg = sb.toString();\r
+       }\r
+    \r
+    /**\r
+     * Add the fact that some class limit was exceeded while generating\r
+     * the class. Text is the simple string passed in.\r
+     * @param rawText Text to be reported.\r
+     * \r
+     * @see BCClass#addLimitExceeded(BCMethod, String, int, int)\r
+     */\r
+    void addLimitExceeded(String rawText)\r
+    {\r
+        if (limitMsg != null)\r
+        {\r
+            limitMsg = limitMsg + ", " + rawText;\r
+       }\r
+        else\r
+        {\r
+            limitMsg = rawText;\r
+        }\r
+    }\r
+\r
+}\r