MapCreator.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 static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; 29import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; 30 31import java.util.ArrayList; 32import java.util.List; 33import jdk.nashorn.internal.ir.Symbol; 34import jdk.nashorn.internal.runtime.AccessorProperty; 35import jdk.nashorn.internal.runtime.Property; 36import jdk.nashorn.internal.runtime.PropertyMap; 37import jdk.nashorn.internal.runtime.ScriptObject; 38import jdk.nashorn.internal.runtime.SpillProperty; 39 40/** 41 * Class that creates PropertyMap sent to script object constructors. 42 * @param <T> value type for tuples, e.g. Symbol 43 */ 44public class MapCreator<T> { 45 /** Object structure for objects associated with this map */ 46 private final Class<?> structure; 47 48 /** key set for object map */ 49 private final List<MapTuple<T>> tuples; 50 51 /** 52 * Constructor 53 * 54 * @param structure structure to generate map for (a JO subclass) 55 * @param keys list of keys for map 56 * @param symbols list of symbols for map 57 */ 58 MapCreator(final Class<? extends ScriptObject> structure, final List<MapTuple<T>> tuples) { 59 this.structure = structure; 60 this.tuples = tuples; 61 } 62 63 /** 64 * Constructs a property map based on a set of fields. 65 * 66 * @param hasArguments does the created object have an "arguments" property 67 * @param fieldCount Number of fields in use. 68 * @param fieldMaximum Number of fields available. 69 * @param evalCode is this property map created for 'eval' code? 70 * @return New map populated with accessor properties. 71 */ 72 PropertyMap makeFieldMap(final boolean hasArguments, final int fieldCount, final int fieldMaximum, final boolean evalCode) { 73 final List<Property> properties = new ArrayList<>(); 74 assert tuples != null; 75 76 for (final MapTuple<T> tuple : tuples) { 77 final String key = tuple.key; 78 final Symbol symbol = tuple.symbol; 79 final Class<?> initialType = tuple.getValueType(); 80 81 if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) { 82 final int flags = getPropertyFlags(symbol, hasArguments, evalCode); 83 final Property property = new AccessorProperty( 84 key, 85 flags, 86 structure, 87 symbol.getFieldIndex(), 88 initialType); 89 properties.add(property); 90 } 91 } 92 93 return PropertyMap.newMap(properties, structure.getName(), fieldCount, fieldMaximum, 0); 94 } 95 96 PropertyMap makeSpillMap(final boolean hasArguments) { 97 final List<Property> properties = new ArrayList<>(); 98 int spillIndex = 0; 99 assert tuples != null; 100 101 for (final MapTuple<T> tuple : tuples) { 102 final String key = tuple.key; 103 final Symbol symbol = tuple.symbol; 104 105 //TODO initial type is object here no matter what. Is that right? 106 if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) { 107 final int flags = getPropertyFlags(symbol, hasArguments, false); 108 properties.add( 109 new SpillProperty( 110 key, 111 flags, 112 spillIndex++)); 113 } 114 } 115 116 return PropertyMap.newMap(properties, structure.getName(), 0, 0, spillIndex); 117 } 118 119 /** 120 * Compute property flags given local state of a field. May be overridden and extended, 121 * 122 * @param symbol symbol to check 123 * @param hasArguments does the created object have an "arguments" property 124 * 125 * @return flags to use for fields 126 */ 127 static int getPropertyFlags(final Symbol symbol, final boolean hasArguments, final boolean evalCode) { 128 int flags = 0; 129 130 if (symbol.isParam()) { 131 flags |= Property.IS_PARAMETER; 132 } 133 134 if (hasArguments) { 135 flags |= Property.HAS_ARGUMENTS; 136 } 137 138 // See ECMA 5.1 10.5 Declaration Binding Instantiation. 139 // Step 2 If code is eval code, then let configurableBindings 140 // be true else let configurableBindings be false. 141 // We have to make vars, functions declared in 'eval' code 142 // configurable. But vars, functions from any other code is 143 // not configurable. 144 if (symbol.isScope() && !evalCode) { 145 flags |= Property.NOT_CONFIGURABLE; 146 } 147 148 if (symbol.isFunctionDeclaration()) { 149 flags |= Property.IS_FUNCTION_DECLARATION; 150 } 151 152 return flags; 153 } 154} 155