summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/image_writer.cc5
-rw-r--r--compiler/image_writer.h2
-rw-r--r--dex2oat/dex2oat.cc13
-rw-r--r--runtime/class_linker.cc13
-rw-r--r--runtime/class_linker.h5
-rw-r--r--runtime/read_barrier.h1
-rw-r--r--test/144-static-field-sigquit/expected.txt4
-rw-r--r--test/144-static-field-sigquit/info.txt8
-rw-r--r--test/144-static-field-sigquit/src/ClassWithStaticField.java21
-rw-r--r--test/144-static-field-sigquit/src/Main.java32
-rw-r--r--test/144-static-field-sigquit/src/SigQuit.java68
-rw-r--r--test/144-static-field-sigquit/src/SynchronizedUse.java26
-rw-r--r--test/973-default-multidex/expected.txt1
-rw-r--r--test/973-default-multidex/info.txt5
-rw-r--r--test/973-default-multidex/smali-multidex/iface.smali40
-rw-r--r--test/973-default-multidex/smali/concreteclass.smali47
-rw-r--r--test/973-default-multidex/src/Main.java31
17 files changed, 299 insertions, 23 deletions
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 6abc6fae8a..8b7fbf6910 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -2274,12 +2274,11 @@ const ImageWriter::ImageInfo& ImageWriter::GetImageInfo(size_t index) const {
return GetConstImageInfo(oat_filenames_[index]);
}
-void ImageWriter::UpdateOatFile(const char* oat_filename) {
- std::unique_ptr<File> oat_file(OS::OpenFileForReading(oat_filename));
+void ImageWriter::UpdateOatFile(File* oat_file, const char* oat_filename) {
DCHECK(oat_file != nullptr);
size_t oat_loaded_size = 0;
size_t oat_data_offset = 0;
- ElfWriter::GetOatElfInformation(oat_file.get(), &oat_loaded_size, &oat_data_offset);
+ ElfWriter::GetOatElfInformation(oat_file, &oat_loaded_size, &oat_data_offset);
ImageInfo& cur_image_info = GetImageInfo(oat_filename);
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 622eb1985b..9371d9ffa9 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -123,7 +123,7 @@ class ImageWriter FINAL {
// Update the oat size for the given oat file. This will make the oat_offset for the next oat
// file valid.
- void UpdateOatFile(const char* oat_filename);
+ void UpdateOatFile(File* oat_file, const char* oat_filename);
private:
bool AllocMemory();
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index f56fc385af..48716481cc 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1709,7 +1709,10 @@ class Dex2Oat FINAL {
if (IsImage()) {
// Update oat estimates.
- UpdateImageWriter(i);
+ DCHECK(image_writer_ != nullptr);
+ DCHECK_LT(i, oat_filenames_.size());
+
+ image_writer_->UpdateOatFile(oat_file.get(), oat_filenames_[i]);
}
VLOG(compiler) << "Oat file written successfully: " << oat_filenames_[i];
@@ -2351,14 +2354,6 @@ class Dex2Oat FINAL {
return res.substr(0, penultimate_slash) + res.substr(last_slash);
}
- // Update the estimate for the oat file with the given index.
- void UpdateImageWriter(size_t index) {
- DCHECK(image_writer_ != nullptr);
- DCHECK_LT(index, oat_filenames_.size());
-
- image_writer_->UpdateOatFile(oat_filenames_[index]);
- }
-
std::unique_ptr<CompilerOptions> compiler_options_;
Compiler::Kind compiler_kind_;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e98baba5ab..5ef199cb60 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3666,7 +3666,7 @@ void ClassLinker::VerifyClass(Thread* self, Handle<mirror::Class> klass) {
}
self->AssertNoPendingException();
// Make sure all classes referenced by catch blocks are resolved.
- ResolveClassExceptionHandlerTypes(dex_file, klass);
+ ResolveClassExceptionHandlerTypes(klass);
if (verifier_failure == verifier::MethodVerifier::kNoFailure) {
// Even though there were no verifier failures we need to respect whether the super-class and
// super-default-interfaces were verified or requiring runtime reverification.
@@ -3802,17 +3802,16 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file,
UNREACHABLE();
}
-void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
- Handle<mirror::Class> klass) {
+void ClassLinker::ResolveClassExceptionHandlerTypes(Handle<mirror::Class> klass) {
for (ArtMethod& method : klass->GetMethods(image_pointer_size_)) {
- ResolveMethodExceptionHandlerTypes(dex_file, &method);
+ ResolveMethodExceptionHandlerTypes(&method);
}
}
-void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file,
- ArtMethod* method) {
+void ClassLinker::ResolveMethodExceptionHandlerTypes(ArtMethod* method) {
// similar to DexVerifier::ScanTryCatchBlocks and dex2oat's ResolveExceptionsForMethod.
- const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
+ const DexFile::CodeItem* code_item =
+ method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset());
if (code_item == nullptr) {
return; // native or abstract method
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 99dd073d56..5176cbd3ea 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -441,11 +441,10 @@ class ClassLinker {
mirror::Class::Status& oat_file_class_status)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!dex_lock_);
- void ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
- Handle<mirror::Class> klass)
+ void ResolveClassExceptionHandlerTypes(Handle<mirror::Class> klass)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!dex_lock_);
- void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, ArtMethod* klass)
+ void ResolveMethodExceptionHandlerTypes(ArtMethod* klass)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!dex_lock_);
diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h
index 77be6cf71e..b7bd99b6f5 100644
--- a/runtime/read_barrier.h
+++ b/runtime/read_barrier.h
@@ -80,6 +80,7 @@ class ReadBarrier {
static void AssertToSpaceInvariant(GcRootSource* gc_root_source, mirror::Object* ref)
SHARED_REQUIRES(Locks::mutator_lock_);
+ // ALWAYS_INLINE on this caused a performance regression b/26744236.
static mirror::Object* Mark(mirror::Object* obj) SHARED_REQUIRES(Locks::mutator_lock_);
static mirror::Object* WhitePtr() {
diff --git a/test/144-static-field-sigquit/expected.txt b/test/144-static-field-sigquit/expected.txt
new file mode 100644
index 0000000000..e0c3e90221
--- /dev/null
+++ b/test/144-static-field-sigquit/expected.txt
@@ -0,0 +1,4 @@
+Starting threads...
+Performing sigquits for 5 seconds
+Got date field
+Joined threads
diff --git a/test/144-static-field-sigquit/info.txt b/test/144-static-field-sigquit/info.txt
new file mode 100644
index 0000000000..5dcfc7603b
--- /dev/null
+++ b/test/144-static-field-sigquit/info.txt
@@ -0,0 +1,8 @@
+Regression test for ag/853775
+
+Tests that unresolved classes are not put into the dex cache by the verifier.
+This was potentially happening when receiving a signal while in the static
+initilizer of a class and also within a synchronized block.
+
+This test is flaky and produces the issue rarely, but it should be good enough
+to trigger occasionally with the buildbots.
diff --git a/test/144-static-field-sigquit/src/ClassWithStaticField.java b/test/144-static-field-sigquit/src/ClassWithStaticField.java
new file mode 100644
index 0000000000..0b2c8553f5
--- /dev/null
+++ b/test/144-static-field-sigquit/src/ClassWithStaticField.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+import java.util.Date;
+
+public class ClassWithStaticField {
+ public static Date mDate = new Date();
+}
diff --git a/test/144-static-field-sigquit/src/Main.java b/test/144-static-field-sigquit/src/Main.java
new file mode 100644
index 0000000000..ab94da3ff3
--- /dev/null
+++ b/test/144-static-field-sigquit/src/Main.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+ Thread thread1 = new Thread(new SigQuit());
+ Thread thread2 = new Thread(new SynchronizedUse());
+
+ System.out.println("Starting threads...");
+ thread1.start();
+ Thread.sleep(2000);
+ thread2.start();
+
+ thread1.join();
+ thread2.join();
+ System.out.println("Joined threads");
+ }
+}
diff --git a/test/144-static-field-sigquit/src/SigQuit.java b/test/144-static-field-sigquit/src/SigQuit.java
new file mode 100644
index 0000000000..bed23e4a2d
--- /dev/null
+++ b/test/144-static-field-sigquit/src/SigQuit.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+import java.lang.reflect.*;
+
+public class SigQuit implements Runnable {
+ private final static int sigquit;
+ private final static Method kill;
+ private final static int pid;
+
+ static {
+ int pidTemp = -1;
+ int sigquitTemp = -1;
+ Method killTemp = null;
+
+ try {
+ Class<?> osClass = Class.forName("android.system.Os");
+ Method getpid = osClass.getDeclaredMethod("getpid");
+ pidTemp = (Integer) getpid.invoke(null);
+
+ Class<?> osConstants = Class.forName("android.system.OsConstants");
+ Field sigquitField = osConstants.getDeclaredField("SIGQUIT");
+ sigquitTemp = (Integer) sigquitField.get(null);
+
+ killTemp = osClass.getDeclaredMethod("kill", int.class, int.class);
+ } catch (Exception e) {
+ if (!e.getClass().getName().equals("ErrnoException")) {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ pid = pidTemp;
+ sigquit = sigquitTemp;
+ kill = killTemp;
+ }
+
+ public boolean perform() {
+ try {
+ kill.invoke(null, pid, sigquit);
+ } catch (Exception e) {
+ if (!e.getClass().getName().equals("ErrnoException")) {
+ e.printStackTrace(System.out);
+ }
+ }
+ return true;
+ }
+
+ public void run() {
+ long endTime = System.currentTimeMillis() + 5000;
+ System.out.println("Performing sigquits for 5 seconds");
+ while (System.currentTimeMillis() < endTime) {
+ perform();
+ }
+ }
+}
diff --git a/test/144-static-field-sigquit/src/SynchronizedUse.java b/test/144-static-field-sigquit/src/SynchronizedUse.java
new file mode 100644
index 0000000000..43af1d9c8d
--- /dev/null
+++ b/test/144-static-field-sigquit/src/SynchronizedUse.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+import java.util.Date;
+
+public class SynchronizedUse implements Runnable {
+ public void run() {
+ synchronized (this) {
+ Date dateField = ClassWithStaticField.mDate;
+ System.out.println("Got date field");
+ }
+ }
+}
diff --git a/test/973-default-multidex/expected.txt b/test/973-default-multidex/expected.txt
new file mode 100644
index 0000000000..b376e81554
--- /dev/null
+++ b/test/973-default-multidex/expected.txt
@@ -0,0 +1 @@
+STRING!!!STRING!!!
diff --git a/test/973-default-multidex/info.txt b/test/973-default-multidex/info.txt
new file mode 100644
index 0000000000..17c0b7d279
--- /dev/null
+++ b/test/973-default-multidex/info.txt
@@ -0,0 +1,5 @@
+Smali-based tests for interface default methods.
+
+Obviously needs to run under ART or a Java 8 Language runtime and compiler.
+
+Tests that we handle referenced throws across dex files.
diff --git a/test/973-default-multidex/smali-multidex/iface.smali b/test/973-default-multidex/smali-multidex/iface.smali
new file mode 100644
index 0000000000..fa6d27f527
--- /dev/null
+++ b/test/973-default-multidex/smali-multidex/iface.smali
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2016 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.
+
+
+.class public abstract interface LIface;
+.super Ljava/lang/Object;
+
+# public interface Iface {
+# public default String getTwice() {
+# return getString() + getString();
+# }
+# public String getString();
+# }
+
+.method public getTwice()Ljava/lang/String;
+.locals 2
+ invoke-static {p0}, Ljava/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;
+ invoke-interface {p0}, LIface;->getString()Ljava/lang/String;
+ move-result-object v0
+ invoke-interface {p0}, LIface;->getString()Ljava/lang/String;
+ move-result-object v1
+ invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
+
+.method public abstract getString()Ljava/lang/String;
+.end method
diff --git a/test/973-default-multidex/smali/concreteclass.smali b/test/973-default-multidex/smali/concreteclass.smali
new file mode 100644
index 0000000000..e177f2698a
--- /dev/null
+++ b/test/973-default-multidex/smali/concreteclass.smali
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2016 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.
+
+
+.class public LConcreteClass;
+.super Ljava/lang/Object;
+.implements LIface;
+
+# public class ConcreteClass implements Iface {
+# public String getString() {
+# return "STRING!!!";
+# }
+# public String callMethod() {
+# return this.getTwice();
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public getString()Ljava/lang/String;
+.registers 2
+ const-string v0, "STRING!!!"
+ return-object v0
+.end method
+
+.method public callMethod()Ljava/lang/String;
+.registers 2
+ invoke-virtual {p0}, LConcreteClass;->getTwice()Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
diff --git a/test/973-default-multidex/src/Main.java b/test/973-default-multidex/src/Main.java
new file mode 100644
index 0000000000..b93265a5b8
--- /dev/null
+++ b/test/973-default-multidex/src/Main.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 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.
+ */
+
+import java.lang.reflect.*;
+public class Main {
+ public static void main(String[] args) {
+ Class<?> c = null;
+ try {
+ c = Class.forName("ConcreteClass");
+ Method m = c.getMethod("callMethod");
+ System.out.println(m.invoke(c.newInstance(), new Object[0]));
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("FAILED: Could not call method");
+ return;
+ }
+ }
+}