aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
diff options
context:
space:
mode:
authorDenis S. Fokin <Denis.Fokin@gmail.com>2015-10-29 14:35:35 +0300
committerDenis S. Fokin <Denis.Fokin@gmail.com>2015-10-29 14:35:35 +0300
commit65de49fac48ef400da91c0500eeea9b52e23f045 (patch)
tree91cc50316697e665cdcaa0e2a9be39333f68b5b4 /src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
parent8ec2a4d4e720accdab0fc5d069211bc7e03129e7 (diff)
parent79867aa8b3f50e06365efa3c2111912766300538 (diff)
downloadjdk8u_nashorn-65de49fac48ef400da91c0500eeea9b52e23f045.tar.gz
Merge with default before merge with jdk8u60
--HG-- branch : 8u40-verified-fixes
Diffstat (limited to 'src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java')
-rw-r--r--src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java166
1 files changed, 110 insertions, 56 deletions
diff --git a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
index dcf1b1ba..87a0802c 100644
--- a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
+++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
@@ -31,7 +31,7 @@ import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
-
+import jdk.nashorn.internal.IntDeque;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.FunctionNode;
@@ -63,6 +63,10 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
* i.e. should we keep it or throw it away */
private final Deque<Node> discard = new ArrayDeque<>();
+ private final Deque<Map<String, Collection<Label>>> unwarrantedOptimismHandlers = new ArrayDeque<>();
+ private final Deque<StringBuilder> slotTypesDescriptors = new ArrayDeque<>();
+ private final IntDeque splitNodes = new IntDeque();
+
/** A stack tracking the next free local variable slot in the blocks. There's one entry for every block
* currently on the lexical context stack. */
private int[] nextFreeSlots = new int[16];
@@ -70,46 +74,56 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
/** size of next free slot vector */
private int nextFreeSlotsSize;
+ private boolean isWithBoundary(final LexicalContextNode node) {
+ return node instanceof Block && !isEmpty() && peek() instanceof WithNode;
+ }
+
@Override
public <T extends LexicalContextNode> T push(final T node) {
- if (isDynamicScopeBoundary(node)) {
- ++dynamicScopeCount;
+ if (isWithBoundary(node)) {
+ dynamicScopeCount++;
+ } else if (node instanceof FunctionNode) {
+ if (((FunctionNode)node).inDynamicContext()) {
+ dynamicScopeCount++;
+ }
+ splitNodes.push(0);
}
return super.push(node);
}
+ void enterSplitNode() {
+ splitNodes.getAndIncrement();
+ pushFreeSlots(methodEmitters.peek().getUsedSlotsWithLiveTemporaries());
+ }
+
+ void exitSplitNode() {
+ final int count = splitNodes.decrementAndGet();
+ assert count >= 0;
+ }
+
@Override
public <T extends LexicalContextNode> T pop(final T node) {
final T popped = super.pop(node);
- if (isDynamicScopeBoundary(popped)) {
- --dynamicScopeCount;
- }
- if (node instanceof Block) {
- --nextFreeSlotsSize;
- }
- return popped;
- }
-
- private boolean isDynamicScopeBoundary(final LexicalContextNode node) {
- if (node instanceof Block) {
- // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture
- // processing of WithNode.expression too, but it should be unaffected.
- return !isEmpty() && peek() instanceof WithNode;
+ if (isWithBoundary(node)) {
+ dynamicScopeCount--;
+ assert dynamicScopeCount >= 0;
} else if (node instanceof FunctionNode) {
- // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
- // variable into the function's scope), and it isn't strict (as evals in strict functions get an
- // isolated scope).
- return isFunctionDynamicScope((FunctionNode)node);
+ if (((FunctionNode)node).inDynamicContext()) {
+ dynamicScopeCount--;
+ assert dynamicScopeCount >= 0;
+ }
+ assert splitNodes.peek() == 0;
+ splitNodes.pop();
}
- return false;
+ return popped;
}
boolean inDynamicScope() {
return dynamicScopeCount > 0;
}
- static boolean isFunctionDynamicScope(FunctionNode fn) {
- return fn.hasEval() && !fn.isStrict();
+ boolean inSplitNode() {
+ return !splitNodes.isEmpty() && splitNodes.peek() > 0;
}
MethodEmitter pushMethodEmitter(final MethodEmitter newMethod) {
@@ -123,6 +137,20 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
return methodEmitters.isEmpty() ? null : methodEmitters.peek();
}
+ void pushUnwarrantedOptimismHandlers() {
+ unwarrantedOptimismHandlers.push(new HashMap<String, Collection<Label>>());
+ slotTypesDescriptors.push(new StringBuilder());
+ }
+
+ Map<String, Collection<Label>> getUnwarrantedOptimismHandlers() {
+ return unwarrantedOptimismHandlers.peek();
+ }
+
+ Map<String, Collection<Label>> popUnwarrantedOptimismHandlers() {
+ slotTypesDescriptors.pop();
+ return unwarrantedOptimismHandlers.pop();
+ }
+
CompileUnit pushCompileUnit(final CompileUnit newUnit) {
compileUnits.push(newUnit);
return newUnit;
@@ -130,7 +158,9 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
CompileUnit popCompileUnit(final CompileUnit oldUnit) {
assert compileUnits.peek() == oldUnit;
- compileUnits.pop();
+ final CompileUnit unit = compileUnits.pop();
+ assert unit.hasCode() : "compile unit popped without code";
+ unit.setUsed();
return compileUnits.isEmpty() ? null : compileUnits.peek();
}
@@ -167,50 +197,77 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
* Get a shared static method representing a dynamic scope get access.
*
* @param unit current compile unit
- * @param type the type of the variable
* @param symbol the symbol
+ * @param valueType the type of the variable
* @param flags the callsite flags
* @return an object representing a shared scope call
*/
- SharedScopeCall getScopeGet(final CompileUnit unit, final Type type, final Symbol symbol, final int flags) {
- final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags);
- if (scopeCalls.containsKey(scopeCall)) {
- return scopeCalls.get(scopeCall);
- }
- scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName(":scopeCall"));
- scopeCalls.put(scopeCall, scopeCall);
- return scopeCall;
+ SharedScopeCall getScopeGet(final CompileUnit unit, final Symbol symbol, final Type valueType, final int flags) {
+ return getScopeCall(unit, symbol, valueType, valueType, null, flags);
}
+ void onEnterBlock(final Block block) {
+ pushFreeSlots(assignSlots(block, isFunctionBody() ? 0 : getUsedSlotCount()));
+ }
- void nextFreeSlot(final Block block) {
- final boolean isFunctionBody = isFunctionBody();
-
- final int nextFreeSlot;
- if (isFunctionBody) {
- // On entry to function, start with slot 0
- nextFreeSlot = 0;
- } else {
- // Otherwise, continue from previous block's first free slot
- nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1];
- }
+ private void pushFreeSlots(final int freeSlots) {
if (nextFreeSlotsSize == nextFreeSlots.length) {
final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2];
System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize);
nextFreeSlots = newNextFreeSlots;
}
- nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot);
+ nextFreeSlots[nextFreeSlotsSize++] = freeSlots;
+ }
+
+ int getUsedSlotCount() {
+ return nextFreeSlots[nextFreeSlotsSize - 1];
+ }
+
+ void releaseSlots() {
+ --nextFreeSlotsSize;
+ final int undefinedFromSlot = nextFreeSlotsSize == 0 ? 0 : nextFreeSlots[nextFreeSlotsSize - 1];
+ if(!slotTypesDescriptors.isEmpty()) {
+ slotTypesDescriptors.peek().setLength(undefinedFromSlot);
+ }
+ methodEmitters.peek().undefineLocalVariables(undefinedFromSlot, false);
}
- private static int assignSlots(final Block block, final int firstSlot) {
- int nextSlot = firstSlot;
+ private int assignSlots(final Block block, final int firstSlot) {
+ int fromSlot = firstSlot;
+ final MethodEmitter method = methodEmitters.peek();
for (final Symbol symbol : block.getSymbols()) {
if (symbol.hasSlot()) {
- symbol.setSlot(nextSlot);
- nextSlot += symbol.slotCount();
+ symbol.setFirstSlot(fromSlot);
+ final int toSlot = fromSlot + symbol.slotCount();
+ method.defineBlockLocalVariable(fromSlot, toSlot);
+ fromSlot = toSlot;
}
}
- return nextSlot;
+ return fromSlot;
+ }
+
+ static Type getTypeForSlotDescriptor(final char typeDesc) {
+ // Recognizing both lowercase and uppercase as we're using both to signify symbol boundaries; see
+ // MethodEmitter.markSymbolBoundariesInLvarTypesDescriptor().
+ switch (typeDesc) {
+ case 'I':
+ case 'i':
+ return Type.INT;
+ case 'J':
+ case 'j':
+ return Type.LONG;
+ case 'D':
+ case 'd':
+ return Type.NUMBER;
+ case 'A':
+ case 'a':
+ return Type.OBJECT;
+ case 'U':
+ case 'u':
+ return Type.UNKNOWN;
+ default:
+ throw new AssertionError();
+ }
}
void pushDiscard(final Node node) {
@@ -225,11 +282,8 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
return discard.peek();
}
- int quickSlot(final Symbol symbol) {
- final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1];
- nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount();
- return quickSlot;
+ int quickSlot(final Type type) {
+ return methodEmitters.peek().defineTemporaryLocalVariable(type.getSlots());
}
-
}