Merge "ART: Enhance comment"
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index e7051b3..e97c6a0 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -16,6 +16,9 @@
#include "class_loader_context.h"
+#include <stdlib.h>
+
+#include "android-base/file.h"
#include "art_field-inl.h"
#include "base/dchecked_vector.h"
#include "base/stl_util.h"
@@ -202,10 +205,21 @@
for (ClassLoaderInfo& info : class_loader_chain_) {
for (const std::string& cp_elem : info.classpath) {
// If path is relative, append it to the provided base directory.
- std::string location = cp_elem;
- if (location[0] != '/') {
- location = classpath_dir + '/' + location;
+ std::string raw_location = cp_elem;
+ if (raw_location[0] != '/') {
+ raw_location = classpath_dir + '/' + raw_location;
}
+
+ std::string location; // the real location of the class path element.
+
+ if (!android::base::Realpath(raw_location, &location)) {
+ // If we can't get the realpath of the location there might be something wrong with the
+ // classpath (maybe the file was deleted).
+ // Do not continue in this case and return false.
+ PLOG(ERROR) << "Could not get the realpath of dex location " << raw_location;
+ return false;
+ }
+
std::string error_msg;
// When opening the dex files from the context we expect their checksum to match their
// contents. So pass true to verify_checksum.
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index d4688c1..458f9f3 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -15,14 +15,16 @@
*/
#include <gtest/gtest.h>
+#include <stdlib.h>
-#include "class_loader_context.h"
-#include "common_runtime_test.h"
#include "base/dchecked_vector.h"
#include "base/stl_util.h"
+#include "class_loader_context.h"
#include "class_linker.h"
+#include "common_runtime_test.h"
#include "dex_file.h"
+#include "dex2oat_environment_test.h"
#include "handle_scope-inl.h"
#include "mirror/class.h"
#include "mirror/class_loader.h"
@@ -89,9 +91,22 @@
info.opened_dex_files[cur_open_dex_index++];
std::unique_ptr<const DexFile>& expected_dex_file = dex_files_for_cp_elem[i];
- ASSERT_EQ(expected_dex_file->GetLocation(), opened_dex_file->GetLocation());
+ std::string expected_location = expected_dex_file->GetBaseLocation();
+ UniqueCPtr<const char[]> expected_real_location(
+ realpath(expected_location.c_str(), nullptr));
+ ASSERT_TRUE(expected_real_location != nullptr) << expected_location;
+ expected_location.assign(expected_real_location.get());
+ expected_location += DexFile::GetMultiDexSuffix(expected_dex_file->GetLocation());
+
+ ASSERT_EQ(expected_location, opened_dex_file->GetLocation());
ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
- ASSERT_EQ(info.classpath[k], opened_dex_file->GetBaseLocation());
+
+ std::string class_path_location = info.classpath[k];
+ UniqueCPtr<const char[]> class_path_location_real(
+ realpath(class_path_location.c_str(), nullptr));
+ ASSERT_TRUE(class_path_location_real != nullptr);
+ class_path_location.assign(class_path_location_real.get());
+ ASSERT_EQ(class_path_location, opened_dex_file->GetBaseLocation());
}
}
}
@@ -234,7 +249,6 @@
std::string dex_name = GetTestDexFileName("Main");
std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
-
std::unique_ptr<ClassLoaderContext> context =
ClassLoaderContext::Create(
"PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
@@ -253,6 +267,43 @@
VerifyOpenDexFiles(context.get(), 1, all_dex_files1);
}
+class ScratchSymLink {
+ public:
+ explicit ScratchSymLink(const std::string& file) {
+ // Use a temporary scratch file to get a unique name for the link.
+ ScratchFile scratchFile;
+ scratch_link_name_ = scratchFile.GetFilename() + ".link.jar";
+ CHECK_EQ(0, symlink(file.c_str(), scratch_link_name_.c_str()));
+ }
+
+ ~ScratchSymLink() {
+ CHECK_EQ(0, unlink(scratch_link_name_.c_str()));
+ }
+
+ const std::string& GetFilename() { return scratch_link_name_; }
+
+ private:
+ std::string scratch_link_name_;
+};
+
+TEST_F(ClassLoaderContextTest, OpenValidDexFilesSymLink) {
+ std::string myclass_dex_name = GetTestDexFileName("MyClass");
+ // Now replace the dex location with a symlink.
+ ScratchSymLink link(myclass_dex_name);
+
+ std::unique_ptr<ClassLoaderContext> context =
+ ClassLoaderContext::Create("PCL[" + link.GetFilename() + "]");
+
+ ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
+
+ VerifyContextSize(context.get(), 1);
+ std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
+ std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
+ all_dex_files0.push_back(&myclass_dex_files);
+
+ VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
+}
+
TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
std::string dex_name = GetTestDexFileName("Main");
std::unique_ptr<ClassLoaderContext> context =
diff --git a/test/testrunner/run_build_test_target.py b/test/testrunner/run_build_test_target.py
index b1274c9..49444d4 100755
--- a/test/testrunner/run_build_test_target.py
+++ b/test/testrunner/run_build_test_target.py
@@ -100,6 +100,8 @@
run_test_command += ['-b']
run_test_command += ['--host']
run_test_command += ['--verbose']
+ run_test_command += ['--dex2oat-jobs']
+ run_test_command += ['4']
sys.stdout.write(str(run_test_command) + '\n')
sys.stdout.flush()
diff --git a/tools/ahat/src/dominators/DominatorsComputation.java b/tools/ahat/src/dominators/DominatorsComputation.java
index 9a2a272..58b7b59 100644
--- a/tools/ahat/src/dominators/DominatorsComputation.java
+++ b/tools/ahat/src/dominators/DominatorsComputation.java
@@ -88,33 +88,17 @@
// Invariant: srcS.id < this.id
public NodeS srcS;
+ // The largest id of the nodes we have seen so far on a path from the root
+ // to this node. Used to keep track of which nodes we have already seen
+ // and avoid processing them again.
+ public long seenid;
+
// The set of nodes X reachable by 'this' on a path of nodes from the
// root with increasing ids (possibly excluding X) that this node does not
// dominate (this.id > X.domid).
- // We can use a List instead of a Set for this because we guarentee that
- // we don't add the same node more than once to the list (see below).
+ // We can use a List instead of a Set for this because we guarentee based
+ // on seenid that we don't add the same node more than once to the list.
public List<NodeS> undom = new ArrayList<NodeS>();
-
- // The largest id of the node X for which we did X.undom.add(this).
- // This is an optimization to avoid adding duplicate node entries to the
- // undom set.
- //
- // The first time we see this node, we reach it through a path of nodes
- // with IDs 0,...,a,this. These form our src chain to the root.
- //
- // The next time we see this node, we reach it through a path of nodes
- // with IDS 0,...,b,c,...,d,this. Where all 0,...,b < a and all c,...,d > a.
- //
- // The next time we see this node, we reach it through a path of nodes
- // with IDS 0,...,e,f,...,g,this. With all 0,...,e < d and all f,...,g > d.
- // And so on.
- //
- // The first time we see this node, we set undomid to a.id. Nodes 0,...,a
- // will be added as undom in the 'revisit' phase of the node.
- //
- // The next times we see this node, we mark a+,...,d as undom and
- // change undomid to d. And so on.
- public long undomid;
}
private static class Link {
@@ -171,7 +155,7 @@
dstS.domid = link.srcS.id;
dstS.domS = link.srcS;
dstS.srcS = link.srcS;
- dstS.undomid = dstS.domid;
+ dstS.seenid = dstS.domid;
nodes.add(dstS);
link.dst.setDominatorsComputationState(dstS);
@@ -184,13 +168,11 @@
NodeS srcS = link.srcS;
boolean revisiting = dstS.domid < dstS.domS.id;
- while (srcS.id > dstS.domid) {
- if (srcS.id > dstS.undomid) {
- srcS.undom.add(dstS);
- }
+ while (srcS.id > dstS.seenid) {
+ srcS.undom.add(dstS);
srcS = srcS.srcS;
}
- dstS.undomid = link.srcS.id;
+ dstS.seenid = link.srcS.id;
if (srcS.id < dstS.domid) {
// In this case, dstS.domid must be wrong, because we just found a