Wed, 20 Feb 2013 17:08:32 +0530
8008207: Make constants array and source fields private
Reviewed-by: hannesw, lagergren
jlaskey@3 | 1 | /* |
jlaskey@7 | 2 | * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
jlaskey@3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
jlaskey@3 | 4 | * |
jlaskey@3 | 5 | * This code is free software; you can redistribute it and/or modify it |
jlaskey@3 | 6 | * under the terms of the GNU General Public License version 2 only, as |
jlaskey@3 | 7 | * published by the Free Software Foundation. Oracle designates this |
jlaskey@3 | 8 | * particular file as subject to the "Classpath" exception as provided |
jlaskey@3 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
jlaskey@3 | 10 | * |
jlaskey@3 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
jlaskey@3 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
jlaskey@3 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
jlaskey@3 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
jlaskey@3 | 15 | * accompanied this code). |
jlaskey@3 | 16 | * |
jlaskey@3 | 17 | * You should have received a copy of the GNU General Public License version |
jlaskey@3 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
jlaskey@3 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
jlaskey@3 | 20 | * |
jlaskey@3 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
jlaskey@3 | 22 | * or visit www.oracle.com if you need additional information or have any |
jlaskey@3 | 23 | * questions. |
jlaskey@3 | 24 | */ |
jlaskey@3 | 25 | |
jlaskey@3 | 26 | package jdk.nashorn.internal.codegen; |
jlaskey@3 | 27 | |
jlaskey@3 | 28 | import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS; |
jlaskey@3 | 29 | import static jdk.nashorn.internal.codegen.CompilerConstants.DEFAULT_SCRIPT_NAME; |
lagergren@89 | 30 | import static jdk.nashorn.internal.codegen.CompilerConstants.LAZY; |
jlaskey@3 | 31 | import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE; |
jlaskey@3 | 32 | import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE; |
jlaskey@3 | 33 | import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; |
attila@90 | 34 | |
jlaskey@3 | 35 | import java.io.File; |
sundar@106 | 36 | import java.lang.reflect.Field; |
sundar@106 | 37 | import java.security.AccessController; |
sundar@106 | 38 | import java.security.PrivilegedActionException; |
sundar@106 | 39 | import java.security.PrivilegedExceptionAction; |
lagergren@89 | 40 | import java.util.Arrays; |
jlaskey@3 | 41 | import java.util.EnumSet; |
lagergren@89 | 42 | import java.util.HashMap; |
jlaskey@3 | 43 | import java.util.HashSet; |
lagergren@89 | 44 | import java.util.LinkedList; |
jlaskey@3 | 45 | import java.util.Map; |
jlaskey@3 | 46 | import java.util.Map.Entry; |
jlaskey@3 | 47 | import java.util.Set; |
attila@90 | 48 | import jdk.internal.dynalink.support.NameCodec; |
jlaskey@3 | 49 | import jdk.nashorn.internal.codegen.ClassEmitter.Flag; |
jlaskey@3 | 50 | import jdk.nashorn.internal.codegen.types.Type; |
jlaskey@3 | 51 | import jdk.nashorn.internal.ir.FunctionNode; |
lagergren@89 | 52 | import jdk.nashorn.internal.ir.FunctionNode.CompilationState; |
jlaskey@3 | 53 | import jdk.nashorn.internal.runtime.CodeInstaller; |
jlaskey@3 | 54 | import jdk.nashorn.internal.runtime.Context; |
jlaskey@3 | 55 | import jdk.nashorn.internal.runtime.DebugLogger; |
jlaskey@3 | 56 | import jdk.nashorn.internal.runtime.Source; |
jlaskey@3 | 57 | import jdk.nashorn.internal.runtime.options.Options; |
jlaskey@3 | 58 | |
jlaskey@3 | 59 | /** |
jlaskey@3 | 60 | * Responsible for converting JavaScripts to java byte code. Main entry |
lagergren@89 | 61 | * point for code generator. The compiler may also install classes given some |
lagergren@89 | 62 | * predefined Code installation policy, given to it at construction time. |
lagergren@89 | 63 | * @see CodeInstaller |
jlaskey@3 | 64 | */ |
jlaskey@3 | 65 | public final class Compiler { |
jlaskey@3 | 66 | |
jlaskey@3 | 67 | /** Name of the scripts package */ |
jlaskey@3 | 68 | public static final String SCRIPTS_PACKAGE = "jdk/nashorn/internal/scripts"; |
jlaskey@3 | 69 | |
jlaskey@3 | 70 | /** Name of the objects package */ |
jlaskey@3 | 71 | public static final String OBJECTS_PACKAGE = "jdk/nashorn/internal/objects"; |
jlaskey@3 | 72 | |
lagergren@89 | 73 | static final boolean LAZY_JIT = Options.getBooleanProperty("nashorn.compiler.lazy"); |
sundar@82 | 74 | |
lagergren@89 | 75 | static final boolean TIME_COMPILATION = Options.getBooleanProperty("nashorn.compiler.time"); |
jlaskey@3 | 76 | |
lagergren@89 | 77 | private final Map<String, byte[]> bytecode; |
jlaskey@3 | 78 | |
jlaskey@3 | 79 | private final Set<CompileUnit> compileUnits; |
jlaskey@3 | 80 | |
jlaskey@3 | 81 | private final ConstantData constantData; |
jlaskey@3 | 82 | |
lagergren@89 | 83 | private final FunctionNode functionNode; |
lagergren@89 | 84 | |
lagergren@89 | 85 | private final CompilationSequence sequence; |
lagergren@89 | 86 | |
lagergren@89 | 87 | private final Context context; |
lagergren@89 | 88 | |
lagergren@89 | 89 | private final String scriptName; |
lagergren@89 | 90 | |
lagergren@89 | 91 | private boolean strict; |
lagergren@89 | 92 | |
lagergren@89 | 93 | private CodeInstaller<Context> installer; |
lagergren@89 | 94 | |
jlaskey@3 | 95 | static final DebugLogger LOG = new DebugLogger("compiler"); |
jlaskey@3 | 96 | |
lagergren@89 | 97 | /** |
lagergren@89 | 98 | * This array contains names that need to be reserved at the start |
lagergren@89 | 99 | * of a compile, to avoid conflict with variable names later introduced. |
lagergren@89 | 100 | * See {@link CompilerConstants} for special names used for structures |
lagergren@89 | 101 | * during a compile. |
lagergren@89 | 102 | */ |
lagergren@89 | 103 | private static String[] RESERVED_NAMES = { |
lagergren@89 | 104 | SCOPE.tag(), |
lagergren@89 | 105 | THIS.tag() |
lagergren@89 | 106 | }; |
jlaskey@3 | 107 | |
lagergren@89 | 108 | /** |
lagergren@89 | 109 | * This class makes it possible to do your own compilation sequence |
lagergren@89 | 110 | * from the code generation package. There are predefined compilation |
lagergren@89 | 111 | * sequences already |
lagergren@89 | 112 | */ |
lagergren@89 | 113 | @SuppressWarnings("serial") |
lagergren@89 | 114 | static class CompilationSequence extends LinkedList<CompilationPhase> { |
jlaskey@3 | 115 | |
lagergren@89 | 116 | CompilationSequence(final CompilationPhase... phases) { |
lagergren@89 | 117 | super(Arrays.asList(phases)); |
lagergren@89 | 118 | } |
jlaskey@3 | 119 | |
lagergren@89 | 120 | CompilationSequence(final CompilationSequence sequence) { |
lagergren@89 | 121 | this(sequence.toArray(new CompilationPhase[sequence.size()])); |
lagergren@89 | 122 | } |
jlaskey@3 | 123 | |
lagergren@89 | 124 | CompilationSequence insertAfter(final CompilationPhase phase, final CompilationPhase newPhase) { |
lagergren@89 | 125 | final CompilationSequence newSeq = new CompilationSequence(); |
lagergren@89 | 126 | for (final CompilationPhase elem : this) { |
lagergren@89 | 127 | newSeq.add(phase); |
lagergren@89 | 128 | if (elem.equals(phase)) { |
lagergren@89 | 129 | newSeq.add(newPhase); |
lagergren@89 | 130 | } |
lagergren@89 | 131 | } |
lagergren@89 | 132 | assert newSeq.contains(newPhase); |
lagergren@89 | 133 | return newSeq; |
lagergren@89 | 134 | } |
jlaskey@3 | 135 | |
lagergren@89 | 136 | CompilationSequence insertBefore(final CompilationPhase phase, final CompilationPhase newPhase) { |
lagergren@89 | 137 | final CompilationSequence newSeq = new CompilationSequence(); |
lagergren@89 | 138 | for (final CompilationPhase elem : this) { |
lagergren@89 | 139 | if (elem.equals(phase)) { |
lagergren@89 | 140 | newSeq.add(newPhase); |
lagergren@89 | 141 | } |
lagergren@89 | 142 | newSeq.add(phase); |
lagergren@89 | 143 | } |
lagergren@89 | 144 | assert newSeq.contains(newPhase); |
lagergren@89 | 145 | return newSeq; |
lagergren@89 | 146 | } |
lagergren@89 | 147 | |
lagergren@89 | 148 | CompilationSequence insertFirst(final CompilationPhase phase) { |
lagergren@89 | 149 | final CompilationSequence newSeq = new CompilationSequence(this); |
lagergren@89 | 150 | newSeq.addFirst(phase); |
lagergren@89 | 151 | return newSeq; |
lagergren@89 | 152 | } |
lagergren@89 | 153 | |
lagergren@89 | 154 | CompilationSequence insertLast(final CompilationPhase phase) { |
lagergren@89 | 155 | final CompilationSequence newSeq = new CompilationSequence(this); |
lagergren@89 | 156 | newSeq.addLast(phase); |
lagergren@89 | 157 | return newSeq; |
lagergren@89 | 158 | } |
lagergren@89 | 159 | } |
lagergren@89 | 160 | |
lagergren@89 | 161 | /** |
lagergren@89 | 162 | * Standard (non-lazy) compilation, that basically will take an entire script |
lagergren@89 | 163 | * and JIT it at once. This can lead to long startup time and fewer type |
lagergren@89 | 164 | * specializations |
lagergren@89 | 165 | */ |
lagergren@89 | 166 | final static CompilationSequence SEQUENCE_NORMAL = new CompilationSequence( |
lagergren@89 | 167 | CompilationPhase.CONSTANT_FOLDING_PHASE, |
lagergren@89 | 168 | CompilationPhase.LOWERING_PHASE, |
lagergren@89 | 169 | CompilationPhase.ATTRIBUTION_PHASE, |
lagergren@89 | 170 | CompilationPhase.SPLITTING_PHASE, |
lagergren@89 | 171 | CompilationPhase.TYPE_FINALIZATION_PHASE, |
lagergren@89 | 172 | CompilationPhase.BYTECODE_GENERATION_PHASE); |
lagergren@89 | 173 | |
lagergren@89 | 174 | final static CompilationSequence SEQUENCE_LAZY = |
lagergren@89 | 175 | SEQUENCE_NORMAL.insertFirst(CompilationPhase.LAZY_INITIALIZATION_PHASE); |
lagergren@89 | 176 | |
lagergren@89 | 177 | final static CompilationSequence SEQUENCE_DEFAULT = |
lagergren@89 | 178 | LAZY_JIT ? |
lagergren@89 | 179 | SEQUENCE_LAZY : |
lagergren@89 | 180 | SEQUENCE_NORMAL; |
lagergren@89 | 181 | |
lagergren@89 | 182 | /** |
lagergren@89 | 183 | * Constructor |
lagergren@89 | 184 | * |
lagergren@89 | 185 | * @param installer code installer from |
lagergren@89 | 186 | * @param functionNode function node (in any available {@link CompilationState}) to compile |
lagergren@89 | 187 | * @param sequence {@link Compiler#CompilationSequence} of {@link CompilationPhase}s to apply as this compilation |
lagergren@89 | 188 | * @param strict should this compilation use strict mode semantics |
lagergren@89 | 189 | */ |
lagergren@89 | 190 | Compiler(final Context context, final CodeInstaller<Context> installer, final FunctionNode functionNode, final CompilationSequence sequence, final boolean strict) { |
lagergren@89 | 191 | this.context = context; |
lagergren@89 | 192 | this.functionNode = functionNode; |
lagergren@89 | 193 | this.sequence = sequence; |
lagergren@89 | 194 | this.installer = installer; |
lagergren@89 | 195 | this.strict = strict || functionNode.isStrictMode(); |
lagergren@89 | 196 | this.constantData = new ConstantData(); |
lagergren@89 | 197 | this.compileUnits = new HashSet<>(); |
lagergren@89 | 198 | this.bytecode = new HashMap<>(); |
lagergren@89 | 199 | |
lagergren@89 | 200 | final StringBuilder sb = new StringBuilder(); |
lagergren@89 | 201 | sb.append(functionNode.uniqueName(DEFAULT_SCRIPT_NAME.tag())). |
lagergren@89 | 202 | append('$'). |
lagergren@89 | 203 | append(safeSourceName(functionNode.getSource())). |
lagergren@89 | 204 | append(functionNode.isLazy() ? LAZY.tag() : ""); |
lagergren@89 | 205 | |
lagergren@89 | 206 | this.scriptName = sb.toString(); |
lagergren@89 | 207 | |
lagergren@89 | 208 | LOG.info("Initializing compiler for scriptName = " + scriptName + ", root function: '" + functionNode.getName() + "'"); |
lagergren@89 | 209 | } |
lagergren@89 | 210 | |
lagergren@89 | 211 | /** |
lagergren@89 | 212 | * Constructor |
lagergren@89 | 213 | * |
lagergren@89 | 214 | * @param installer code installer from context |
lagergren@89 | 215 | * @param functionNode function node (in any available {@link CompilationState}) to compile |
lagergren@89 | 216 | * @param strict should this compilation use strict mode semantics |
lagergren@89 | 217 | */ |
lagergren@89 | 218 | public Compiler(final CodeInstaller<Context> installer, final FunctionNode functionNode, final boolean strict) { |
lagergren@89 | 219 | this(installer.getOwner(), installer, functionNode, SEQUENCE_DEFAULT, strict); |
lagergren@89 | 220 | } |
lagergren@89 | 221 | |
lagergren@89 | 222 | /** |
lagergren@89 | 223 | * Constructor - compilation will use the same strict semantics as context |
lagergren@89 | 224 | * |
lagergren@89 | 225 | * @param installer code installer from context |
lagergren@89 | 226 | * @param functionNode function node (in any available {@link CompilationState}) to compile |
lagergren@89 | 227 | */ |
lagergren@89 | 228 | public Compiler(final CodeInstaller<Context> installer, final FunctionNode functionNode) { |
lagergren@89 | 229 | this(installer.getOwner(), installer, functionNode, SEQUENCE_DEFAULT, installer.getOwner()._strict); |
lagergren@89 | 230 | } |
lagergren@89 | 231 | |
lagergren@89 | 232 | /** |
lagergren@89 | 233 | * Constructor - compilation needs no installer, but uses a context |
lagergren@89 | 234 | * Used in "compile only" scenarios |
lagergren@89 | 235 | * @param context a context |
lagergren@89 | 236 | * @param functionNode functionNode to compile |
lagergren@89 | 237 | */ |
lagergren@89 | 238 | public Compiler(final Context context, final FunctionNode functionNode) { |
lagergren@89 | 239 | this(context, null, functionNode, SEQUENCE_DEFAULT, context._strict); |
lagergren@89 | 240 | } |
lagergren@89 | 241 | |
lagergren@89 | 242 | /** |
lagergren@89 | 243 | * Execute the compilation this Compiler was created with |
lagergren@89 | 244 | * @return true if compilation succeeds. |
lagergren@89 | 245 | */ |
lagergren@89 | 246 | public boolean compile() { |
lagergren@89 | 247 | for (final String reservedName : RESERVED_NAMES) { |
lagergren@89 | 248 | functionNode.uniqueName(reservedName); |
lagergren@89 | 249 | } |
lagergren@89 | 250 | |
lagergren@89 | 251 | for (final CompilationPhase phase : sequence) { |
lagergren@89 | 252 | LOG.info("Entering compile phase " + phase + " for function '" + functionNode.getName() + "'"); |
lagergren@89 | 253 | if (phase.isApplicable(functionNode)) { |
lagergren@89 | 254 | if (!phase.apply(this, functionNode)) { //TODO exceptions, error logging |
lagergren@89 | 255 | return false; |
lagergren@89 | 256 | } |
lagergren@89 | 257 | } |
lagergren@89 | 258 | } |
lagergren@89 | 259 | return true; |
lagergren@89 | 260 | } |
lagergren@89 | 261 | |
lagergren@89 | 262 | /** |
lagergren@89 | 263 | * Install compiled classes into a given loader |
lagergren@89 | 264 | * @return root script class - if there are several compile units they will also be installed |
lagergren@89 | 265 | */ |
lagergren@89 | 266 | public Class<?> install() { |
lagergren@89 | 267 | Class<?> rootClass = null; |
lagergren@89 | 268 | |
lagergren@89 | 269 | for (final Entry<String, byte[]> entry : bytecode.entrySet()) { |
lagergren@89 | 270 | final String className = entry.getKey(); |
lagergren@89 | 271 | LOG.info("Installing class " + className); |
lagergren@89 | 272 | |
lagergren@89 | 273 | final byte[] code = entry.getValue(); |
lagergren@89 | 274 | final Class<?> clazz = installer.install(Compiler.binaryName(className), code); |
lagergren@89 | 275 | |
lagergren@89 | 276 | if (rootClass == null && firstCompileUnitName().equals(className)) { |
lagergren@89 | 277 | rootClass = clazz; |
lagergren@89 | 278 | } |
lagergren@89 | 279 | |
lagergren@89 | 280 | try { |
sundar@106 | 281 | final Source source = getSource(); |
sundar@106 | 282 | final Object[] constants = getConstantData().toArray(); |
sundar@106 | 283 | // Need doPrivileged because these fields are private |
sundar@106 | 284 | AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { |
sundar@106 | 285 | @Override |
sundar@106 | 286 | public Void run() throws Exception { |
sundar@106 | 287 | //use reflection to write source and constants table to installed classes |
sundar@106 | 288 | final Field sourceField = clazz.getDeclaredField(SOURCE.tag()); |
sundar@106 | 289 | final Field constantsField = clazz.getDeclaredField(CONSTANTS.tag()); |
sundar@106 | 290 | sourceField.setAccessible(true); |
sundar@106 | 291 | constantsField.setAccessible(true); |
sundar@106 | 292 | sourceField.set(null, source); |
sundar@106 | 293 | constantsField.set(null, constants); |
sundar@106 | 294 | return null; |
sundar@106 | 295 | } |
sundar@106 | 296 | }); |
sundar@106 | 297 | } catch (final PrivilegedActionException e) { |
lagergren@89 | 298 | throw new RuntimeException(e); |
lagergren@89 | 299 | } |
lagergren@89 | 300 | } |
lagergren@89 | 301 | |
lagergren@89 | 302 | LOG.info("Root class: " + rootClass); |
lagergren@89 | 303 | return rootClass; |
lagergren@89 | 304 | } |
lagergren@89 | 305 | |
lagergren@89 | 306 | Set<CompileUnit> getCompileUnits() { |
lagergren@89 | 307 | return compileUnits; |
lagergren@89 | 308 | } |
lagergren@89 | 309 | |
lagergren@89 | 310 | boolean getStrictMode() { |
lagergren@89 | 311 | return strict; |
lagergren@89 | 312 | } |
lagergren@89 | 313 | |
lagergren@89 | 314 | void setStrictMode(final boolean strict) { |
lagergren@89 | 315 | this.strict = strict; |
lagergren@89 | 316 | } |
lagergren@89 | 317 | |
lagergren@89 | 318 | FunctionNode getFunctionNode() { |
lagergren@89 | 319 | return functionNode; |
lagergren@89 | 320 | } |
lagergren@89 | 321 | |
lagergren@89 | 322 | ConstantData getConstantData() { |
lagergren@89 | 323 | return constantData; |
lagergren@89 | 324 | } |
lagergren@89 | 325 | |
lagergren@89 | 326 | CodeInstaller<Context> getCodeInstaller() { |
lagergren@89 | 327 | return installer; |
lagergren@89 | 328 | } |
lagergren@89 | 329 | |
lagergren@89 | 330 | Source getSource() { |
lagergren@89 | 331 | return functionNode.getSource(); |
lagergren@89 | 332 | } |
lagergren@89 | 333 | |
lagergren@89 | 334 | void addClass(final String name, final byte[] code) { |
lagergren@89 | 335 | bytecode.put(name, code); |
lagergren@89 | 336 | } |
lagergren@89 | 337 | |
lagergren@89 | 338 | Context getContext() { |
lagergren@89 | 339 | return this.context; |
lagergren@89 | 340 | } |
lagergren@89 | 341 | |
lagergren@89 | 342 | private static String safeSourceName(final Source source) { |
lagergren@89 | 343 | String baseName = new File(source.getName()).getName(); |
lagergren@89 | 344 | |
lagergren@89 | 345 | final int index = baseName.lastIndexOf(".js"); |
lagergren@89 | 346 | if (index != -1) { |
lagergren@89 | 347 | baseName = baseName.substring(0, index); |
lagergren@89 | 348 | } |
lagergren@89 | 349 | |
lagergren@89 | 350 | baseName = baseName.replace('.', '_').replace('-', '_'); |
lagergren@89 | 351 | final String mangled = NameCodec.encode(baseName); |
lagergren@89 | 352 | |
lagergren@89 | 353 | return mangled != null ? mangled : baseName; |
lagergren@89 | 354 | } |
lagergren@89 | 355 | |
lagergren@89 | 356 | private int nextCompileUnitIndex() { |
lagergren@89 | 357 | return compileUnits.size() + 1; |
lagergren@89 | 358 | } |
lagergren@89 | 359 | |
lagergren@89 | 360 | String firstCompileUnitName() { |
lagergren@89 | 361 | return SCRIPTS_PACKAGE + '/' + scriptName; |
lagergren@89 | 362 | } |
lagergren@89 | 363 | |
lagergren@89 | 364 | private String nextCompileUnitName() { |
lagergren@89 | 365 | return firstCompileUnitName() + '$' + nextCompileUnitIndex(); |
lagergren@89 | 366 | } |
lagergren@89 | 367 | |
lagergren@89 | 368 | CompileUnit addCompileUnit(final long initialWeight) { |
lagergren@89 | 369 | return addCompileUnit(nextCompileUnitName(), initialWeight); |
lagergren@89 | 370 | } |
lagergren@89 | 371 | |
lagergren@89 | 372 | CompileUnit addCompileUnit(final String unitClassName) { |
lagergren@89 | 373 | return addCompileUnit(unitClassName, 0L); |
lagergren@89 | 374 | } |
lagergren@89 | 375 | |
lagergren@89 | 376 | private CompileUnit addCompileUnit(final String unitClassName, final long initialWeight) { |
lagergren@89 | 377 | final CompileUnit compileUnit = initCompileUnit(unitClassName, initialWeight); |
lagergren@89 | 378 | compileUnits.add(compileUnit); |
lagergren@89 | 379 | LOG.info("Added compile unit " + compileUnit); |
lagergren@89 | 380 | return compileUnit; |
lagergren@89 | 381 | } |
lagergren@89 | 382 | |
lagergren@89 | 383 | private CompileUnit initCompileUnit(final String unitClassName, final long initialWeight) { |
lagergren@89 | 384 | final ClassEmitter classEmitter = new ClassEmitter(context, functionNode.getSource().getName(), unitClassName, strict); |
lagergren@89 | 385 | final CompileUnit compileUnit = new CompileUnit(unitClassName, classEmitter, initialWeight); |
lagergren@89 | 386 | |
lagergren@89 | 387 | classEmitter.begin(); |
lagergren@89 | 388 | |
lagergren@89 | 389 | final MethodEmitter initMethod = classEmitter.init(EnumSet.of(Flag.PRIVATE)); |
lagergren@89 | 390 | initMethod.begin(); |
lagergren@89 | 391 | initMethod.load(Type.OBJECT, 0); |
lagergren@89 | 392 | initMethod.newInstance(jdk.nashorn.internal.scripts.JS$.class); |
lagergren@89 | 393 | initMethod.returnVoid(); |
lagergren@89 | 394 | initMethod.end(); |
lagergren@89 | 395 | |
lagergren@89 | 396 | return compileUnit; |
lagergren@89 | 397 | } |
lagergren@89 | 398 | |
lagergren@89 | 399 | CompileUnit findUnit(final long weight) { |
lagergren@89 | 400 | for (final CompileUnit unit : compileUnits) { |
lagergren@89 | 401 | if (unit.canHold(weight)) { |
lagergren@89 | 402 | unit.addWeight(weight); |
lagergren@89 | 403 | return unit; |
lagergren@89 | 404 | } |
lagergren@89 | 405 | } |
lagergren@89 | 406 | |
lagergren@89 | 407 | return addCompileUnit(weight); |
lagergren@89 | 408 | } |
lagergren@89 | 409 | |
lagergren@89 | 410 | /** |
lagergren@89 | 411 | * Convert a package/class name to a binary name. |
lagergren@89 | 412 | * |
lagergren@89 | 413 | * @param name Package/class name. |
lagergren@89 | 414 | * @return Binary name. |
lagergren@89 | 415 | */ |
lagergren@89 | 416 | public static String binaryName(final String name) { |
lagergren@89 | 417 | return name.replace('/', '.'); |
lagergren@89 | 418 | } |
jlaskey@3 | 419 | |
jlaskey@3 | 420 | /** |
jlaskey@3 | 421 | * Should we use integers for arithmetic operations as well? |
jlaskey@3 | 422 | * TODO: We currently generate no overflow checks so this is |
jlaskey@3 | 423 | * disabled |
jlaskey@3 | 424 | * |
jlaskey@3 | 425 | * @see #shouldUseIntegers() |
jlaskey@3 | 426 | * |
jlaskey@3 | 427 | * @return true if arithmetic operations should not widen integer |
jlaskey@3 | 428 | * operands by default. |
jlaskey@3 | 429 | */ |
jlaskey@3 | 430 | static boolean shouldUseIntegerArithmetic() { |
lagergren@57 | 431 | return USE_INT_ARITH; |
jlaskey@3 | 432 | } |
jlaskey@3 | 433 | |
jlaskey@3 | 434 | private static final boolean USE_INT_ARITH; |
jlaskey@3 | 435 | |
jlaskey@3 | 436 | static { |
jlaskey@3 | 437 | USE_INT_ARITH = Options.getBooleanProperty("nashorn.compiler.intarithmetic"); |
jlaskey@3 | 438 | assert !USE_INT_ARITH : "Integer arithmetic is not enabled"; |
jlaskey@3 | 439 | } |
jlaskey@3 | 440 | |
lagergren@89 | 441 | static { |
lagergren@89 | 442 | if (TIME_COMPILATION) { |
lagergren@89 | 443 | Runtime.getRuntime().addShutdownHook(new Thread() { |
jlaskey@3 | 444 | @Override |
lagergren@89 | 445 | public void run() { |
lagergren@89 | 446 | for (final CompilationPhase phase : CompilationPhase.values()) { |
lagergren@89 | 447 | final StringBuilder sb = new StringBuilder(); |
lagergren@89 | 448 | sb.append(phase); |
lagergren@89 | 449 | while (sb.length() < 32) { |
lagergren@89 | 450 | sb.append(' '); |
lagergren@89 | 451 | } |
lagergren@89 | 452 | sb.append(CompilationPhase.getAccumulatedTime(phase)); |
lagergren@89 | 453 | sb.append(' '); |
lagergren@89 | 454 | sb.append(" ms"); |
lagergren@89 | 455 | System.err.println(sb.toString()); //Context err is gone by shutdown TODO |
jlaskey@3 | 456 | } |
jlaskey@3 | 457 | } |
jlaskey@3 | 458 | }); |
jlaskey@3 | 459 | } |
jlaskey@3 | 460 | } |
jlaskey@3 | 461 | } |