ObjectCreator.java revision 1435:6e5080fdfaad
138032Speter/* 2111823Sgshapiro * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 364562Sgshapiro * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 438032Speter * 538032Speter * This code is free software; you can redistribute it and/or modify it 638032Speter * under the terms of the GNU General Public License version 2 only, as 738032Speter * published by the Free Software Foundation. Oracle designates this 838032Speter * particular file as subject to the "Classpath" exception as provided 938032Speter * by Oracle in the LICENSE file that accompanied this code. 1038032Speter * 1138032Speter * This code is distributed in the hope that it will be useful, but WITHOUT 1238032Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1338032Speter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1464562Sgshapiro * version 2 for more details (a copy is included in the LICENSE file that 1564562Sgshapiro * accompanied this code). 16111823Sgshapiro * 1738032Speter * You should have received a copy of the GNU General Public License version 1890792Sgshapiro * 2 along with this work; if not, write to the Free Software Foundation, 1938032Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2090792Sgshapiro * 2190792Sgshapiro * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2290792Sgshapiro * or visit www.oracle.com if you need additional information or have any 2390792Sgshapiro * questions. 2490792Sgshapiro */ 2590792Sgshapiro 26110560Sgshapiropackage jdk.nashorn.internal.codegen; 27110560Sgshapiro 28110560Sgshapiroimport static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE; 29110560Sgshapiro 3090792Sgshapiroimport java.util.List; 3190792Sgshapiroimport jdk.nashorn.internal.codegen.types.Type; 3290792Sgshapiroimport jdk.nashorn.internal.runtime.PropertyMap; 3390792Sgshapiroimport jdk.nashorn.internal.runtime.ScriptObject; 3464562Sgshapiro 3590792Sgshapiro/** 3690792Sgshapiro * Base class for object creation code generation. 3790792Sgshapiro * @param <T> value type 3890792Sgshapiro */ 3990792Sgshapiropublic abstract class ObjectCreator<T> implements CodeGenerator.SplitLiteralCreator { 4090792Sgshapiro 4190792Sgshapiro /** List of keys & symbols to initiate in this ObjectCreator */ 4290792Sgshapiro final List<MapTuple<T>> tuples; 4390792Sgshapiro 4490792Sgshapiro /** Code generator */ 4564562Sgshapiro final CodeGenerator codegen; 4690792Sgshapiro 4790792Sgshapiro /** Property map */ 4838032Speter protected PropertyMap propertyMap; 4938032Speter 5038032Speter private final boolean isScope; 5138032Speter private final boolean hasArguments; 5238032Speter 5338032Speter /** 5438032Speter * Constructor 5538032Speter * 5638032Speter * @param codegen the code generator 5738032Speter * @param tuples key,symbol,value (optional) tuples 5838032Speter * @param isScope is this object scope 5990792Sgshapiro * @param hasArguments does the created object have an "arguments" property 6090792Sgshapiro */ 6190792Sgshapiro ObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples, final boolean isScope, final boolean hasArguments) { 6290792Sgshapiro this.codegen = codegen; 6338032Speter this.tuples = tuples; 6438032Speter this.isScope = isScope; 6538032Speter this.hasArguments = hasArguments; 6638032Speter } 6738032Speter 6890792Sgshapiro /** 6990792Sgshapiro * Generate code for making the object. 7038032Speter * @param method Script method. 7190792Sgshapiro */ 7294334Sgshapiro public void makeObject(final MethodEmitter method) { 7394334Sgshapiro createObject(method); 7490792Sgshapiro // We need to store the object in a temporary slot as populateRange expects to load the 7590792Sgshapiro // object from a slot (as it is also invoked within split methods). Note that this also 76111823Sgshapiro // helps optimistic continuations to handle the stack in case an optimistic assumption 7790792Sgshapiro // fails during initialization (see JDK-8079269). 7890792Sgshapiro final int objectSlot = method.getUsedSlotsWithLiveTemporaries(); 7990792Sgshapiro final Type objectType = method.peekType(); 8090792Sgshapiro method.storeTemp(objectType, objectSlot); 8190792Sgshapiro populateRange(method, objectType, objectSlot, 0, tuples.size()); 8290792Sgshapiro } 8390792Sgshapiro 8490792Sgshapiro /** 8590792Sgshapiro * Generate code for creating and initializing the object. 8690792Sgshapiro * @param method the method emitter 8790792Sgshapiro */ 8890792Sgshapiro protected abstract void createObject(final MethodEmitter method); 8990792Sgshapiro 9090792Sgshapiro /** 9190792Sgshapiro * Construct the property map appropriate for the object. 9290792Sgshapiro * @return the newly created property map 9390792Sgshapiro */ 9490792Sgshapiro protected abstract PropertyMap makeMap(); 9590792Sgshapiro 9690792Sgshapiro /** 9790792Sgshapiro * Create a new MapCreator 9890792Sgshapiro * @param clazz type of MapCreator 9990792Sgshapiro * @return map creator instantiated by type 10090792Sgshapiro */ 10190792Sgshapiro protected MapCreator<?> newMapCreator(final Class<? extends ScriptObject> clazz) { 10290792Sgshapiro return new MapCreator<>(clazz, tuples); 10390792Sgshapiro } 10490792Sgshapiro 10590792Sgshapiro /** 10690792Sgshapiro * Loads the scope on the stack through the passed method emitter. 10790792Sgshapiro * @param method the method emitter to use 10890792Sgshapiro */ 10990792Sgshapiro protected void loadScope(final MethodEmitter method) { 11090792Sgshapiro method.loadCompilerConstant(SCOPE); 11190792Sgshapiro } 11290792Sgshapiro 11390792Sgshapiro /** 11490792Sgshapiro * Emit the correct map for the object. 11590792Sgshapiro * @param method method emitter 11690792Sgshapiro * @return the method emitter 11790792Sgshapiro */ 11890792Sgshapiro protected MethodEmitter loadMap(final MethodEmitter method) { 11990792Sgshapiro codegen.loadConstant(propertyMap); 12090792Sgshapiro return method; 12190792Sgshapiro } 12290792Sgshapiro 12394334Sgshapiro PropertyMap getMap() { 12464562Sgshapiro return propertyMap; 12590792Sgshapiro } 12690792Sgshapiro 12790792Sgshapiro /** 12890792Sgshapiro * Is this a scope object 12990792Sgshapiro * @return true if scope 13064562Sgshapiro */ 13164562Sgshapiro protected boolean isScope() { 13264562Sgshapiro return isScope; 13364562Sgshapiro } 13464562Sgshapiro 135110560Sgshapiro /** 13690792Sgshapiro * Does the created object have an "arguments" property 13790792Sgshapiro * @return true if has an "arguments" property 13890792Sgshapiro */ 13990792Sgshapiro protected boolean hasArguments() { 14090792Sgshapiro return hasArguments; 14138032Speter } 14290792Sgshapiro 14390792Sgshapiro /** 14490792Sgshapiro * Get the class of objects created by this ObjectCreator 14590792Sgshapiro * @return class of created object 14690792Sgshapiro */ 14790792Sgshapiro abstract protected Class<? extends ScriptObject> getAllocatorClass(); 14880785Sgshapiro 14990792Sgshapiro /** 15090792Sgshapiro * Technique for loading an initial value. Defined by anonymous subclasses in code gen. 15190792Sgshapiro * 15290792Sgshapiro * @param value Value to load. 15390792Sgshapiro * @param type the type of the value to load 15490792Sgshapiro */ 15590792Sgshapiro protected abstract void loadValue(T value, Type type); 15690792Sgshapiro 15790792Sgshapiro MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple, final boolean pack) { 15890792Sgshapiro loadValue(tuple.value, tuple.type); 15990792Sgshapiro if (pack && codegen.useDualFields() && tuple.isPrimitive()) { 16090792Sgshapiro method.pack(); 16190792Sgshapiro } else { 16290792Sgshapiro method.convert(Type.OBJECT); 16390792Sgshapiro } 16490792Sgshapiro return method; 16590792Sgshapiro } 16690792Sgshapiro 16790792Sgshapiro MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) { 16890792Sgshapiro return loadTuple(method, tuple, true); 16990792Sgshapiro } 17090792Sgshapiro} 17190792Sgshapiro