Merge "ART: Remember whether the cache was pruned"
diff --git a/Android.mk b/Android.mk
index e89f617..a518d2f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -270,9 +270,9 @@
test-art-host-dexdump: $(addprefix $(HOST_OUT_EXECUTABLES)/, dexdump2 dexlist)
ANDROID_HOST_OUT=$(realpath $(HOST_OUT)) art/test/dexdump/run-all-tests
-# Valgrind. Currently only 32b gtests. TODO: change this from 32-bit only to both 32-bit and 64-bit.
+# Valgrind.
.PHONY: valgrind-test-art-host
-valgrind-test-art-host: valgrind-test-art-host-gtest32
+valgrind-test-art-host: valgrind-test-art-host-gtest
$(hide) $(call ART_TEST_PREREQ_FINISHED,$@)
.PHONY: valgrind-test-art-host32
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 5d8e3ba..cd9d80f 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -376,7 +376,8 @@
support_boot_image_fixup_(instruction_set != kMips && instruction_set != kMips64),
dex_files_for_oat_file_(nullptr),
compiled_method_storage_(swap_fd),
- profile_compilation_info_(profile_compilation_info) {
+ profile_compilation_info_(profile_compilation_info),
+ max_arena_alloc_(0) {
DCHECK(compiler_options_ != nullptr);
DCHECK(method_inliner_map_ != nullptr);
@@ -2487,6 +2488,9 @@
parallel_thread_pool_.get(),
parallel_thread_count_,
timings);
+ const ArenaPool* const arena_pool = Runtime::Current()->GetArenaPool();
+ const size_t arena_alloc = arena_pool->GetBytesAllocated();
+ max_arena_alloc_ = std::max(arena_alloc, max_arena_alloc_);
Runtime::Current()->ReclaimArenaPoolMemory();
}
VLOG(compiler) << "Compile: " << GetMemoryUsageString(false);
@@ -2726,12 +2730,9 @@
std::string CompilerDriver::GetMemoryUsageString(bool extended) const {
std::ostringstream oss;
- Runtime* const runtime = Runtime::Current();
- const ArenaPool* const arena_pool = runtime->GetArenaPool();
- const gc::Heap* const heap = runtime->GetHeap();
- const size_t arena_alloc = arena_pool->GetBytesAllocated();
+ const gc::Heap* const heap = Runtime::Current()->GetHeap();
const size_t java_alloc = heap->GetBytesAllocated();
- oss << "arena alloc=" << PrettySize(arena_alloc) << " (" << arena_alloc << "B)";
+ oss << "arena alloc=" << PrettySize(max_arena_alloc_) << " (" << max_arena_alloc_ << "B)";
oss << " java alloc=" << PrettySize(java_alloc) << " (" << java_alloc << "B)";
#if defined(__BIONIC__) || defined(__GLIBC__)
const struct mallinfo info = mallinfo();
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 42a5bc1..4ef26dd 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -694,6 +694,7 @@
// Info for profile guided compilation.
const ProfileCompilationInfo* const profile_compilation_info_;
+ size_t max_arena_alloc_;
friend class CompileClassVisitor;
DISALLOW_COPY_AND_ASSIGN(CompilerDriver);
};
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 3bf8921..43bdbf3 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -35,7 +35,6 @@
include_patch_information_(kDefaultIncludePatchInformation),
top_k_profile_threshold_(kDefaultTopKProfileThreshold),
debuggable_(false),
- native_debuggable_(kDefaultNativeDebuggable),
generate_debug_info_(kDefaultGenerateDebugInfo),
generate_mini_debug_info_(kDefaultGenerateMiniDebugInfo),
implicit_null_checks_(true),
@@ -92,7 +91,6 @@
include_patch_information_(include_patch_information),
top_k_profile_threshold_(top_k_profile_threshold),
debuggable_(debuggable),
- native_debuggable_(kDefaultNativeDebuggable),
generate_debug_info_(generate_debug_info),
generate_mini_debug_info_(kDefaultGenerateMiniDebugInfo),
implicit_null_checks_(implicit_null_checks),
@@ -226,9 +224,6 @@
generate_mini_debug_info_ = false;
} else if (option == "--debuggable") {
debuggable_ = true;
- } else if (option == "--native-debuggable") {
- native_debuggable_ = true;
- debuggable_ = true;
} else if (option.starts_with("--top-k-profile-threshold=")) {
ParseDouble(option.data(), '=', 0.0, 100.0, &top_k_profile_threshold_, Usage);
} else if (option == "--include-patch-information") {
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 4db82a6..fbfa7c8 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -49,7 +49,6 @@
static const size_t kDefaultTinyMethodThreshold = 20;
static const size_t kDefaultNumDexMethodsThreshold = 900;
static constexpr double kDefaultTopKProfileThreshold = 90.0;
- static const bool kDefaultNativeDebuggable = false;
static const bool kDefaultGenerateDebugInfo = false;
static const bool kDefaultGenerateMiniDebugInfo = false;
static const bool kDefaultIncludePatchInformation = false;
@@ -179,7 +178,7 @@
}
bool GetNativeDebuggable() const {
- return native_debuggable_;
+ return GetDebuggable() && GetGenerateDebugInfo();
}
// This flag controls whether the compiler collects debugging information.
@@ -292,7 +291,6 @@
// When using a profile file only the top K% of the profiled samples will be compiled.
double top_k_profile_threshold_;
bool debuggable_;
- bool native_debuggable_;
bool generate_debug_info_;
bool generate_mini_debug_info_;
bool implicit_null_checks_;
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index b1b971f..0b69810 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -1542,15 +1542,16 @@
}
case kNativeObjectRelocationTypeArtMethodArrayClean:
case kNativeObjectRelocationTypeArtMethodArrayDirty: {
- memcpy(dest, pair.first, LengthPrefixedArray<ArtMethod>::ComputeSize(
- 0,
- ArtMethod::Size(target_ptr_size_),
- ArtMethod::Alignment(target_ptr_size_)));
+ size_t size = ArtMethod::Size(target_ptr_size_);
+ size_t alignment = ArtMethod::Alignment(target_ptr_size_);
+ memcpy(dest, pair.first, LengthPrefixedArray<ArtMethod>::ComputeSize(0, size, alignment));
+ // Clear padding to avoid non-deterministic data in the image (and placate valgrind).
+ reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(dest)->ClearPadding(size, alignment);
break;
+ }
case kNativeObjectRelocationTypeDexCacheArray:
// Nothing to copy here, everything is done in FixupDexCache().
break;
- }
}
}
// Fixup the image method roots.
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index af50363..f198727 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -706,7 +706,7 @@
uint32_t dex_pc,
SlowPathCode* slow_path) {
if (instruction != nullptr) {
- // The code generated for some type conversions and comparisons
+ // The code generated for some type conversions
// may call the runtime, thus normally requiring a subsequent
// call to this method. However, the method verifier does not
// produce PC information for certain instructions, which are
@@ -717,7 +717,7 @@
// CodeGenerator::RecordPcInfo without triggering an error in
// CodeGenerator::BuildNativeGCMap ("Missing ref for dex pc 0x")
// thereafter.
- if (instruction->IsTypeConversion() || instruction->IsCompare()) {
+ if (instruction->IsTypeConversion()) {
return;
}
if (instruction->IsRem()) {
@@ -1110,6 +1110,16 @@
}
}
+void CodeGenerator::GenerateNullCheck(HNullCheck* instruction) {
+ if (IsImplicitNullCheckAllowed(instruction)) {
+ MaybeRecordStat(kImplicitNullCheckGenerated);
+ GenerateImplicitNullCheck(instruction);
+ } else {
+ MaybeRecordStat(kExplicitNullCheckGenerated);
+ GenerateExplicitNullCheck(instruction);
+ }
+}
+
void CodeGenerator::ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check) const {
LocationSummary* locations = suspend_check->GetLocations();
HBasicBlock* block = suspend_check->GetBlock();
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 9297fc9..3066048 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -278,6 +278,9 @@
bool CanMoveNullCheckToUser(HNullCheck* null_check);
void MaybeRecordImplicitNullCheck(HInstruction* instruction);
+ void GenerateNullCheck(HNullCheck* null_check);
+ virtual void GenerateImplicitNullCheck(HNullCheck* null_check) = 0;
+ virtual void GenerateExplicitNullCheck(HNullCheck* null_check) = 0;
// Records a stack map which the runtime might use to set catch phi values
// during exception delivery.
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 0b7fefa..34fd9ff 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -3151,6 +3151,7 @@
Location value = locations->InAt(0);
switch (instruction->GetType()) {
+ case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
case Primitive::kPrimChar:
case Primitive::kPrimShort:
@@ -3671,6 +3672,10 @@
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
switch (compare->InputAt(0)->GetType()) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -3701,6 +3706,10 @@
Primitive::Type type = compare->InputAt(0)->GetType();
Condition less_cond;
switch (type) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt: {
__ LoadImmediate(out, 0);
__ cmp(left.AsRegister<Register>(),
@@ -4284,19 +4293,19 @@
}
}
-void InstructionCodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
- if (codegen_->CanMoveNullCheckToUser(instruction)) {
+void CodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ if (CanMoveNullCheckToUser(instruction)) {
return;
}
Location obj = instruction->GetLocations()->InAt(0);
__ LoadFromOffset(kLoadWord, IP, obj.AsRegister<Register>(), 0);
- codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+ RecordPcInfo(instruction, instruction->GetDexPc());
}
-void InstructionCodeGeneratorARM::GenerateExplicitNullCheck(HNullCheck* instruction) {
+void CodeGeneratorARM::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
- codegen_->AddSlowPath(slow_path);
+ AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
Location obj = locations->InAt(0);
@@ -4305,11 +4314,7 @@
}
void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
- if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
- GenerateImplicitNullCheck(instruction);
- } else {
- GenerateExplicitNullCheck(instruction);
- }
+ codegen_->GenerateNullCheck(instruction);
}
void LocationsBuilderARM::VisitArrayGet(HArrayGet* instruction) {
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 06e7c00..5c0f31c 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -274,9 +274,6 @@
Location root,
Register obj,
uint32_t offset);
-
- void GenerateImplicitNullCheck(HNullCheck* instruction);
- void GenerateExplicitNullCheck(HNullCheck* instruction);
void GenerateTestAndBranch(HInstruction* instruction,
size_t condition_input_index,
Label* true_target,
@@ -514,6 +511,9 @@
void GenerateNop();
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
+
private:
// Factored implementation of GenerateFieldLoadWithBakerReadBarrier
// and GenerateArrayLoadWithBakerReadBarrier.
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 89b9e2c..a220e59 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -2388,6 +2388,10 @@
new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
Primitive::Type in_type = compare->InputAt(0)->GetType();
switch (in_type) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -2417,6 +2421,10 @@
// 1 if: left > right
// -1 if: left < right
switch (in_type) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
Register result = OutputRegister(compare);
@@ -2718,8 +2726,8 @@
Primitive::Type type = instruction->GetType();
- if ((type == Primitive::kPrimBoolean) || !Primitive::IsIntegralType(type)) {
- LOG(FATAL) << "Unexpected type " << type << " for DivZeroCheck.";
+ if (!Primitive::IsIntegralType(type)) {
+ LOG(FATAL) << "Unexpected type " << type << " for DivZeroCheck.";
return;
}
@@ -4193,20 +4201,20 @@
}
}
-void InstructionCodeGeneratorARM64::GenerateImplicitNullCheck(HNullCheck* instruction) {
- if (codegen_->CanMoveNullCheckToUser(instruction)) {
+void CodeGeneratorARM64::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ if (CanMoveNullCheckToUser(instruction)) {
return;
}
BlockPoolsScope block_pools(GetVIXLAssembler());
Location obj = instruction->GetLocations()->InAt(0);
__ Ldr(wzr, HeapOperandFrom(obj, Offset(0)));
- codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+ RecordPcInfo(instruction, instruction->GetDexPc());
}
-void InstructionCodeGeneratorARM64::GenerateExplicitNullCheck(HNullCheck* instruction) {
+void CodeGeneratorARM64::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCodeARM64* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM64(instruction);
- codegen_->AddSlowPath(slow_path);
+ AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
Location obj = locations->InAt(0);
@@ -4215,11 +4223,7 @@
}
void InstructionCodeGeneratorARM64::VisitNullCheck(HNullCheck* instruction) {
- if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
- GenerateImplicitNullCheck(instruction);
- } else {
- GenerateExplicitNullCheck(instruction);
- }
+ codegen_->GenerateNullCheck(instruction);
}
void LocationsBuilderARM64::VisitOr(HOr* instruction) {
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 10f1e7f..a1f686e 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -258,8 +258,6 @@
uint32_t offset);
void HandleShift(HBinaryOperation* instr);
- void GenerateImplicitNullCheck(HNullCheck* instruction);
- void GenerateExplicitNullCheck(HNullCheck* instruction);
void GenerateTestAndBranch(HInstruction* instruction,
size_t condition_input_index,
vixl::Label* true_target,
@@ -537,6 +535,9 @@
void GenerateNop();
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
+
private:
// Factored implementation of GenerateFieldLoadWithBakerReadBarrier
// and GenerateArrayLoadWithBakerReadBarrier.
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index f3c12ef..3c2c0b0 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -2070,6 +2070,10 @@
new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
switch (in_type) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt:
case Primitive::kPrimLong:
locations->SetInAt(0, Location::RequiresRegister());
@@ -2100,6 +2104,10 @@
// 1 if: left > right
// -1 if: left < right
switch (in_type) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt: {
Register lhs = locations->InAt(0).AsRegister<Register>();
Register rhs = locations->InAt(1).AsRegister<Register>();
@@ -2530,6 +2538,7 @@
Primitive::Type type = instruction->GetType();
switch (type) {
+ case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
case Primitive::kPrimChar:
case Primitive::kPrimShort:
@@ -4395,19 +4404,19 @@
}
}
-void InstructionCodeGeneratorMIPS::GenerateImplicitNullCheck(HNullCheck* instruction) {
- if (codegen_->CanMoveNullCheckToUser(instruction)) {
+void CodeGeneratorMIPS::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ if (CanMoveNullCheckToUser(instruction)) {
return;
}
Location obj = instruction->GetLocations()->InAt(0);
__ Lw(ZERO, obj.AsRegister<Register>(), 0);
- codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+ RecordPcInfo(instruction, instruction->GetDexPc());
}
-void InstructionCodeGeneratorMIPS::GenerateExplicitNullCheck(HNullCheck* instruction) {
+void CodeGeneratorMIPS::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCodeMIPS* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathMIPS(instruction);
- codegen_->AddSlowPath(slow_path);
+ AddSlowPath(slow_path);
Location obj = instruction->GetLocations()->InAt(0);
@@ -4415,11 +4424,7 @@
}
void InstructionCodeGeneratorMIPS::VisitNullCheck(HNullCheck* instruction) {
- if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
- GenerateImplicitNullCheck(instruction);
- } else {
- GenerateExplicitNullCheck(instruction);
- }
+ codegen_->GenerateNullCheck(instruction);
}
void LocationsBuilderMIPS::VisitOr(HOr* instruction) {
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index 605c794..b720573 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -226,8 +226,6 @@
void HandleShift(HBinaryOperation* operation);
void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info, uint32_t dex_pc);
void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info, uint32_t dex_pc);
- void GenerateImplicitNullCheck(HNullCheck* instruction);
- void GenerateExplicitNullCheck(HNullCheck* instruction);
void GenerateIntCompare(IfCondition cond, LocationSummary* locations);
void GenerateIntCompareAndBranch(IfCondition cond,
LocationSummary* locations,
@@ -362,6 +360,8 @@
}
void GenerateNop();
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
private:
// Labels for each block that will be compiled.
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index c2b84b4..ddc873d 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -1691,6 +1691,10 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
switch (in_type) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt:
case Primitive::kPrimLong:
locations->SetInAt(0, Location::RequiresRegister());
@@ -1719,6 +1723,10 @@
// 1 if: left > right
// -1 if: left < right
switch (in_type) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
GpuRegister lhs = locations->InAt(0).AsRegister<GpuRegister>();
@@ -1726,18 +1734,18 @@
bool use_imm = rhs_location.IsConstant();
GpuRegister rhs = ZERO;
if (use_imm) {
- if (in_type == Primitive::kPrimInt) {
- int32_t value = CodeGenerator::GetInt32ValueOf(rhs_location.GetConstant()->AsConstant());
- if (value != 0) {
- rhs = AT;
- __ LoadConst32(rhs, value);
- }
- } else {
+ if (in_type == Primitive::kPrimLong) {
int64_t value = CodeGenerator::GetInt64ValueOf(rhs_location.GetConstant()->AsConstant());
if (value != 0) {
rhs = AT;
__ LoadConst64(rhs, value);
}
+ } else {
+ int32_t value = CodeGenerator::GetInt32ValueOf(rhs_location.GetConstant()->AsConstant());
+ if (value != 0) {
+ rhs = AT;
+ __ LoadConst32(rhs, value);
+ }
}
} else {
rhs = rhs_location.AsRegister<GpuRegister>();
@@ -2172,8 +2180,8 @@
Primitive::Type type = instruction->GetType();
- if ((type == Primitive::kPrimBoolean) || !Primitive::IsIntegralType(type)) {
- LOG(FATAL) << "Unexpected type " << type << " for DivZeroCheck.";
+ if (!Primitive::IsIntegralType(type)) {
+ LOG(FATAL) << "Unexpected type " << type << " for DivZeroCheck.";
return;
}
@@ -3550,19 +3558,19 @@
}
}
-void InstructionCodeGeneratorMIPS64::GenerateImplicitNullCheck(HNullCheck* instruction) {
- if (codegen_->CanMoveNullCheckToUser(instruction)) {
+void CodeGeneratorMIPS64::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ if (CanMoveNullCheckToUser(instruction)) {
return;
}
Location obj = instruction->GetLocations()->InAt(0);
__ Lw(ZERO, obj.AsRegister<GpuRegister>(), 0);
- codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+ RecordPcInfo(instruction, instruction->GetDexPc());
}
-void InstructionCodeGeneratorMIPS64::GenerateExplicitNullCheck(HNullCheck* instruction) {
+void CodeGeneratorMIPS64::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCodeMIPS64* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathMIPS64(instruction);
- codegen_->AddSlowPath(slow_path);
+ AddSlowPath(slow_path);
Location obj = instruction->GetLocations()->InAt(0);
@@ -3570,11 +3578,7 @@
}
void InstructionCodeGeneratorMIPS64::VisitNullCheck(HNullCheck* instruction) {
- if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
- GenerateImplicitNullCheck(instruction);
- } else {
- GenerateExplicitNullCheck(instruction);
- }
+ codegen_->GenerateNullCheck(instruction);
}
void LocationsBuilderMIPS64::VisitOr(HOr* instruction) {
diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h
index ba9eaff..9464a14 100644
--- a/compiler/optimizing/code_generator_mips64.h
+++ b/compiler/optimizing/code_generator_mips64.h
@@ -228,8 +228,6 @@
const FieldInfo& field_info,
bool value_can_be_null);
void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
- void GenerateImplicitNullCheck(HNullCheck* instruction);
- void GenerateExplicitNullCheck(HNullCheck* instruction);
void GenerateTestAndBranch(HInstruction* instruction,
size_t condition_input_index,
Mips64Label* true_target,
@@ -354,6 +352,8 @@
}
void GenerateNop();
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
private:
// Labels for each block that will be compiled.
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 6b4a18c..9acaa1d 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -3662,6 +3662,7 @@
: LocationSummary::kNoCall;
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
switch (instruction->GetType()) {
+ case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
case Primitive::kPrimChar:
case Primitive::kPrimShort:
@@ -3692,6 +3693,7 @@
Location value = locations->InAt(0);
switch (instruction->GetType()) {
+ case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
case Primitive::kPrimChar:
case Primitive::kPrimShort:
@@ -4184,6 +4186,10 @@
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
switch (compare->InputAt(0)->GetType()) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -4219,6 +4225,10 @@
Condition less_cond = kLess;
switch (compare->InputAt(0)->GetType()) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt: {
GenerateIntCompare(left, right);
break;
@@ -4971,20 +4981,20 @@
}
}
-void InstructionCodeGeneratorX86::GenerateImplicitNullCheck(HNullCheck* instruction) {
- if (codegen_->CanMoveNullCheckToUser(instruction)) {
+void CodeGeneratorX86::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ if (CanMoveNullCheckToUser(instruction)) {
return;
}
LocationSummary* locations = instruction->GetLocations();
Location obj = locations->InAt(0);
__ testl(EAX, Address(obj.AsRegister<Register>(), 0));
- codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+ RecordPcInfo(instruction, instruction->GetDexPc());
}
-void InstructionCodeGeneratorX86::GenerateExplicitNullCheck(HNullCheck* instruction) {
+void CodeGeneratorX86::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction);
- codegen_->AddSlowPath(slow_path);
+ AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
Location obj = locations->InAt(0);
@@ -5003,11 +5013,7 @@
}
void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
- if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
- GenerateImplicitNullCheck(instruction);
- } else {
- GenerateExplicitNullCheck(instruction);
- }
+ codegen_->GenerateNullCheck(instruction);
}
void LocationsBuilderX86::VisitArrayGet(HArrayGet* instruction) {
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 0795f3b..c397899 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -271,8 +271,6 @@
void PushOntoFPStack(Location source, uint32_t temp_offset,
uint32_t stack_adjustment, bool is_fp, bool is_wide);
- void GenerateImplicitNullCheck(HNullCheck* instruction);
- void GenerateExplicitNullCheck(HNullCheck* instruction);
template<class LabelType>
void GenerateTestAndBranch(HInstruction* instruction,
size_t condition_input_index,
@@ -541,6 +539,8 @@
}
void GenerateNop();
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
private:
// Factored implementation of GenerateFieldLoadWithBakerReadBarrier
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index c132663..51bc8c2 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1860,6 +1860,10 @@
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
switch (compare->InputAt(0)->GetType()) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -1890,6 +1894,10 @@
Condition less_cond = kLess;
switch (type) {
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimShort:
+ case Primitive::kPrimChar:
case Primitive::kPrimInt: {
CpuRegister left_reg = left.AsRegister<CpuRegister>();
if (right.IsConstant()) {
@@ -3713,6 +3721,7 @@
Location value = locations->InAt(0);
switch (instruction->GetType()) {
+ case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
case Primitive::kPrimChar:
case Primitive::kPrimShort:
@@ -4487,20 +4496,20 @@
}
}
-void InstructionCodeGeneratorX86_64::GenerateImplicitNullCheck(HNullCheck* instruction) {
- if (codegen_->CanMoveNullCheckToUser(instruction)) {
+void CodeGeneratorX86_64::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ if (CanMoveNullCheckToUser(instruction)) {
return;
}
LocationSummary* locations = instruction->GetLocations();
Location obj = locations->InAt(0);
__ testl(CpuRegister(RAX), Address(obj.AsRegister<CpuRegister>(), 0));
- codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+ RecordPcInfo(instruction, instruction->GetDexPc());
}
-void InstructionCodeGeneratorX86_64::GenerateExplicitNullCheck(HNullCheck* instruction) {
+void CodeGeneratorX86_64::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86_64(instruction);
- codegen_->AddSlowPath(slow_path);
+ AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
Location obj = locations->InAt(0);
@@ -4519,11 +4528,7 @@
}
void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
- if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
- GenerateImplicitNullCheck(instruction);
- } else {
- GenerateExplicitNullCheck(instruction);
- }
+ codegen_->GenerateNullCheck(instruction);
}
void LocationsBuilderX86_64::VisitArrayGet(HArrayGet* instruction) {
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index b3d27e1..c3fce6e 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -260,8 +260,6 @@
CpuRegister obj,
uint32_t offset);
- void GenerateImplicitNullCheck(HNullCheck* instruction);
- void GenerateExplicitNullCheck(HNullCheck* instruction);
void PushOntoFPStack(Location source, uint32_t temp_offset,
uint32_t stack_adjustment, bool is_float);
void GenerateCompareTest(HCondition* condition);
@@ -514,6 +512,8 @@
}
void GenerateNop();
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
private:
// Factored implementation of GenerateFieldLoadWithBakerReadBarrier
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 4a49c83..1fbb2d5 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -661,19 +661,6 @@
}
}
-static Primitive::Type PrimitiveKind(Primitive::Type type) {
- switch (type) {
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimShort:
- case Primitive::kPrimChar:
- case Primitive::kPrimInt:
- return Primitive::kPrimInt;
- default:
- return type;
- }
-}
-
static bool IsSameSizeConstant(HInstruction* insn1, HInstruction* insn2) {
return insn1->IsConstant()
&& insn2->IsConstant()
@@ -716,10 +703,10 @@
// Ensure that the inputs have the same primitive kind as the phi.
for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
HInstruction* input = phi->InputAt(i);
- if (PrimitiveKind(input->GetType()) != PrimitiveKind(phi->GetType())) {
+ if (Primitive::PrimitiveKind(input->GetType()) != Primitive::PrimitiveKind(phi->GetType())) {
AddError(StringPrintf(
"Input %d at index %zu of phi %d from block %d does not have the "
- "same type as the phi: %s versus %s",
+ "same kind as the phi: %s versus %s",
input->GetId(), i, phi->GetId(), phi->GetBlock()->GetBlockId(),
Primitive::PrettyDescriptor(input->GetType()),
Primitive::PrettyDescriptor(phi->GetType())));
@@ -910,9 +897,9 @@
}
HInstruction* lhs = op->InputAt(0);
HInstruction* rhs = op->InputAt(1);
- if (PrimitiveKind(lhs->GetType()) != PrimitiveKind(rhs->GetType())) {
+ if (Primitive::PrimitiveKind(lhs->GetType()) != Primitive::PrimitiveKind(rhs->GetType())) {
AddError(StringPrintf(
- "Condition %s %d has inputs of different types: %s, and %s.",
+ "Condition %s %d has inputs of different kinds: %s, and %s.",
op->DebugName(), op->GetId(),
Primitive::PrettyDescriptor(lhs->GetType()),
Primitive::PrettyDescriptor(rhs->GetType())));
@@ -932,42 +919,39 @@
void GraphChecker::VisitBinaryOperation(HBinaryOperation* op) {
VisitInstruction(op);
+ Primitive::Type lhs_type = op->InputAt(0)->GetType();
+ Primitive::Type rhs_type = op->InputAt(1)->GetType();
+ Primitive::Type result_type = op->GetType();
if (op->IsUShr() || op->IsShr() || op->IsShl() || op->IsRor()) {
- if (PrimitiveKind(op->InputAt(1)->GetType()) != Primitive::kPrimInt) {
- AddError(StringPrintf(
- "Shift operation %s %d has a non-int kind second input: "
- "%s of type %s.",
- op->DebugName(), op->GetId(),
- op->InputAt(1)->DebugName(),
- Primitive::PrettyDescriptor(op->InputAt(1)->GetType())));
+ if (Primitive::PrimitiveKind(rhs_type) != Primitive::kPrimInt) {
+ AddError(StringPrintf("Shift operation %s %d has a non-int kind second input: %s of type %s.",
+ op->DebugName(), op->GetId(),
+ op->InputAt(1)->DebugName(),
+ Primitive::PrettyDescriptor(rhs_type)));
}
} else {
- if (PrimitiveKind(op->InputAt(0)->GetType()) != PrimitiveKind(op->InputAt(1)->GetType())) {
- AddError(StringPrintf(
- "Binary operation %s %d has inputs of different types: "
- "%s, and %s.",
- op->DebugName(), op->GetId(),
- Primitive::PrettyDescriptor(op->InputAt(0)->GetType()),
- Primitive::PrettyDescriptor(op->InputAt(1)->GetType())));
+ if (Primitive::PrimitiveKind(lhs_type) != Primitive::PrimitiveKind(rhs_type)) {
+ AddError(StringPrintf("Binary operation %s %d has inputs of different kinds: %s, and %s.",
+ op->DebugName(), op->GetId(),
+ Primitive::PrettyDescriptor(lhs_type),
+ Primitive::PrettyDescriptor(rhs_type)));
}
}
if (op->IsCompare()) {
- if (op->GetType() != Primitive::kPrimInt) {
- AddError(StringPrintf(
- "Compare operation %d has a non-int result type: %s.",
- op->GetId(),
- Primitive::PrettyDescriptor(op->GetType())));
+ if (result_type != Primitive::kPrimInt) {
+ AddError(StringPrintf("Compare operation %d has a non-int result type: %s.",
+ op->GetId(),
+ Primitive::PrettyDescriptor(result_type)));
}
} else {
// Use the first input, so that we can also make this check for shift operations.
- if (PrimitiveKind(op->GetType()) != PrimitiveKind(op->InputAt(0)->GetType())) {
- AddError(StringPrintf(
- "Binary operation %s %d has a result type different "
- "from its input type: %s vs %s.",
- op->DebugName(), op->GetId(),
- Primitive::PrettyDescriptor(op->GetType()),
- Primitive::PrettyDescriptor(op->InputAt(0)->GetType())));
+ if (Primitive::PrimitiveKind(result_type) != Primitive::PrimitiveKind(lhs_type)) {
+ AddError(StringPrintf("Binary operation %s %d has a result kind different "
+ "from its input kind: %s vs %s.",
+ op->DebugName(), op->GetId(),
+ Primitive::PrettyDescriptor(result_type),
+ Primitive::PrettyDescriptor(lhs_type)));
}
}
}
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index d861e39..573b583 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -293,7 +293,11 @@
}
if (actual_method != nullptr) {
- return TryInlineAndReplace(invoke_instruction, actual_method, /* do_rtp */ true);
+ bool result = TryInlineAndReplace(invoke_instruction, actual_method, /* do_rtp */ true);
+ if (result && !invoke_instruction->IsInvokeStaticOrDirect()) {
+ MaybeRecordStat(kInlinedInvokeVirtualOrInterface);
+ }
+ return result;
}
DCHECK(!invoke_instruction->IsInvokeStaticOrDirect());
@@ -1279,10 +1283,14 @@
// some functionality from the reference type propagation.
DCHECK(return_replacement->IsPhi());
size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- ReferenceTypeInfo::TypeHandle return_handle =
- handles_->NewHandle(resolved_method->GetReturnType(true /* resolve */, pointer_size));
- return_replacement->SetReferenceTypeInfo(ReferenceTypeInfo::Create(
- return_handle, return_handle->CannotBeAssignedFromOtherTypes() /* is_exact */));
+ mirror::Class* cls = resolved_method->GetReturnType(false /* resolve */, pointer_size);
+ if (cls != nullptr) {
+ ReferenceTypeInfo::TypeHandle return_handle = handles_->NewHandle(cls);
+ return_replacement->SetReferenceTypeInfo(ReferenceTypeInfo::Create(
+ return_handle, return_handle->CannotBeAssignedFromOtherTypes() /* is_exact */));
+ } else {
+ return_replacement->SetReferenceTypeInfo(graph_->GetInexactObjectRti());
+ }
}
if (do_rtp) {
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 09f841c..dd2977f 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -34,8 +34,12 @@
void RecordSimplification() {
simplification_occurred_ = true;
simplifications_at_current_position_++;
- if (stats_) {
- stats_->RecordStat(kInstructionSimplifications);
+ MaybeRecordStat(kInstructionSimplifications);
+ }
+
+ void MaybeRecordStat(MethodCompilationStat stat) {
+ if (stats_ != nullptr) {
+ stats_->RecordStat(stat);
}
}
@@ -95,7 +99,7 @@
void SimplifyRotate(HInvoke* invoke, bool is_left);
void SimplifySystemArrayCopy(HInvoke* invoke);
void SimplifyStringEquals(HInvoke* invoke);
- void SimplifyCompare(HInvoke* invoke, bool has_zero_op);
+ void SimplifyCompare(HInvoke* invoke, bool is_signum, Primitive::Type type);
void SimplifyIsNaN(HInvoke* invoke);
void SimplifyFP2Int(HInvoke* invoke);
void SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind);
@@ -235,7 +239,10 @@
HInstruction* input_other = instruction->GetLeastConstantLeft();
if (input_cst != nullptr) {
- if (input_cst->IsZero()) {
+ int64_t cst = Int64FromConstant(input_cst);
+ int64_t mask =
+ (input_other->GetType() == Primitive::kPrimLong) ? kMaxLongShiftValue : kMaxIntShiftValue;
+ if ((cst & mask) == 0) {
// Replace code looking like
// SHL dst, src, 0
// with
@@ -463,9 +470,7 @@
if (object->IsNullConstant()) {
check_cast->GetBlock()->RemoveInstruction(check_cast);
- if (stats_ != nullptr) {
- stats_->RecordStat(MethodCompilationStat::kRemovedCheckedCast);
- }
+ MaybeRecordStat(MethodCompilationStat::kRemovedCheckedCast);
return;
}
@@ -475,9 +480,7 @@
if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) {
if (outcome) {
check_cast->GetBlock()->RemoveInstruction(check_cast);
- if (stats_ != nullptr) {
- stats_->RecordStat(MethodCompilationStat::kRemovedCheckedCast);
- }
+ MaybeRecordStat(MethodCompilationStat::kRemovedCheckedCast);
if (!load_class->HasUses()) {
// We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
// However, here we know that it cannot because the checkcast was successfull, hence
@@ -507,6 +510,7 @@
HGraph* graph = GetGraph();
if (object->IsNullConstant()) {
+ MaybeRecordStat(kRemovedInstanceOf);
instruction->ReplaceWith(graph->GetIntConstant(0));
instruction->GetBlock()->RemoveInstruction(instruction);
RecordSimplification();
@@ -517,6 +521,7 @@
// the return value check with the `outcome` check, b/27651442 .
bool outcome = false;
if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) {
+ MaybeRecordStat(kRemovedInstanceOf);
if (outcome && can_be_null) {
// Type test will succeed, we just need a null test.
HNotEqual* test = new (graph->GetArena()) HNotEqual(graph->GetNullConstant(), object);
@@ -1614,12 +1619,13 @@
}
}
-void InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke, bool is_signum) {
+void InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke,
+ bool is_signum,
+ Primitive::Type type) {
DCHECK(invoke->IsInvokeStaticOrDirect());
uint32_t dex_pc = invoke->GetDexPc();
HInstruction* left = invoke->InputAt(0);
HInstruction* right;
- Primitive::Type type = left->GetType();
if (!is_signum) {
right = invoke->InputAt(1);
} else if (type == Primitive::kPrimLong) {
@@ -1696,12 +1702,16 @@
SimplifyRotate(instruction, true);
break;
case Intrinsics::kIntegerCompare:
+ SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimInt);
+ break;
case Intrinsics::kLongCompare:
- SimplifyCompare(instruction, /* is_signum */ false);
+ SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimLong);
break;
case Intrinsics::kIntegerSignum:
+ SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimInt);
+ break;
case Intrinsics::kLongSignum:
- SimplifyCompare(instruction, /* is_signum */ true);
+ SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimLong);
break;
case Intrinsics::kFloatIsNaN:
case Intrinsics::kDoubleIsNaN:
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 1bb5f5d..e2a54f4 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2543,7 +2543,7 @@
return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
}
bool IsZero() const OVERRIDE {
- return value_ == 0.0f;
+ return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(0.0f);
}
bool IsOne() const OVERRIDE {
return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
@@ -2585,7 +2585,7 @@
return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
}
bool IsZero() const OVERRIDE {
- return value_ == 0.0;
+ return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((0.0));
}
bool IsOne() const OVERRIDE {
return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
@@ -3428,7 +3428,10 @@
// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
class HCompare : public HBinaryOperation {
public:
- HCompare(Primitive::Type type,
+ // Note that `comparison_type` is the type of comparison performed
+ // between the comparison's inputs, not the type of the instantiated
+ // HCompare instruction (which is always Primitive::kPrimInt).
+ HCompare(Primitive::Type comparison_type,
HInstruction* first,
HInstruction* second,
ComparisonBias bias,
@@ -3436,11 +3439,13 @@
: HBinaryOperation(Primitive::kPrimInt,
first,
second,
- SideEffectsForArchRuntimeCalls(type),
+ SideEffectsForArchRuntimeCalls(comparison_type),
dex_pc) {
SetPackedField<ComparisonBiasField>(bias);
- DCHECK_EQ(type, first->GetType());
- DCHECK_EQ(type, second->GetType());
+ if (kIsDebugBuild) {
+ DCHECK_EQ(comparison_type, Primitive::PrimitiveKind(first->GetType()));
+ DCHECK_EQ(comparison_type, Primitive::PrimitiveKind(second->GetType()));
+ }
}
template <typename T>
@@ -3485,9 +3490,9 @@
return GetBias() == ComparisonBias::kGtBias;
}
- static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type type) {
- // MIPS64 uses a runtime call for FP comparisons.
- return Primitive::IsFloatingPointType(type) ? SideEffects::CanTriggerGC() : SideEffects::None();
+ static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type type ATTRIBUTE_UNUSED) {
+ // Comparisons do not require a runtime call in any back end.
+ return SideEffects::None();
}
DECLARE_INSTRUCTION(Compare);
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 7a82063..4d2469c 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -63,6 +63,7 @@
#include "instruction_simplifier_arm.h"
#include "intrinsics.h"
#include "jit/debugger_interface.h"
+#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "jni/quick/jni_compiler.h"
#include "licm.h"
@@ -697,7 +698,8 @@
CodeGenerator::Create(graph,
instruction_set,
*compiler_driver->GetInstructionSetFeatures(),
- compiler_driver->GetCompilerOptions()));
+ compiler_driver->GetCompilerOptions(),
+ compilation_stats_.get()));
if (codegen.get() == nullptr) {
MaybeRecordStat(MethodCompilationStat::kNotCompiledNoCodegen);
return nullptr;
@@ -891,7 +893,7 @@
}
size_t stack_map_size = codegen->ComputeStackMapsSize();
- uint8_t* stack_map_data = code_cache->ReserveData(self, stack_map_size);
+ uint8_t* stack_map_data = code_cache->ReserveData(self, stack_map_size, method);
if (stack_map_data == nullptr) {
return false;
}
@@ -945,6 +947,8 @@
elf_file.size());
}
+ Runtime::Current()->GetJit()->AddMemoryUsage(method, arena.BytesUsed());
+
return true;
}
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index 179004b..3717926 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -60,6 +60,10 @@
kIntrinsicRecognized,
kLoopInvariantMoved,
kSelectGenerated,
+ kRemovedInstanceOf,
+ kInlinedInvokeVirtualOrInterface,
+ kImplicitNullCheckGenerated,
+ kExplicitNullCheckGenerated,
kLastStat
};
@@ -133,6 +137,10 @@
case kIntrinsicRecognized : name = "IntrinsicRecognized"; break;
case kLoopInvariantMoved : name = "LoopInvariantMoved"; break;
case kSelectGenerated : name = "SelectGenerated"; break;
+ case kRemovedInstanceOf: name = "RemovedInstanceOf"; break;
+ case kInlinedInvokeVirtualOrInterface: name = "InlinedInvokeVirtualOrInterface"; break;
+ case kImplicitNullCheckGenerated: name = "ImplicitNullCheckGenerated"; break;
+ case kExplicitNullCheckGenerated: name = "ExplicitNullCheckGenerated"; break;
case kLastStat:
LOG(FATAL) << "invalid stat "
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index ce4f38a..2981011 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -255,6 +255,7 @@
UsageError("");
UsageError(" --compiler-filter="
"(verify-none"
+ "|verify-at-runtime"
"|interpret-only"
"|space"
"|balanced"
@@ -287,8 +288,8 @@
UsageError("");
UsageError(" --num-dex-methods=<method-count>: threshold size for a small dex file for");
UsageError(" compiler filter tuning. If the input has fewer than this many methods");
- UsageError(" and the filter is not interpret-only or verify-none, overrides the");
- UsageError(" filter to use speed");
+ UsageError(" and the filter is not interpret-only or verify-none or verify-at-runtime, ");
+ UsageError(" overrides the filter to use speed");
UsageError(" Example: --num-dex-method=%d", CompilerOptions::kDefaultNumDexMethodsThreshold);
UsageError(" Default: %d", CompilerOptions::kDefaultNumDexMethodsThreshold);
UsageError("");
@@ -317,7 +318,7 @@
UsageError(" -g");
UsageError(" --generate-debug-info: Generate debug information for native debugging,");
UsageError(" such as stack unwinding information, ELF symbols and DWARF sections.");
- UsageError(" If used without --native-debuggable, it will be best-effort only.");
+ UsageError(" If used without --debuggable, it will be best-effort only.");
UsageError(" This option does not affect the generated code. (disabled by default)");
UsageError("");
UsageError(" --no-generate-debug-info: Do not generate debug information for native debugging.");
@@ -325,13 +326,10 @@
UsageError(" --generate-mini-debug-info: Generate minimal amount of LZMA-compressed");
UsageError(" debug information necessary to print backtraces. (disabled by default)");
UsageError("");
- UsageError(" --no-generate-mini-debug-info: Do do generated backtrace info.");
+ UsageError(" --no-generate-mini-debug-info: Do not generate backtrace info.");
UsageError("");
UsageError(" --debuggable: Produce code debuggable with Java debugger.");
UsageError("");
- UsageError(" --native-debuggable: Produce code debuggable with native debugger (like LLDB).");
- UsageError(" Implies --debuggable.");
- UsageError("");
UsageError(" --runtime-arg <argument>: used to specify various arguments for the runtime,");
UsageError(" such as initial heap size, maximum heap size, and verbose output.");
UsageError(" Use a separate --runtime-arg switch for each argument.");
@@ -1037,7 +1035,7 @@
compiler_options_->debuggable_ ? OatHeader::kTrueValue : OatHeader::kFalseValue);
key_value_store_->Put(
OatHeader::kNativeDebuggableKey,
- compiler_options_->native_debuggable_ ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+ compiler_options_->GetNativeDebuggable() ? OatHeader::kTrueValue : OatHeader::kFalseValue);
if (compiler_options_->IsExtractOnly()) {
key_value_store_->Put(OatHeader::kCompilationType, OatHeader::kExtractOnlyValue);
} else if (UseProfileGuidedCompilation()) {
@@ -1452,8 +1450,8 @@
}
/*
- * If we're not in interpret-only or verify-none mode, go ahead and compile small applications.
- * Don't bother to check if we're doing the image.
+ * If we're not in interpret-only or verify-none or verify-at-runtime mode, go ahead and
+ * compile small applications. Don't bother to check if we're doing the image.
*/
if (!IsBootImage() &&
compiler_options_->IsCompilationEnabled() &&
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 84660a3..f70e696 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -140,7 +140,6 @@
native/java_lang_Class.cc \
native/java_lang_DexCache.cc \
native/java_lang_Object.cc \
- native/java_lang_Runtime.cc \
native/java_lang_String.cc \
native/java_lang_StringFactory.cc \
native/java_lang_System.cc \
diff --git a/runtime/base/histogram-inl.h b/runtime/base/histogram-inl.h
index 03980e3..c7a0ba2 100644
--- a/runtime/base/histogram-inl.h
+++ b/runtime/base/histogram-inl.h
@@ -26,6 +26,7 @@
#include "base/bit_utils.h"
#include "base/time_utils.h"
+#include "utils.h"
namespace art {
@@ -200,6 +201,13 @@
}
template <class Value>
+inline void Histogram<Value>::PrintMemoryUse(std::ostream &os) const {
+ os << Name()
+ << ": Avg: " << PrettySize(Mean()) << " Max: "
+ << PrettySize(Max()) << " Min: " << PrettySize(Min()) << "\n";
+}
+
+template <class Value>
inline void Histogram<Value>::CreateHistogram(CumulativeData* out_data) const {
DCHECK_GT(sample_size_, 0ull);
out_data->freq_.clear();
diff --git a/runtime/base/histogram.h b/runtime/base/histogram.h
index ef3a5d7..bcb7b3b 100644
--- a/runtime/base/histogram.h
+++ b/runtime/base/histogram.h
@@ -59,6 +59,7 @@
double Percentile(double per, const CumulativeData& data) const;
void PrintConfidenceIntervals(std::ostream& os, double interval,
const CumulativeData& data) const;
+ void PrintMemoryUse(std::ostream& os) const;
void PrintBins(std::ostream& os, const CumulativeData& data) const;
void DumpBins(std::ostream& os) const;
Value GetRange(size_t bucket_idx) const;
diff --git a/runtime/base/length_prefixed_array.h b/runtime/base/length_prefixed_array.h
index d632871..8060263 100644
--- a/runtime/base/length_prefixed_array.h
+++ b/runtime/base/length_prefixed_array.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
#include <stddef.h> // for offsetof()
+#include <string.h> // for memset()
#include "stride_iterator.h"
#include "base/bit_utils.h"
@@ -84,6 +85,13 @@
size_ = dchecked_integral_cast<uint32_t>(length);
}
+ // Clear the potentially uninitialized padding between the size_ and actual data.
+ void ClearPadding(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
+ size_t gap_offset = offsetof(LengthPrefixedArray<T>, data);
+ size_t gap_size = OffsetOfElement(0, element_size, alignment) - gap_offset;
+ memset(reinterpret_cast<uint8_t*>(this) + gap_offset, 0, gap_size);
+ }
+
private:
T& AtUnchecked(size_t index, size_t element_size, size_t alignment) {
return *reinterpret_cast<T*>(
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 52beb15..3c69323 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2528,8 +2528,18 @@
size_t num_32 = 0;
size_t num_64 = 0;
if (class_data != nullptr) {
+ // We allow duplicate definitions of the same field in a class_data_item
+ // but ignore the repeated indexes here, b/21868015.
+ uint32_t last_field_idx = DexFile::kDexNoIndex;
for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
- const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex());
+ uint32_t field_idx = it.GetMemberIndex();
+ // Ordering enforced by DexFileVerifier.
+ DCHECK(last_field_idx == DexFile::kDexNoIndex || last_field_idx <= field_idx);
+ if (UNLIKELY(field_idx == last_field_idx)) {
+ continue;
+ }
+ last_field_idx = field_idx;
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
char c = descriptor[0];
switch (c) {
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index b107b72..a0c6bfb 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -83,7 +83,8 @@
deoptimized_methods_lock_("deoptimized methods lock"),
deoptimization_enabled_(false),
interpreter_handler_table_(kMainHandlerTable),
- quick_alloc_entry_points_instrumentation_counter_(0) {
+ quick_alloc_entry_points_instrumentation_counter_(0),
+ alloc_entrypoints_instrumented_(false) {
}
void Instrumentation::InstallStubsForClass(mirror::Class* klass) {
@@ -642,10 +643,12 @@
MutexLock mu(self, *Locks::runtime_shutdown_lock_);
SetQuickAllocEntryPointsInstrumented(instrumented);
ResetQuickAllocEntryPoints();
+ alloc_entrypoints_instrumented_ = instrumented;
} else {
MutexLock mu(self, *Locks::runtime_shutdown_lock_);
SetQuickAllocEntryPointsInstrumented(instrumented);
ResetQuickAllocEntryPoints();
+ alloc_entrypoints_instrumented_ = instrumented;
}
}
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index b3cdb41..d07f47b 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -422,7 +422,7 @@
// Does not hold lock, used to check if someone changed from not instrumented to instrumented
// during a GC suspend point.
bool AllocEntrypointsInstrumented() const SHARED_REQUIRES(Locks::mutator_lock_) {
- return quick_alloc_entry_points_instrumentation_counter_ > 0;
+ return alloc_entrypoints_instrumented_;
}
private:
@@ -579,6 +579,12 @@
// Greater than 0 if quick alloc entry points instrumented.
size_t quick_alloc_entry_points_instrumentation_counter_;
+
+ // alloc_entrypoints_instrumented_ is only updated with all the threads suspended, this is done
+ // to prevent races with the GC where the GC relies on thread suspension only see
+ // alloc_entrypoints_instrumented_ change during suspend points.
+ bool alloc_entrypoints_instrumented_;
+
friend class InstrumentationTest; // For GetCurrentInstrumentationLevel and ConfigureStubs.
DISALLOW_COPY_AND_ASSIGN(Instrumentation);
diff --git a/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S b/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S
index db18aa7..9868f41 100644
--- a/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S
+++ b/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S
@@ -3,9 +3,9 @@
ubfx w2, wINST, #8, #4 // w2<- A
GET_VREG_WIDE d1, w1 // d1<- vB
GET_VREG_WIDE d0, w2 // d0<- vA
- FETCH_ADVANCE_INST 1 // advance rPC, load rINST
bl fmod
ubfx w2, wINST, #8, #4 // w2<- A (need to reload - killed across call)
+ FETCH_ADVANCE_INST 1 // advance rPC, load rINST
GET_INST_OPCODE ip // extract opcode from rINST
SET_VREG_WIDE d0, w2 // vAA<- result
GOTO_OPCODE ip // jump to next instruction
diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S
index cdb27e8..6ae59d8 100644
--- a/runtime/interpreter/mterp/out/mterp_arm64.S
+++ b/runtime/interpreter/mterp/out/mterp_arm64.S
@@ -5984,9 +5984,9 @@
ubfx w2, wINST, #8, #4 // w2<- A
GET_VREG_WIDE d1, w1 // d1<- vB
GET_VREG_WIDE d0, w2 // d0<- vA
- FETCH_ADVANCE_INST 1 // advance rPC, load rINST
bl fmod
ubfx w2, wINST, #8, #4 // w2<- A (need to reload - killed across call)
+ FETCH_ADVANCE_INST 1 // advance rPC, load rINST
GET_INST_OPCODE ip // extract opcode from rINST
SET_VREG_WIDE d0, w2 // vAA<- result
GOTO_OPCODE ip // jump to next instruction
diff --git a/runtime/jit/debugger_interface.cc b/runtime/jit/debugger_interface.cc
index f08a1a9..d9d7a19 100644
--- a/runtime/jit/debugger_interface.cc
+++ b/runtime/jit/debugger_interface.cc
@@ -58,6 +58,10 @@
__asm__("");
}
+ // Call __jit_debug_register_code indirectly via global variable.
+ // This gives the debugger an easy way to inject custom code to handle the events.
+ void (*__jit_debug_register_code_ptr)() = __jit_debug_register_code;
+
// GDB will inspect contents of this descriptor.
// Static initialization is necessary to prevent GDB from seeing
// uninitialized descriptor.
@@ -85,7 +89,7 @@
__jit_debug_descriptor.relevant_entry_ = entry;
__jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
- __jit_debug_register_code();
+ (*__jit_debug_register_code_ptr)();
return entry;
}
@@ -102,7 +106,7 @@
__jit_debug_descriptor.relevant_entry_ = entry;
__jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
- __jit_debug_register_code();
+ (*__jit_debug_register_code_ptr)();
delete[] entry->symfile_addr_;
delete entry;
}
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 5bd9a6b..7e73e5c 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -83,6 +83,8 @@
void Jit::DumpInfo(std::ostream& os) {
code_cache_->Dump(os);
cumulative_timings_.Dump(os);
+ MutexLock mu(Thread::Current(), lock_);
+ memory_use_.PrintMemoryUse(os);
}
void Jit::AddTimingLogger(const TimingLogger& logger) {
@@ -95,6 +97,8 @@
jit_compile_method_(nullptr),
dump_info_on_shutdown_(false),
cumulative_timings_("JIT timings"),
+ memory_use_("Memory used for compilation", 16),
+ lock_("JIT memory use lock"),
save_profiling_info_(false),
generate_debug_info_(false) {
}
@@ -433,5 +437,16 @@
return true;
}
+void Jit::AddMemoryUsage(ArtMethod* method, size_t bytes) {
+ if (bytes > 4 * MB) {
+ LOG(INFO) << "Compiler allocated "
+ << PrettySize(bytes)
+ << " to compile "
+ << PrettyMethod(method);
+ }
+ MutexLock mu(Thread::Current(), lock_);
+ memory_use_.AddValue(bytes);
+}
+
} // namespace jit
} // namespace art
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index d5c2134..37d0bdb 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -17,14 +17,11 @@
#ifndef ART_RUNTIME_JIT_JIT_H_
#define ART_RUNTIME_JIT_JIT_H_
-#include <unordered_map>
-
-#include "atomic.h"
+#include "base/arena_allocator.h"
+#include "base/histogram-inl.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "base/timing_logger.h"
-#include "gc_root.h"
-#include "jni.h"
#include "object_callbacks.h"
#include "offline_profiling_info.h"
#include "thread_pool.h"
@@ -62,9 +59,14 @@
void DeleteThreadPool();
// Dump interesting info: #methods compiled, code vs data size, compile / verify cumulative
// loggers.
- void DumpInfo(std::ostream& os);
+ void DumpInfo(std::ostream& os) REQUIRES(!lock_);
// Add a timing logger to cumulative_timings_.
void AddTimingLogger(const TimingLogger& logger);
+
+ void AddMemoryUsage(ArtMethod* method, size_t bytes)
+ REQUIRES(!lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
+
JitInstrumentationCache* GetInstrumentationCache() const {
return instrumentation_cache_.get();
}
@@ -82,7 +84,7 @@
const std::string& app_dir);
void StopProfileSaver();
- void DumpForSigQuit(std::ostream& os) {
+ void DumpForSigQuit(std::ostream& os) REQUIRES(!lock_) {
DumpInfo(os);
}
@@ -125,6 +127,8 @@
// Performance monitoring.
bool dump_info_on_shutdown_;
CumulativeLogger cumulative_timings_;
+ Histogram<uint64_t> memory_use_ GUARDED_BY(lock_);
+ Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
std::unique_ptr<jit::JitInstrumentationCache> instrumentation_cache_;
std::unique_ptr<jit::JitCodeCache> code_cache_;
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index af47da6..c681ed7 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -40,6 +40,9 @@
static constexpr int kProtData = PROT_READ | PROT_WRITE;
static constexpr int kProtCode = PROT_READ | PROT_EXEC;
+static constexpr size_t kCodeSizeLogThreshold = 50 * KB;
+static constexpr size_t kStackMapSizeLogThreshold = 50 * KB;
+
#define CHECKED_MPROTECT(memory, size, prot) \
do { \
int rc = mprotect(memory, size, prot); \
@@ -134,7 +137,10 @@
number_of_compilations_(0),
number_of_osr_compilations_(0),
number_of_deoptimizations_(0),
- number_of_collections_(0) {
+ number_of_collections_(0),
+ histogram_stack_map_memory_use_("Memory used for stack maps", 16),
+ histogram_code_memory_use_("Memory used for compiled code", 16),
+ histogram_profiling_info_memory_use_("Memory used for profiling info", 16) {
DCHECK_GE(max_capacity, initial_code_capacity + initial_data_capacity);
code_mspace_ = create_mspace_with_base(code_map_->Begin(), code_end_, false /*locked*/);
@@ -377,6 +383,13 @@
<< " dcache_size=" << PrettySize(DataCacheSizeLocked()) << ": "
<< reinterpret_cast<const void*>(method_header->GetEntryPoint()) << ","
<< reinterpret_cast<const void*>(method_header->GetEntryPoint() + method_header->code_size_);
+ histogram_code_memory_use_.AddValue(code_size);
+ if (code_size > kCodeSizeLogThreshold) {
+ LOG(INFO) << "JIT allocated "
+ << PrettySize(code_size)
+ << " for compiled code of "
+ << PrettyMethod(method);
+ }
}
return reinterpret_cast<uint8_t*>(method_header);
@@ -405,7 +418,7 @@
FreeData(reinterpret_cast<uint8_t*>(data));
}
-uint8_t* JitCodeCache::ReserveData(Thread* self, size_t size) {
+uint8_t* JitCodeCache::ReserveData(Thread* self, size_t size, ArtMethod* method) {
size = RoundUp(size, sizeof(void*));
uint8_t* result = nullptr;
@@ -425,15 +438,14 @@
result = AllocateData(size);
}
- return result;
-}
-
-uint8_t* JitCodeCache::AddDataArray(Thread* self, const uint8_t* begin, const uint8_t* end) {
- uint8_t* result = ReserveData(self, end - begin);
- if (result == nullptr) {
- return nullptr; // Out of space in the data cache.
+ MutexLock mu(self, lock_);
+ histogram_stack_map_memory_use_.AddValue(size);
+ if (size > kStackMapSizeLogThreshold) {
+ LOG(INFO) << "JIT allocated "
+ << PrettySize(size)
+ << " for stack maps of "
+ << PrettyMethod(method);
}
- std::copy(begin, end, result);
return result;
}
@@ -868,6 +880,7 @@
method->SetProfilingInfo(info);
profiling_infos_.push_back(info);
+ histogram_profiling_info_memory_use_.AddValue(profile_info_size);
return info;
}
@@ -1021,6 +1034,9 @@
<< number_of_osr_compilations_ << "\n"
<< "Total number of deoptimizations: " << number_of_deoptimizations_ << "\n"
<< "Total number of JIT code cache collections: " << number_of_collections_ << std::endl;
+ histogram_stack_map_memory_use_.PrintMemoryUse(os);
+ histogram_code_memory_use_.PrintMemoryUse(os);
+ histogram_profiling_info_memory_use_.PrintMemoryUse(os);
}
} // namespace jit
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 98dd70d..a54f04f 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -20,6 +20,7 @@
#include "instrumentation.h"
#include "atomic.h"
+#include "base/histogram-inl.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "gc/accounting/bitmap.h"
@@ -109,7 +110,7 @@
bool ContainsMethod(ArtMethod* method) REQUIRES(!lock_);
// Reserve a region of data of size at least "size". Returns null if there is no more room.
- uint8_t* ReserveData(Thread* self, size_t size)
+ uint8_t* ReserveData(Thread* self, size_t size, ArtMethod* method)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!lock_);
@@ -118,12 +119,6 @@
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!lock_);
- // Add a data array of size (end - begin) with the associated contents, returns null if there
- // is no more room.
- uint8_t* AddDataArray(Thread* self, const uint8_t* begin, const uint8_t* end)
- SHARED_REQUIRES(Locks::mutator_lock_)
- REQUIRES(!lock_);
-
CodeCacheBitmap* GetLiveBitmap() const {
return live_bitmap_.get();
}
@@ -332,6 +327,15 @@
// Number of code cache collections done throughout the lifetime of the JIT.
size_t number_of_collections_ GUARDED_BY(lock_);
+ // Histograms for keeping track of stack map size statistics.
+ Histogram<uint64_t> histogram_stack_map_memory_use_ GUARDED_BY(lock_);
+
+ // Histograms for keeping track of code size statistics.
+ Histogram<uint64_t> histogram_code_memory_use_ GUARDED_BY(lock_);
+
+ // Histograms for keeping track of profiling info statistics.
+ Histogram<uint64_t> histogram_profiling_info_memory_use_ GUARDED_BY(lock_);
+
DISALLOW_IMPLICIT_CONSTRUCTORS(JitCodeCache);
};
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index a092b9f..65002df 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -119,7 +119,8 @@
}
if ((debug_flags & DEBUG_NATIVE_DEBUGGABLE) != 0) {
- runtime->AddCompilerOption("--native-debuggable");
+ runtime->AddCompilerOption("--debuggable");
+ runtime->AddCompilerOption("--generate-debug-info");
debug_flags &= ~DEBUG_NATIVE_DEBUGGABLE;
}
diff --git a/runtime/native/java_lang_Runtime.cc b/runtime/native/java_lang_Runtime.cc
deleted file mode 100644
index df794e1..0000000
--- a/runtime/native/java_lang_Runtime.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-#include "java_lang_Runtime.h"
-
-#include <dlfcn.h>
-#include <limits.h>
-#include <unistd.h>
-
-#include "base/macros.h"
-#include "gc/heap.h"
-#include "handle_scope-inl.h"
-#include "jni_internal.h"
-#include "mirror/class_loader.h"
-#include "runtime.h"
-#include "scoped_thread_state_change.h"
-#include "ScopedUtfChars.h"
-#include "verify_object-inl.h"
-
-#include <sstream>
-#ifdef __ANDROID__
-// This function is provided by android linker.
-extern "C" void android_update_LD_LIBRARY_PATH(const char* ld_library_path);
-#endif // __ANDROID__
-
-namespace art {
-
-static void Runtime_gc(JNIEnv*, jclass) {
- if (Runtime::Current()->IsExplicitGcDisabled()) {
- LOG(INFO) << "Explicit GC skipped.";
- return;
- }
- Runtime::Current()->GetHeap()->CollectGarbage(false);
-}
-
-NO_RETURN static void Runtime_nativeExit(JNIEnv*, jclass, jint status) {
- LOG(INFO) << "System.exit called, status: " << status;
- Runtime::Current()->CallExitHook(status);
- exit(status);
-}
-
-static void SetLdLibraryPath(JNIEnv* env, jstring javaLdLibraryPath) {
-#ifdef __ANDROID__
- if (javaLdLibraryPath != nullptr) {
- ScopedUtfChars ldLibraryPath(env, javaLdLibraryPath);
- if (ldLibraryPath.c_str() != nullptr) {
- android_update_LD_LIBRARY_PATH(ldLibraryPath.c_str());
- }
- }
-
-#else
- LOG(WARNING) << "android_update_LD_LIBRARY_PATH not found; .so dependencies will not work!";
- UNUSED(javaLdLibraryPath, env);
-#endif
-}
-
-static jstring Runtime_nativeLoad(JNIEnv* env,
- jclass,
- jstring javaFilename,
- jobject javaLoader,
- jstring javaLibrarySearchPath) {
- ScopedUtfChars filename(env, javaFilename);
- if (filename.c_str() == nullptr) {
- return nullptr;
- }
-
- int32_t target_sdk_version = Runtime::Current()->GetTargetSdkVersion();
-
- // Starting with N nativeLoad uses classloader local
- // linker namespace instead of global LD_LIBRARY_PATH
- // (23 is Marshmallow). This call is here to preserve
- // backwards compatibility for the apps targeting sdk
- // version <= 23
- if (target_sdk_version == 0) {
- SetLdLibraryPath(env, javaLibrarySearchPath);
- }
-
- std::string error_msg;
- {
- JavaVMExt* vm = Runtime::Current()->GetJavaVM();
- bool success = vm->LoadNativeLibrary(env,
- filename.c_str(),
- javaLoader,
- javaLibrarySearchPath,
- &error_msg);
- if (success) {
- return nullptr;
- }
- }
-
- // Don't let a pending exception from JNI_OnLoad cause a CheckJNI issue with NewStringUTF.
- env->ExceptionClear();
- return env->NewStringUTF(error_msg.c_str());
-}
-
-static jlong Runtime_maxMemory(JNIEnv*, jclass) {
- return Runtime::Current()->GetHeap()->GetMaxMemory();
-}
-
-static jlong Runtime_totalMemory(JNIEnv*, jclass) {
- return Runtime::Current()->GetHeap()->GetTotalMemory();
-}
-
-static jlong Runtime_freeMemory(JNIEnv*, jclass) {
- return Runtime::Current()->GetHeap()->GetFreeMemory();
-}
-
-static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Runtime, freeMemory, "!()J"),
- NATIVE_METHOD(Runtime, gc, "()V"),
- NATIVE_METHOD(Runtime, maxMemory, "!()J"),
- NATIVE_METHOD(Runtime, nativeExit, "(I)V"),
- NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String;"),
- NATIVE_METHOD(Runtime, totalMemory, "!()J"),
-};
-
-void register_java_lang_Runtime(JNIEnv* env) {
- REGISTER_NATIVE_METHODS("java/lang/Runtime");
-}
-
-} // namespace art
diff --git a/runtime/openjdkjvm/OpenjdkJvm.cc b/runtime/openjdkjvm/OpenjdkJvm.cc
index d377457..aff9b61 100644
--- a/runtime/openjdkjvm/OpenjdkJvm.cc
+++ b/runtime/openjdkjvm/OpenjdkJvm.cc
@@ -342,15 +342,15 @@
// Starting with N nativeLoad uses classloader local
// linker namespace instead of global LD_LIBRARY_PATH
- // (23 is Marshmallow)
- if (target_sdk_version <= 23) {
+ // (23 is Marshmallow). This call is here to preserve
+ // backwards compatibility for the apps targeting sdk
+ // version <= 23
+ if (target_sdk_version == 0) {
SetLdLibraryPath(env, javaLibrarySearchPath);
}
std::string error_msg;
{
- art::ScopedObjectAccess soa(env);
- art::StackHandleScope<1> hs(soa.Self());
art::JavaVMExt* vm = art::Runtime::Current()->GetJavaVM();
bool success = vm->LoadNativeLibrary(env,
filename.c_str(),
diff --git a/runtime/primitive.h b/runtime/primitive.h
index 2454a21..9c19ad5 100644
--- a/runtime/primitive.h
+++ b/runtime/primitive.h
@@ -166,6 +166,20 @@
return type == kPrimLong || type == kPrimDouble;
}
+ // Return the general kind of `type`, fusing integer-like types as kPrimInt.
+ static Type PrimitiveKind(Type type) {
+ switch (type) {
+ case kPrimBoolean:
+ case kPrimByte:
+ case kPrimShort:
+ case kPrimChar:
+ case kPrimInt:
+ return kPrimInt;
+ default:
+ return type;
+ }
+ }
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive);
};
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 66a3828..364ae5d 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -94,7 +94,6 @@
#include "native/java_lang_Class.h"
#include "native/java_lang_DexCache.h"
#include "native/java_lang_Object.h"
-#include "native/java_lang_Runtime.h"
#include "native/java_lang_String.h"
#include "native/java_lang_StringFactory.h"
#include "native/java_lang_System.h"
@@ -1341,7 +1340,6 @@
register_java_lang_reflect_Method(env);
register_java_lang_reflect_Proxy(env);
register_java_lang_ref_Reference(env);
- register_java_lang_Runtime(env);
register_java_lang_String(env);
register_java_lang_StringFactory(env);
register_java_lang_System(env);
diff --git a/test/003-omnibus-opcodes/src/FloatMath.java b/test/003-omnibus-opcodes/src/FloatMath.java
index 96befe9..fcdb4fe 100644
--- a/test/003-omnibus-opcodes/src/FloatMath.java
+++ b/test/003-omnibus-opcodes/src/FloatMath.java
@@ -135,7 +135,8 @@
static float[] floatOperTest(float x, float y) {
System.out.println("FloatMath.floatOperTest");
- float[] results = new float[9];
+ float[] results = new float[10];
+ float tmp;
/* this seems to generate "op-float" instructions */
results[0] = x + y;
@@ -145,7 +146,21 @@
results[4] = x % -y;
/* this seems to generate "op-float/2addr" instructions */
- results[8] = x + (((((x + y) - y) * y) / y) % y);
+ tmp = x;
+ tmp += y;
+ results[5] = tmp;
+ tmp = x;
+ tmp -= y;
+ results[6] = tmp;
+ tmp = x;
+ tmp *= y;
+ results[7] = tmp;
+ tmp = x;
+ tmp /= y;
+ results[8] = tmp;
+ tmp = x;
+ tmp %= -y;
+ results[9] = tmp;
return results;
}
@@ -155,7 +170,11 @@
Main.assertTrue(results[2] > -210000.01f && results[2] < -209999.99f);
Main.assertTrue(results[3] > -23333.34f && results[3] < -23333.32f);
Main.assertTrue(results[4] > 0.999f && results[4] < 1.001f);
- Main.assertTrue(results[8] > 70000.99f && results[8] < 70001.01f);
+ Main.assertTrue(results[5] > 69996.99f && results[5] < 69997.01f);
+ Main.assertTrue(results[6] > 70002.99f && results[6] < 70003.01f);
+ Main.assertTrue(results[7] > -210000.01f && results[7] < -209999.99f);
+ Main.assertTrue(results[8] > -23333.34f && results[8] < -23333.32f);
+ Main.assertTrue(results[9] > 0.999f && results[9] < 1.001f);
}
/*
@@ -165,7 +184,8 @@
static double[] doubleOperTest(double x, double y) {
System.out.println("FloatMath.doubleOperTest");
- double[] results = new double[9];
+ double[] results = new double[10];
+ double tmp;
/* this seems to generate "op-double" instructions */
results[0] = x + y;
@@ -175,7 +195,21 @@
results[4] = x % -y;
/* this seems to generate "op-double/2addr" instructions */
- results[8] = x + (((((x + y) - y) * y) / y) % y);
+ tmp = x;
+ tmp += y;
+ results[5] = tmp;
+ tmp = x;
+ tmp -= y;
+ results[6] = tmp;
+ tmp = x;
+ tmp *= y;
+ results[7] = tmp;
+ tmp = x;
+ tmp /= y;
+ results[8] = tmp;
+ tmp = x;
+ tmp %= -y;
+ results[9] = tmp;
return results;
}
@@ -185,7 +219,11 @@
Main.assertTrue(results[2] > -210000.01 && results[2] < -209999.99);
Main.assertTrue(results[3] > -23333.34 && results[3] < -23333.32);
Main.assertTrue(results[4] > 0.999 && results[4] < 1.001);
- Main.assertTrue(results[8] > 70000.99 && results[8] < 70001.01);
+ Main.assertTrue(results[5] > 69996.99 && results[5] < 69997.01);
+ Main.assertTrue(results[6] > 70002.99 && results[6] < 70003.01);
+ Main.assertTrue(results[7] > -210000.01 && results[7] < -209999.99);
+ Main.assertTrue(results[8] > -23333.34 && results[8] < -23333.32);
+ Main.assertTrue(results[9] > 0.999 && results[9] < 1.001);
}
/*
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index f7c721a..53c2e0b 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -414,6 +414,23 @@
return arg >> 0;
}
+ /// CHECK-START: long Main.Shr64(long) instruction_simplifier (before)
+ /// CHECK-DAG: <<Arg:j\d+>> ParameterValue
+ /// CHECK-DAG: <<Const64:i\d+>> IntConstant 64
+ /// CHECK-DAG: <<Shr:j\d+>> Shr [<<Arg>>,<<Const64>>]
+ /// CHECK-DAG: Return [<<Shr>>]
+
+ /// CHECK-START: long Main.Shr64(long) instruction_simplifier (after)
+ /// CHECK-DAG: <<Arg:j\d+>> ParameterValue
+ /// CHECK-DAG: Return [<<Arg>>]
+
+ /// CHECK-START: long Main.Shr64(long) instruction_simplifier (after)
+ /// CHECK-NOT: Shr
+
+ public static long Shr64(long arg) {
+ return arg >> 64;
+ }
+
/// CHECK-START: long Main.Sub0(long) instruction_simplifier (before)
/// CHECK-DAG: <<Arg:j\d+>> ParameterValue
/// CHECK-DAG: <<Const0:j\d+>> LongConstant 0
@@ -1671,6 +1688,7 @@
assertLongEquals(OrSame(arg), arg);
assertIntEquals(Shl0(arg), arg);
assertLongEquals(Shr0(arg), arg);
+ assertLongEquals(Shr64(arg), arg);
assertLongEquals(Sub0(arg), arg);
assertIntEquals(SubAliasNeg(arg), -arg);
assertLongEquals(UShr0(arg), arg);
diff --git a/test/529-checker-unresolved/build b/test/529-checker-unresolved/build
deleted file mode 100644
index d85035b..0000000
--- a/test/529-checker-unresolved/build
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/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
-
-# We can't use src-ex testing infrastructure because src and src-ex are compiled
-# with javac independetely and can't share code (without reflection).
-
-mkdir classes
-${JAVAC} -d classes `find src -name '*.java'`
-
-mkdir classes-ex
-mv classes/UnresolvedClass.class classes-ex
-mv classes/UnresolvedInterface.class classes-ex
-mv classes/UnresolvedSuperClass.class classes-ex
-
-if [ ${USE_JACK} = "true" ]; then
- jar cf classes.jill.jar -C classes .
- jar cf classes-ex.jill.jar -C classes-ex .
-
- ${JACK} --import classes.jill.jar --output-dex .
- zip $TEST_NAME.jar classes.dex
- ${JACK} --import classes-ex.jill.jar --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/529-checker-unresolved/src/Unresolved.java b/test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedClass.java
similarity index 83%
rename from test/529-checker-unresolved/src/Unresolved.java
rename to test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedClass.java
index 20ac6e0..8b3bb3c 100644
--- a/test/529-checker-unresolved/src/Unresolved.java
+++ b/test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedClass.java
@@ -14,17 +14,7 @@
* limitations under the License.
*/
-interface UnresolvedInterface {
- void interfaceMethod();
-}
-
-class UnresolvedSuperClass {
- public void superMethod() {
- System.out.println("UnresolvedClass.superMethod()");
- }
-}
-
-class UnresolvedClass extends UnresolvedSuperClass implements UnresolvedInterface {
+public class UnresolvedClass extends UnresolvedSuperClass implements UnresolvedInterface {
static public void staticMethod() {
System.out.println("UnresolvedClass.staticMethod()");
}
diff --git a/runtime/native/java_lang_Runtime.h b/test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedInterface.java
similarity index 64%
rename from runtime/native/java_lang_Runtime.h
rename to test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedInterface.java
index ceda06b..6e6b14b 100644
--- a/runtime/native/java_lang_Runtime.h
+++ b/test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedInterface.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,15 +14,6 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
-#define ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
-
-#include <jni.h>
-
-namespace art {
-
-void register_java_lang_Runtime(JNIEnv* env);
-
-} // namespace art
-
-#endif // ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
+public interface UnresolvedInterface {
+ void interfaceMethod();
+}
diff --git a/runtime/native/java_lang_Runtime.h b/test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedSuperClass.java
similarity index 64%
copy from runtime/native/java_lang_Runtime.h
copy to test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedSuperClass.java
index ceda06b..dd3be00 100644
--- a/runtime/native/java_lang_Runtime.h
+++ b/test/529-checker-unresolved/src-dex2oat-unresolved/UnresolvedSuperClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,15 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
-#define ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
-
-#include <jni.h>
-
-namespace art {
-
-void register_java_lang_Runtime(JNIEnv* env);
-
-} // namespace art
-
-#endif // ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
+public class UnresolvedSuperClass {
+ public void superMethod() {
+ System.out.println("UnresolvedClass.superMethod()");
+ }
+}
diff --git a/test/551-checker-shifter-operand/src/Main.java b/test/551-checker-shifter-operand/src/Main.java
index 9c86154..edb8a68 100644
--- a/test/551-checker-shifter-operand/src/Main.java
+++ b/test/551-checker-shifter-operand/src/Main.java
@@ -483,9 +483,7 @@
/// CHECK: Arm64DataProcWithShifterOp
/// CHECK: Arm64DataProcWithShifterOp
/// CHECK: Arm64DataProcWithShifterOp
- /// CHECK: Arm64DataProcWithShifterOp
- /// CHECK: Arm64DataProcWithShifterOp
- /// CHECK: Arm64DataProcWithShifterOp
+ // Note: `b << 32`, `b >> 32` and `b >>> 32` are optimized away by generic simplifier.
/// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after)
/// CHECK-NOT: Shl
diff --git a/test/566-checker-signum/src/Main.java b/test/566-checker-signum/src/Main.java
index 0ad0042..5f2cf3d 100644
--- a/test/566-checker-signum/src/Main.java
+++ b/test/566-checker-signum/src/Main.java
@@ -16,65 +16,213 @@
public class Main {
- /// CHECK-START: int Main.sign32(int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
- /// CHECK-DAG: Return [<<Result>>]
- private static int sign32(int x) {
+ /// CHECK-START: int Main.signBoolean(boolean) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<One:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<One>>,<<Zero>>]
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Phi>>,<<Method>>] intrinsic:IntegerSignum
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signBoolean(boolean) instruction_simplifier (after)
+ /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<One:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<One>>,<<Zero>>]
+ /// CHECK-DAG: <<Result:i\d+>> Compare [<<Phi>>,<<Zero>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signBoolean(boolean) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START: int Main.signBoolean(boolean) select_generator (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<One:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Sel:i\d+>> Select [<<Zero>>,<<One>>,<<Arg>>]
+ /// CHECK-DAG: <<Result:i\d+>> Compare [<<Sel>>,<<Zero>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signBoolean(boolean) select_generator (after)
+ /// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.signBoolean(boolean) instruction_simplifier_after_bce (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Result:i\d+>> Compare [<<Arg>>,<<Zero>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signBoolean(boolean) instruction_simplifier_after_bce (after)
+ /// CHECK-NOT: Select
+
+ private static int signBoolean(boolean x) {
+ return Integer.signum(x ? 1 : 0);
+ }
+
+ /// CHECK-START: int Main.signByte(byte) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signByte(byte) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signByte(byte) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int signByte(byte x) {
return Integer.signum(x);
}
- /// CHECK-START: int Main.sign64(long) intrinsics_recognition (after)
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongSignum
- /// CHECK-DAG: Return [<<Result>>]
- private static int sign64(long x) {
+ /// CHECK-START: int Main.signShort(short) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signShort(short) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signShort(short) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int signShort(short x) {
+ return Integer.signum(x);
+ }
+
+ /// CHECK-START: int Main.signChar(char) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signChar(char) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signChar(char) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int signChar(char x) {
+ return Integer.signum(x);
+ }
+
+ /// CHECK-START: int Main.signInt(int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signInt(int) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signInt(int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int signInt(int x) {
+ return Integer.signum(x);
+ }
+
+ /// CHECK-START: int Main.signLong(long) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongSignum
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signLong(long) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.signLong(long) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int signLong(long x) {
return Long.signum(x);
}
- public static void main(String args[]) {
- expectEquals(-1, sign32(Integer.MIN_VALUE));
- expectEquals(-1, sign32(-12345));
- expectEquals(-1, sign32(-1));
- expectEquals(0, sign32(0));
- expectEquals(1, sign32(1));
- expectEquals(1, sign32(12345));
- expectEquals(1, sign32(Integer.MAX_VALUE));
+
+ public static void testSignBoolean() {
+ expectEquals(0, signBoolean(false));
+ expectEquals(1, signBoolean(true));
+ }
+
+ public static void testSignByte() {
+ expectEquals(-1, signByte((byte)Byte.MIN_VALUE));
+ expectEquals(-1, signByte((byte)-64));
+ expectEquals(-1, signByte((byte)-1));
+ expectEquals(0, signByte((byte)0));
+ expectEquals(1, signByte((byte)1));
+ expectEquals(1, signByte((byte)64));
+ expectEquals(1, signByte((byte)Byte.MAX_VALUE));
+ }
+
+ public static void testSignShort() {
+ expectEquals(-1, signShort((short)Short.MIN_VALUE));
+ expectEquals(-1, signShort((short)-12345));
+ expectEquals(-1, signShort((short)-1));
+ expectEquals(0, signShort((short)0));
+ expectEquals(1, signShort((short)1));
+ expectEquals(1, signShort((short)12345));
+ expectEquals(1, signShort((short)Short.MAX_VALUE));
+ }
+
+ public static void testSignChar() {
+ expectEquals(0, signChar((char)0));
+ expectEquals(1, signChar((char)1));
+ expectEquals(1, signChar((char)12345));
+ expectEquals(1, signChar((char)Character.MAX_VALUE));
+ }
+
+ public static void testSignInt() {
+ expectEquals(-1, signInt(Integer.MIN_VALUE));
+ expectEquals(-1, signInt(-12345));
+ expectEquals(-1, signInt(-1));
+ expectEquals(0, signInt(0));
+ expectEquals(1, signInt(1));
+ expectEquals(1, signInt(12345));
+ expectEquals(1, signInt(Integer.MAX_VALUE));
for (int i = -11; i <= 11; i++) {
int expected = 0;
if (i < 0) expected = -1;
else if (i > 0) expected = 1;
- expectEquals(expected, sign32(i));
+ expectEquals(expected, signInt(i));
}
+ }
- expectEquals(-1, sign64(Long.MIN_VALUE));
- expectEquals(-1, sign64(-12345L));
- expectEquals(-1, sign64(-1L));
- expectEquals(0, sign64(0L));
- expectEquals(1, sign64(1L));
- expectEquals(1, sign64(12345L));
- expectEquals(1, sign64(Long.MAX_VALUE));
+ public static void testSignLong() {
+ expectEquals(-1, signLong(Long.MIN_VALUE));
+ expectEquals(-1, signLong(-12345L));
+ expectEquals(-1, signLong(-1L));
+ expectEquals(0, signLong(0L));
+ expectEquals(1, signLong(1L));
+ expectEquals(1, signLong(12345L));
+ expectEquals(1, signLong(Long.MAX_VALUE));
- expectEquals(-1, sign64(0x800000007FFFFFFFL));
- expectEquals(-1, sign64(0x80000000FFFFFFFFL));
- expectEquals(1, sign64(0x000000007FFFFFFFL));
- expectEquals(1, sign64(0x00000000FFFFFFFFL));
- expectEquals(1, sign64(0x7FFFFFFF7FFFFFFFL));
- expectEquals(1, sign64(0x7FFFFFFFFFFFFFFFL));
+ expectEquals(-1, signLong(0x800000007FFFFFFFL));
+ expectEquals(-1, signLong(0x80000000FFFFFFFFL));
+ expectEquals(1, signLong(0x000000007FFFFFFFL));
+ expectEquals(1, signLong(0x00000000FFFFFFFFL));
+ expectEquals(1, signLong(0x7FFFFFFF7FFFFFFFL));
+ expectEquals(1, signLong(0x7FFFFFFFFFFFFFFFL));
for (long i = -11L; i <= 11L; i++) {
int expected = 0;
if (i < 0) expected = -1;
else if (i > 0) expected = 1;
- expectEquals(expected, sign64(i));
+ expectEquals(expected, signLong(i));
}
for (long i = Long.MIN_VALUE; i <= Long.MIN_VALUE + 11L; i++) {
- expectEquals(-1, sign64(i));
+ expectEquals(-1, signLong(i));
}
for (long i = Long.MAX_VALUE; i >= Long.MAX_VALUE - 11L; i--) {
- expectEquals(1, sign64(i));
+ expectEquals(1, signLong(i));
}
+ }
+
+
+ public static void main(String args[]) {
+ testSignBoolean();
+ testSignByte();
+ testSignShort();
+ testSignChar();
+ testSignInt();
+ testSignLong();
System.out.println("passed");
}
diff --git a/test/567-checker-compare/src/Main.java b/test/567-checker-compare/src/Main.java
index 951d2c7..f95ff1a 100644
--- a/test/567-checker-compare/src/Main.java
+++ b/test/567-checker-compare/src/Main.java
@@ -16,98 +16,902 @@
public class Main {
- /// CHECK-START: int Main.compare32(int, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
- /// CHECK-DAG: Return [<<Result>>]
- private static int compare32(int x, int y) {
+ /// CHECK-START: int Main.compareBooleans(boolean, boolean) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<One:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<PhiX:i\d+>> Phi [<<One>>,<<Zero>>]
+ /// CHECK-DAG: <<PhiY:i\d+>> Phi [<<One>>,<<Zero>>]
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<PhiX>>,<<PhiY>>,<<Method>>] intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareBooleans(boolean, boolean) instruction_simplifier (after)
+ /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<One:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<PhiX:i\d+>> Phi [<<One>>,<<Zero>>]
+ /// CHECK-DAG: <<PhiY:i\d+>> Phi [<<One>>,<<Zero>>]
+ /// CHECK-DAG: <<Result:i\d+>> Compare [<<PhiX>>,<<PhiY>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareBooleans(boolean, boolean) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START: int Main.compareBooleans(boolean, boolean) select_generator (after)
+ /// CHECK: <<ArgX:z\d+>> ParameterValue
+ /// CHECK: <<ArgY:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<One:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<SelX:i\d+>> Select [<<Zero>>,<<One>>,<<ArgX>>]
+ /// CHECK-DAG: <<SelY:i\d+>> Select [<<Zero>>,<<One>>,<<ArgY>>]
+ /// CHECK-DAG: <<Result:i\d+>> Compare [<<SelX>>,<<SelY>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareBooleans(boolean, boolean) select_generator (after)
+ /// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.compareBooleans(boolean, boolean) instruction_simplifier_after_bce (after)
+ /// CHECK: <<ArgX:z\d+>> ParameterValue
+ /// CHECK: <<ArgY:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> Compare [<<ArgX>>,<<ArgY>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareBooleans(boolean, boolean) instruction_simplifier_after_bce (after)
+ /// CHECK-NOT: Select
+
+ private static int compareBooleans(boolean x, boolean y) {
+ return Integer.compare((x ? 1 : 0), (y ? 1 : 0));
+ }
+
+ /// CHECK-START: int Main.compareBytes(byte, byte) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareBytes(byte, byte) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareBytes(byte, byte) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int compareBytes(byte x, byte y) {
return Integer.compare(x, y);
}
- /// CHECK-START: int Main.compare64(long, long) intrinsics_recognition (after)
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongCompare
- /// CHECK-DAG: Return [<<Result>>]
- private static int compare64(long x, long y) {
+ /// CHECK-START: int Main.compareShorts(short, short) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareShorts(short, short) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareShorts(short, short) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int compareShorts(short x, short y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareChars(char, char) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareChars(char, char) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareChars(char, char) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int compareChars(char x, char y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareInts(int, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareInts(int, int) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareInts(int, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int compareInts(int x, int y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareLongs(long, long) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareLongs(long, long) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareLongs(long, long) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int compareLongs(long x, long y) {
return Long.compare(x, y);
}
- public static void main(String args[]) {
- expectEquals(-1, compare32(Integer.MIN_VALUE, Integer.MIN_VALUE + 1));
- expectEquals(-1, compare32(Integer.MIN_VALUE, -1));
- expectEquals(-1, compare32(Integer.MIN_VALUE, 0));
- expectEquals(-1, compare32(Integer.MIN_VALUE, 1));
- expectEquals(-1, compare32(Integer.MIN_VALUE, Integer.MAX_VALUE));
- expectEquals(-1, compare32(-1, 0));
- expectEquals(-1, compare32(-1, 1));
- expectEquals(-1, compare32(0, 1));
- expectEquals(0, compare32(Integer.MIN_VALUE, Integer.MIN_VALUE));
- expectEquals(0, compare32(-1, -1));
- expectEquals(0, compare32(0, 0));
- expectEquals(0, compare32(1, 1));
- expectEquals(0, compare32(Integer.MAX_VALUE, Integer.MAX_VALUE));
+ /// CHECK-START: int Main.compareByteShort(byte, short) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
- expectEquals(1, compare32(0, -1));
- expectEquals(1, compare32(1, -1));
- expectEquals(1, compare32(1, 0));
- expectEquals(1, compare32(Integer.MAX_VALUE, Integer.MIN_VALUE));
- expectEquals(1, compare32(Integer.MAX_VALUE, -1));
- expectEquals(1, compare32(Integer.MAX_VALUE, 0));
- expectEquals(1, compare32(Integer.MAX_VALUE, 1));
- expectEquals(1, compare32(Integer.MAX_VALUE, Integer.MAX_VALUE - 1));
+ /// CHECK-START: int Main.compareByteShort(byte, short) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareByteShort(byte, short) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareByteShort(byte x, short y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareByteChar(byte, char) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareByteChar(byte, char) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareByteChar(byte, char) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareByteChar(byte x, char y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareByteInt(byte, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareByteInt(byte, int) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareByteInt(byte, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareByteInt(byte x, int y) {
+ return Integer.compare(x, y);
+ }
+
+
+ /// CHECK-START: int Main.compareShortByte(short, byte) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareShortByte(short, byte) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareShortByte(short, byte) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareShortByte(short x, byte y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareShortChar(short, char) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareShortChar(short, char) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareShortChar(short, char) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareShortChar(short x, char y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareShortInt(short, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareShortInt(short, int) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareShortInt(short, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareShortInt(short x, int y) {
+ return Integer.compare(x, y);
+ }
+
+
+ /// CHECK-START: int Main.compareCharByte(char, byte) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareCharByte(char, byte) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareCharByte(char, byte) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareCharByte(char x, byte y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareCharShort(char, short) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareCharShort(char, short) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareCharShort(char, short) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareCharShort(char x, short y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareCharInt(char, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareCharInt(char, int) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareCharInt(char, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareCharInt(char x, int y) {
+ return Integer.compare(x, y);
+ }
+
+
+ /// CHECK-START: int Main.compareIntByte(int, byte) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareIntByte(int, byte) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareIntByte(int, byte) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareIntByte(int x, byte y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareIntShort(int, short) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareIntShort(int, short) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareIntShort(int, short) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareIntShort(int x, short y) {
+ return Integer.compare(x, y);
+ }
+
+ /// CHECK-START: int Main.compareIntChar(int, char) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareIntChar(int, char) instruction_simplifier (after)
+ /// CHECK-DAG: <<Result:i\d+>> Compare
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.compareIntChar(int, char) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ public static int compareIntChar(int x, char y) {
+ return Integer.compare(x, y);
+ }
+
+
+ public static void testCompareBooleans() {
+ expectEquals(-1, compareBooleans(false, true));
+
+ expectEquals(0, compareBooleans(false, false));
+ expectEquals(0, compareBooleans(true, true));
+
+ expectEquals(1, compareBooleans(true, false));
+ }
+
+ public static void testCompareBytes() {
+ expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
+ expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)-1));
+ expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)0));
+ expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)1));
+ expectEquals(-1, compareBytes(Byte.MIN_VALUE, Byte.MAX_VALUE));
+ expectEquals(-1, compareBytes((byte)-1, (byte)0));
+ expectEquals(-1, compareBytes((byte)-1, (byte)1));
+ expectEquals(-1, compareBytes((byte)0, (byte)1));
+
+ expectEquals(0, compareBytes(Byte.MIN_VALUE, Byte.MIN_VALUE));
+ expectEquals(0, compareBytes((byte)-1, (byte)-1));
+ expectEquals(0, compareBytes((byte)0, (byte)0));
+ expectEquals(0, compareBytes((byte)1, (byte)1));
+ expectEquals(0, compareBytes(Byte.MAX_VALUE, Byte.MAX_VALUE));
+
+ expectEquals(1, compareBytes((byte)0, (byte)-1));
+ expectEquals(1, compareBytes((byte)1, (byte)-1));
+ expectEquals(1, compareBytes((byte)1, (byte)0));
+ expectEquals(1, compareBytes(Byte.MAX_VALUE, Byte.MIN_VALUE));
+ expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)-1));
+ expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)0));
+ expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)1));
+ expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
+
+ for (byte i = -11; i <= 11; i++) {
+ for (byte j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareBytes(i, j));
+ }
+ }
+ }
+
+ public static void testCompareShorts() {
+ expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
+ expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)-1));
+ expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)0));
+ expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)1));
+ expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)Short.MAX_VALUE));
+ expectEquals(-1, compareShorts((short)-1, (short)0));
+ expectEquals(-1, compareShorts((short)-1, (short)1));
+ expectEquals(-1, compareShorts((short)0, (short)1));
+
+ expectEquals(0, compareShorts(Short.MIN_VALUE, Short.MIN_VALUE));
+ expectEquals(0, compareShorts((short)-1, (short)-1));
+ expectEquals(0, compareShorts((short)0, (short)0));
+ expectEquals(0, compareShorts((short)1, (short)1));
+ expectEquals(0, compareShorts(Short.MAX_VALUE, Short.MAX_VALUE));
+
+ expectEquals(1, compareShorts((short)0, (short)-1));
+ expectEquals(1, compareShorts((short)1, (short)-1));
+ expectEquals(1, compareShorts((short)1, (short)0));
+ expectEquals(1, compareShorts(Short.MAX_VALUE, Short.MIN_VALUE));
+ expectEquals(1, compareShorts(Short.MAX_VALUE, (short)-1));
+ expectEquals(1, compareShorts(Short.MAX_VALUE, (short)0));
+ expectEquals(1, compareShorts(Short.MAX_VALUE, (short)1));
+ expectEquals(1, compareShorts(Short.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
+
+ for (short i = -11; i <= 11; i++) {
+ for (short j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareShorts(i, j));
+ }
+ }
+ }
+
+ public static void testCompareChars() {
+ expectEquals(-1, compareChars((char)0, Character.MAX_VALUE));
+ expectEquals(-1, compareChars((char)0, (char)1));
+
+ expectEquals(0, compareChars((char)0, (char)0));
+ expectEquals(0, compareChars((char)1, (char)1));
+ expectEquals(0, compareChars(Character.MAX_VALUE, Character.MAX_VALUE));
+
+ expectEquals(1, compareChars((char)1, (char)0));
+ expectEquals(1, compareChars(Character.MAX_VALUE, (char)0));
+ expectEquals(1, compareChars(Character.MAX_VALUE, (char)1));
+ expectEquals(1, compareChars(Character.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
+
+ for (char i = 0; i <= 11; i++) {
+ for (char j = 0; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareChars(i, j));
+ }
+ }
+ }
+
+ public static void testCompareInts() {
+ expectEquals(-1, compareInts(Integer.MIN_VALUE, Integer.MIN_VALUE + 1));
+ expectEquals(-1, compareInts(Integer.MIN_VALUE, -1));
+ expectEquals(-1, compareInts(Integer.MIN_VALUE, 0));
+ expectEquals(-1, compareInts(Integer.MIN_VALUE, 1));
+ expectEquals(-1, compareInts(Integer.MIN_VALUE, Integer.MAX_VALUE));
+ expectEquals(-1, compareInts(-1, 0));
+ expectEquals(-1, compareInts(-1, 1));
+ expectEquals(-1, compareInts(0, 1));
+
+ expectEquals(0, compareInts(Integer.MIN_VALUE, Integer.MIN_VALUE));
+ expectEquals(0, compareInts(-1, -1));
+ expectEquals(0, compareInts(0, 0));
+ expectEquals(0, compareInts(1, 1));
+ expectEquals(0, compareInts(Integer.MAX_VALUE, Integer.MAX_VALUE));
+
+ expectEquals(1, compareInts(0, -1));
+ expectEquals(1, compareInts(1, -1));
+ expectEquals(1, compareInts(1, 0));
+ expectEquals(1, compareInts(Integer.MAX_VALUE, Integer.MIN_VALUE));
+ expectEquals(1, compareInts(Integer.MAX_VALUE, -1));
+ expectEquals(1, compareInts(Integer.MAX_VALUE, 0));
+ expectEquals(1, compareInts(Integer.MAX_VALUE, 1));
+ expectEquals(1, compareInts(Integer.MAX_VALUE, Integer.MAX_VALUE - 1));
for (int i = -11; i <= 11; i++) {
for (int j = -11; j <= 11; j++) {
int expected = 0;
if (i < j) expected = -1;
else if (i > j) expected = 1;
- expectEquals(expected, compare32(i, j));
+ expectEquals(expected, compareInts(i, j));
}
}
+ }
- expectEquals(-1, compare64(Long.MIN_VALUE, Long.MIN_VALUE + 1L));
- expectEquals(-1, compare64(Long.MIN_VALUE, -1L));
- expectEquals(-1, compare64(Long.MIN_VALUE, 0L));
- expectEquals(-1, compare64(Long.MIN_VALUE, 1L));
- expectEquals(-1, compare64(Long.MIN_VALUE, Long.MAX_VALUE));
- expectEquals(-1, compare64(-1L, 0L));
- expectEquals(-1, compare64(-1L, 1L));
- expectEquals(-1, compare64(0L, 1L));
+ public static void testCompareLongs() {
+ expectEquals(-1, compareLongs(Long.MIN_VALUE, Long.MIN_VALUE + 1L));
+ expectEquals(-1, compareLongs(Long.MIN_VALUE, -1L));
+ expectEquals(-1, compareLongs(Long.MIN_VALUE, 0L));
+ expectEquals(-1, compareLongs(Long.MIN_VALUE, 1L));
+ expectEquals(-1, compareLongs(Long.MIN_VALUE, Long.MAX_VALUE));
+ expectEquals(-1, compareLongs(-1L, 0L));
+ expectEquals(-1, compareLongs(-1L, 1L));
+ expectEquals(-1, compareLongs(0L, 1L));
- expectEquals(0, compare64(Long.MIN_VALUE, Long.MIN_VALUE));
- expectEquals(0, compare64(-1L, -1L));
- expectEquals(0, compare64(0L, 0L));
- expectEquals(0, compare64(1L, 1L));
- expectEquals(0, compare64(Long.MAX_VALUE, Long.MAX_VALUE));
+ expectEquals(0, compareLongs(Long.MIN_VALUE, Long.MIN_VALUE));
+ expectEquals(0, compareLongs(-1L, -1L));
+ expectEquals(0, compareLongs(0L, 0L));
+ expectEquals(0, compareLongs(1L, 1L));
+ expectEquals(0, compareLongs(Long.MAX_VALUE, Long.MAX_VALUE));
- expectEquals(1, compare64(0L, -1L));
- expectEquals(1, compare64(1L, -1L));
- expectEquals(1, compare64(1L, 0L));
- expectEquals(1, compare64(Long.MAX_VALUE, Long.MIN_VALUE));
- expectEquals(1, compare64(Long.MAX_VALUE, -1L));
- expectEquals(1, compare64(Long.MAX_VALUE, 0L));
- expectEquals(1, compare64(Long.MAX_VALUE, 1L));
- expectEquals(1, compare64(Long.MAX_VALUE, Long.MAX_VALUE - 1L));
+ expectEquals(1, compareLongs(0L, -1L));
+ expectEquals(1, compareLongs(1L, -1L));
+ expectEquals(1, compareLongs(1L, 0L));
+ expectEquals(1, compareLongs(Long.MAX_VALUE, Long.MIN_VALUE));
+ expectEquals(1, compareLongs(Long.MAX_VALUE, -1L));
+ expectEquals(1, compareLongs(Long.MAX_VALUE, 0L));
+ expectEquals(1, compareLongs(Long.MAX_VALUE, 1L));
+ expectEquals(1, compareLongs(Long.MAX_VALUE, Long.MAX_VALUE - 1L));
- expectEquals(-1, compare64(0x111111117FFFFFFFL, 0x11111111FFFFFFFFL));
- expectEquals(0, compare64(0x111111117FFFFFFFL, 0x111111117FFFFFFFL));
- expectEquals(1, compare64(0x11111111FFFFFFFFL, 0x111111117FFFFFFFL));
+ expectEquals(-1, compareLongs(0x111111117FFFFFFFL, 0x11111111FFFFFFFFL));
+ expectEquals(0, compareLongs(0x111111117FFFFFFFL, 0x111111117FFFFFFFL));
+ expectEquals(1, compareLongs(0x11111111FFFFFFFFL, 0x111111117FFFFFFFL));
for (long i = -11L; i <= 11L; i++) {
for (long j = -11L; j <= 11L; j++) {
int expected = 0;
if (i < j) expected = -1;
else if (i > j) expected = 1;
- expectEquals(expected, compare64(i, j));
+ expectEquals(expected, compareLongs(i, j));
}
}
for (long i = Long.MIN_VALUE; i <= Long.MIN_VALUE + 11L; i++) {
- expectEquals(-1, compare64(i, 0));
+ expectEquals(-1, compareLongs(i, 0));
}
for (long i = Long.MAX_VALUE; i >= Long.MAX_VALUE - 11L; i--) {
- expectEquals(1, compare64(i, 0));
+ expectEquals(1, compareLongs(i, 0));
}
+ }
+
+
+ public static void testCompareByteShort() {
+ expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)-1));
+ expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)0));
+ expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)1));
+ expectEquals(-1, compareByteShort(Byte.MIN_VALUE, Short.MAX_VALUE));
+ expectEquals(-1, compareByteShort((byte)-1, (short)0));
+ expectEquals(-1, compareByteShort((byte)-1, (short)1));
+ expectEquals(-1, compareByteShort((byte)0, (short)1));
+ expectEquals(-1, compareByteShort(Byte.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
+ expectEquals(-1, compareByteShort(Byte.MAX_VALUE, Short.MAX_VALUE));
+
+ expectEquals(0, compareByteShort((byte)-1, (short)-1));
+ expectEquals(0, compareByteShort((byte)0, (short)0));
+ expectEquals(0, compareByteShort((byte)1, (short)1));
+
+ expectEquals(1, compareByteShort(Byte.MIN_VALUE, Short.MIN_VALUE));
+ expectEquals(1, compareByteShort(Byte.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
+ expectEquals(1, compareByteShort((byte)0, (short)-1));
+ expectEquals(1, compareByteShort((byte)1, (short)-1));
+ expectEquals(1, compareByteShort((byte)1, (short)0));
+ expectEquals(1, compareByteShort(Byte.MAX_VALUE, Short.MIN_VALUE));
+ expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)-1));
+ expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)0));
+ expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)1));
+
+ for (byte i = -11; i <= 11; i++) {
+ for (short j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareByteShort(i, j));
+ }
+ }
+ }
+
+ public static void testCompareByteChar() {
+ expectEquals(-1, compareByteChar(Byte.MIN_VALUE, (char)0));
+ expectEquals(-1, compareByteChar(Byte.MIN_VALUE, (char)1));
+ expectEquals(-1, compareByteChar(Byte.MIN_VALUE, Character.MAX_VALUE));
+ expectEquals(-1, compareByteChar((byte)-1, (char)0));
+ expectEquals(-1, compareByteChar((byte)-1, (char)1));
+ expectEquals(-1, compareByteChar((byte)0, (char)1));
+ expectEquals(-1, compareByteChar(Byte.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
+ expectEquals(-1, compareByteChar(Byte.MAX_VALUE, Character.MAX_VALUE));
+
+ expectEquals(0, compareByteChar((byte)0, (char)0));
+ expectEquals(0, compareByteChar((byte)1, (char)1));
+
+ expectEquals(1, compareByteChar((byte)1, (char)0));
+ expectEquals(1, compareByteChar(Byte.MAX_VALUE, (char)0));
+ expectEquals(1, compareByteChar(Byte.MAX_VALUE, (char)1));
+
+ for (byte i = -11; i <= 11; i++) {
+ for (char j = 0; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareByteChar(i, j));
+ }
+ }
+ }
+
+ public static void testCompareByteInt() {
+ expectEquals(-1, compareByteInt(Byte.MIN_VALUE, -1));
+ expectEquals(-1, compareByteInt(Byte.MIN_VALUE, 0));
+ expectEquals(-1, compareByteInt(Byte.MIN_VALUE, 1));
+ expectEquals(-1, compareByteInt(Byte.MIN_VALUE, Integer.MAX_VALUE));
+ expectEquals(-1, compareByteInt((byte)-1, 0));
+ expectEquals(-1, compareByteInt((byte)-1, 1));
+ expectEquals(-1, compareByteInt((byte)0, 1));
+ expectEquals(-1, compareByteInt(Byte.MAX_VALUE, Integer.MAX_VALUE - 1));
+ expectEquals(-1, compareByteInt(Byte.MAX_VALUE, Integer.MAX_VALUE));
+
+ expectEquals(0, compareByteInt((byte)-1, -1));
+ expectEquals(0, compareByteInt((byte)0, 0));
+ expectEquals(0, compareByteInt((byte)1, 1));
+
+ expectEquals(1, compareByteInt(Byte.MIN_VALUE, Integer.MIN_VALUE));
+ expectEquals(1, compareByteInt(Byte.MIN_VALUE, Integer.MIN_VALUE + 1));
+ expectEquals(1, compareByteInt((byte)0, -1));
+ expectEquals(1, compareByteInt((byte)1, -1));
+ expectEquals(1, compareByteInt((byte)1, 0));
+ expectEquals(1, compareByteInt(Byte.MAX_VALUE, Integer.MIN_VALUE));
+ expectEquals(1, compareByteInt(Byte.MAX_VALUE, -1));
+ expectEquals(1, compareByteInt(Byte.MAX_VALUE, 0));
+ expectEquals(1, compareByteInt(Byte.MAX_VALUE, 1));
+
+ for (byte i = -11; i <= 11; i++) {
+ for (int j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareByteInt(i, j));
+ }
+ }
+ }
+
+
+ public static void testCompareShortByte() {
+ expectEquals(-1, compareShortByte(Short.MIN_VALUE, Byte.MIN_VALUE));
+ expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
+ expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)-1));
+ expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)0));
+ expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)1));
+ expectEquals(-1, compareShortByte(Short.MIN_VALUE, Byte.MAX_VALUE));
+ expectEquals(-1, compareShortByte((short)-1, (byte)0));
+ expectEquals(-1, compareShortByte((short)-1, (byte)1));
+ expectEquals(-1, compareShortByte((short)0, (byte)1));
+
+ expectEquals(0, compareShortByte((short)-1, (byte)-1));
+ expectEquals(0, compareShortByte((short)0, (byte)0));
+ expectEquals(0, compareShortByte((short)1, (byte)1));
+
+ expectEquals(1, compareShortByte((short)0, (byte)-1));
+ expectEquals(1, compareShortByte((short)1, (byte)-1));
+ expectEquals(1, compareShortByte((short)1, (byte)0));
+ expectEquals(1, compareShortByte(Short.MAX_VALUE, Byte.MIN_VALUE));
+ expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)-1));
+ expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)0));
+ expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)1));
+ expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
+ expectEquals(1, compareShortByte(Short.MAX_VALUE, Byte.MAX_VALUE));
+
+ for (short i = -11; i <= 11; i++) {
+ for (byte j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareShortByte(i, j));
+ }
+ }
+ }
+
+ public static void testCompareShortChar() {
+ expectEquals(-1, compareShortChar(Short.MIN_VALUE, (char)0));
+ expectEquals(-1, compareShortChar(Short.MIN_VALUE, (char)1));
+ expectEquals(-1, compareShortChar(Short.MIN_VALUE, Character.MAX_VALUE));
+ expectEquals(-1, compareShortChar((short)-1, (char)0));
+ expectEquals(-1, compareShortChar((short)-1, (char)1));
+ expectEquals(-1, compareShortChar((short)0, (char)1));
+ expectEquals(-1, compareShortChar(Short.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
+ expectEquals(-1, compareShortChar(Short.MAX_VALUE, Character.MAX_VALUE));
+
+ expectEquals(0, compareShortChar((short)0, (char)0));
+ expectEquals(0, compareShortChar((short)1, (char)1));
+
+ expectEquals(1, compareShortChar((short)1, (char)0));
+ expectEquals(1, compareShortChar(Short.MAX_VALUE, (char)0));
+ expectEquals(1, compareShortChar(Short.MAX_VALUE, (char)1));
+
+ for (short i = -11; i <= 11; i++) {
+ for (char j = 0; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareShortChar(i, j));
+ }
+ }
+ }
+
+ public static void testCompareShortInt() {
+ expectEquals(-1, compareShortInt(Short.MIN_VALUE, -1));
+ expectEquals(-1, compareShortInt(Short.MIN_VALUE, 0));
+ expectEquals(-1, compareShortInt(Short.MIN_VALUE, 1));
+ expectEquals(-1, compareShortInt(Short.MIN_VALUE, Integer.MAX_VALUE));
+ expectEquals(-1, compareShortInt((short)-1, 0));
+ expectEquals(-1, compareShortInt((short)-1, 1));
+ expectEquals(-1, compareShortInt((short)0, 1));
+ expectEquals(-1, compareShortInt(Short.MAX_VALUE, Integer.MAX_VALUE - 1));
+ expectEquals(-1, compareShortInt(Short.MAX_VALUE, Integer.MAX_VALUE));
+
+ expectEquals(0, compareShortInt((short)-1, -1));
+ expectEquals(0, compareShortInt((short)0, 0));
+ expectEquals(0, compareShortInt((short)1, 1));
+
+ expectEquals(1, compareShortInt(Short.MIN_VALUE, Integer.MIN_VALUE));
+ expectEquals(1, compareShortInt(Short.MIN_VALUE, Integer.MIN_VALUE + 1));
+ expectEquals(1, compareShortInt((short)0, -1));
+ expectEquals(1, compareShortInt((short)1, -1));
+ expectEquals(1, compareShortInt((short)1, 0));
+ expectEquals(1, compareShortInt(Short.MAX_VALUE, Integer.MIN_VALUE));
+ expectEquals(1, compareShortInt(Short.MAX_VALUE, -1));
+ expectEquals(1, compareShortInt(Short.MAX_VALUE, 0));
+ expectEquals(1, compareShortInt(Short.MAX_VALUE, 1));
+
+ for (short i = -11; i <= 11; i++) {
+ for (int j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareShortInt(i, j));
+ }
+ }
+ }
+
+
+ public static void testCompareCharByte() {
+ expectEquals(-1, compareCharByte((char)0, (byte)1));
+ expectEquals(-1, compareCharByte((char)0, Byte.MAX_VALUE));
+
+ expectEquals(0, compareCharByte((char)0, (byte)0));
+ expectEquals(0, compareCharByte((char)1, (byte)1));
+
+ expectEquals(1, compareCharByte((char)0, Byte.MIN_VALUE));
+ expectEquals(1, compareCharByte((char)0, (byte)(Byte.MIN_VALUE + 1)));
+ expectEquals(1, compareCharByte((char)0, (byte)-1));
+ expectEquals(1, compareCharByte((char)1, (byte)-1));
+ expectEquals(1, compareCharByte((char)1, (byte)0));
+ expectEquals(1, compareCharByte(Character.MAX_VALUE, Byte.MIN_VALUE));
+ expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)-1));
+ expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)0));
+ expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)1));
+ expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
+ expectEquals(1, compareCharByte(Character.MAX_VALUE, Byte.MAX_VALUE));
+
+ for (char i = 0; i <= 11; i++) {
+ for (byte j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareCharByte(i, j));
+ }
+ }
+ }
+
+ public static void testCompareCharShort() {
+ expectEquals(-1, compareCharShort((char)0, (short)1));
+ expectEquals(-1, compareCharShort((char)0, Short.MAX_VALUE));
+
+ expectEquals(0, compareCharShort((char)0, (short)0));
+ expectEquals(0, compareCharShort((char)1, (short)1));
+
+ expectEquals(1, compareCharShort((char)0, Short.MIN_VALUE));
+ expectEquals(1, compareCharShort((char)0, (short)(Short.MIN_VALUE + 1)));
+ expectEquals(1, compareCharShort((char)0, (short)-1));
+ expectEquals(1, compareCharShort((char)1, (short)-1));
+ expectEquals(1, compareCharShort((char)1, (short)0));
+ expectEquals(1, compareCharShort(Character.MAX_VALUE, Short.MIN_VALUE));
+ expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)-1));
+ expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)0));
+ expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)1));
+ expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
+ expectEquals(1, compareCharShort(Character.MAX_VALUE, Short.MAX_VALUE));
+
+ for (char i = 0; i <= 11; i++) {
+ for (short j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareCharShort(i, j));
+ }
+ }
+ }
+
+ public static void testCompareCharInt() {
+ expectEquals(-1, compareCharInt((char)0, 1));
+ expectEquals(-1, compareCharInt((char)0, Integer.MAX_VALUE));
+ expectEquals(-1, compareCharInt(Character.MAX_VALUE, Integer.MAX_VALUE - 1));
+ expectEquals(-1, compareCharInt(Character.MAX_VALUE, Integer.MAX_VALUE));
+
+ expectEquals(0, compareCharInt((char)0, 0));
+ expectEquals(0, compareCharInt((char)1, 1));
+
+ expectEquals(1, compareCharInt((char)0, Integer.MIN_VALUE));
+ expectEquals(1, compareCharInt((char)0, Integer.MIN_VALUE + 1));
+ expectEquals(1, compareCharInt((char)0, -1));
+ expectEquals(1, compareCharInt((char)1, -1));
+ expectEquals(1, compareCharInt((char)1, 0));
+ expectEquals(1, compareCharInt(Character.MAX_VALUE, Integer.MIN_VALUE));
+ expectEquals(1, compareCharInt(Character.MAX_VALUE, -1));
+ expectEquals(1, compareCharInt(Character.MAX_VALUE, 0));
+ expectEquals(1, compareCharInt(Character.MAX_VALUE, 1));
+
+ for (char i = 0; i <= 11; i++) {
+ for (int j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareCharInt(i, j));
+ }
+ }
+ }
+
+
+ public static void testCompareIntByte() {
+ expectEquals(-1, compareIntByte(Integer.MIN_VALUE, Byte.MIN_VALUE));
+ expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
+ expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)-1));
+ expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)0));
+ expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)1));
+ expectEquals(-1, compareIntByte(Integer.MIN_VALUE, Byte.MAX_VALUE));
+ expectEquals(-1, compareIntByte(-1, (byte)0));
+ expectEquals(-1, compareIntByte(-1, (byte)1));
+ expectEquals(-1, compareIntByte(0, (byte)1));
+
+ expectEquals(0, compareIntByte(-1, (byte)-1));
+ expectEquals(0, compareIntByte(0, (byte)0));
+ expectEquals(0, compareIntByte(1, (byte)1));
+
+ expectEquals(1, compareIntByte(0, (byte)-1));
+ expectEquals(1, compareIntByte(1, (byte)-1));
+ expectEquals(1, compareIntByte(1, (byte)0));
+ expectEquals(1, compareIntByte(Integer.MAX_VALUE, Byte.MIN_VALUE));
+ expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)-1));
+ expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)0));
+ expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)1));
+ expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
+ expectEquals(1, compareIntByte(Integer.MAX_VALUE, Byte.MAX_VALUE));
+
+ for (int i = -11; i <= 11; i++) {
+ for (byte j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareIntByte(i, j));
+ }
+ }
+ }
+
+ public static void testCompareIntShort() {
+ expectEquals(-1, compareIntShort(Integer.MIN_VALUE, Short.MIN_VALUE));
+ expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
+ expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)-1));
+ expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)0));
+ expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)1));
+ expectEquals(-1, compareIntShort(Integer.MIN_VALUE, Short.MAX_VALUE));
+ expectEquals(-1, compareIntShort(-1, (short)0));
+ expectEquals(-1, compareIntShort(-1, (short)1));
+ expectEquals(-1, compareIntShort(0, (short)1));
+
+ expectEquals(0, compareIntShort(-1, (short)-1));
+ expectEquals(0, compareIntShort(0, (short)0));
+ expectEquals(0, compareIntShort(1, (short)1));
+
+ expectEquals(1, compareIntShort(0, (short)-1));
+ expectEquals(1, compareIntShort(1, (short)-1));
+ expectEquals(1, compareIntShort(1, (short)0));
+ expectEquals(1, compareIntShort(Integer.MAX_VALUE, Short.MIN_VALUE));
+ expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)-1));
+ expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)0));
+ expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)1));
+ expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
+ expectEquals(1, compareIntShort(Integer.MAX_VALUE, Short.MAX_VALUE));
+
+ for (int i = -11; i <= 11; i++) {
+ for (short j = -11; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareIntShort(i, j));
+ }
+ }
+ }
+
+ public static void testCompareIntChar() {
+ expectEquals(-1, compareIntChar(Integer.MIN_VALUE, (char)0));
+ expectEquals(-1, compareIntChar(Integer.MIN_VALUE, (char)1));
+ expectEquals(-1, compareIntChar(Integer.MIN_VALUE, Character.MAX_VALUE));
+ expectEquals(-1, compareIntChar(-1, (char)0));
+ expectEquals(-1, compareIntChar(-1, (char)1));
+ expectEquals(-1, compareIntChar(0, (char)1));
+
+ expectEquals(0, compareIntChar(0, (char)0));
+ expectEquals(0, compareIntChar(1, (char)1));
+
+ expectEquals(1, compareIntChar(1, (char)0));
+ expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)0));
+ expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)1));
+ expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
+ expectEquals(1, compareIntChar(Integer.MAX_VALUE, Character.MAX_VALUE));
+
+ for (int i = -11; i <= 11; i++) {
+ for (char j = 0; j <= 11; j++) {
+ int expected = 0;
+ if (i < j) expected = -1;
+ else if (i > j) expected = 1;
+ expectEquals(expected, compareIntChar(i, j));
+ }
+ }
+ }
+
+
+ public static void main(String args[]) {
+ testCompareBooleans();
+ testCompareBytes();
+ testCompareShorts();
+ testCompareChars();
+ testCompareInts();
+ testCompareLongs();
+
+ testCompareByteShort();
+ testCompareByteChar();
+ testCompareByteInt();
+
+ testCompareShortByte();
+ testCompareShortChar();
+ testCompareShortInt();
+
+ testCompareCharByte();
+ testCompareCharShort();
+ testCompareCharInt();
+
+ testCompareIntByte();
+ testCompareIntShort();
+ testCompareIntChar();
System.out.println("passed");
}
diff --git a/test/583-checker-zero/expected.txt b/test/583-checker-zero/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/583-checker-zero/expected.txt
diff --git a/test/583-checker-zero/info.txt b/test/583-checker-zero/info.txt
new file mode 100644
index 0000000..8ec5d48
--- /dev/null
+++ b/test/583-checker-zero/info.txt
@@ -0,0 +1,2 @@
+Regression test for optimizing that used to think 0.0 has the same bits
+as -0.0.
diff --git a/test/583-checker-zero/src/Main.java b/test/583-checker-zero/src/Main.java
new file mode 100644
index 0000000..f1f7f05
--- /dev/null
+++ b/test/583-checker-zero/src/Main.java
@@ -0,0 +1,29 @@
+/*
+ * 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 {
+ // Test that by inlining new Float(-0f), we still keep the store of
+ // -0f to the instance field. We used to remove it due to wrong assumptions
+ // around HConstant.IsZero.
+
+ /// CHECK-START: void Main.main(java.lang.String[]) inliner (after)
+ /// CHECK: InstanceFieldSet
+ public static void main(String[] args) {
+ if (new Float(0f).equals(new Float(-0f))) {
+ throw new Error("Expected not equal");
+ }
+ }
+}
diff --git a/test/584-checker-div-bool/expected.txt b/test/584-checker-div-bool/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/584-checker-div-bool/expected.txt
diff --git a/test/584-checker-div-bool/info.txt b/test/584-checker-div-bool/info.txt
new file mode 100644
index 0000000..59650d5
--- /dev/null
+++ b/test/584-checker-div-bool/info.txt
@@ -0,0 +1,2 @@
+Regression test for optimizing that used to not accept
+HDivZeroCheck taking a boolean.
diff --git a/test/584-checker-div-bool/src/Main.java b/test/584-checker-div-bool/src/Main.java
new file mode 100644
index 0000000..fadc995
--- /dev/null
+++ b/test/584-checker-div-bool/src/Main.java
@@ -0,0 +1,41 @@
+/*
+ * 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) {
+ try {
+ foo(intField);
+ throw new Error("Expected ArithmeticException");
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ /// CHECK-START: int Main.foo(int) register (after)
+ /// CHECK: <<BoolField:z\d+>> StaticFieldGet
+ /// CHECK: DivZeroCheck [<<BoolField>>]
+ public static int foo(int a) {
+ return a / bar();
+ }
+
+ public static int bar() {
+ return booleanField ? 1 : 0;
+ }
+
+ public static boolean booleanField;
+ public static int intField;
+}
diff --git a/test/585-inline-unresolved/expected.txt b/test/585-inline-unresolved/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/585-inline-unresolved/expected.txt
diff --git a/test/585-inline-unresolved/info.txt b/test/585-inline-unresolved/info.txt
new file mode 100644
index 0000000..414f638
--- /dev/null
+++ b/test/585-inline-unresolved/info.txt
@@ -0,0 +1,2 @@
+Regression test for optimizing that used to crash when inlining
+a method whose return type is unresolved.
diff --git a/test/585-inline-unresolved/smali/TestCase.smali b/test/585-inline-unresolved/smali/TestCase.smali
new file mode 100644
index 0000000..f260092
--- /dev/null
+++ b/test/585-inline-unresolved/smali/TestCase.smali
@@ -0,0 +1,48 @@
+# 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 LTestCase;
+
+.super Ljava/lang/Object;
+
+.field static private test1:Z
+
+.method public static topLevel()V
+ .registers 1
+ invoke-static {}, LTestCase;->$inline$foo()LUnresolved;
+ return-void
+.end method
+
+# We need multiple returns to trigger the crash.
+.method public static $inline$foo()LUnresolved;
+ .registers 2
+ const v1, 0x0
+ sget-boolean v0, LTestCase;->test1:Z
+ if-eqz v0, :other_return
+ return-object v1
+ :other_return
+ invoke-static {}, LTestCase;->$noinline$bar()LUnresolved;
+ move-result-object v0
+ return-object v0
+.end method
+
+.method public static $noinline$bar()LUnresolved;
+ .registers 2
+ const v1, 0x0
+ sget-boolean v0, LTestCase;->test1:Z
+ if-eqz v0, :return
+ throw v1
+ :return
+ return-object v1
+.end method
diff --git a/runtime/native/java_lang_Runtime.h b/test/585-inline-unresolved/src/Main.java
similarity index 64%
copy from runtime/native/java_lang_Runtime.h
copy to test/585-inline-unresolved/src/Main.java
index ceda06b..67ad4d2 100644
--- a/runtime/native/java_lang_Runtime.h
+++ b/test/585-inline-unresolved/src/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,15 +14,9 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
-#define ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
-
-#include <jni.h>
-
-namespace art {
-
-void register_java_lang_Runtime(JNIEnv* env);
-
-} // namespace art
-
-#endif // ART_RUNTIME_NATIVE_JAVA_LANG_RUNTIME_H_
+public class Main {
+ public static void main(String[] args) throws Exception {
+ Class<?> c = Class.forName("TestCase");
+ c.getMethod("topLevel").invoke(null);
+ }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 7036bdc..bb7daf8 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -223,12 +223,9 @@
# Disable 097-duplicate-method while investigation (broken by latest Jack release, b/27358065)
# Disable 137-cfi (b/27391690).
-# Disable 536-checker-needs-access-check and 537-checker-inline-and-unverified (b/27425061)
# Disable 577-profile-foreign-dex (b/27454772).
TEST_ART_BROKEN_ALL_TARGET_TESTS := \
097-duplicate-method \
- 536-checker-needs-access-check \
- 537-checker-inline-and-unverified \
577-profile-foreign-dex \
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
diff --git a/test/etc/default-build b/test/etc/default-build
index 5f78496..d048757 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -54,6 +54,12 @@
HAS_SRC_EX=false
fi
+if [ -d src-dex2oat-unresolved ]; then
+ HAS_SRC_DEX2OAT_UNRESOLVED=true
+else
+ HAS_SRC_DEX2OAT_UNRESOLVED=false
+fi
+
DX_FLAGS=""
SKIP_DX_MERGER="false"
EXPERIMENTAL=""
@@ -116,59 +122,80 @@
SKIP_DX_MERGER="true"
fi
-if [ ${USE_JACK} = "true" ]; then
- # Jack toolchain
- if [ "${HAS_SRC}" = "true" ]; then
- if [ "${HAS_SRC_MULTIDEX}" = "true" ]; then
- # Compile src and src-multidex in the same .jack file. We will apply multidex partitioning
- # when creating the output .dex file.
- ${JACK} ${JACK_ARGS} --output-jack src.jack src src src-multidex
- jack_extra_args="${jack_extra_args} -D jack.dex.output.policy=minimal-multidex"
- jack_extra_args="${jack_extra_args} -D jack.preprocessor=true"
- jack_extra_args="${jack_extra_args} -D jack.preprocessor.file=multidex.jpp"
- else
- ${JACK} ${JACK_ARGS} --output-jack src.jack src
+if [ ${HAS_SRC_DEX2OAT_UNRESOLVED} = "true" ]; then
+ mkdir classes
+ mkdir classes-ex
+ ${JAVAC} ${JAVAC_ARGS} -implicit:none -sourcepath src-dex2oat-unresolved -d classes `find src -name '*.java'`
+ ${JAVAC} ${JAVAC_ARGS} -implicit:none -sourcepath src -d classes-ex `find src-dex2oat-unresolved -name '*.java'`
+ if [ ${USE_JACK} = "true" ]; then
+ jar cf classes.jill.jar -C classes .
+ jar cf classes-ex.jill.jar -C classes-ex .
+
+ ${JACK} --import classes-ex.jill.jar --output-dex .
+ zip ${TEST_NAME}-ex.jar classes.dex
+ ${JACK} --import classes.jill.jar --output-dex .
+ else
+ if [ ${NEED_DEX} = "true" ]; then
+ ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+ zip ${TEST_NAME}-ex.jar classes.dex
+ ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
fi
- jack_extra_args="${jack_extra_args} --import src.jack"
- fi
-
- if [ "${HAS_SRC2}" = "true" ]; then
- ${JACK} ${JACK_ARGS} --output-jack src2.jack src2
- # In case of duplicate classes, we want to take into account the classes from src2. Therefore
- # we apply the 'keep-first' policy and import src2.jack file *before* the src.jack file.
- jack_extra_args="${jack_extra_args} -D jack.import.type.policy=keep-first"
- jack_extra_args="--import src2.jack ${jack_extra_args}"
- fi
-
- # Compile jack files into a DEX file.
- if [ "${HAS_SRC}" = "true" ] || [ "${HAS_SRC2}" = "true" ]; then
- ${JACK} ${JACK_ARGS} ${jack_extra_args} --output-dex .
fi
else
- # Legacy toolchain with javac+dx
- if [ "${HAS_SRC}" = "true" ]; then
- mkdir classes
- ${JAVAC} ${JAVAC_ARGS} -implicit:none -classpath src-multidex -d classes `find src -name '*.java'`
- fi
-
- if [ "${HAS_SRC_MULTIDEX}" = "true" ]; 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
+ if [ ${USE_JACK} = "true" ]; then
+ # Jack toolchain
+ if [ "${HAS_SRC}" = "true" ]; then
+ if [ "${HAS_SRC_MULTIDEX}" = "true" ]; then
+ # Compile src and src-multidex in the same .jack file. We will apply multidex partitioning
+ # when creating the output .dex file.
+ ${JACK} ${JACK_ARGS} --output-jack src.jack src src src-multidex
+ jack_extra_args="${jack_extra_args} -D jack.dex.output.policy=minimal-multidex"
+ jack_extra_args="${jack_extra_args} -D jack.preprocessor=true"
+ jack_extra_args="${jack_extra_args} -D jack.preprocessor.file=multidex.jpp"
+ else
+ ${JACK} ${JACK_ARGS} --output-jack src.jack src
+ fi
+ jack_extra_args="${jack_extra_args} --import src.jack"
fi
- fi
- if [ "${HAS_SRC2}" = "true" ]; then
- mkdir -p classes
- ${JAVAC} ${JAVAC_ARGS} -d classes `find src2 -name '*.java'`
- fi
+ if [ "${HAS_SRC2}" = "true" ]; then
+ ${JACK} ${JACK_ARGS} --output-jack src2.jack src2
+ # In case of duplicate classes, we want to take into account the classes from src2. Therefore
+ # we apply the 'keep-first' policy and import src2.jack file *before* the src.jack file.
+ jack_extra_args="${jack_extra_args} -D jack.import.type.policy=keep-first"
+ jack_extra_args="--import src2.jack ${jack_extra_args}"
+ fi
- if [ "${HAS_SRC}" = "true" ] || [ "${HAS_SRC2}" = "true" ]; then
- 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
+ # Compile jack files into a DEX file.
+ if [ "${HAS_SRC}" = "true" ] || [ "${HAS_SRC2}" = "true" ]; then
+ ${JACK} ${JACK_ARGS} ${jack_extra_args} --output-dex .
+ fi
+ else
+ # Legacy toolchain with javac+dx
+ if [ "${HAS_SRC}" = "true" ]; then
+ mkdir classes
+ ${JAVAC} ${JAVAC_ARGS} -implicit:none -classpath src-multidex -d classes `find src -name '*.java'`
+ fi
+
+ if [ "${HAS_SRC_MULTIDEX}" = "true" ]; 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 [ "${HAS_SRC2}" = "true" ]; then
+ mkdir -p classes
+ ${JAVAC} ${JAVAC_ARGS} -d classes `find src2 -name '*.java'`
+ fi
+
+ if [ "${HAS_SRC}" = "true" ] || [ "${HAS_SRC2}" = "true" ]; then
+ 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
fi
fi
diff --git a/test/run-test b/test/run-test
index d0f93b9..6bb1549 100755
--- a/test/run-test
+++ b/test/run-test
@@ -45,7 +45,7 @@
export RUN="${progdir}/etc/run-test-jar"
export DEX_LOCATION=/data/run-test/${test_dir}
export NEED_DEX="true"
-export USE_JACK="false"
+export USE_JACK="true"
export SMALI_ARGS="--experimental --api-level 23"
# If dx was not set by the environment variable, assume it is in the path.
@@ -73,11 +73,6 @@
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
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 46100ae..4c3aea4 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -270,5 +270,10 @@
description: "Only work with --mode=activity",
result: EXEC_FAILED,
names: [ "libcore.java.io.FileTest#testJavaIoTmpdirMutable" ]
+},
+{
+ description: "Wrong junit constructor for test",
+ result: EXEC_FAILED,
+ names: [ "jsr166.CollectionTest#testEmptyMeansEmpty" ]
}
]