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