…lines 1–192 unchanged (192 lines)
193 * For all variables in this scope, see if they are only used once.
194 * If it looks safe to do so, inline them.
195 */
196 private void doInlinesForScope(NodeTraversal t,
197 Map<Var, ReferenceCollection> referenceMap) {
198
199 boolean maybeModifiedArguments =
200 maybeEscapedOrModifiedArguments(t.getScope(), referenceMap);
201 for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
202 Var v = it.next();
203
204 ReferenceCollection referenceInfo = referenceMap.get(v);
205
206 // referenceInfo will be null if we're in constants-only mode
…lines 207–215 unchanged (9 lines)
216 staleVars.add(v);
217 } else if (mode == Mode.CONSTANTS_ONLY) {
218 // If we're in constants-only mode, don't run more aggressive
219 // inlining heuristics. See InlineConstantsTest.
220 continue;
221 } else {
222 inlineNonConstants(v, referenceInfo, maybeModifiedArguments);
223 }
224 }
225 }
226
227 private boolean maybeEscapedOrModifiedArguments(
228 Scope scope, Map<Var, ReferenceCollection> referenceMap) {
229 if (scope.isLocal()) {
230 Var arguments = scope.getArgumentsVar();
231 ReferenceCollection refs = referenceMap.get(arguments);
232 if (refs != null && !refs.references.isEmpty()) {
233 for (Reference ref : refs.references) {
234 Node refNode = ref.getNameNode();
235 Node refParent = ref.getParent();
236 // Any reference that is not a read of the arguments property
237 // consider a escape of the arguments object.
238 if (!(NodeUtil.isGet(refParent)
239 && refNode == ref.getParent().getFirstChild()
240 && !isLValue(refParent))) {
241 return true;
242 }
243 }
244 }
245 }
246 return false;
247 }
248
249 private boolean isLValue(Node n) {
250 Node parent = n.getParent();
251 return (parent.getType() == Token.INC
252 || parent.getType() == Token.DEC
253 || (NodeUtil.isAssignmentOp(parent)
254 && parent.getFirstChild() == n));
255 }
256
257 private void inlineNonConstants(
258 Var v, ReferenceCollection referenceInfo,
259 boolean maybeModifiedArguments) {
260 int refCount = referenceInfo.references.size();
261 Reference declaration = referenceInfo.references.get(0);
262 Reference init = referenceInfo.getInitializingReference();
263 int firstRefAfterInit = (declaration == init) ? 2 : 3;
264
265 if (refCount > 1 &&
…lines 266–297 unchanged (32 lines)
298 }
299
300 // If this variable was not inlined normally, check if we can
301 // inline an alias of it. (If the variable was inlined, then the
302 // reference data is out of sync. We're better off just waiting for
303 // the next pass.)
304 if (!maybeModifiedArguments &&
305 !staleVars.contains(v) && referenceInfo.isWellDefined() &&
306 referenceInfo.isAssignedOnceInLifetime()) {
307 List<Reference> refs = referenceInfo.references;
308 for (int i = 1 /* start from a read */; i < refs.size(); i++) {
309 Node nameNode = refs.get(i).getNameNode();
310 if (aliasCandidates.containsKey(nameNode)) {
…lines 311–723 unchanged (413 lines)