@Override public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { IMethod target = base.getCalleeTarget(caller, site, receiver); if (target != null && target.getReference().equals(loadFileFunRef)) { Set<String> names = new HashSet<String>(); SSAInstruction call = caller.getIR() .getInstructions()[ caller.getIR().getCallInstructionIndices(site).intIterator().next()]; if (call.getNumberOfUses() > 1) { LocalPointerKey fileNameV = new LocalPointerKey(caller, call.getUse(1)); OrdinalSet<InstanceKey> ptrs = builder.getPointerAnalysis().getPointsToSet(fileNameV); for (InstanceKey k : ptrs) { if (k instanceof ConstantKey) { Object v = ((ConstantKey) k).getValue(); if (v instanceof String) { names.add((String) v); } } } if (names.size() == 1) { String str = names.iterator().next(); try { JavaScriptLoader cl = (JavaScriptLoader) builder.getClassHierarchy().getLoader(JavaScriptTypes.jsLoader); URL url = new URL(builder.getBaseURL(), str); if (!loadedFiles.contains(url)) { // try to open the input stream for the URL. if it fails, we'll get an IOException // and fall through to default case InputStream inputStream = url.openConnection().getInputStream(); inputStream.close(); JSCallGraphUtil.loadAdditionalFile(builder.getClassHierarchy(), cl, url); loadedFiles.add(url); IClass script = builder .getClassHierarchy() .lookupClass( TypeReference.findOrCreate(cl.getReference(), "L" + url.getFile())); return script.getMethod(JavaScriptMethods.fnSelector); } } catch (MalformedURLException e1) { // do nothing, fall through and return 'target' } catch (IOException e) { // do nothing, fall through and return 'target' } catch (RuntimeException e) { // do nothing, fall through and return 'target' } } } } return target; }
@Override public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { if (site.getDeclaredTarget().equals(JavaScriptMethods.ctorReference)) { assert cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.Root)); IR callerIR = caller.getIR(); SSAAbstractInvokeInstruction callStmts[] = callerIR.getCalls(site); assert callStmts.length == 1; int nargs = callStmts[0].getNumberOfParameters(); return findOrCreateConstructorMethod(callerIR, callStmts[0], receiver, nargs - 1); } else { return base.getCalleeTarget(caller, site, receiver); } }
/** * Check to see if a particular call site should be bypassed, before checking normal resolution of * the receiver. * * @throws IllegalArgumentException if site is null */ @Override public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass dispatchType) { if (site == null) { throw new IllegalArgumentException("site is null"); } // first, see if we'd like to bypass the CHA-based target for the site MethodReference ref = site.getDeclaredTarget(); IMethod chaTarget = chaMethodTargetSelector.getCalleeTarget(caller, site, dispatchType); IMethod target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget, site.isStatic()); if (DEBUG) { System.err.println("target is initially " + target); } if (target != null) { return target; } else { // didn't bypass the CHA target; check if we should bypass the parent target if (canIgnore(site.getDeclaredTarget())) { // we want to generate a NoOpSummary for this method. return findOrCreateSyntheticMethod(site.getDeclaredTarget(), site.isStatic()); } if (parent instanceof ClassHierarchyMethodTargetSelector) { // already checked this case and decided not to bypass return chaTarget; } target = parent.getCalleeTarget(caller, site, dispatchType); if (DEBUG) { System.err.println("target becomes " + target); } if (target != null) { IMethod bypassTarget = findOrCreateSyntheticMethod(target, site.isStatic()); if (DEBUG) System.err.println("bypassTarget is " + target); return (bypassTarget == null) ? target : bypassTarget; } else return target; } }