ObjectCreator.java revision 1435:6e5080fdfaad
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.codegen.CompilerConstants.SCOPE;
29
30import java.util.List;
31import jdk.nashorn.internal.codegen.types.Type;
32import jdk.nashorn.internal.runtime.PropertyMap;
33import jdk.nashorn.internal.runtime.ScriptObject;
34
35/**
36 * Base class for object creation code generation.
37 * @param <T> value type
38 */
39public abstract class ObjectCreator<T> implements CodeGenerator.SplitLiteralCreator {
40
41    /** List of keys & symbols to initiate in this ObjectCreator */
42    final List<MapTuple<T>> tuples;
43
44    /** Code generator */
45    final CodeGenerator codegen;
46
47    /** Property map */
48    protected PropertyMap   propertyMap;
49
50    private final boolean       isScope;
51    private final boolean       hasArguments;
52
53    /**
54     * Constructor
55     *
56     * @param codegen      the code generator
57     * @param tuples       key,symbol,value (optional) tuples
58     * @param isScope      is this object scope
59     * @param hasArguments does the created object have an "arguments" property
60     */
61    ObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples, final boolean isScope, final boolean hasArguments) {
62        this.codegen       = codegen;
63        this.tuples        = tuples;
64        this.isScope       = isScope;
65        this.hasArguments  = hasArguments;
66    }
67
68    /**
69     * Generate code for making the object.
70     * @param method Script method.
71     */
72    public void makeObject(final MethodEmitter method) {
73        createObject(method);
74        // We need to store the object in a temporary slot as populateRange expects to load the
75        // object from a slot (as it is also invoked within split methods). Note that this also
76        // helps optimistic continuations to handle the stack in case an optimistic assumption
77        // fails during initialization (see JDK-8079269).
78        final int objectSlot = method.getUsedSlotsWithLiveTemporaries();
79        final Type objectType = method.peekType();
80        method.storeTemp(objectType, objectSlot);
81        populateRange(method, objectType, objectSlot, 0, tuples.size());
82    }
83
84    /**
85     * Generate code for creating and initializing the object.
86     * @param method the method emitter
87     */
88    protected abstract void createObject(final MethodEmitter method);
89
90    /**
91     * Construct the property map appropriate for the object.
92     * @return the newly created property map
93     */
94    protected abstract PropertyMap makeMap();
95
96    /**
97     * Create a new MapCreator
98     * @param clazz type of MapCreator
99     * @return map creator instantiated by type
100     */
101    protected MapCreator<?> newMapCreator(final Class<? extends ScriptObject> clazz) {
102        return new MapCreator<>(clazz, tuples);
103    }
104
105    /**
106     * Loads the scope on the stack through the passed method emitter.
107     * @param method the method emitter to use
108     */
109    protected void loadScope(final MethodEmitter method) {
110        method.loadCompilerConstant(SCOPE);
111    }
112
113    /**
114     * Emit the correct map for the object.
115     * @param method method emitter
116     * @return the method emitter
117     */
118    protected MethodEmitter loadMap(final MethodEmitter method) {
119        codegen.loadConstant(propertyMap);
120        return method;
121    }
122
123    PropertyMap getMap() {
124        return propertyMap;
125    }
126
127    /**
128     * Is this a scope object
129     * @return true if scope
130     */
131    protected boolean isScope() {
132        return isScope;
133    }
134
135    /**
136     * Does the created object have an "arguments" property
137     * @return true if has an "arguments" property
138     */
139    protected boolean hasArguments() {
140        return hasArguments;
141    }
142
143    /**
144     * Get the class of objects created by this ObjectCreator
145     * @return class of created object
146     */
147    abstract protected Class<? extends ScriptObject> getAllocatorClass();
148
149    /**
150     * Technique for loading an initial value. Defined by anonymous subclasses in code gen.
151     *
152     * @param value Value to load.
153     * @param type the type of the value to load
154     */
155    protected abstract void loadValue(T value, Type type);
156
157    MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple, final boolean pack) {
158        loadValue(tuple.value, tuple.type);
159        if (pack && codegen.useDualFields() && tuple.isPrimitive()) {
160            method.pack();
161        } else {
162            method.convert(Type.OBJECT);
163        }
164        return method;
165    }
166
167    MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) {
168        return loadTuple(method, tuple, true);
169    }
170}
171