CompileUnit.java revision 953:221a84ef44c0
1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.codegen; 27 28import java.util.Collections; 29import java.util.LinkedHashSet; 30import java.util.Set; 31import java.util.TreeSet; 32import jdk.nashorn.internal.ir.FunctionNode; 33import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 34 35/** 36 * Used to track split class compilation. 37 */ 38public final class CompileUnit implements Comparable<CompileUnit> { 39 /** Current class name */ 40 private final String className; 41 42 /** Current class generator */ 43 private ClassEmitter classEmitter; 44 45 private long weight; 46 47 private Class<?> clazz; 48 49 private Set<FunctionInitializer> functionInitializers = new LinkedHashSet<>(); 50 51 private static class FunctionInitializer { 52 final RecompilableScriptFunctionData data; 53 final FunctionNode functionNode; 54 55 FunctionInitializer(final RecompilableScriptFunctionData data, final FunctionNode functionNode) { 56 this.data = data; 57 this.functionNode = functionNode; 58 } 59 60 void initializeCode() { 61 data.initializeCode(functionNode); 62 } 63 64 @Override 65 public int hashCode() { 66 return data.hashCode() + 31 * functionNode.hashCode(); 67 } 68 69 @Override 70 public boolean equals(final Object obj) { 71 if (obj == null || obj.getClass() != FunctionInitializer.class) { 72 return false; 73 } 74 final FunctionInitializer other = (FunctionInitializer)obj; 75 return data == other.data && functionNode == other.functionNode; 76 } 77 } 78 79 CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) { 80 this.className = className; 81 this.weight = initialWeight; 82 this.classEmitter = classEmitter; 83 } 84 85 static Set<CompileUnit> createCompileUnitSet() { 86 return new TreeSet<>(); 87 } 88 89 /** 90 * Return the class that contains the code for this unit, null if not 91 * generated yet 92 * 93 * @return class with compile unit code 94 */ 95 public Class<?> getCode() { 96 return clazz; 97 } 98 99 /** 100 * Set class when it exists. Only accessible from compiler 101 * @param clazz class with code for this compile unit 102 */ 103 void setCode(final Class<?> clazz) { 104 clazz.getClass(); // null check 105 this.clazz = clazz; 106 // Revisit this - refactor to avoid null-ed out non-final fields 107 // null out emitter 108 this.classEmitter = null; 109 } 110 111 void addFunctionInitializer(final RecompilableScriptFunctionData data, final FunctionNode functionNode) { 112 functionInitializers.add(new FunctionInitializer(data, functionNode)); 113 } 114 115 /** 116 * Returns true if this compile unit is responsible for initializing the specified function data with specified 117 * function node. 118 * @param data the function data to check 119 * @param functionNode the function node to check 120 * @return true if this unit is responsible for initializing the function data with the function node, otherwise 121 * false 122 */ 123 public boolean isInitializing(final RecompilableScriptFunctionData data, final FunctionNode functionNode) { 124 return functionInitializers.contains(new FunctionInitializer(data, functionNode)); 125 } 126 127 void initializeFunctionsCode() { 128 for(final FunctionInitializer init : functionInitializers) { 129 init.initializeCode(); 130 } 131 functionInitializers = Collections.emptySet(); 132 } 133 134 /** 135 * Add weight to this compile unit 136 * @param w weight to add 137 */ 138 void addWeight(final long w) { 139 this.weight += w; 140 } 141 142 /** 143 * Get the current weight of the compile unit. 144 * @return the unit's weight 145 */ 146 long getWeight() { 147 return weight; 148 } 149 150 /** 151 * Check if this compile unit can hold {@code weight} more units of weight 152 * @param w weight to check if can be added 153 * @return true if weight fits in this compile unit 154 */ 155 public boolean canHold(final long w) { 156 return (this.weight + w) < Splitter.SPLIT_THRESHOLD; 157 } 158 159 /** 160 * Get the class emitter for this compile unit 161 * @return class emitter 162 */ 163 public ClassEmitter getClassEmitter() { 164 return classEmitter; 165 } 166 167 /** 168 * Get the class name for this compile unit 169 * @return the class name 170 */ 171 public String getUnitClassName() { 172 return className; 173 } 174 175 private static String shortName(final String name) { 176 return name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1); 177 } 178 179 @Override 180 public String toString() { 181 return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + ']'; 182 } 183 184 @Override 185 public int compareTo(final CompileUnit o) { 186 return className.compareTo(o.className); 187 } 188} 189