Path: blob/master/sourcetools/com.ibm.jpp.preprocessor/com/ibm/jpp/om/JitAttributes.java
6004 views
/*******************************************************************************1* Copyright (c) 1999, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21package com.ibm.jpp.om;2223import java.io.File;24import java.io.FileOutputStream;25import java.io.IOException;26import java.io.PrintWriter;27import java.util.HashMap;28import java.util.Map;2930/**31* Format of JCL annotations:32* [ATTR <Type> <Signature>]33* where Type is one of:34* SkipNullChecks35* SkipBoundChecks36* SkipCheckCasts37* SkipDivChecks38* SkipArrayStoreChecks39* SkipChecksOnArrayCopies40* SkipZeroInitializationOnNewarrays41*42* These Types are always applied to a method. Signature must be of the43* form com_ibm_oti_Foo.blah(II)V.44*45* or [ATTR Recognized <Signature>]46*47* The given method is a "recognized" method (used for special,48* non-generalizable optimizations).49*50* or [ATTR <Type> <Arg> <FQN/Signature>]51* where Type is one of:52* Trusted53* Untrusted54*55* Trusted means arguments will not escape the methods. The Trusted56* attribute may be applied to either a method or a class. If it is57* applied to a method, Signature must be the same form as above. If it58* is applied to a class, use the fully qualified class name, like59* java_lang_Object. Untrusted can only be used for methods, and is used60* to indicate exceptions to Trusted classes.61*62* For Trusted and Untrusted, Arg is an integer indicating for which63* argument(s) the attribute applies. -1 means all arguments. The number64* must be formatted such that it can be converted to a Java int using65* Integer.parseInt().66*67* eg.68* [ATTR Trusted -1 com_ibm_oti_Foo]69* All arguments of all methods in com.ibm.oti.Foo will not escape.70*71* [ATTR Trusted 2 com_ibm_oti_Foo]72* The third argument of all methods in the class will not escape.73*74* [ATTR Trusted -1 com_ibm_oti_Foo]75* [ATTR Untrusted -1 com_ibm_oti_Foo.blah()V]76* All arguments of all methods will not escape, except blah(), where77* all arguments will escape.78*79* [ATTR Trusted 0 com_bim_oti_Foo.blah()V]80* The first argument of blah() will not escape.81*82*/83public class JitAttributes {8485static Map<String, Integer> recognizedMethods;8687static {88/* This set of methods should be synchronized with the89* "enum RecognizedMethod" in codegen_common/Symbol.hpp.90* ie., the contents and order should be the same.91*/92String[] methods = {93"unknownMethod",94"java_lang_Double_doubleToLongBits",95"java_lang_Double_longBitsToDouble",96"java_lang_Float_floatToIntBits",97"java_lang_Float_intBitsToFloat",98"java_lang_Object_getClass",99"java_lang_Object_hashCodeImpl",100"java_lang_String_hashCode",101"java_lang_System_arraycopy",102"java_lang_System_currentTimeMillis",103"java_lang_Thread_currentThread",104"java_lang_Throwable_fillInStackTrace",105"java_lang_Throwable_printStackTrace",106"java_util_HashtableHashEnumerator_hasMoreElements",107"com_ibm_oti_vm_VM_callerClass",108"com_ibm_oti_vm_VM_callerClassLoader" };109recognizedMethods = new HashMap<>();110for (int i = 0; i < methods.length; i++) {111recognizedMethods.put(methods[i], Integer.valueOf(i));112}113}114115AttributesMap map = new AttributesMap();116117public void skipNullChecksFor(String method) {118checkMethod(method);119map.getOrAdd(method).skipNullChecks = true;120}121122public void skipBoundChecksFor(String method) {123checkMethod(method);124map.getOrAdd(method).skipBoundChecks = true;125}126127public void skipCheckCastsFor(String method) {128checkMethod(method);129map.getOrAdd(method).skipCheckCasts = true;130}131132public void skipDivChecksFor(String method) {133checkMethod(method);134map.getOrAdd(method).skipDivChecks = true;135}136137public void skipArrayStoreChecksFor(String method) {138checkMethod(method);139map.getOrAdd(method).skipArrayStoreChecks = true;140}141142public void skipChecksOnArrayCopiesFor(String method) {143checkMethod(method);144map.getOrAdd(method).skipChecksOnArrayCopies = true;145}146147public void skipZeroInitializationOnNewarraysFor(String method) {148checkMethod(method);149map.getOrAdd(method).skipZeroInitializationOnNewarrays = true;150}151152public void addTrustedMethodOrClass(String name, int argNum) {153if (argNum < -1 || argNum >= 100) {154throw new PreprocessorException("Argument must be between -1 and 99 inclusive");155}156Attributes attr = map.getOrAdd(name);157attr.trusted = true;158attr.argNum = argNum;159}160161public void addUntrustedMethod(String method, int argNum) {162checkMethod(method);163if (argNum < -1 || argNum >= 100) {164throw new PreprocessorException("Argument must be between -1 and 99 inclusive");165}166Attributes attr = map.getOrAdd(method);167attr.untrusted = true;168attr.argNum = argNum;169}170171public void addRecognizedMethod(String method) {172checkMethod(method);173174/* Convert from com_ibm_oti_Foo.blah() to com_ibm_oti_Foo_blah, to match175* the format of the enum values.176*/177StringBuffer chopped = new StringBuffer(method.substring(0, method.indexOf("(")));178chopped.setCharAt(method.indexOf("."), '_');179180Integer integer = recognizedMethods.get(chopped.toString());181if (integer == null) {182throw new PreprocessorException(method + " is not a recognized method");183}184int value = integer.intValue();185if (value < 0 || value >= 100) {186throw new PreprocessorException("Not expecting recognizedMethodId < 0 or >= 100");187}188Attributes attr = map.getOrAdd(method);189attr.recognized = true;190attr.recognizedMethodId = value;191}192193public void write(String filename) throws IOException {194if (map.size() == 0) {195return;196}197File outputFile = new File(filename);198outputFile.mkdirs();199try (FileOutputStream stream = new FileOutputStream(filename);200PrintWriter out = new PrintWriter(stream)) {201out.print(map.toString());202}203}204205private static void checkMethod(String method) {206boolean valid = true;207int dot = method.indexOf('.');208209// if the first char is the dot, or there is more210// than one dot, it's not a valid method name211if (dot == 0 || method.indexOf('.', dot + 1) > 0) {212valid = false;213} else {214// ensure that there is both a left bracket and a right215// bracket, and that they appear in the right order.216int left = method.indexOf('(', dot + 1);217if (left == -1) {218valid = false;219} else {220int right = method.indexOf(')', left + 1);221if (right == -1) {222valid = false;223}224}225}226227if (!valid) {228throw new PreprocessorException(method + " does not appear to be a valid method name.");229}230}231}232233class Attributes {234String name;235236boolean skipNullChecks = false;237boolean skipBoundChecks = false;238boolean skipCheckCasts = false;239boolean skipDivChecks = false;240boolean skipArrayStoreChecks = false;241boolean skipChecksOnArrayCopies = false;242boolean skipZeroInitializationOnNewarrays = false;243244boolean trusted = false;245boolean untrusted = false;246int argNum;247boolean recognized = false;248int recognizedMethodId;249250@Override251public String toString() {252StringBuffer ret = new StringBuffer();253254if (trusted) {255if (argNum == -1) {256ret.append("T");257} else {258ret.append("t");259if (argNum < 10) {260ret.append("0");261}262ret.append(argNum);263}264} else if (untrusted) {265if (argNum == -1) {266ret.append("U");267} else {268ret.append("u");269if (argNum < 10) {270ret.append("0");271}272ret.append(argNum);273}274}275/* These attributes are only for methods */276if (name.indexOf(".") != -1) {277if (recognized) {278ret.append("r");279if (recognizedMethodId < 10) {280ret.append("0");281}282ret.append(recognizedMethodId);283}284ret.append(skipNullChecks ? "y" : "n");285ret.append(skipBoundChecks ? "y" : "n");286ret.append(skipCheckCasts ? "y" : "n");287ret.append(skipDivChecks ? "y" : "n");288ret.append(skipArrayStoreChecks ? "y" : "n");289ret.append(skipChecksOnArrayCopies ? "y" : "n");290ret.append(skipZeroInitializationOnNewarrays ? "y" : "n");291}292293return ret.toString();294}295}296297class AttributesMap extends HashMap<String, Attributes> {298299/**300* serialVersionUID301*/302private static final long serialVersionUID = 3257003276233683256L;303304public Attributes getOrAdd(String name) {305Attributes attr = get(name);306if (attr == null) {307attr = new Attributes();308attr.name = name;309put(name, attr);310}311return attr;312}313314@Override315public String toString() {316StringBuffer ret = new StringBuffer();317318for (Attributes next : values()) {319ret.append(next.name);320ret.append("\n");321ret.append(next.toString());322ret.append("\n");323}324325return ret.toString();326}327328}329330331