src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java

Print this page

        

@@ -101,13 +101,11 @@
      * @param allocatorMap       allocator map to seed instances with, when constructing
      */
     public RecompilableScriptFunctionData(final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, final PropertyMap allocatorMap) {
         super(functionName(functionNode),
               functionNode.getParameters().size(),
-              functionNode.isStrict(),
-              false,
-              true);
+              getFlags(functionNode));
 
         this.functionNode       = functionNode;
         this.source             = functionNode.getSource();
         this.token              = tokenFor(functionNode);
         this.installer          = installer;

@@ -127,14 +125,15 @@
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder();
 
         if (source != null) {
-            sb.append(source.getName())
-                .append(':')
-                .append(functionNode.getLineNumber())
-                .append(' ');
+            sb.append(source.getName());
+            if (functionNode != null) {
+                sb.append(':').append(functionNode.getLineNumber());
+            }
+            sb.append(' ');
         }
 
         return sb.toString() + super.toString();
     }
 

@@ -157,10 +156,24 @@
         final int  length     = Token.descPosition(fn.getLastToken()) - position + Token.descLength(fn.getLastToken());
 
         return Token.toDesc(TokenType.FUNCTION, position, length);
     }
 
+    private static int getFlags(final FunctionNode functionNode) {
+        int flags = IS_CONSTRUCTOR;
+        if (functionNode.isStrict()) {
+            flags |= IS_STRICT;
+        }
+        if (functionNode.needsCallee()) {
+            flags |= NEEDS_CALLEE;
+        }
+        if (functionNode.usesThis() || functionNode.hasEval()) {
+            flags |= USES_THIS;
+        }
+        return flags;
+    }
+
     @Override
     ScriptObject allocate(final PropertyMap map) {
         try {
             ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try
             return allocator == null ? null : (ScriptObject)allocator.invokeExact(map);

@@ -180,30 +193,31 @@
     @Override
     PropertyMap getAllocatorMap() {
         return allocatorMap;
     }
 
-    @Override
-    protected synchronized void ensureCodeGenerated() {
-         if (!code.isEmpty()) {
-             return; // nothing to do, we have code, at least some.
-         }
 
-         if (functionNode.isLazy()) {
+    @Override
+    protected void ensureCompiled() {
+        if (functionNode != null && functionNode.isLazy()) {
              Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
              final Compiler compiler = new Compiler(installer);
              functionNode = compiler.compile(functionNode);
              assert !functionNode.isLazy();
              compiler.install(functionNode);
+            flags = getFlags(functionNode);
+        }
+    }
 
-             /*
-              * We don't need to update any flags - varArgs and needsCallee are instrincic
-              * in the function world we need to get a destination node from the compile instead
-              * and replace it with our function node. TODO
-              */
+    @Override
+    protected synchronized void ensureCodeGenerated() {
+        if (!code.isEmpty()) {
+            return; // nothing to do, we have code, at least some.
          }
 
+        ensureCompiled();
+
          /*
           * We can't get to this program point unless we have bytecode, either from
           * eager compilation or from running a lazy compile on the lines above
           */