aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/codegen/FindScopeDepths.java')
-rw-r--r--src/jdk/nashorn/internal/codegen/FindScopeDepths.java362
1 files changed, 0 insertions, 362 deletions
diff --git a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
deleted file mode 100644
index bcdf73fc..00000000
--- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.codegen;
-
-import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
-import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
-import jdk.nashorn.internal.runtime.logging.DebugLogger;
-import jdk.nashorn.internal.runtime.logging.Loggable;
-import jdk.nashorn.internal.runtime.logging.Logger;
-
-/**
- * Establishes depth of scope for non local symbols at the start of method.
- * If this is a recompilation, the previous data from eager compilation is
- * stored in the RecompilableScriptFunctionData and is transferred to the
- * FunctionNode being compiled
- */
-@Logger(name="scopedepths")
-final class FindScopeDepths extends SimpleNodeVisitor implements Loggable {
-
- private final Compiler compiler;
- private final Map<Integer, Map<Integer, RecompilableScriptFunctionData>> fnIdToNestedFunctions = new HashMap<>();
- private final Map<Integer, Map<String, Integer>> externalSymbolDepths = new HashMap<>();
- private final Map<Integer, Set<String>> internalSymbols = new HashMap<>();
- private final Set<Block> withBodies = new HashSet<>();
-
- private final DebugLogger log;
-
- private int dynamicScopeCount;
-
- FindScopeDepths(final Compiler compiler) {
- this.compiler = compiler;
- this.log = initLogger(compiler.getContext());
- }
-
- @Override
- public DebugLogger getLogger() {
- return log;
- }
-
- @Override
- public DebugLogger initLogger(final Context context) {
- return context.getLogger(this.getClass());
- }
-
- static int findScopesToStart(final LexicalContext lc, final FunctionNode fn, final Block block) {
- final Block bodyBlock = findBodyBlock(lc, fn, block);
- final Iterator<Block> iter = lc.getBlocks(block);
- Block b = iter.next();
- int scopesToStart = 0;
- while (true) {
- if (b.needsScope()) {
- scopesToStart++;
- }
- if (b == bodyBlock) {
- break;
- }
- b = iter.next();
- }
- return scopesToStart;
- }
-
- static int findInternalDepth(final LexicalContext lc, final FunctionNode fn, final Block block, final Symbol symbol) {
- final Block bodyBlock = findBodyBlock(lc, fn, block);
- final Iterator<Block> iter = lc.getBlocks(block);
- Block b = iter.next();
- int scopesToStart = 0;
- while (true) {
- if (definedInBlock(b, symbol)) {
- return scopesToStart;
- }
- if (b.needsScope()) {
- scopesToStart++;
- }
- if (b == bodyBlock) {
- break; //don't go past body block, but process it
- }
- b = iter.next();
- }
- return -1;
- }
-
- private static boolean definedInBlock(final Block block, final Symbol symbol) {
- if (symbol.isGlobal()) {
- if (block.isGlobalScope()) {
- return true;
- }
- //globals cannot be defined anywhere else
- return false;
- }
- return block.getExistingSymbol(symbol.getName()) == symbol;
- }
-
- static Block findBodyBlock(final LexicalContext lc, final FunctionNode fn, final Block block) {
- final Iterator<Block> iter = lc.getBlocks(block);
- while (iter.hasNext()) {
- final Block next = iter.next();
- if (fn.getBody() == next) {
- return next;
- }
- }
- return null;
- }
-
- private static Block findGlobalBlock(final LexicalContext lc, final Block block) {
- final Iterator<Block> iter = lc.getBlocks(block);
- Block globalBlock = null;
- while (iter.hasNext()) {
- globalBlock = iter.next();
- }
- return globalBlock;
- }
-
- private static boolean isDynamicScopeBoundary(final FunctionNode fn) {
- return fn.needsDynamicScope();
- }
-
- private boolean isDynamicScopeBoundary(final Block block) {
- return withBodies.contains(block);
- }
-
- @Override
- public boolean enterFunctionNode(final FunctionNode functionNode) {
- if (compiler.isOnDemandCompilation()) {
- return true;
- }
-
- if (isDynamicScopeBoundary(functionNode)) {
- increaseDynamicScopeCount(functionNode);
- }
-
- final int fnId = functionNode.getId();
- Map<Integer, RecompilableScriptFunctionData> nestedFunctions = fnIdToNestedFunctions.get(fnId);
- if (nestedFunctions == null) {
- nestedFunctions = new HashMap<>();
- fnIdToNestedFunctions.put(fnId, nestedFunctions);
- }
-
- return true;
- }
-
- //external symbols hold the scope depth of sc11 from global at the start of the method
- @Override
- public Node leaveFunctionNode(final FunctionNode functionNode) {
- final String name = functionNode.getName();
- FunctionNode newFunctionNode = functionNode;
- if (compiler.isOnDemandCompilation()) {
- final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(newFunctionNode.getId());
- if (data.inDynamicContext()) {
- log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope.");
- newFunctionNode = newFunctionNode.setInDynamicContext(lc);
- }
- if (newFunctionNode == lc.getOutermostFunction() && !newFunctionNode.hasApplyToCallSpecialization()) {
- data.setCachedAst(newFunctionNode);
- }
- return newFunctionNode;
- }
-
- if (inDynamicScope()) {
- log.fine("Tagging ", quote(name), " as defined in dynamic scope");
- newFunctionNode = newFunctionNode.setInDynamicContext(lc);
- }
-
- //create recompilable scriptfunctiondata
- final int fnId = newFunctionNode.getId();
- final Map<Integer, RecompilableScriptFunctionData> nestedFunctions = fnIdToNestedFunctions.remove(fnId);
-
- assert nestedFunctions != null;
- // Generate the object class and property map in case this function is ever used as constructor
- final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData(
- newFunctionNode,
- compiler.getCodeInstaller(),
- ObjectClassGenerator.createAllocationStrategy(newFunctionNode.getThisProperties(), compiler.getContext().useDualFields()),
- nestedFunctions,
- externalSymbolDepths.get(fnId),
- internalSymbols.get(fnId));
-
- if (lc.getOutermostFunction() != newFunctionNode) {
- final FunctionNode parentFn = lc.getParentFunction(newFunctionNode);
- if (parentFn != null) {
- fnIdToNestedFunctions.get(parentFn.getId()).put(fnId, data);
- }
- } else {
- compiler.setData(data);
- }
-
- if (isDynamicScopeBoundary(functionNode)) {
- decreaseDynamicScopeCount(functionNode);
- }
-
- return newFunctionNode;
- }
-
- private boolean inDynamicScope() {
- return dynamicScopeCount > 0;
- }
-
- private void increaseDynamicScopeCount(final Node node) {
- assert dynamicScopeCount >= 0;
- ++dynamicScopeCount;
- if (log.isEnabled()) {
- log.finest(quote(lc.getCurrentFunction().getName()), " ++dynamicScopeCount = ", dynamicScopeCount, " at: ", node, node.getClass());
- }
- }
-
- private void decreaseDynamicScopeCount(final Node node) {
- --dynamicScopeCount;
- assert dynamicScopeCount >= 0;
- if (log.isEnabled()) {
- log.finest(quote(lc.getCurrentFunction().getName()), " --dynamicScopeCount = ", dynamicScopeCount, " at: ", node, node.getClass());
- }
- }
-
- @Override
- public boolean enterWithNode(final WithNode node) {
- withBodies.add(node.getBody());
- return true;
- }
-
- @Override
- public boolean enterBlock(final Block block) {
- if (compiler.isOnDemandCompilation()) {
- return true;
- }
-
- if (isDynamicScopeBoundary(block)) {
- increaseDynamicScopeCount(block);
- }
-
- if (!lc.isFunctionBody()) {
- return true;
- }
-
- //the below part only happens on eager compilation when we have the entire hierarchy
- //block is a function body
- final FunctionNode fn = lc.getCurrentFunction();
-
- //get all symbols that are referenced inside this function body
- final Set<Symbol> symbols = new HashSet<>();
- block.accept(new SimpleNodeVisitor() {
- @Override
- public boolean enterIdentNode(final IdentNode identNode) {
- final Symbol symbol = identNode.getSymbol();
- if (symbol != null && symbol.isScope()) {
- //if this is an internal symbol, skip it.
- symbols.add(symbol);
- }
- return true;
- }
- });
-
- final Map<String, Integer> internals = new HashMap<>();
-
- final Block globalBlock = findGlobalBlock(lc, block);
- final Block bodyBlock = findBodyBlock(lc, fn, block);
-
- assert globalBlock != null;
- assert bodyBlock != null;
-
- for (final Symbol symbol : symbols) {
- Iterator<Block> iter;
-
- final int internalDepth = findInternalDepth(lc, fn, block, symbol);
- final boolean internal = internalDepth >= 0;
- if (internal) {
- internals.put(symbol.getName(), internalDepth);
- }
-
- // if not internal, we have to continue walking until we reach the top. We
- // start outside the body and each new scope adds a depth count. When we
- // find the symbol, we store its depth count
- if (!internal) {
- int depthAtStart = 0;
- //not internal - keep looking.
- iter = lc.getAncestorBlocks(bodyBlock);
- while (iter.hasNext()) {
- final Block b2 = iter.next();
- if (definedInBlock(b2, symbol)) {
- addExternalSymbol(fn, symbol, depthAtStart);
- break;
- }
- if (b2.needsScope()) {
- depthAtStart++;
- }
- }
- }
- }
-
- addInternalSymbols(fn, internals.keySet());
-
- if (log.isEnabled()) {
- log.info(fn.getName() + " internals=" + internals + " externals=" + externalSymbolDepths.get(fn.getId()));
- }
-
- return true;
- }
-
- @Override
- public Node leaveBlock(final Block block) {
- if (compiler.isOnDemandCompilation()) {
- return block;
- }
- if (isDynamicScopeBoundary(block)) {
- decreaseDynamicScopeCount(block);
- }
- return block;
- }
-
- private void addInternalSymbols(final FunctionNode functionNode, final Set<String> symbols) {
- final int fnId = functionNode.getId();
- assert internalSymbols.get(fnId) == null || internalSymbols.get(fnId).equals(symbols); //e.g. cloned finally block
- internalSymbols.put(fnId, symbols);
- }
-
- private void addExternalSymbol(final FunctionNode functionNode, final Symbol symbol, final int depthAtStart) {
- final int fnId = functionNode.getId();
- Map<String, Integer> depths = externalSymbolDepths.get(fnId);
- if (depths == null) {
- depths = new HashMap<>();
- externalSymbolDepths.put(fnId, depths);
- }
- depths.put(symbol.getName(), depthAtStart);
- }
-
-}