< prev index next >
src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
Print this page
@@ -255,10 +255,13 @@
private final IntDeque labeledBlockBreakLiveLocals = new IntDeque();
//is this a rest of compilation
private final int[] continuationEntryPoints;
+ // Scope object creators needed for for-of and for-in loops
+ private Deque<FieldObjectCreator<?>> scopeObjectCreators = new ArrayDeque<>();
+
/**
* Constructor.
*
* @param compiler
*/
@@ -1276,10 +1279,18 @@
boolean useOptimisticTypes() {
return !lc.inSplitNode() && compiler.useOptimisticTypes();
}
+ // Determine whether a block needs to provide its scope object creator for use by its child nodes.
+ // This is only necessary for synthetic parent blocks of for-in loops with lexical declarations.
+ boolean providesScopeCreator(final Block block) {
+ return block.needsScope() && compiler.getScriptEnvironment()._es6
+ && block.isSynthetic() && (block.getLastStatement() instanceof ForNode)
+ && ((ForNode) block.getLastStatement()).needsScopeCreator();
+ }
+
@Override
public Node leaveBlock(final Block block) {
popBlockScope(block);
method.beforeJoinPoint(block);
@@ -1295,10 +1306,13 @@
}
private void popBlockScope(final Block block) {
final Label breakLabel = block.getBreakLabel();
+ if (providesScopeCreator(block)) {
+ scopeObjectCreators.pop();
+ }
if(!block.needsScope() || lc.isFunctionBody()) {
emitBlockBreakLabel(breakLabel);
return;
}
@@ -1810,10 +1824,18 @@
}.emit();
}
}.store();
body.accept(this);
+ if (forNode.needsScopeCreator() && providesScopeCreator(lc.getCurrentBlock())) {
+ // for-in loops with lexical declaration need a new scope for each iteration.
+ final FieldObjectCreator<?> creator = scopeObjectCreators.peek();
+ assert creator != null;
+ creator.createForInIterationScope(method);
+ method.storeCompilerConstant(SCOPE);
+ }
+
if(method.isReachable()) {
method._goto(continueLabel);
}
method.label(breakLabel);
}
@@ -1921,16 +1943,20 @@
/*
* Create a new object based on the symbols and values, generate
* bootstrap code for object
*/
- new FieldObjectCreator<Symbol>(this, tuples, true, hasArguments) {
+ final FieldObjectCreator<Symbol> creator = new FieldObjectCreator<Symbol>(this, tuples, true, hasArguments) {
@Override
protected void loadValue(final Symbol value, final Type type) {
method.load(value, type);
}
- }.makeObject(method);
+ };
+ creator.makeObject(method);
+ if (providesScopeCreator(block)) {
+ scopeObjectCreators.push(creator);
+ }
// program function: merge scope into global
if (isFunctionBody && function.isProgram()) {
method.invoke(ScriptRuntime.MERGE_SCOPE);
}
@@ -4478,11 +4504,11 @@
@Override
public boolean enterIdentNode(final IdentNode node) {
final Symbol symbol = node.getSymbol();
assert symbol != null;
if (symbol.isScope()) {
- final int flags = getScopeCallSiteFlags(symbol);
+ final int flags = getScopeCallSiteFlags(symbol) | (node.isDeclaredHere() ? CALLSITE_DECLARE : 0);
if (isFastScope(symbol)) {
storeFastScopeVar(symbol, flags);
} else {
method.dynamicSet(node.getName(), flags, false);
}
< prev index next >