Java源码示例:jdk.nashorn.internal.ir.Block
示例1
@Override
public Node leaveIfNode(final IfNode ifNode) {
final Node test = ifNode.getTest();
if (test instanceof LiteralNode.PrimitiveLiteralNode) {
final boolean isTrue = ((LiteralNode.PrimitiveLiteralNode<?>)test).isTrue();
final Block executed = isTrue ? ifNode.getPass() : ifNode.getFail();
final Block dropped = isTrue ? ifNode.getFail() : ifNode.getPass();
final List<Statement> statements = new ArrayList<>();
if (executed != null) {
statements.addAll(executed.getStatements()); // Get statements form executed branch
}
if (dropped != null) {
extractVarNodes(dropped, statements); // Get var-nodes from non-executed branch
}
if (statements.isEmpty()) {
return new EmptyNode(ifNode);
}
return BlockStatement.createReplacement(ifNode, ifNode.getFinish(), statements);
}
return ifNode;
}
示例2
@Override
public boolean enterCatchNode(final CatchNode catchNode) {
final IdentNode exception = catchNode.getException();
final Block block = lc.getCurrentBlock();
start(catchNode);
// define block-local exception variable
final String exname = exception.getName();
// If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its
// symbol is naturally internal, and should be treated as such.
final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName());
// IS_LET flag is required to make sure symbol is not visible outside catch block. However, we need to
// clear the IS_LET flag after creation to allow redefinition of symbol inside the catch block.
final Symbol symbol = defineSymbol(block, exname, catchNode, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE);
symbol.clearFlag(IS_LET);
return true;
}
示例3
@Override
public Node leaveBlock(final Block block) {
assert !block.isCatchBlock();
Block newBlock = block;
// Block was heavier than SLIT_THRESHOLD in enter, but a sub-block may have
// been split already, so weigh again before splitting.
long weight = WeighNodes.weigh(block, weightCache);
if (weight >= SPLIT_THRESHOLD) {
final FunctionNode currentFunction = lc.getCurrentFunction();
newBlock = splitBlock(block, currentFunction);
weight = WeighNodes.weigh(newBlock, weightCache);
lc.setFlag(currentFunction, FunctionNode.IS_SPLIT);
}
weightCache.put(newBlock, weight);
return newBlock;
}
示例4
/**
* Initialize parameters for function node. This may require specializing
* types if a specialization profile is known
*
* @param functionNode the function node
*/
private void initParameters(final FunctionNode functionNode, final Block body) {
int pos = 0;
for (final IdentNode param : functionNode.getParameters()) {
addLocalDef(param.getName());
final Type callSiteParamType = functionNode.getHints().getParameterType(pos);
int flags = IS_PARAM;
if (callSiteParamType != null) {
LOG.info("Param ", param, " has a callsite type ", callSiteParamType, ". Using that.");
flags |= Symbol.IS_SPECIALIZED_PARAM;
}
final Symbol paramSymbol = defineSymbol(body, param.getName(), flags);
assert paramSymbol != null;
newType(paramSymbol, callSiteParamType == null ? Type.UNKNOWN : callSiteParamType);
LOG.info("Initialized param ", pos, "=", paramSymbol);
pos++;
}
}
示例5
@Override
public boolean enterBlock(final Block block) {
start(block);
if (lc.isFunctionBody()) {
assert !block.hasSymbols();
final FunctionNode fn = lc.getCurrentFunction();
if (isUnparsedFunction(fn)) {
// It's a skipped nested function. Just mark the symbols being used by it as being in use.
for(final String name: compiler.getScriptFunctionData(fn.getId()).getExternalSymbolNames()) {
nameIsUsed(name, null);
}
// Don't bother descending into it, it must be empty anyway.
assert block.getStatements().isEmpty();
return false;
}
enterFunctionBody();
}
return true;
}
示例6
@Override
public Node leaveIfNode(final IfNode ifNode) {
final Node test = ifNode.getTest();
if (test instanceof LiteralNode.PrimitiveLiteralNode) {
final boolean isTrue = ((LiteralNode.PrimitiveLiteralNode<?>)test).isTrue();
final Block executed = isTrue ? ifNode.getPass() : ifNode.getFail();
final Block dropped = isTrue ? ifNode.getFail() : ifNode.getPass();
final List<Statement> statements = new ArrayList<>();
if (executed != null) {
statements.addAll(executed.getStatements()); // Get statements form executed branch
}
if (dropped != null) {
extractVarNodesFromDeadCode(dropped, statements); // Get var-nodes from non-executed branch
}
if (statements.isEmpty()) {
return new EmptyNode(ifNode);
}
return BlockStatement.createReplacement(ifNode, ifNode.getFinish(), statements);
}
return ifNode;
}
示例7
private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) {
initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE);
initCompileConstant(THIS, body, IS_PARAM | IS_THIS | HAS_OBJECT_VALUE);
if (functionNode.isVarArg()) {
initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE);
if (functionNode.needsArguments()) {
initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE);
defineSymbol(body, ARGUMENTS_VAR.symbolName(), null, IS_VAR | HAS_OBJECT_VALUE);
}
}
initParameters(functionNode, body);
initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE);
initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL);
}
示例8
private void defineFunctionSelfSymbol(final FunctionNode functionNode, final Block body) {
// Function self-symbol is only declared as a local variable for named function expressions. Declared functions
// don't need it as they are local variables in their declaring scope.
if (!functionNode.isNamedFunctionExpression()) {
return;
}
final String name = functionNode.getIdent().getName();
assert name != null; // As it's a named function expression.
if (body.getExistingSymbol(name) != null) {
// Body already has a declaration for the name. It's either a parameter "function x(x)" or a
// top-level variable "function x() { ... var x; ... }".
return;
}
defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
if(functionNode.allVarsInScope()) { // basically, has deep eval
// We must conservatively presume that eval'd code can dynamically use the function symbol.
lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
}
}
示例9
@Override
public Node leaveBlock(final Block block) {
if (!artificialBlock) {
if (lc.isFunctionBody()) {
// Prepend declaration-only var statements to the top of the statement list.
lc.prependStatements(getCurrentFunctionState().varStatements);
} else if (lc.isSplitBody()) {
appendSplitReturn(FALLTHROUGH_STATE, NO_LINE_NUMBER);
if (getCurrentFunctionState().fn.isProgram()) {
// If we're splitting the program, make sure every shard ends with "return :return" and
// begins with ":return = :return-in;".
lc.prependStatement(new ExpressionStatement(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH,
new BinaryNode(Token.toDesc(TokenType.ASSIGN, 0, 0), createReturnIdent(), createReturnParamIdent())));
}
}
}
return block;
}
示例10
/**
* ...IterationStatement :
* ...
* while ( Expression ) Statement
* ...
*
* See 12.6
*
* Parse while statement.
*/
private void whileStatement() {
// Capture WHILE token.
final long whileToken = token;
// WHILE tested in caller.
next();
// Construct WHILE node.
WhileNode whileNode = new WhileNode(line, whileToken, Token.descPosition(whileToken), false);
lc.push(whileNode);
try {
expect(LPAREN);
final int whileLine = line;
final JoinPredecessorExpression test = joinPredecessorExpression();
expect(RPAREN);
final Block body = getStatement();
appendStatement(whileNode =
new WhileNode(whileLine, whileToken, finish, false).
setTest(lc, test).
setBody(lc, body));
} finally {
lc.pop(whileNode);
}
}
示例11
/**
* ...IterationStatement :
* ...
* while ( Expression ) Statement
* ...
*
* See 12.6
*
* Parse while statement.
*/
private void whileStatement() {
// Capture WHILE token.
final long whileToken = token;
// WHILE tested in caller.
next();
// Construct WHILE node.
WhileNode whileNode = new WhileNode(line, whileToken, Token.descPosition(whileToken), false);
lc.push(whileNode);
try {
expect(LPAREN);
final int whileLine = line;
final JoinPredecessorExpression test = joinPredecessorExpression();
expect(RPAREN);
final Block body = getStatement();
appendStatement(whileNode =
new WhileNode(whileLine, whileToken, finish, false).
setTest(lc, test).
setBody(lc, body));
} finally {
lc.pop(whileNode);
}
}
示例12
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;
}
示例13
@Override
public boolean enterBlock(final Block block) {
boolean cloned = false;
for(final Symbol symbol: block.getSymbols()) {
if(symbol.isBytecodeLocal()) {
if (getLocalVariableTypeOrNull(symbol) == null) {
if (!cloned) {
cloneOrNewLocalVariableTypes();
cloned = true;
}
localVariableTypes.put(symbol, LvarType.UNDEFINED);
}
// In case we're repeating analysis of a lexical scope (e.g. it's in a loop),
// make sure all symbols lexically scoped by the block become valid again.
invalidatedSymbols.remove(symbol);
}
}
return true;
}
示例14
@Override
public boolean enterBlock(final Block block) {
boolean cloned = false;
for(final Symbol symbol: block.getSymbols()) {
if(symbol.isBytecodeLocal()) {
if (getLocalVariableTypeOrNull(symbol) == null) {
if (!cloned) {
cloneOrNewLocalVariableTypes();
cloned = true;
}
localVariableTypes.put(symbol, LvarType.UNDEFINED);
}
// In case we're repeating analysis of a lexical scope (e.g. it's in a loop),
// make sure all symbols lexically scoped by the block become valid again.
invalidatedSymbols.remove(symbol);
}
}
return true;
}
示例15
private Map<Symbol, LvarType> getBreakTargetTypes(final LexicalContextNode target) {
// Remove symbols defined in the the blocks that are being broken out of.
Map<Symbol, LvarType> types = localVariableTypes;
for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
final LexicalContextNode node = it.next();
if(node instanceof Block) {
for(final Symbol symbol: ((Block)node).getSymbols()) {
if(localVariableTypes.containsKey(symbol)) {
if(types == localVariableTypes) {
types = cloneMap(localVariableTypes);
}
types.remove(symbol);
}
}
}
if(node == target) {
break;
}
}
return types;
}
示例16
/**
* Initialize parameters for function node. This may require specializing
* types if a specialization profile is known
*
* @param functionNode the function node
*/
private void initParameters(final FunctionNode functionNode, final Block body) {
int pos = 0;
for (final IdentNode param : functionNode.getParameters()) {
addLocalDef(param.getName());
final Type callSiteParamType = functionNode.getHints().getParameterType(pos);
int flags = IS_PARAM;
if (callSiteParamType != null) {
LOG.info("Param ", param, " has a callsite type ", callSiteParamType, ". Using that.");
flags |= Symbol.IS_SPECIALIZED_PARAM;
}
final Symbol paramSymbol = defineSymbol(body, param.getName(), flags);
assert paramSymbol != null;
newType(paramSymbol, callSiteParamType == null ? Type.UNKNOWN : callSiteParamType);
LOG.info("Initialized param ", pos, "=", paramSymbol);
pos++;
}
}
示例17
@Override
public boolean enterBlock(final Block block) {
start(block);
if (lc.isFunctionBody()) {
assert !block.hasSymbols();
final FunctionNode fn = lc.getCurrentFunction();
if (isUnparsedFunction(fn)) {
// It's a skipped nested function. Just mark the symbols being used by it as being in use.
for(final String name: compiler.getScriptFunctionData(fn.getId()).getExternalSymbolNames()) {
nameIsUsed(name, null);
}
// Don't bother descending into it, it must be empty anyway.
assert block.getStatements().isEmpty();
return false;
}
enterFunctionBody();
}
return true;
}
示例18
private Map<Symbol, LvarType> getBreakTargetTypes(final LexicalContextNode target) {
// Remove symbols defined in the the blocks that are being broken out of.
Map<Symbol, LvarType> types = localVariableTypes;
for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
final LexicalContextNode node = it.next();
if(node instanceof Block) {
for(final Symbol symbol: ((Block)node).getSymbols()) {
if(localVariableTypes.containsKey(symbol)) {
if(types == localVariableTypes) {
types = cloneMap(localVariableTypes);
}
types.remove(symbol);
}
}
}
if(node == target) {
break;
}
}
return types;
}
示例19
private static Block createFinallyBlock(final Block finallyBody) {
final List<Statement> newStatements = new ArrayList<>();
for (final Statement statement : finallyBody.getStatements()) {
newStatements.add(statement);
if (statement.hasTerminalFlags()) {
break;
}
}
return finallyBody.setStatements(null, newStatements);
}
示例20
@Override
public boolean enterIfNode(final IfNode ifNode) {
lineNumber(ifNode);
final Expression test = ifNode.getTest();
final Block pass = ifNode.getPass();
final Block fail = ifNode.getFail();
final Label failLabel = new Label("if_fail");
final Label afterLabel = fail == null ? failLabel : new Label("if_done");
new BranchOptimizer(this, method).execute(test, failLabel, false);
boolean passTerminal = false;
boolean failTerminal = false;
pass.accept(this);
if (!pass.hasTerminalFlags()) {
method._goto(afterLabel); //don't fallthru to fail block
} else {
passTerminal = pass.isTerminal();
}
if (fail != null) {
method.label(failLabel);
fail.accept(this);
failTerminal = fail.isTerminal();
}
//if if terminates, put the after label there
if (!passTerminal || !failTerminal) {
method.label(afterLabel);
}
return false;
}
示例21
private static Block prependFinally(final Block finallyBlock, final Statement statement) {
final Block inlinedFinally = ensureUniqueNamesIn(finallyBlock);
if (isTerminalFinally(finallyBlock)) {
return inlinedFinally;
}
final List<Statement> stmts = inlinedFinally.getStatements();
final List<Statement> newStmts = new ArrayList<>(stmts.size() + 1);
newStmts.addAll(stmts);
newStmts.add(statement);
return new Block(inlinedFinally.getToken(), statement.getFinish(), newStmts);
}
示例22
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.setFirstSlot(fromSlot);
final int toSlot = fromSlot + symbol.slotCount();
method.defineBlockLocalVariable(fromSlot, toSlot);
fromSlot = toSlot;
}
}
return fromSlot;
}
示例23
/**
* ...IterationStatement :
* ...
* do Statement while( Expression ) ;
* ...
*
* See 12.6
*
* Parse DO WHILE statement.
*/
private void doStatement() {
// Capture DO token.
final long doToken = token;
// DO tested in the caller.
next();
WhileNode doWhileNode = new WhileNode(-1, doToken, Token.descPosition(doToken), true);
lc.push(doWhileNode);
try {
// Get DO body.
final Block body = getStatement();
expect(WHILE);
expect(LPAREN);
final int doLine = line;
final JoinPredecessorExpression test = joinPredecessorExpression();
expect(RPAREN);
if (type == SEMICOLON) {
endOfLine();
}
doWhileNode.setFinish(finish);
//line number is last
appendStatement(doWhileNode =
new WhileNode(doLine, doToken, finish, true).
setBody(lc, body).
setTest(lc, test));
} finally {
lc.pop(doWhileNode);
}
}
示例24
private static void extractVarNodes(final Block block, final List<Statement> statements) {
final LexicalContext lc = new LexicalContext();
block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
@Override
public boolean enterVarNode(VarNode varNode) {
statements.add(varNode.setInit(null));
return false;
}
});
}
示例25
private FunctionNode createSyntheticInitializers(final FunctionNode functionNode) {
final List<VarNode> syntheticInitializers = new ArrayList<>(2);
// Must visit the new var nodes in the context of the body. We could also just set the new statements into the
// block and then revisit the entire block, but that seems to be too much double work.
final Block body = functionNode.getBody();
lc.push(body);
try {
if (functionNode.usesSelfSymbol()) {
// "var fn = :callee"
syntheticInitializers.add(createSyntheticInitializer(functionNode.getIdent(), CALLEE, functionNode));
}
if (functionNode.needsArguments()) {
// "var arguments = :arguments"
syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()),
ARGUMENTS, functionNode));
}
if (syntheticInitializers.isEmpty()) {
return functionNode;
}
for(final ListIterator<VarNode> it = syntheticInitializers.listIterator(); it.hasNext();) {
it.set((VarNode)it.next().accept(this));
}
} finally {
lc.pop(body);
}
final List<Statement> stmts = body.getStatements();
final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
newStatements.addAll(syntheticInitializers);
newStatements.addAll(stmts);
return functionNode.setBody(lc, body.setStatements(lc, newStatements));
}
示例26
/**
* Search for symbol in the lexical context starting from the given block.
* @param name Symbol name.
* @return Found symbol or null if not found.
*/
private Symbol findSymbol(final Block block, final String name) {
for (final Iterator<Block> blocks = lc.getBlocks(block); blocks.hasNext();) {
final Symbol symbol = blocks.next().getExistingSymbol(name);
if (symbol != null) {
return symbol;
}
}
return null;
}
示例27
@Override
public boolean enterIfNode(final IfNode ifNode) {
lineNumber(ifNode);
final Expression test = ifNode.getTest();
final Block pass = ifNode.getPass();
final Block fail = ifNode.getFail();
final Label failLabel = new Label("if_fail");
final Label afterLabel = fail == null ? failLabel : new Label("if_done");
new BranchOptimizer(this, method).execute(test, failLabel, false);
boolean passTerminal = false;
boolean failTerminal = false;
pass.accept(this);
if (!pass.hasTerminalFlags()) {
method._goto(afterLabel); //don't fallthru to fail block
} else {
passTerminal = pass.isTerminal();
}
if (fail != null) {
method.label(failLabel);
fail.accept(this);
failTerminal = fail.isTerminal();
}
//if if terminates, put the after label there
if (!passTerminal || !failTerminal) {
method.label(afterLabel);
}
return false;
}
示例28
/**
* Split a block into sub methods.
*
* @param block Block or function to split.
*
* @return new weight for the resulting block.
*/
private Block splitBlock(final Block block, final FunctionNode function) {
final List<Statement> splits = new ArrayList<>();
List<Statement> statements = new ArrayList<>();
long statementsWeight = 0;
for (final Statement statement : block.getStatements()) {
final long weight = WeighNodes.weigh(statement, weightCache);
if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal()) {
if (!statements.isEmpty()) {
splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
statements = new ArrayList<>();
statementsWeight = 0;
}
}
if (statement.isTerminal()) {
splits.add(statement);
} else {
statements.add(statement);
statementsWeight += weight;
}
}
if (!statements.isEmpty()) {
splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
}
return block.setStatements(lc, splits);
}
示例29
/**
* Determines if the symbol has to be a scope symbol. In general terms, it has to be a scope symbol if it can only
* be reached from the current block by traversing a function node, a split node, or a with node.
* @param symbol the symbol checked for needing to be a scope symbol
* @return true if the symbol has to be a scope symbol.
*/
private boolean symbolNeedsToBeScope(final Symbol symbol) {
if (symbol.isThis() || symbol.isInternal()) {
return false;
}
final FunctionNode func = lc.getCurrentFunction();
if ( func.allVarsInScope() || (!symbol.isBlockScoped() && func.isProgram())) {
return true;
}
boolean previousWasBlock = false;
for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
final LexicalContextNode node = it.next();
if (node instanceof FunctionNode || isSplitLiteral(node)) {
// We reached the function boundary or a splitting boundary without seeing a definition for the symbol.
// It needs to be in scope.
return true;
} else if (node instanceof WithNode) {
if (previousWasBlock) {
// We reached a WithNode; the symbol must be scoped. Note that if the WithNode was not immediately
// preceded by a block, this means we're currently processing its expression, not its body,
// therefore it doesn't count.
return true;
}
previousWasBlock = false;
} else if (node instanceof Block) {
if (((Block)node).getExistingSymbol(symbol.getName()) == symbol) {
// We reached the block that defines the symbol without reaching either the function boundary, or a
// WithNode. The symbol need not be scoped.
return false;
}
previousWasBlock = true;
} else {
previousWasBlock = false;
}
}
throw new AssertionError();
}
示例30
@Override
public boolean enterBlock(final Block block) {
if (block.isCatchBlock()) {
return false;
}
final long weight = WeighNodes.weigh(block, weightCache);
if (weight < SPLIT_THRESHOLD) {
weightCache.put(block, weight);
return false;
}
return true;
}