protected void doFieldWrite( WalkContext context, int receiver, CAstNode elt, CAstNode parent, int rval) { this.visit(elt, context, this); if (elt.getKind() == CAstNode.CONSTANT && elt.getValue() instanceof String) { String field = (String) elt.getValue(); if (isPrologueScript(context) && "__proto__".equals(field)) { context.cfg().addInstruction(((JSInstructionFactory) insts).SetPrototype(receiver, rval)); return; } } /* } else { context.currentScope().getConstantValue(field); SSAPutInstruction put = ((JSInstructionFactory) insts).PutInstruction(receiver, rval, field); try { assert field.equals(put.getDeclaredField().getName().toUnicodeString()); } catch (UTFDataFormatException e) { Assertions.UNREACHABLE(); } context.cfg().addInstruction(put); } } else { */ context .cfg() .addInstruction( ((JSInstructionFactory) insts).PropertyWrite(receiver, context.getValue(elt), rval)); // } }
private void doPrimitiveNew(WalkContext context, int resultVal, String typeName) { doNewObject(context, null, resultVal, typeName + "Object", null); // set the class property of the new object int rval = context.currentScope().getConstantValue(typeName); context.currentScope().getConstantValue("class"); context .cfg() .addInstruction(((JSInstructionFactory) insts).PutInstruction(resultVal, rval, "class")); }
protected void doPrologue(WalkContext context) { super.doPrologue(context); int tempVal = context.currentScope().allocateTempValue(); doNewObject(context, null, tempVal, "Array", null); CAstSymbol args = new CAstSymbolImpl("arguments"); context.currentScope().declare(args, tempVal); // context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(1, tempVal, // "arguments")); }
/** * generate an instruction that checks if readVn is undefined and throws an exception if it isn't */ private void addDefinedCheck(CAstNode n, WalkContext context, int readVn) { context.cfg().addPreNode(n); context.cfg().addInstruction(((JSInstructionFactory) insts).CheckReference(readVn)); CAstNode target = context.getControlFlow().getTarget(n, JavaScriptTypes.ReferenceError); if (target != null) { context.cfg().addPreEdge(n, target, true); } else { context.cfg().addPreEdgeToExit(n, true); } context.cfg().newBlock(true); }
protected void leaveInstanceOf(CAstNode n, WalkContext c, CAstVisitor<WalkContext> visitor) { WalkContext context = (WalkContext) c; int result = context.getValue(n); visit(n.getChild(0), context, visitor); int value = context.getValue(n.getChild(0)); visit(n.getChild(1), context, visitor); int type = context.getValue(n.getChild(1)); context.cfg().addInstruction(new JavaScriptInstanceOf(result, value, type)); }
protected void doNewObject( WalkContext context, CAstNode newNode, int result, Object type, int[] arguments) { assert arguments == null; TypeReference typeRef = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName("L" + type)); context .cfg() .addInstruction( insts.NewInstruction( result, NewSiteReference.make(context.cfg().getCurrentInstruction(), typeRef))); }
protected void doMaterializeFunction( CAstNode n, WalkContext context, int result, int exception, CAstEntity fn) { int nm = context.currentScope().getConstantValue("L" + composeEntityName(context, fn)); // "Function" is the name we use to model the constructor of function values int tmp = super.doGlobalRead(n, context, "Function"); context .cfg() .addInstruction( ((JSInstructionFactory) insts) .Invoke( tmp, result, new int[] {nm}, exception, new JSCallSiteReference( JavaScriptMethods.ctorReference, context.cfg().getCurrentInstruction()))); }
protected void doIsFieldDefined(WalkContext context, int result, int ref, CAstNode f) { if (f.getKind() == CAstNode.CONSTANT && f.getValue() instanceof String) { String field = (String) f.getValue(); FieldReference fieldRef = FieldReference.findOrCreate( JavaScriptTypes.Root, Atom.findOrCreateUnicodeAtom((String) field), JavaScriptTypes.Root); context .cfg() .addInstruction( ((JSInstructionFactory) insts).IsDefinedInstruction(result, ref, fieldRef)); } else { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .IsDefinedInstruction(result, ref, context.getValue(f))); } }
protected void doCall( WalkContext context, CAstNode call, int result, int exception, CAstNode name, int receiver, int[] arguments) { MethodReference ref = name.getValue().equals("ctor") ? JavaScriptMethods.ctorReference : name.getValue().equals("dispatch") ? JavaScriptMethods.dispatchReference : AstMethodReference.fnReference(JavaScriptTypes.CodeBody); context .cfg() .addInstruction( ((JSInstructionFactory) insts) .Invoke( receiver, result, arguments, exception, new JSCallSiteReference(ref, context.cfg().getCurrentInstruction()))); context.cfg().addPreNode(call, context.getUnwindState()); // this new block is for the normal termination case context.cfg().newBlock(true); // exceptional case: flow to target given in CAst, or if null, the exit node if (context.getControlFlow().getTarget(call, null) != null) context.cfg().addPreEdge(call, context.getControlFlow().getTarget(call, null), true); else context.cfg().addPreEdgeToExit(call, true); }
protected boolean doVisit(CAstNode n, WalkContext cntxt, CAstVisitor<WalkContext> visitor) { WalkContext context = (WalkContext) cntxt; switch (n.getKind()) { case CAstNode.TYPE_OF: { int result = context.currentScope().allocateTempValue(); this.visit(n.getChild(0), context, this); int ref = context.getValue(n.getChild(0)); context .cfg() .addInstruction(((JSInstructionFactory) insts).TypeOfInstruction(result, ref)); context.setValue(n, result); return true; } case JavaScriptCAstNode.ENTER_WITH: case JavaScriptCAstNode.EXIT_WITH: { this.visit(n.getChild(0), context, this); int ref = context.getValue(n.getChild(0)); context .cfg() .addInstruction( ((JSInstructionFactory) insts) .WithRegion(ref, n.getKind() == JavaScriptCAstNode.ENTER_WITH)); return true; } default: { return false; } } }
private boolean isPrologueScript(WalkContext context) { return JavaScriptLoader.bootstrapFileNames.contains(context.getModule().getName()); }
protected boolean visitInstanceOf(CAstNode n, WalkContext c, CAstVisitor<WalkContext> visitor) { WalkContext context = (WalkContext) c; int result = context.currentScope().allocateTempValue(); context.setValue(n, result); return false; }
protected void doPrimitive(int resultVal, WalkContext context, CAstNode primitiveCall) { try { String name = (String) primitiveCall.getChild(0).getValue(); if (name.equals("GlobalNaN")) { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction( resultVal, context.currentScope().getConstantValue(new Float(Float.NaN)))); } else if (name.equals("GlobalInfinity")) { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction( resultVal, context .currentScope() .getConstantValue(new Float(Float.POSITIVE_INFINITY)))); } else if (name.equals("MathE")) { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction( resultVal, context.currentScope().getConstantValue(new Double(Math.E)))); } else if (name.equals("MathPI")) { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction( resultVal, context.currentScope().getConstantValue(new Double(Math.PI)))); } else if (name.equals("MathSQRT1_2")) { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction( resultVal, context.currentScope().getConstantValue(new Double(Math.sqrt(.5))))); } else if (name.equals("MathSQRT2")) { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction( resultVal, context.currentScope().getConstantValue(new Double(Math.sqrt(2))))); } else if (name.equals("MathLN2")) { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction( resultVal, context.currentScope().getConstantValue(new Double(Math.log(2))))); } else if (name.equals("MathLN10")) { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction( resultVal, context.currentScope().getConstantValue(new Double(Math.log(10))))); } else if (name.equals("NewObject")) { doNewObject(context, null, resultVal, "Object", null); } else if (name.equals("NewArray")) { doNewObject(context, null, resultVal, "Array", null); } else if (name.equals("NewString")) { doPrimitiveNew(context, resultVal, "String"); } else if (name.equals("NewNumber")) { doPrimitiveNew(context, resultVal, "Number"); } else if (name.equals("NewRegExp")) { doPrimitiveNew(context, resultVal, "RegExp"); } else if (name.equals("NewFunction")) { doNewObject(context, null, resultVal, "Function", null); } else if (name.equals("NewUndefined")) { doNewObject(context, null, resultVal, "Undefined", null); } else { context .cfg() .addInstruction( ((JSInstructionFactory) insts) .AssignInstruction(resultVal, context.currentScope().getConstantValue(null))); } } catch (ClassCastException e) { throw new RuntimeException( "Cannot translate primitive " + primitiveCall.getChild(0).getValue()); } }
protected void doFieldRead( WalkContext context, int result, int receiver, CAstNode elt, CAstNode readNode) { this.visit(elt, context, this); int x = context.currentScope().allocateTempValue(); context.cfg().addInstruction(((JSInstructionFactory) insts).AssignInstruction(x, receiver)); context.cfg().addInstruction(((JSInstructionFactory) insts).PrototypeLookup(x, x)); if (elt.getKind() == CAstNode.CONSTANT && elt.getValue() instanceof String) { String field = (String) elt.getValue(); // symtab needs to have this value context.currentScope().getConstantValue(field); context.cfg().addInstruction(((JSInstructionFactory) insts).GetInstruction(result, x, field)); } else { context .cfg() .addInstruction( ((JSInstructionFactory) insts).PropertyRead(result, x, context.getValue(elt))); } // generate code to handle read of non-existent property if (context.getControlFlow().getMappedNodes().contains(readNode)) { context.cfg().addPreNode(readNode, context.getUnwindState()); context.cfg().newBlock(true); if (context.getControlFlow().getTarget(readNode, JavaScriptTypes.TypeError) != null) context .cfg() .addPreEdge( readNode, context.getControlFlow().getTarget(readNode, JavaScriptTypes.TypeError), true); else context.cfg().addPreEdgeToExit(readNode, true); } }
protected void doThrow(WalkContext context, int exception) { context.cfg().addInstruction(insts.ThrowInstruction(exception)); }
protected String composeEntityName(WalkContext parent, CAstEntity f) { if (f.getKind() == CAstEntity.SCRIPT_ENTITY) return f.getName(); else return parent.getName() + "/" + f.getName(); }