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 26 package jdk.nashorn.internal.codegen.objects; 27 28 import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.HANDLE_STATIC; 29 import static jdk.nashorn.internal.codegen.Compiler.SCRIPTFUNCTION_IMPL_OBJECT; 30 import static jdk.nashorn.internal.codegen.CompilerConstants.ALLOCATE; 31 import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; 32 import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor; 33 34 import java.lang.invoke.MethodHandle; 35 import java.util.ArrayList; 36 import java.util.EnumSet; 37 38 import jdk.nashorn.internal.codegen.CodeGenerator; 39 import jdk.nashorn.internal.codegen.FunctionSignature; 40 import jdk.nashorn.internal.codegen.MethodEmitter; 41 import jdk.nashorn.internal.ir.FunctionNode; 42 import jdk.nashorn.internal.ir.Symbol; 43 import jdk.nashorn.internal.runtime.PropertyMap; 44 import jdk.nashorn.internal.codegen.ScriptFunctionData; 45 import jdk.nashorn.internal.runtime.ScriptObject; 46 47 /** 48 * Analyze a function object's characteristics for appropriate code 49 * generation. This generates code for the instantiation of ScriptFunctions. 50 */ 51 public class FunctionObjectCreator extends ObjectCreator { 52 53 private final FunctionNode functionNode; 54 55 /** 56 * Constructor 57 * 58 * @param codegen the code generator 59 * @param functionNode the function node to turn into a ScriptFunction implementation 60 */ 61 public FunctionObjectCreator(final CodeGenerator codegen, final FunctionNode functionNode) { 62 super(codegen, new ArrayList<String>(), new ArrayList<Symbol>(), false, false); 63 this.functionNode = functionNode; 64 } 65 66 private void loadHandle(final MethodEmitter method, final String signature) { 67 method.loadHandle(functionNode.getCompileUnit().getUnitClassName(), functionNode.getName(), signature, EnumSet.of(HANDLE_STATIC)); // function 68 } 69 70 /** 71 * Emit code for creating the object 72 * 73 * @param method the method emitter 74 */ 75 @Override 76 public void makeObject(final MethodEmitter method) { 77 78 final PropertyMap map = makeMap(); 79 final String signature = new FunctionSignature(true, functionNode.needsCallee(), functionNode.getReturnType(), functionNode.isVarArg() ? null : functionNode.getParameters()).toString(); 80 final ScriptFunctionData scriptFunctionData = new ScriptFunctionData(functionNode, map); 81 82 /* 83 * Instantiate the function object 84 */ 85 method._new(SCRIPTFUNCTION_IMPL_OBJECT).dup(); 86 codegen.loadConstant(scriptFunctionData); 87 loadHandle(method, signature); 88 if(functionNode.needsParentScope()) { 89 method.loadScope(); 90 } else { 91 method.loadNull(); 92 } 93 method.loadHandle(getClassName(), ALLOCATE.tag(), methodDescriptor(ScriptObject.class, PropertyMap.class), EnumSet.of(HANDLE_STATIC)); 94 95 /* 96 * Invoke the constructor 97 */ 98 method.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_OBJECT, ScriptFunctionData.class, MethodHandle.class, ScriptObject.class, MethodHandle.class)); 99 100 } 101 }