/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.tools.perflib.heap; import com.android.annotations.NonNull; import java.util.ArrayDeque; import java.util.Deque; import gnu.trove.TLongHashSet; /** * Non-recursive depth-first visitor, managing its own stack. */ public class NonRecursiveVisitor implements Visitor { protected final Deque<Instance> mStack = new ArrayDeque<Instance>(); // Marks nodes that have been visited. protected final TLongHashSet mSeen = new TLongHashSet(); protected void defaultAction(Instance instance) { } @Override public void visitRootObj(@NonNull RootObj root) { defaultAction(root); } @Override public void visitArrayInstance(@NonNull ArrayInstance instance) { defaultAction(instance); } @Override public void visitClassInstance(@NonNull ClassInstance instance) { defaultAction(instance); } @Override public void visitClassObj(@NonNull ClassObj instance) { defaultAction(instance); } @Override public void visitLater(Instance parent, @NonNull Instance child) { mStack.push(child); } public void doVisit(Iterable<? extends Instance> startNodes) { for (Instance node : startNodes) { if (node instanceof RootObj) { // RootObj nodes don't have their own id, they should be visited right away. node.accept(this); } else { visitLater(null, node); } } while (!mStack.isEmpty()) { Instance node = mStack.pop(); if (mSeen.add(node.getId())) { node.accept(this); } } } }