String getBodyMethodSignature(ScriptNode n) { StringBuilder sb = new StringBuilder(); sb.append('('); sb.append(mainClassSignature); sb.append("Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;"); if (n.getType() == Token.FUNCTION) { OptFunctionNode ofn = OptFunctionNode.get(n); if (ofn.isTargetOfDirectCall()) { int pCount = ofn.fnode.getParamCount(); for (int i = 0; i != pCount; i++) { sb.append("Ljava/lang/Object;D"); } } } sb.append("[Ljava/lang/Object;)Ljava/lang/Object;"); return sb.toString(); }
private void printLiveOnEntrySet(OptFunctionNode fn) { if (DEBUG) { for (int i = 0; i < fn.getVarCount(); i++) { String name = fn.fnode.getParamOrVarName(i); if (itsUseBeforeDefSet.test(i)) System.out.println(name + " is used before def'd"); if (itsNotDefSet.test(i)) System.out.println(name + " is not def'd"); if (itsLiveOnEntrySet.test(i)) System.out.println(name + " is live on entry"); if (itsLiveOnExitSet.test(i)) System.out.println(name + " is live on exit"); } } }
private int nodeIsDirectCallParameter(Node node) { if (node.getType() == Token.GETVAR && inDirectCallFunction && !itsForcedObjectParameters) { int varIndex = fnCurrent.getVarIndex(node); if (fnCurrent.isParameter(varIndex)) { return varRegisters[varIndex]; } } return -1; }
OptFunctionNode.get(tree).itsContainsCalls0 = true; if (!ofn.isTargetOfDirectCall()) { int index = directCallTargets.size(); directCallTargets.add(ofn); ofn.setDirectTargetIndex(index);
private void visitGetVar(Node node) { if (!hasVarsInRegs) Kit.codeBug(); int varIndex = fnCurrent.getVarIndex(node); short reg = varRegisters[varIndex]; if (varIsDirectCallParameter(varIndex)) { // Remember that here the isNumber flag means that we // want to use the incoming parameter in a Number // context, so test the object type and convert the // value as necessary. if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { dcpLoadAsNumber(reg); } else { dcpLoadAsObject(reg); } } else if (fnCurrent.isNumberVar(varIndex)) { cfw.addDLoad(reg); } else { cfw.addALoad(reg); } }
private void optimizeFunction(OptFunctionNode theFunction) { if (theFunction.fnode.requiresActivation()) return; inDirectCallFunction = theFunction.isTargetOfDirectCall(); this.theFunction = theFunction; ObjArray statementsArray = new ObjArray(); buildStatementList_r(theFunction.fnode, statementsArray); Node[] theStatementNodes = new Node[statementsArray.size()]; statementsArray.toArray(theStatementNodes); Block.runFlowAnalyzes(theFunction, theStatementNodes); if (!theFunction.fnode.requiresActivation()) { /* * Now that we know which local vars are in fact always * Numbers, we re-write the tree to take advantage of * that. Any arithmetic or assignment op involving just * Number typed vars is marked so that the codegen will * generate non-object code. */ parameterUsedInNumberContext = false; for (int i = 0; i < theStatementNodes.length; i++) { rewriteForNumberVariables(theStatementNodes[i], NumberType); } theFunction.setParameterNumberContext(parameterUsedInNumberContext); } }
if (!fnCurrent.getParameterNumberContext()) { cfw.addAStore(reg); } else if (fnCurrent.isNumberVar(i)) { reg = getNewWordPairLocal(constDeclarations[i]); cfw.addPush(0.0); if (constDeclarations[i]) { cfw.addPush(0); cfw.addIStore(reg + (fnCurrent.isNumberVar(i) ? 2 : 1)); String type = fnCurrent.isNumberVar(i) ? "D" : "Ljava/lang/Object;"; int startPC = cfw.getCurrentCodeOffset();
if (!fnCurrent.getParameterNumberContext()) { cfw.addAStore(reg); } else if (fnCurrent.isNumberVar(i)) { reg = getNewWordPairLocal(constDeclarations[i]); cfw.addPush(0.0); if (constDeclarations[i]) { cfw.addPush(0); cfw.addIStore(reg + (fnCurrent.isNumberVar(i) ? 2 : 1)); String type = fnCurrent.isNumberVar(i) ? "D" : "Ljava/lang/Object;"; int startPC = cfw.getCurrentCodeOffset(); OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, i); if (ofn.fnode.getFunctionType() == FunctionNode.FUNCTION_STATEMENT)
void optimize(ScriptOrFnNode scriptOrFn) { // run on one function at a time for now int functionCount = scriptOrFn.getFunctionCount(); for (int i = 0; i != functionCount; ++i) { OptFunctionNode f = OptFunctionNode.get(scriptOrFn, i); optimizeFunction(f); } }
private static void initOptFunctions_r(ScriptOrFnNode scriptOrFn) { for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) { FunctionNode fn = scriptOrFn.getFunctionNode(i); new OptFunctionNode(fn); initOptFunctions_r(fn); } }
int varIndex = fnCurrent.fnode.getIndexForNameNode(node); if (varIndex >= 0) { if (fnCurrent.isNumberVar(varIndex)) { cfw.addPush("number"); } else if (varIsDirectCallParameter(varIndex)) {
private boolean varIsDirectCallParameter(int varIndex) { return fnCurrent.isParameter(varIndex) && inDirectCallFunction && !itsForcedObjectParameters; }
OptFunctionNode.get(tree).itsContainsCalls0 = true; if (!ofn.isTargetOfDirectCall()) { int index = directCallTargets.size(); directCallTargets.add(ofn); ofn.setDirectTargetIndex(index);
private void visitGetVar(Node node) { if (!hasVarsInRegs) Kit.codeBug(); int varIndex = fnCurrent.getVarIndex(node); short reg = varRegisters[varIndex]; if (varIsDirectCallParameter(varIndex)) { // Remember that here the isNumber flag means that we // want to use the incoming parameter in a Number // context, so test the object type and convert the // value as necessary. if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { dcpLoadAsNumber(reg); } else { dcpLoadAsObject(reg); } } else if (fnCurrent.isNumberVar(varIndex)) { cfw.addDLoad(reg); } else { cfw.addALoad(reg); } }
private void optimizeFunction(OptFunctionNode theFunction) { if (theFunction.fnode.requiresActivation()) return; inDirectCallFunction = theFunction.isTargetOfDirectCall(); this.theFunction = theFunction; ObjArray statementsArray = new ObjArray(); buildStatementList_r(theFunction.fnode, statementsArray); Node[] theStatementNodes = new Node[statementsArray.size()]; statementsArray.toArray(theStatementNodes); Block.runFlowAnalyzes(theFunction, theStatementNodes); if (!theFunction.fnode.requiresActivation()) { /* * Now that we know which local vars are in fact always * Numbers, we re-write the tree to take advantage of * that. Any arithmetic or assignment op involving just * Number typed vars is marked so that the codegen will * generate non-object code. */ parameterUsedInNumberContext = false; for (Node theStatementNode : theStatementNodes) { rewriteForNumberVariables(theStatementNode, NumberType); } theFunction.setParameterNumberContext(parameterUsedInNumberContext); } }
if (!fnCurrent.getParameterNumberContext()) { cfw.addAStore(reg); } else if (fnCurrent.isNumberVar(i)) { reg = getNewWordPairLocal(constDeclarations[i]); cfw.addPush(0.0); if (constDeclarations[i]) { cfw.addPush(0); cfw.addIStore(reg + (fnCurrent.isNumberVar(i) ? 2 : 1)); String type = fnCurrent.isNumberVar(i) ? "D" : "Ljava/lang/Object;"; int startPC = cfw.getCurrentCodeOffset();
void optimize(ScriptNode scriptOrFn) { // run on one function at a time for now int functionCount = scriptOrFn.getFunctionCount(); for (int i = 0; i != functionCount; ++i) { OptFunctionNode f = OptFunctionNode.get(scriptOrFn, i); optimizeFunction(f); } }
private static void initOptFunctions_r(ScriptNode scriptOrFn) { for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) { FunctionNode fn = scriptOrFn.getFunctionNode(i); new OptFunctionNode(fn); initOptFunctions_r(fn); } }