Merge "ART: Add regression test"
diff --git a/Android.mk b/Android.mk
index ff39d53..c01464a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -240,8 +240,8 @@
# Dexdump/list regression test.
.PHONY: test-art-host-dexdump
-test-art-host-dexdump: dexdump2 dexlist2
- art/test/dexdump/run-all-tests
+test-art-host-dexdump: $(addprefix $(HOST_OUT_EXECUTABLES)/, dexdump2 dexlist2)
+ ANDROID_HOST_OUT=$(realpath $(HOST_OUT)) art/test/dexdump/run-all-tests
# Valgrind. Currently only 32b gtests.
.PHONY: valgrind-test-art-host
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index 183f4e3..a561c5f 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -88,4 +88,8 @@
HOST_CORE_DEX_FILES := $(foreach jar,$(HOST_CORE_JARS), $(call intermediates-dir-for,JAVA_LIBRARIES,$(jar),t,COMMON)/javalib.jar)
TARGET_CORE_DEX_FILES := $(foreach jar,$(TARGET_CORE_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar), ,COMMON)/javalib.jar)
+
+# Classpath for Jack compilation: we only need core-libart.
+HOST_JACK_CLASSPATH := $(abspath $(call intermediates-dir-for,JAVA_LIBRARIES,core-libart-hostdex,t,COMMON)/classes.jack)
+TARGET_JACK_CLASSPATH := $(abspath $(call intermediates-dir-for,JAVA_LIBRARIES,core-libart, ,COMMON)/classes.jack)
endif # ART_ANDROID_COMMON_PATH_MK
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 8bf744d..bb1b40a 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -272,11 +272,7 @@
// Instructions in the block may throw. Find a TryItem covering this block.
int32_t try_item_idx = DexFile::FindTryItem(code_item, block->GetDexPc());
- if (try_item_idx == -1) {
- return nullptr;
- } else {
- return DexFile::GetTryItems(code_item, try_item_idx);
- }
+ return (try_item_idx == -1) ? nullptr : DexFile::GetTryItems(code_item, try_item_idx);
}
void HGraphBuilder::CreateBlocksForTryCatch(const DexFile::CodeItem& code_item) {
@@ -357,13 +353,9 @@
// (c) link the new blocks to corresponding exception handlers.
// We cannot iterate only over blocks in `branch_targets_` because switch-case
// blocks share the same dex_pc.
- for (size_t block_id = 1; block_id < num_blocks - 1; ++block_id) {
+ for (size_t block_id = 0; block_id < num_blocks; ++block_id) {
HBasicBlock* try_block = graph_->GetBlocks().Get(block_id);
- // Iteration starts from 1 to skip the entry block.
- DCHECK_NE(try_block, entry_block_);
- // Iteration ends at num_blocks - 1 to skip the exit block.
- DCHECK_NE(try_block, exit_block_);
// TryBoundary blocks are added at the end of the list and not iterated over.
DCHECK(!try_block->IsSingleTryBoundary());
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index de46b35..97d170e 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -4836,6 +4836,9 @@
CHECK(!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
records = &dummy;
}
+ // We don't need to wait on the condition variable records->new_record_condition_, because this
+ // function only reads the class objects, which are already marked so it doesn't change their
+ // reachability.
//
// Part 1: generate string tables.
@@ -4850,7 +4853,7 @@
count > 0 && it != end; count--, it++) {
const gc::AllocRecord* record = it->second;
std::string temp;
- class_names.Add(record->GetClass()->GetDescriptor(&temp));
+ class_names.Add(record->GetClassDescriptor(&temp));
for (size_t i = 0, depth = record->GetDepth(); i < depth; i++) {
ArtMethod* m = record->StackElement(i).GetMethod();
class_names.Add(m->GetDeclaringClassDescriptor());
@@ -4902,7 +4905,7 @@
const gc::AllocRecord* record = it->second;
size_t stack_depth = record->GetDepth();
size_t allocated_object_class_name_index =
- class_names.IndexOf(record->GetClass()->GetDescriptor(&temp));
+ class_names.IndexOf(record->GetClassDescriptor(&temp));
JDWP::Append4BE(bytes, record->ByteCount());
JDWP::Append2BE(bytes, static_cast<uint16_t>(record->GetTid()));
JDWP::Append2BE(bytes, allocated_object_class_name_index);
diff --git a/runtime/gc/allocation_record.cc b/runtime/gc/allocation_record.cc
index 11921f4..6537ed2 100644
--- a/runtime/gc/allocation_record.cc
+++ b/runtime/gc/allocation_record.cc
@@ -32,6 +32,15 @@
return method_->GetLineNumFromDexPC(dex_pc_);
}
+const char* AllocRecord::GetClassDescriptor(std::string* storage) const {
+ // klass_ could contain null only if we implement class unloading.
+ if (UNLIKELY(klass_.IsNull())) {
+ return "null";
+ } else {
+ return klass_.Read()->GetDescriptor(storage);
+ }
+}
+
void AllocRecordObjectMap::SetProperties() {
#ifdef HAVE_ANDROID_OS
// Check whether there's a system property overriding the max number of records.
@@ -97,7 +106,7 @@
// Only visit the last recent_record_max_ number of allocation records in entries_ and mark the
// klass_ fields as strong roots.
for (auto it = entries_.rbegin(), end = entries_.rend(); count > 0 && it != end; count--, ++it) {
- buffered_visitor.VisitRoot(it->second->GetClassGcRoot());
+ buffered_visitor.VisitRootIfNonNull(it->second->GetClassGcRoot());
}
}
@@ -107,6 +116,8 @@
GcRoot<mirror::Class>& klass = record->GetClassGcRoot();
// This does not need a read barrier because this is called by GC.
mirror::Object* old_object = klass.Read<kWithoutReadBarrier>();
+ // The class object can become null if we implement class unloading.
+ // In that case we might still want to keep the class name string (not implemented).
mirror::Object* new_object = UNLIKELY(old_object == nullptr) ?
nullptr : callback(old_object, arg);
if (UNLIKELY(old_object != new_object)) {
@@ -163,11 +174,6 @@
allow_new_record_ = false;
}
-void AllocRecordObjectMap::EnsureNewAllocationRecordsDisallowed() {
- CHECK(!allow_new_record_);
-}
-
-
struct AllocRecordStackVisitor : public StackVisitor {
AllocRecordStackVisitor(Thread* thread, AllocRecordStackTrace* trace_in, size_t max)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
diff --git a/runtime/gc/allocation_record.h b/runtime/gc/allocation_record.h
index f567153..06721c8 100644
--- a/runtime/gc/allocation_record.h
+++ b/runtime/gc/allocation_record.h
@@ -188,7 +188,10 @@
return klass_.Read();
}
- GcRoot<mirror::Class>& GetClassGcRoot() {
+ const char* GetClassDescriptor(std::string* storage) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ GcRoot<mirror::Class>& GetClassGcRoot() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return klass_;
}
@@ -262,15 +265,18 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_);
+ // Allocation tracking could be enabled by user in between DisallowNewAllocationRecords() and
+ // AllowNewAllocationRecords(), in which case new allocation records can be added although they
+ // should be disallowed. However, this is GC-safe because new objects are not processed in this GC
+ // cycle. The only downside of not handling this case is that such new allocation records can be
+ // swept from the list. But missing the first few records is acceptable for using the button to
+ // enable allocation tracking.
void DisallowNewAllocationRecords()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_);
void AllowNewAllocationRecords()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_);
- void EnsureNewAllocationRecordsDisallowed()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_);
// TODO: Is there a better way to hide the entries_'s type?
EntryList::iterator Begin()
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index c7d2e9f..5e69b79 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -334,6 +334,8 @@
}
}
}
+ // TODO: Other garbage collectors uses Runtime::VisitConcurrentRoots(), refactor this part
+ // to also use the same function.
{
TimingLogger::ScopedTiming split2("VisitConstantRoots", GetTimings());
Runtime::Current()->VisitConstantRoots(this);
@@ -351,6 +353,7 @@
TimingLogger::ScopedTiming split5("VisitNonThreadRoots", GetTimings());
Runtime::Current()->VisitNonThreadRoots(this);
}
+ Runtime::Current()->GetHeap()->VisitAllocationRecords(this);
// Immune spaces.
for (auto& space : heap_->GetContinuousSpaces()) {
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 1b45ea1..a782fc8 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3734,17 +3734,6 @@
}
}
-void Heap::EnsureNewAllocationRecordsDisallowed() const {
- if (IsAllocTrackingEnabled()) {
- // Lock and unlock once to ensure that no threads are still in the
- // middle of adding new allocation records.
- MutexLock mu(Thread::Current(), *Locks::alloc_tracker_lock_);
- if (IsAllocTrackingEnabled()) {
- GetAllocationRecords()->EnsureNewAllocationRecordsDisallowed();
- }
- }
-}
-
// Based on debug malloc logic from libc/bionic/debug_stacktrace.cpp.
class StackCrawlState {
public:
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 1c75bd0..cfb6e06 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -721,10 +721,6 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
LOCKS_EXCLUDED(Locks::alloc_tracker_lock_);
- void EnsureNewAllocationRecordsDisallowed() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- LOCKS_EXCLUDED(Locks::alloc_tracker_lock_);
-
private:
class ConcurrentGCTask;
class CollectorTransitionTask;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 20e4149..5067b0d 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1510,7 +1510,6 @@
monitor_list_->EnsureNewMonitorsDisallowed();
intern_table_->EnsureNewInternsDisallowed();
java_vm_->EnsureNewWeakGlobalsDisallowed();
- heap_->EnsureNewAllocationRecordsDisallowed();
}
void Runtime::SetInstructionSet(InstructionSet instruction_set) {
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 92c9eb8..09db7cd 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -4133,7 +4133,9 @@
<< " to be compatible with type '" << insn_type
<< "' but found type '" << *field_type
<< "' in get-object";
- work_line_->SetRegisterType(this, vregA, reg_types_.Conflict());
+ if (error != VERIFY_ERROR_BAD_CLASS_HARD) {
+ work_line_->SetRegisterType(this, vregA, reg_types_.Conflict());
+ }
return;
}
}
diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h
index 244deed..9cd2bdf 100644
--- a/runtime/verifier/register_line-inl.h
+++ b/runtime/verifier/register_line-inl.h
@@ -38,10 +38,9 @@
verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Expected category1 register type not '"
<< new_type << "'";
return false;
- } else if (new_type.IsConflict()) { // should only be set during a merge
- verifier->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Set register to unknown type " << new_type;
- return false;
} else {
+ // Note: previously we failed when asked to set a conflict. However, conflicts are OK as long
+ // as they are not accessed, and our backends can handle this nowadays.
line_[vdst] = new_type.GetId();
}
// Clear the monitor entry bits for this register.
@@ -93,8 +92,9 @@
if (!SetRegisterType(verifier, vdst, type)) {
return;
}
- if ((cat == kTypeCategory1nr && !type.IsCategory1Types()) ||
- (cat == kTypeCategoryRef && !type.IsReferenceTypes())) {
+ if (!type.IsConflict() && // Allow conflicts to be copied around.
+ ((cat == kTypeCategory1nr && !type.IsCategory1Types()) ||
+ (cat == kTypeCategoryRef && !type.IsReferenceTypes()))) {
verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy1 v" << vdst << "<-v" << vsrc << " type=" << type
<< " cat=" << static_cast<int>(cat);
} else if (cat == kTypeCategoryRef) {
diff --git a/test/003-omnibus-opcodes/build b/test/003-omnibus-opcodes/build
index f909fb2..faa2983 100644
--- a/test/003-omnibus-opcodes/build
+++ b/test/003-omnibus-opcodes/build
@@ -22,5 +22,10 @@
rm classes/UnresClass.class
${JAVAC} -d classes `find src2 -name '*.java'`
-${DX} -JXmx256m --debug --dex --output=classes.dex classes
+if [ ${USE_JACK} = "true" ]; then
+ ${JILL} classes --output classes.jack
+ ${JACK} --import classes.jack --output-dex .
+else
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
+ fi
zip $TEST_NAME.jar classes.dex
diff --git a/test/004-ReferenceMap/build b/test/004-ReferenceMap/build
new file mode 100644
index 0000000..08987b5
--- /dev/null
+++ b/test/004-ReferenceMap/build
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# 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.
+
+# Stop if something fails.
+set -e
+
+# The test relies on DEX file produced by javac+dx so keep building with them for now
+# (see b/19467889)
+mkdir classes
+${JAVAC} -d classes `find src -name '*.java'`
+${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
+ --dump-width=1000 ${DX_FLAGS} classes
+zip $TEST_NAME.jar classes.dex
diff --git a/test/004-StackWalk/build b/test/004-StackWalk/build
new file mode 100644
index 0000000..08987b5
--- /dev/null
+++ b/test/004-StackWalk/build
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# 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.
+
+# Stop if something fails.
+set -e
+
+# The test relies on DEX file produced by javac+dx so keep building with them for now
+# (see b/19467889)
+mkdir classes
+${JAVAC} -d classes `find src -name '*.java'`
+${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
+ --dump-width=1000 ${DX_FLAGS} classes
+zip $TEST_NAME.jar classes.dex
diff --git a/test/005-annotations/build b/test/005-annotations/build
index 2474055..3f00a1a 100644
--- a/test/005-annotations/build
+++ b/test/005-annotations/build
@@ -25,4 +25,12 @@
# ...but not at run time.
rm 'classes/android/test/anno/MissingAnnotation.class'
rm 'classes/android/test/anno/ClassWithInnerAnnotationClass$MissingInnerAnnotationClass.class'
-${DX} -JXmx256m --debug --dex --output=$TEST_NAME.jar classes
+
+if [ ${USE_JACK} = "true" ]; then
+ ${JILL} classes --output classes.jack
+ ${JACK} --import classes.jack --output-dex .
+else
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
+fi
+
+zip $TEST_NAME.jar classes.dex
diff --git a/test/022-interface/build b/test/022-interface/build
index c86b1dc..3f8915c 100644
--- a/test/022-interface/build
+++ b/test/022-interface/build
@@ -19,5 +19,11 @@
# Use classes that are compiled with ecj that exposes an invokeinterface
# issue when interfaces override methods in Object
-${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+if [ ${USE_JACK} = "true" ]; then
+ ${JILL} classes --output classes.jack
+ ${JACK} --import classes.jack --output-dex .
+else
+ ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+fi
+
zip $TEST_NAME.jar classes.dex
diff --git a/test/023-many-interfaces/build b/test/023-many-interfaces/build
index ad42a2d..3bb6747 100644
--- a/test/023-many-interfaces/build
+++ b/test/023-many-interfaces/build
@@ -21,8 +21,14 @@
gcc -Wall -Werror -o iface-gen iface-gen.c
./iface-gen
-mkdir classes
-${JAVAC} -d classes src/*.java
+if [ ${USE_JACK} = "true" ]; then
+ # Use the default Jack commands
+ ./default-build
+else
+ mkdir classes
+ ${JAVAC} -d classes src/*.java
-${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
-zip $TEST_NAME.jar classes.dex
+ # dx needs more memory for that test so do not pass Xmx option here.
+ ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+ zip $TEST_NAME.jar classes.dex
+fi
diff --git a/test/036-finalizer/src/Main.java b/test/036-finalizer/src/Main.java
index 8c7c27d..0de56f9 100644
--- a/test/036-finalizer/src/Main.java
+++ b/test/036-finalizer/src/Main.java
@@ -68,14 +68,17 @@
return s[0];
}
+ private static void printWeakReference(WeakReference<FinalizerTest> wimp) {
+ // Reference ft so we are sure the WeakReference cannot be cleared.
+ FinalizerTest keepLive = wimp.get();
+ System.out.println("wimp: " + wimpString(wimp));
+ }
+
public static void main(String[] args) {
WeakReference<FinalizerTest> wimp = makeRef();
- FinalizerTest keepLive = wimp.get();
-
- System.out.println("wimp: " + wimpString(wimp));
+ printWeakReference(wimp);
/* this will try to collect and finalize ft */
- keepLive = null;
System.out.println("gc");
Runtime.getRuntime().gc();
diff --git a/test/056-const-string-jumbo/build b/test/056-const-string-jumbo/build
index ef286d1..ae42519 100644
--- a/test/056-const-string-jumbo/build
+++ b/test/056-const-string-jumbo/build
@@ -39,8 +39,13 @@
printf("}\n") > fileName;
}'
-mkdir classes
-${JAVAC} -d classes src/*.java
+if [ ${USE_JACK} = "true" ]; then
+ ${JACK} --output-dex . src
+else
+ mkdir classes
+ ${JAVAC} -d classes src/*.java
-${DX} -JXmx500m --debug --dex --no-optimize --positions=none --no-locals --output=classes.dex classes
+ ${DX} -JXmx500m --debug --dex --no-optimize --positions=none --no-locals --output=classes.dex classes
+fi
+
zip $TEST_NAME.jar classes.dex
diff --git a/test/074-gc-thrash/src/Main.java b/test/074-gc-thrash/src/Main.java
index 238e73a..f947d0b 100644
--- a/test/074-gc-thrash/src/Main.java
+++ b/test/074-gc-thrash/src/Main.java
@@ -218,17 +218,7 @@
return;
}
- /*
- * Check the results of the last trip through. Everything in
- * "weak" should be matched in "strong", and the two should be
- * equivalent (object-wise, not just string-equality-wise).
- */
- for (int i = 0; i < MAX_DEPTH; i++) {
- if (strong[i] != weak[i].get()) {
- System.err.println("Deep: " + i + " strong=" + strong[i] +
- ", weak=" + weak[i].get());
- }
- }
+ checkStringReferences();
/*
* Wipe "strong", do a GC, see if "weak" got collected.
@@ -248,6 +238,26 @@
System.out.println("Deep: iters=" + iter / MAX_DEPTH);
}
+
+ /**
+ * Check the results of the last trip through. Everything in
+ * "weak" should be matched in "strong", and the two should be
+ * equivalent (object-wise, not just string-equality-wise).
+ *
+ * We do that check in a separate method to avoid retaining these
+ * String references in local DEX registers. In interpreter mode,
+ * they would retain these references until the end of the method
+ * or until they are updated to another value.
+ */
+ private static void checkStringReferences() {
+ for (int i = 0; i < MAX_DEPTH; i++) {
+ if (strong[i] != weak[i].get()) {
+ System.err.println("Deep: " + i + " strong=" + strong[i] +
+ ", weak=" + weak[i].get());
+ }
+ }
+ }
+
/**
* Recursively dive down, setting one or more local variables.
*
diff --git a/test/085-old-style-inner-class/build b/test/085-old-style-inner-class/build
index 963d6b3..6f50a76 100644
--- a/test/085-old-style-inner-class/build
+++ b/test/085-old-style-inner-class/build
@@ -22,7 +22,12 @@
mkdir classes
${JAVAC} -source 1.4 -target 1.4 -d classes `find src -name '*.java'`
-# Suppress stderr to keep the inner class warnings out of the expected output.
-${DX} --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes 2>/dev/null
+if [ ${USE_JACK} = "true" ]; then
+ ${JILL} classes --output classes.jack
+ ${JACK} --import classes.jack --output-dex .
+else
+ # Suppress stderr to keep the inner class warnings out of the expected output.
+ ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes 2>/dev/null
+fi
zip $TEST_NAME.jar classes.dex
diff --git a/test/089-many-methods/build b/test/089-many-methods/build
index 7ede759..ff77c60 100644
--- a/test/089-many-methods/build
+++ b/test/089-many-methods/build
@@ -43,7 +43,8 @@
printf("}\n") > fileName;
}'
+# The test relies on the error message produced by dx, not jack, so keep building with dx for now
+# (b/19467889).
mkdir classes
${JAVAC} -d classes `find src -name '*.java'`
${DX} -JXmx1024m --dex --no-optimize classes
-
diff --git a/test/097-duplicate-method/build b/test/097-duplicate-method/build
index 6576779..a855873 100644
--- a/test/097-duplicate-method/build
+++ b/test/097-duplicate-method/build
@@ -18,8 +18,19 @@
set -e
mkdir classes
-${JAVAC} -d classes src/*.java
-${JASMIN} -d classes src/*.j
-${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+if [ ${USE_JACK} = "true" ]; then
+ ${JACK} --output-jack src.jack src
+
+ ${JASMIN} -d classes src/*.j
+ ${JILL} classes --output jasmin.jack
+
+ # We set jack.import.type.policy=keep-first to consider class definitions from jasmin first.
+ ${JACK} --import jasmin.jack --import src.jack -D jack.import.type.policy=keep-first --output-dex .
+else
+ ${JAVAC} -d classes src/*.java
+ ${JASMIN} -d classes src/*.j
+
+ ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+fi
zip $TEST_NAME.jar classes.dex
diff --git a/test/111-unresolvable-exception/build b/test/111-unresolvable-exception/build
index c21a9ef..e772fb8 100644
--- a/test/111-unresolvable-exception/build
+++ b/test/111-unresolvable-exception/build
@@ -21,5 +21,10 @@
${JAVAC} -d classes `find src -name '*.java'`
rm classes/TestException.class
-${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+if [ ${USE_JACK} = "true" ]; then
+ ${JILL} classes --output classes.jack
+ ${JACK} --import classes.jack --output-dex .
+else
+ ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+fi
zip $TEST_NAME.jar classes.dex
diff --git a/test/113-multidex/build b/test/113-multidex/build
index ec8706e..8ef5c0e 100644
--- a/test/113-multidex/build
+++ b/test/113-multidex/build
@@ -17,16 +17,32 @@
# Stop if something fails.
set -e
-mkdir classes
-
# All except Main
+mkdir classes
${JAVAC} -d classes `find src -name '*.java'`
rm classes/Main.class
-${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
# Only Main
-${JAVAC} -d classes `find src -name '*.java'`
-rm classes/Second.class classes/FillerA.class classes/FillerB.class classes/Inf*.class
-${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes
+mkdir classes2
+${JAVAC} -d classes2 `find src -name '*.java'`
+rm classes2/Second.class classes2/FillerA.class classes2/FillerB.class classes2/Inf*.class
+if [ ${USE_JACK} = "true" ]; then
+ # Create .jack files from classes generated with javac.
+ ${JILL} classes --output classes.jack
+ ${JILL} classes2 --output classes2.jack
+
+ # Create DEX files from .jack files.
+ ${JACK} --import classes.jack --output-dex .
+ mv classes.dex classes-1.dex
+ ${JACK} --import classes2.jack --output-dex .
+ mv classes.dex classes2.dex
+ mv classes-1.dex classes.dex
+else
+ # All except Main
+ ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+
+ # Only Main
+ ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes2
+fi
zip $TEST_NAME.jar classes.dex classes2.dex
diff --git a/test/114-ParallelGC/src/Main.java b/test/114-ParallelGC/src/Main.java
index 46029cf..159dd5c 100644
--- a/test/114-ParallelGC/src/Main.java
+++ b/test/114-ParallelGC/src/Main.java
@@ -53,20 +53,21 @@
}
// Allocate objects to definitely run GC before quitting.
- ArrayList<Object> l = new ArrayList<Object>();
- try {
- for (int i = 0; i < 100000; i++) {
- l.add(new ArrayList<Object>(i));
- }
- } catch (OutOfMemoryError oom) {
- }
- // Make the (outer) ArrayList unreachable. Note it may still
- // be reachable under an interpreter or a compiler without a
- // liveness analysis.
- l = null;
+ allocateObjectsToRunGc();
+
new ArrayList<Object>(50);
}
+ private static void allocateObjectsToRunGc() {
+ ArrayList<Object> l = new ArrayList<Object>();
+ try {
+ for (int i = 0; i < 100000; i++) {
+ l.add(new ArrayList<Object>(i));
+ }
+ } catch (OutOfMemoryError oom) {
+ }
+ }
+
private Main(CyclicBarrier startBarrier) {
this.startBarrier = startBarrier;
}
diff --git a/test/121-modifiers/build b/test/121-modifiers/build
index d73be86..85b69e9 100644
--- a/test/121-modifiers/build
+++ b/test/121-modifiers/build
@@ -30,5 +30,11 @@
# mv NonInf.out classes/NonInf.class
# mv Main.class A.class A\$B.class A\$C.class classes/
-${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+if [ ${USE_JACK} = "true" ]; then
+ ${JILL} classes --output classes.jack
+ # Workaround b/19561685: disable sanity checks to produce a DEX file with invalid modifiers.
+ ${JACK} --sanity-checks off --import classes.jack --output-dex .
+else
+ ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+fi
zip $TEST_NAME.jar classes.dex
diff --git a/test/124-missing-classes/build b/test/124-missing-classes/build
index 62e57c8..b92ecf9 100644
--- a/test/124-missing-classes/build
+++ b/test/124-missing-classes/build
@@ -25,4 +25,11 @@
# ...but not at run time.
rm 'classes/MissingClass.class'
rm 'classes/Main$MissingInnerClass.class'
-${DX} -JXmx256m --debug --dex --output=$TEST_NAME.jar classes
+
+if [ ${USE_JACK} = "true" ]; then
+ ${JILL} classes --output classes.jack
+ ${JACK} --import classes.jack --output-dex .
+else
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
+fi
+zip $TEST_NAME.jar classes.dex
diff --git a/test/126-miranda-multidex/build b/test/126-miranda-multidex/build
index 4c30f3f..b7f2118 100644
--- a/test/126-miranda-multidex/build
+++ b/test/126-miranda-multidex/build
@@ -17,16 +17,32 @@
# Stop if something fails.
set -e
+# All except MirandaInterface
mkdir classes
-
-# All except Main
${JAVAC} -d classes `find src -name '*.java'`
rm classes/MirandaInterface.class
-${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
-# Only Main
-${JAVAC} -d classes `find src -name '*.java'`
-rm classes/Main.class classes/MirandaAbstract.class classes/MirandaClass*.class classes/MirandaInterface2*.class
-${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes
+# Only MirandaInterface
+mkdir classes2
+${JAVAC} -d classes2 `find src -name '*.java'`
+rm classes2/Main.class classes2/MirandaAbstract.class classes2/MirandaClass*.class classes2/MirandaInterface2*.class
+if [ ${USE_JACK} = "true" ]; then
+ # Create .jack files from classes generated with javac.
+ ${JILL} classes --output classes.jack
+ ${JILL} classes2 --output classes2.jack
+
+ # Create DEX files from .jack files.
+ ${JACK} --import classes.jack --output-dex .
+ mv classes.dex classes-1.dex
+ ${JACK} --import classes2.jack --output-dex .
+ mv classes.dex classes2.dex
+ mv classes-1.dex classes.dex
+else
+ # All except Main
+ ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+
+ # Only Main
+ ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes2
+fi
zip $TEST_NAME.jar classes.dex classes2.dex
diff --git a/test/127-secondarydex/build b/test/127-secondarydex/build
index 712774f..0d9f4d6 100755
--- a/test/127-secondarydex/build
+++ b/test/127-secondarydex/build
@@ -23,9 +23,21 @@
mkdir classes-ex
mv classes/Super.class classes-ex
-if [ ${NEED_DEX} = "true" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+if [ ${USE_JACK} = "true" ]; then
+ # Create .jack files from classes generated with javac.
+ ${JILL} classes --output classes.jack
+ ${JILL} classes-ex --output classes-ex.jack
+
+ # Create DEX files from .jack files.
+ ${JACK} --import classes.jack --output-dex .
zip $TEST_NAME.jar classes.dex
- ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+ ${JACK} --import classes-ex.jack --output-dex .
zip ${TEST_NAME}-ex.jar classes.dex
+else
+ if [ ${NEED_DEX} = "true" ]; then
+ ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+ zip $TEST_NAME.jar classes.dex
+ ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+ zip ${TEST_NAME}-ex.jar classes.dex
+ fi
fi
diff --git a/test/131-structural-change/build b/test/131-structural-change/build
index 7ddc81d..ff0da20 100755
--- a/test/131-structural-change/build
+++ b/test/131-structural-change/build
@@ -17,15 +17,23 @@
# Stop if something fails.
set -e
-mkdir classes
-${JAVAC} -d classes `find src -name '*.java'`
-
-mkdir classes-ex
-${JAVAC} -d classes-ex `find src-ex -name '*.java'`
-
-if [ ${NEED_DEX} = "true" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+if [ ${USE_JACK} = "true" ]; then
+ ${JACK} --output-dex . src
zip $TEST_NAME.jar classes.dex
- ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+
+ ${JACK} --output-dex . src-ex
zip ${TEST_NAME}-ex.jar classes.dex
+else
+ mkdir classes
+ ${JAVAC} -d classes `find src -name '*.java'`
+
+ mkdir classes-ex
+ ${JAVAC} -d classes-ex `find src-ex -name '*.java'`
+
+ if [ ${NEED_DEX} = "true" ]; then
+ ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+ zip $TEST_NAME.jar classes.dex
+ ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+ zip ${TEST_NAME}-ex.jar classes.dex
+ fi
fi
diff --git a/test/303-verification-stress/build b/test/303-verification-stress/build
index 789d38e..5ff73ec 100644
--- a/test/303-verification-stress/build
+++ b/test/303-verification-stress/build
@@ -21,8 +21,14 @@
gcc -Wall -Werror -o classes-gen classes-gen.c
./classes-gen
-mkdir classes
-${JAVAC} -d classes src/*.java
+if [ ${USE_JACK} = "true" ]; then
+ # Use the default Jack commands
+ ./default-build
+else
+ mkdir classes
+ ${JAVAC} -d classes src/*.java
-${DX} --debug --dex --output=classes.dex classes
-zip $TEST_NAME.jar classes.dex
+ # dx needs more memory for that test so do not pass Xmx option here.
+ ${DX} --debug --dex --output=classes.dex classes
+ zip $TEST_NAME.jar classes.dex
+fi
diff --git a/test/454-get-vreg/build b/test/454-get-vreg/build
new file mode 100644
index 0000000..08987b5
--- /dev/null
+++ b/test/454-get-vreg/build
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# 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.
+
+# Stop if something fails.
+set -e
+
+# The test relies on DEX file produced by javac+dx so keep building with them for now
+# (see b/19467889)
+mkdir classes
+${JAVAC} -d classes `find src -name '*.java'`
+${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
+ --dump-width=1000 ${DX_FLAGS} classes
+zip $TEST_NAME.jar classes.dex
diff --git a/test/701-easy-div-rem/build b/test/701-easy-div-rem/build
index 1dc8452..666fe89 100644
--- a/test/701-easy-div-rem/build
+++ b/test/701-easy-div-rem/build
@@ -23,6 +23,10 @@
# Increase the file size limitation for classes.lst as the machine generated
# source file contains a lot of methods and is quite large.
-ulimit -S 4096
+
+# Jack generates big temp files so only apply ulimit for dx.
+if [ ${USE_JACK} = "false" ]; then
+ ulimit -S 4096
+fi
./default-build
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index fe68c5b..6ee7a5b 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -28,4 +28,5 @@
b/22080519
b/21645819
b/22244733
+b/22331663
Done!
diff --git a/test/800-smali/smali/b_22331663.smali b/test/800-smali/smali/b_22331663.smali
new file mode 100644
index 0000000..af99152
--- /dev/null
+++ b/test/800-smali/smali/b_22331663.smali
@@ -0,0 +1,35 @@
+.class public LB22331663;
+.super Ljava/lang/Object;
+
+
+.method public static run(Z)V
+.registers 6
+ if-eqz v5, :Label2
+
+:Label1
+ # Construct a java.lang.Object completely, and throw a new exception.
+ new-instance v4, Ljava/lang/Object;
+ invoke-direct {v4}, Ljava/lang/Object;-><init>()V
+
+ new-instance v3, Ljava/lang/RuntimeException;
+ invoke-direct {v3}, Ljava/lang/RuntimeException;-><init>()V
+ throw v3
+
+:Label2
+ # Allocate a java.lang.Object (do not initialize), and throw a new exception.
+ new-instance v4, Ljava/lang/Object;
+
+ new-instance v3, Ljava/lang/RuntimeException;
+ invoke-direct {v3}, Ljava/lang/RuntimeException;-><init>()V
+ throw v3
+
+:Label3
+ # Catch handler. Here we had to merge the uninitialized with the initialized reference,
+ # which creates a conflict. Copy the conflict, and then return. This should not make the
+ # verifier fail the method.
+ move-object v0, v4
+
+ return-void
+
+.catchall {:Label1 .. :Label3} :Label3
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 61f0d7b..3dbba8d 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -103,6 +103,8 @@
null, null));
testCases.add(new TestCase("b/22244733", "B22244733", "run", new Object[] { "abc" },
null, "abc"));
+ testCases.add(new TestCase("b/22331663", "B22331663", "run", new Object[] { false },
+ null, null));
}
public void runTests() {
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index c4111f6..c18bb5c 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -33,22 +33,46 @@
TEST_ART_RUN_TEST_BUILD_RULES :=
# Dependencies for actually running a run-test.
-TEST_ART_RUN_TEST_DEPENDENCIES := $(DX) $(HOST_OUT_EXECUTABLES)/jasmin $(HOST_OUT_EXECUTABLES)/smali $(HOST_OUT_EXECUTABLES)/dexmerger
+TEST_ART_RUN_TEST_DEPENDENCIES := \
+ $(DX) \
+ $(HOST_OUT_EXECUTABLES)/jasmin \
+ $(HOST_OUT_EXECUTABLES)/smali \
+ $(HOST_OUT_EXECUTABLES)/dexmerger
+
+ifeq ($(ANDROID_COMPILE_WITH_JACK),true)
+ TEST_ART_RUN_TEST_DEPENDENCIES += \
+ $(JACK_JAR) \
+ $(JACK_LAUNCHER_JAR) \
+ $(JILL_JAR)
+endif
# Helper to create individual build targets for tests. Must be called with $(eval).
# $(1): the test number
define define-build-art-run-test
dmart_target := $(art_run_tests_dir)/art-run-tests/$(1)/touch
+ run_test_options = --build-only
+ ifeq ($(ANDROID_COMPILE_WITH_JACK),true)
+ run_test_options += --build-with-jack
+ else
+ run_test_options += --build-with-javac-dx
+ endif
+$$(dmart_target): PRIVATE_RUN_TEST_OPTIONS := $$(run_test_options)
$$(dmart_target): $(TEST_ART_RUN_TEST_DEPENDENCIES)
$(hide) rm -rf $$(dir $$@) && mkdir -p $$(dir $$@)
$(hide) DX=$(abspath $(DX)) JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \
SMALI=$(abspath $(HOST_OUT_EXECUTABLES)/smali) \
DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \
- $(LOCAL_PATH)/run-test --build-only --output-path $$(abspath $$(dir $$@)) $(1)
+ JACK=$(abspath $(JACK)) \
+ JACK_VM_COMMAND="$(JACK_VM) $(DEFAULT_JACK_VM_ARGS) $(JAVA_TMPDIR_ARG) -jar $(abspath $(JACK_LAUNCHER_JAR)) " \
+ JACK_CLASSPATH=$(TARGET_JACK_CLASSPATH) \
+ JACK_JAR=$(abspath $(JACK_JAR)) \
+ JILL_JAR=$(abspath $(JILL_JAR)) \
+ $(LOCAL_PATH)/run-test $$(PRIVATE_RUN_TEST_OPTIONS) --output-path $$(abspath $$(dir $$@)) $(1)
$(hide) touch $$@
TEST_ART_RUN_TEST_BUILD_RULES += $$(dmart_target)
dmart_target :=
+ run_test_options :=
endef
$(foreach test, $(TEST_ART_RUN_TESTS), $(eval $(call define-build-art-run-test,$(test))))
@@ -599,6 +623,12 @@
prereq_rule :=
test_groups :=
uc_host_or_target :=
+ jack_classpath :=
+ ifeq ($(ANDROID_COMPILE_WITH_JACK),true)
+ run_test_options += --build-with-jack
+ else
+ run_test_options += --build-with-javac-dx
+ endif
ifeq ($(ART_TEST_RUN_TEST_ALWAYS_CLEAN),true)
run_test_options += --always-clean
endif
@@ -607,11 +637,13 @@
test_groups := ART_RUN_TEST_HOST_RULES
run_test_options += --host
prereq_rule := $(ART_TEST_HOST_RUN_TEST_DEPENDENCIES)
+ jack_classpath := $(HOST_JACK_CLASSPATH)
else
ifeq ($(1),target)
uc_host_or_target := TARGET
test_groups := ART_RUN_TEST_TARGET_RULES
prereq_rule := test-art-target-sync
+ jack_classpath := $(TARGET_JACK_CLASSPATH)
else
$$(error found $(1) expected $(TARGET_TYPES))
endif
@@ -806,12 +838,19 @@
run_test_options := --android-root $(ART_TEST_ANDROID_ROOT) $$(run_test_options)
endif
$$(run_test_rule_name): PRIVATE_RUN_TEST_OPTIONS := $$(run_test_options)
+$$(run_test_rule_name): PRIVATE_JACK_CLASSPATH := $$(jack_classpath)
.PHONY: $$(run_test_rule_name)
-$$(run_test_rule_name): $(DX) $(HOST_OUT_EXECUTABLES)/jasmin $(HOST_OUT_EXECUTABLES)/smali $(HOST_OUT_EXECUTABLES)/dexmerger $(HOST_OUT_EXECUTABLES)/hprof-conv $$(prereq_rule)
+$$(run_test_rule_name): $(TEST_ART_RUN_TEST_DEPENDENCIES) $(HOST_OUT_EXECUTABLES)/hprof-conv $$(prereq_rule)
$(hide) $$(call ART_TEST_SKIP,$$@) && \
- DX=$(abspath $(DX)) JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \
+ DX=$(abspath $(DX)) \
+ JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \
SMALI=$(abspath $(HOST_OUT_EXECUTABLES)/smali) \
DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \
+ JACK=$(abspath $(JACK)) \
+ JACK_VM_COMMAND="$(JACK_VM) $(DEFAULT_JACK_VM_ARGS) $(JAVA_TMPDIR_ARG) -jar $(abspath $(JACK_LAUNCHER_JAR)) " \
+ JACK_CLASSPATH=$$(PRIVATE_JACK_CLASSPATH) \
+ JACK_JAR=$(abspath $(JACK_JAR)) \
+ JILL_JAR=$(abspath $(JILL_JAR)) \
art/test/run-test $$(PRIVATE_RUN_TEST_OPTIONS) $(12) \
&& $$(call ART_TEST_PASSED,$$@) || $$(call ART_TEST_FAILED,$$@)
$$(hide) (echo $(MAKECMDGOALS) | grep -q $$@ && \
@@ -826,6 +865,7 @@
run_test_options :=
run_test_rule_name :=
prereq_rule :=
+ jack_classpath :=
endef # define-test-art-run-test
$(foreach target, $(TARGET_TYPES), \
diff --git a/test/etc/default-build b/test/etc/default-build
index 92954a9..c281bca 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -39,24 +39,57 @@
exit 0
fi
-if [ -d src ]; then
- mkdir classes
- ${JAVAC} -implicit:none -classpath src-multidex -d classes `find src -name '*.java'`
-fi
-
-if [ -d src2 ]; then
- mkdir -p classes
- ${JAVAC} -d classes `find src2 -name '*.java'`
-fi
-
if ! [ -d src ] && ! [ -d src2 ]; then
# No src directory? Then forget about trying to run dx.
SKIP_DX_MERGER="true"
fi
-if [ ${NEED_DEX} = "true" -a ${SKIP_DX_MERGER} = "false" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
- --dump-width=1000 ${DX_FLAGS} classes
+if [ -d src-multidex ]; then
+ # Jack does not support this configuration unless we specify how to partition the DEX file
+ # with a .jpp file.
+ USE_JACK="false"
+fi
+
+if [ ${USE_JACK} = "true" ]; then
+ # Jack toolchain
+ if [ -d src ]; then
+ ${JACK} --output-jack src.jack src
+ imported_jack_files="--import src.jack"
+ fi
+
+ if [ -d src2 ]; then
+ ${JACK} --output-jack src2.jack src2
+ imported_jack_files="--import src2.jack ${imported_jack_files}"
+ fi
+
+ # Compile jack files into a DEX file. We set jack.import.type.policy=keep-first to consider
+ # class definitions from src2 first.
+ ${JACK} ${imported_jack_files} -D jack.import.type.policy=keep-first --output-dex .
+else
+ # Legacy toolchain with javac+dx
+ if [ -d src ]; then
+ mkdir classes
+ ${JAVAC} -implicit:none -classpath src-multidex -d classes `find src -name '*.java'`
+ fi
+
+ if [ -d src-multidex ]; then
+ mkdir classes2
+ ${JAVAC} -implicit:none -classpath src -d classes2 `find src-multidex -name '*.java'`
+ if [ ${NEED_DEX} = "true" ]; then
+ ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex \
+ --dump-width=1000 ${DX_FLAGS} classes2
+ fi
+ fi
+
+ if [ -d src2 ]; then
+ mkdir -p classes
+ ${JAVAC} -d classes `find src2 -name '*.java'`
+ fi
+
+ if [ ${NEED_DEX} = "true" -a ${SKIP_DX_MERGER} = "false" ]; then
+ ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
+ --dump-width=1000 ${DX_FLAGS} classes
+ fi
fi
if [ -d smali ]; then
@@ -72,30 +105,34 @@
fi
if [ -d src-ex ]; then
- mkdir classes-ex
- ${JAVAC} -d classes-ex -cp classes `find src-ex -name '*.java'`
- if [ ${NEED_DEX} = "true" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes-ex.dex \
- --dump-width=1000 ${DX_FLAGS} classes-ex
+ if [ ${USE_JACK} = "true" ]; then
+ # Rename previous "classes.dex" so it is not overwritten.
+ mv classes.dex classes-1.dex
+ #TODO find another way to append src.jack to the jack classpath
+ ${JACK}:src.jack --output-dex . src-ex
+ zip $TEST_NAME-ex.jar classes.dex
+ # Restore previous "classes.dex" so it can be zipped.
+ mv classes-1.dex classes.dex
+ else
+ mkdir classes-ex
+ ${JAVAC} -d classes-ex -cp classes `find src-ex -name '*.java'`
+ if [ ${NEED_DEX} = "true" ]; then
+ ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes-ex.dex \
+ --dump-width=1000 ${DX_FLAGS} classes-ex
- # quick shuffle so that the stored name is "classes.dex"
- mv classes.dex classes-1.dex
- mv classes-ex.dex classes.dex
- zip $TEST_NAME-ex.jar classes.dex
- mv classes.dex classes-ex.dex
- mv classes-1.dex classes.dex
+ # quick shuffle so that the stored name is "classes.dex"
+ mv classes.dex classes-1.dex
+ mv classes-ex.dex classes.dex
+ zip $TEST_NAME-ex.jar classes.dex
+ mv classes.dex classes-ex.dex
+ mv classes-1.dex classes.dex
+ fi
fi
fi
# Create a single jar with two dex files for multidex.
if [ -d src-multidex ]; then
- mkdir classes2
- ${JAVAC} -implicit:none -classpath src -d classes2 `find src-multidex -name '*.java'`
- if [ ${NEED_DEX} = "true" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex \
- --dump-width=1000 ${DX_FLAGS} classes2
- zip $TEST_NAME.jar classes.dex classes2.dex
- fi
+ zip $TEST_NAME.jar classes.dex classes2.dex
elif [ ${NEED_DEX} = "true" ]; then
zip $TEST_NAME.jar classes.dex
fi
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index cf6be83..842d87e 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -458,7 +458,9 @@
# When running under gdb, we cannot do piping and grepping...
$cmdline "$@"
else
- $cmdline "$@" 2>&1
+ trap 'kill -INT -$pid' INT
+ $cmdline "$@" 2>&1 & pid=$!
+ wait $pid
# Add extra detail if time out is enabled.
if [ ${PIPESTATUS[0]} = 124 ] && [ "$TIME_OUT" = "y" ]; then
echo -e "\e[91mTEST TIMED OUT!\e[0m" >&2
diff --git a/test/run-test b/test/run-test
index ffa25eb..f5fff09a 100755
--- a/test/run-test
+++ b/test/run-test
@@ -46,6 +46,7 @@
export RUN="${progdir}/etc/run-test-jar"
export DEX_LOCATION=/data/run-test/${test_dir}
export NEED_DEX="true"
+export USE_JACK="false"
# If dx was not set by the environment variable, assume it is in the path.
if [ -z "$DX" ]; then
@@ -67,6 +68,46 @@
export DXMERGER="dexmerger"
fi
+# If jack was not set by the environment variable, assume it is in the path.
+if [ -z "$JACK" ]; then
+ export JACK="jack"
+fi
+
+# If the tree is compiled with Jack, build test with Jack by default.
+if [ "$ANDROID_COMPILE_WITH_JACK" = "true" ]; then
+ USE_JACK="true"
+fi
+
+# ANDROID_BUILD_TOP is not set in a build environment.
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+ export ANDROID_BUILD_TOP=$oldwd
+fi
+
+# If JACK_VM_COMMAND is not set, assume it launches the prebuilt jack-launcher.
+if [ -z "$JACK_VM_COMMAND" ]; then
+ if [ ! -z "$TMPDIR" ]; then
+ jack_temp_dir="-Djava.io.tmpdir=$TMPDIR"
+ fi
+ export JACK_VM_COMMAND="java -Dfile.encoding=UTF-8 -Xms2560m -XX:+TieredCompilation $jack_temp_dir -jar $ANDROID_BUILD_TOP/prebuilts/sdk/tools/jack-launcher.jar"
+fi
+
+# If JACK_CLASSPATH is not set, assume it only contains core-libart.
+if [ -z "$JACK_CLASSPATH" ]; then
+ export JACK_CLASSPATH="$ANDROID_BUILD_TOP/out/host/common/obj/JAVA_LIBRARIES/core-libart-hostdex_intermediates/classes.jack"
+fi
+
+# If JACK_JAR is not set, assume it is located in the prebuilts directory.
+if [ -z "$JACK_JAR" ]; then
+ export JACK_JAR="$ANDROID_BUILD_TOP/prebuilts/sdk/tools/jack.jar"
+fi
+
+# If JILL_JAR is not set, assume it is located in the prebuilts directory.
+if [ -z "$JILL_JAR" ]; then
+ export JILL_JAR="$ANDROID_BUILD_TOP/prebuilts/sdk/tools/jill.jar"
+fi
+
+export JACK="$JACK -g -cp $JACK_CLASSPATH"
+export JILL="java -jar $JILL_JAR"
info="info.txt"
build="build"
@@ -116,6 +157,7 @@
runtime="jvm"
prebuild_mode="no"
NEED_DEX="false"
+ USE_JACK="false"
run_args="${run_args} --jvm"
shift
elif [ "x$1" = "x-O" ]; then
@@ -237,6 +279,12 @@
elif [ "x$1" = "x--build-only" ]; then
build_only="yes"
shift
+ elif [ "x$1" = "x--build-with-javac-dx" ]; then
+ USE_JACK="false"
+ shift
+ elif [ "x$1" = "x--build-with-jack" ]; then
+ USE_JACK="true"
+ shift
elif [ "x$1" = "x--output-path" ]; then
shift
tmp_dir=$1
@@ -369,10 +417,7 @@
fi
elif [ "$runtime" = "art" ]; then
if [ "$target_mode" = "no" ]; then
- # ANDROID_BUILD_TOP and ANDROID_HOST_OUT are not set in a build environment.
- if [ -z "$ANDROID_BUILD_TOP" ]; then
- export ANDROID_BUILD_TOP=$oldwd
- fi
+ # ANDROID_HOST_OUT is not set in a build environment.
if [ -z "$ANDROID_HOST_OUT" ]; then
export ANDROID_HOST_OUT=$ANDROID_BUILD_TOP/out/host/linux-x86
fi
@@ -462,6 +507,8 @@
echo " --debuggable Whether to compile Java code for a debugger."
echo " --gdb Run under gdb; incompatible with some tests."
echo " --build-only Build test files only (off by default)."
+ echo " --build-with-javac-dx Build test files with javac and dx (on by default)."
+ echo " --build-with-jack Build test files with jack and jill (off by default)."
echo " --interpreter Enable interpreter only mode (off by default)."
echo " --jit Enable jit (off by default)."
echo " --optimizing Enable optimizing compiler (default)."
@@ -556,6 +603,10 @@
# if Checker is not invoked and the test only runs the program.
build_args="${build_args} --dx-option --no-optimize"
+ # Jack does not necessarily generate the same DEX output than dx. Because these tests depend
+ # on a particular DEX output, keep building them with dx for now (b/19467889).
+ USE_JACK="false"
+
if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" -a "$target_mode" = "no" -a "$debuggable" = "no" ]; then
run_checker="yes"
run_args="${run_args} -Xcompiler-option --dump-cfg=$tmp_dir/$cfg_output \
@@ -564,14 +615,20 @@
fi
# To cause tests to fail fast, limit the file sizes created by dx, dex2oat and ART output to 2MB.
-file_size_limit=2048
+build_file_size_limit=2048
+run_file_size_limit=2048
if echo "$test_dir" | grep 089; then
- file_size_limit=5120
+ build_file_size_limit=5120
+ run_file_size_limit=5120
elif echo "$test_dir" | grep 083; then
- file_size_limit=5120
+ build_file_size_limit=5120
+ run_file_size_limit=5120
fi
-if ! ulimit -S "$file_size_limit"; then
- echo "ulimit file size setting failed"
+if [ ${USE_JACK} = "false" ]; then
+ # Set ulimit if we build with dx only, Jack can generate big temp files.
+ if ! ulimit -S "$build_file_size_limit"; then
+ echo "ulimit file size setting failed"
+ fi
fi
good="no"
@@ -582,6 +639,9 @@
build_exit="$?"
echo "build exit status: $build_exit" 1>&2
if [ "$build_exit" = '0' ]; then
+ if ! ulimit -S "$run_file_size_limit"; then
+ echo "ulimit file size setting failed"
+ fi
echo "${test_dir}: running..." 1>&2
"./${run}" $run_args "$@" 2>&1
run_exit="$?"
@@ -604,6 +664,9 @@
"./${build}" $build_args >"$build_output" 2>&1
build_exit="$?"
if [ "$build_exit" = '0' ]; then
+ if ! ulimit -S "$run_file_size_limit"; then
+ echo "ulimit file size setting failed"
+ fi
echo "${test_dir}: running..." 1>&2
"./${run}" $run_args "$@" >"$output" 2>&1
if [ "$run_checker" = "yes" ]; then
@@ -635,6 +698,9 @@
"./${build}" $build_args >"$build_output" 2>&1
build_exit="$?"
if [ "$build_exit" = '0' ]; then
+ if ! ulimit -S "$run_file_size_limit"; then
+ echo "ulimit file size setting failed"
+ fi
echo "${test_dir}: running..." 1>&2
"./${run}" $run_args "$@" >"$output" 2>&1
run_exit="$?"