AllocationStrategy.java revision 1245:c55ce3738888
1/*
2 * Copyright (c) 2014, 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 */
25package jdk.nashorn.internal.runtime;
26
27import static jdk.nashorn.internal.lookup.Lookup.MH;
28
29import java.io.Serializable;
30import java.lang.invoke.MethodHandle;
31import java.lang.invoke.MethodHandles;
32import jdk.nashorn.internal.codegen.Compiler;
33import jdk.nashorn.internal.codegen.CompilerConstants;
34import jdk.nashorn.internal.codegen.ObjectClassGenerator;
35
36/**
37 * Encapsulates the allocation strategy for a function when used as a constructor.
38 */
39final public class AllocationStrategy implements Serializable {
40    private static final long serialVersionUID = 1L;
41
42    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
43
44    /** Number of fields in the allocated object */
45    private final int fieldCount;
46
47    /** Whether to use dual field representation */
48    private final boolean dualFields;
49
50    /** Name of class where allocator function resides */
51    private transient String allocatorClassName;
52
53    /** lazily generated allocator */
54    private transient MethodHandle allocator;
55
56    /**
57     * Construct an allocation strategy with the given map and class name.
58     * @param fieldCount number of fields in the allocated object
59     * @param dualFields whether to use dual field representation
60     */
61    public AllocationStrategy(final int fieldCount, final boolean dualFields) {
62        this.fieldCount = fieldCount;
63        this.dualFields = dualFields;
64    }
65
66    private String getAllocatorClassName() {
67        if (allocatorClassName == null) {
68            // These classes get loaded, so an interned variant of their name is most likely around anyway.
69            allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount, dualFields)).intern();
70        }
71        return allocatorClassName;
72    }
73
74    PropertyMap getAllocatorMap() {
75        // Create a new map for each function instance
76        return PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
77    }
78
79    ScriptObject allocate(final PropertyMap map) {
80        try {
81            if (allocator == null) {
82                allocator = MH.findStatic(LOOKUP, Context.forStructureClass(getAllocatorClassName()),
83                        CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class));
84            }
85            return (ScriptObject)allocator.invokeExact(map);
86        } catch (final RuntimeException | Error e) {
87            throw e;
88        } catch (final Throwable t) {
89            throw new RuntimeException(t);
90        }
91    }
92
93    @Override
94    public String toString() {
95        return "AllocationStrategy[fieldCount=" + fieldCount + "]";
96    }
97}
98