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 26 package jdk.nashorn.internal.codegen.objects; 27 28 import java.util.List; 29 import jdk.nashorn.internal.codegen.CodeGenerator; 30 import jdk.nashorn.internal.codegen.CompileUnit; 31 import jdk.nashorn.internal.codegen.Compiler; 32 import jdk.nashorn.internal.codegen.MethodEmitter; 33 import jdk.nashorn.internal.ir.Symbol; 34 import jdk.nashorn.internal.runtime.Context; 35 import jdk.nashorn.internal.runtime.PropertyMap; 36 37 /** 38 * Base class for object creation code generation. 39 */ 40 public abstract class ObjectCreator { 41 42 /** Compile unit for this ObjectCreator, see CompileUnit */ 43 protected final CompileUnit compileUnit; 44 45 /** List of keys to initiate in this ObjectCreator */ 46 protected final List<String> keys; 47 48 /** List of symbols to initiate in this ObjectCreator */ 49 protected final List<Symbol> symbols; 50 51 /** Code generator */ 52 protected final CodeGenerator codegen; 53 54 private final boolean isScope; 55 private final boolean isVarArg; 56 private int fieldCount; 57 private int paramCount; 58 private String fieldObjectClassName; 59 private Class<?> fieldObjectClass; 60 private PropertyMap propertyMap; 61 62 /** 63 * Constructor 64 * 65 * @param codegen the code generator 66 * @param keys the keys 67 * @param symbols the symbols corresponding to keys, same index 68 * @param isScope is this object scope 69 * @param isVarArg is this object var arg 70 */ 71 protected ObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final boolean isScope, final boolean isVarArg) { 72 this.codegen = codegen; 73 this.compileUnit = codegen.getCurrentCompileUnit(); 74 this.keys = keys; 75 this.symbols = symbols; 76 this.isScope = isScope; 77 this.isVarArg = isVarArg; 78 79 countFields(); 80 findClass(); 81 } 82 83 /** 84 * Tally the number of fields and parameters. 85 */ 86 private void countFields() { 87 for (final Symbol symbol : this.symbols) { 88 if (symbol != null) { 89 if (isVarArg() && symbol.isParam()) { 90 symbol.setFieldIndex(paramCount++); 91 } else { 92 symbol.setFieldIndex(fieldCount++); 93 } 94 } 95 } 96 } 97 98 /** 99 * Locate (or indirectly create) the object container class. 100 */ 101 private void findClass() { 102 fieldObjectClassName = isScope() ? 103 ObjectClassGenerator.getClassName(fieldCount, paramCount) : 104 ObjectClassGenerator.getClassName(fieldCount); 105 106 try { 107 this.fieldObjectClass = Context.forStructureClass(Compiler.binaryName(fieldObjectClassName)); 108 } catch (final ClassNotFoundException e) { 109 throw new AssertionError("Nashorn has encountered an internal error. Structure can not be created."); 110 } 111 } 112 113 /** 114 * Generate code for making the object. 115 * @param method Script method. 116 */ 117 public abstract void makeObject(final MethodEmitter method); 118 119 /** 120 * Create a new MapCreator 121 * @param clazz type of MapCreator 122 * @return map creator instantiated by type 123 */ 124 protected MapCreator newMapCreator(final Class<?> clazz) { 125 return new MapCreator(clazz, keys, symbols); 126 } 127 128 /** 129 * Construct the property map appropriate for the object. 130 */ 131 protected void makeMap() { 132 if (keys.isEmpty()) { //empty map 133 propertyMap = PropertyMap.newMap(fieldObjectClass); 134 return; 135 } 136 137 propertyMap = newMapCreator(fieldObjectClass).makeMap(isVarArg()); 138 } 139 140 /** 141 * Emit the correct map for the object. 142 * @param method method emitter 143 * @return the method emitter 144 */ 145 protected MethodEmitter loadMap(final MethodEmitter method) { 146 codegen.loadConstant(propertyMap); 147 return method; 148 } 149 150 /** 151 * Get the class name for the object class, 152 * e.g. {@code com.nashorn.oracle.scripts.JO$2P0} 153 * 154 * @return script class name 155 */ 156 public String getClassName() { 157 return fieldObjectClassName; 158 } 159 160 /** 161 * Is this a scope object 162 * @return true if scope 163 */ 164 protected boolean isScope() { 165 return isScope; 166 } 167 168 /** 169 * Is this a vararg object 170 * @return true if vararg 171 */ 172 protected boolean isVarArg() { 173 return isVarArg; 174 } 175 }