@Override void write(MethodWriter function, Globals globals) { if (reserved.getMaxLoopCounter() > 0) { // if there is infinite loop protection, we do this once: // int #loop = settings.getMaxLoopCounter() function.push(reserved.getMaxLoopCounter()); function.visitVarInsn(Opcodes.ISTORE, loop.getSlot()); } for (AStatement statement : statements) { statement.write(function, globals); } if (!methodEscape) { if (rtnType.sort == Sort.VOID) { function.returnValue(); } else { throw createError(new IllegalStateException("Illegal tree structure.")); } } String staticHandleFieldName = Def.getUserFunctionHandleFieldName(name, parameters.size()); globals.addConstantInitializer( new Constant( location, WriterConstants.METHOD_HANDLE_TYPE, staticHandleFieldName, this::initializeConstant)); }
@Override void analyze(Locals locals) { if (statements == null || statements.isEmpty()) { throw createError( new IllegalArgumentException("Cannot generate an empty function [" + name + "].")); } locals = Locals.newLocalScope(locals); AStatement last = statements.get(statements.size() - 1); for (AStatement statement : statements) { // Note that we do not need to check after the last statement because // there is no statement that can be unreachable after the last. if (allEscape) { throw createError(new IllegalArgumentException("Unreachable statement.")); } statement.lastSource = statement == last; statement.analyze(locals); methodEscape = statement.methodEscape; allEscape = statement.allEscape; } if (!methodEscape && rtnType.sort != Sort.VOID) { throw createError( new IllegalArgumentException( "Not all paths provide a return value for method [" + name + "].")); } if (reserved.getMaxLoopCounter() > 0) { loop = locals.getVariable(null, FunctionReserved.LOOP); } }