Merge "[native bridge] Make sure we always unload the native bridge"
diff --git a/compiler/dex/compiler_ir.cc b/compiler/dex/compiler_ir.cc
index 909c995..a2b3fe4 100644
--- a/compiler/dex/compiler_ir.cc
+++ b/compiler/dex/compiler_ir.cc
@@ -16,6 +16,7 @@
#include "compiler_ir.h"
+#include "base/dumpable.h"
#include "backend.h"
#include "frontend.h"
#include "mir_graph.h"
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 2e21d05..3dc5655 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -19,6 +19,7 @@
#include <cstdint>
#include "backend.h"
+#include "base/dumpable.h"
#include "compiler.h"
#include "compiler_internals.h"
#include "driver/compiler_driver.h"
@@ -134,15 +135,8 @@
(cu.enable_debug & (1 << kDebugVerbose));
}
- if (gVerboseMethods.size() != 0) {
- cu.verbose = false;
- for (size_t i = 0; i < gVerboseMethods.size(); ++i) {
- if (PrettyMethod(method_idx, dex_file).find(gVerboseMethods[i])
- != std::string::npos) {
- cu.verbose = true;
- break;
- }
- }
+ if (driver.GetCompilerOptions().HasVerboseMethods()) {
+ cu.verbose = driver.GetCompilerOptions().IsVerboseMethod(PrettyMethod(method_idx, dex_file));
}
if (cu.verbose) {
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 07034cb..acf5599 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -858,6 +858,11 @@
RegLocation rl_dest = InlineTargetWide(info);
int res_vreg, src1_vreg, src2_vreg;
+ if (rl_dest.s_reg_low == INVALID_SREG) {
+ // Result is unused, the code is dead. Inlining successful, no code generated.
+ return true;
+ }
+
/*
* If the result register is the same as the second element, then we
* need to be careful. The reason is that the first copy will
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 4528688..a60c5bc 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -347,15 +347,11 @@
image_(image),
image_classes_(image_classes),
thread_count_(thread_count),
- start_ns_(0),
stats_(new AOTCompilationStats),
dump_stats_(dump_stats),
dump_passes_(dump_passes),
timings_logger_(timer),
- compiler_library_(nullptr),
compiler_context_(nullptr),
- compiler_enable_auto_elf_loading_(nullptr),
- compiler_get_method_code_addr_(nullptr),
support_boot_image_fixup_(instruction_set != kMips),
dedupe_code_("dedupe code"),
dedupe_src_mapping_table_("dedupe source mapping table"),
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 3d59ef1..0796f48 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -503,7 +503,6 @@
std::unique_ptr<std::set<std::string>> image_classes_;
size_t thread_count_;
- uint64_t start_ns_;
class AOTCompilationStats;
std::unique_ptr<AOTCompilationStats> stats_;
@@ -516,8 +515,6 @@
typedef void (*CompilerCallbackFn)(CompilerDriver& driver);
typedef MutexLock* (*CompilerMutexLockFn)(CompilerDriver& driver);
- void* compiler_library_;
-
typedef void (*DexToDexCompilerFn)(CompilerDriver& driver,
const DexFile::CodeItem* code_item,
uint32_t access_flags, InvokeType invoke_type,
@@ -533,13 +530,6 @@
// Arena pool used by the compiler.
ArenaPool arena_pool_;
- typedef void (*CompilerEnableAutoElfLoadingFn)(CompilerDriver& driver);
- CompilerEnableAutoElfLoadingFn compiler_enable_auto_elf_loading_;
-
- typedef const void* (*CompilerGetMethodCodeAddrFn)
- (const CompilerDriver& driver, const CompiledMethod* cm, const mirror::ArtMethod* method);
- CompilerGetMethodCodeAddrFn compiler_get_method_code_addr_;
-
bool support_boot_image_fixup_;
// DeDuplication data structures, these own the corresponding byte arrays.
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 3a50bfd..fb7aeb9 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -17,9 +17,14 @@
#ifndef ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
#define ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+
namespace art {
-class CompilerOptions {
+class CompilerOptions FINAL {
public:
enum CompilerFilter {
kVerifyNone, // Skip verification and compile nothing except JNI stubs.
@@ -60,11 +65,12 @@
implicit_null_checks_(false),
implicit_so_checks_(false),
implicit_suspend_checks_(false),
- compile_pic_(false)
+ compile_pic_(false),
#ifdef ART_SEA_IR_MODE
- , sea_ir_mode_(false)
+ sea_ir_mode_(false),
#endif
- {}
+ verbose_methods_(nullptr) {
+ }
CompilerOptions(CompilerFilter compiler_filter,
size_t huge_method_threshold,
@@ -79,10 +85,11 @@
bool implicit_null_checks,
bool implicit_so_checks,
bool implicit_suspend_checks,
- bool compile_pic
+ bool compile_pic,
#ifdef ART_SEA_IR_MODE
- , bool sea_ir_mode
+ bool sea_ir_mode,
#endif
+ const std::vector<std::string>* verbose_methods
) : // NOLINT(whitespace/parens)
compiler_filter_(compiler_filter),
huge_method_threshold_(huge_method_threshold),
@@ -97,11 +104,12 @@
implicit_null_checks_(implicit_null_checks),
implicit_so_checks_(implicit_so_checks),
implicit_suspend_checks_(implicit_suspend_checks),
- compile_pic_(compile_pic)
+ compile_pic_(compile_pic),
#ifdef ART_SEA_IR_MODE
- , sea_ir_mode_(sea_ir_mode)
+ sea_ir_mode_(sea_ir_mode),
#endif
- {}
+ verbose_methods_(verbose_methods) {
+ }
CompilerFilter GetCompilerFilter() const {
return compiler_filter_;
@@ -168,28 +176,18 @@
return implicit_null_checks_;
}
- void SetImplicitNullChecks(bool new_val) {
- implicit_null_checks_ = new_val;
- }
-
bool GetImplicitStackOverflowChecks() const {
return implicit_so_checks_;
}
- void SetImplicitStackOverflowChecks(bool new_val) {
- implicit_so_checks_ = new_val;
- }
-
bool GetImplicitSuspendChecks() const {
return implicit_suspend_checks_;
}
- void SetImplicitSuspendChecks(bool new_val) {
- implicit_suspend_checks_ = new_val;
- }
-
#ifdef ART_SEA_IR_MODE
- bool GetSeaIrMode();
+ bool GetSeaIrMode() const {
+ return sea_ir_mode_;
+ }
#endif
bool GetGenerateGDBInformation() const {
@@ -205,25 +203,44 @@
return compile_pic_;
}
+ bool HasVerboseMethods() const {
+ return verbose_methods_ != nullptr && !verbose_methods_->empty();
+ }
+
+ bool IsVerboseMethod(const std::string& pretty_method) const {
+ for (const std::string& cur_method : *verbose_methods_) {
+ if (pretty_method.find(cur_method) != std::string::npos) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private:
CompilerFilter compiler_filter_;
- size_t huge_method_threshold_;
- size_t large_method_threshold_;
- size_t small_method_threshold_;
- size_t tiny_method_threshold_;
- size_t num_dex_methods_threshold_;
- bool generate_gdb_information_;
- bool include_patch_information_;
+ const size_t huge_method_threshold_;
+ const size_t large_method_threshold_;
+ const size_t small_method_threshold_;
+ const size_t tiny_method_threshold_;
+ const size_t num_dex_methods_threshold_;
+ const bool generate_gdb_information_;
+ const bool include_patch_information_;
// When using a profile file only the top K% of the profiled samples will be compiled.
- double top_k_profile_threshold_;
- bool include_debug_symbols_;
- bool implicit_null_checks_;
- bool implicit_so_checks_;
- bool implicit_suspend_checks_;
- bool compile_pic_;
+ const double top_k_profile_threshold_;
+ const bool include_debug_symbols_;
+ const bool implicit_null_checks_;
+ const bool implicit_so_checks_;
+ const bool implicit_suspend_checks_;
+ const bool compile_pic_;
+
#ifdef ART_SEA_IR_MODE
- bool sea_ir_mode_;
+ const bool sea_ir_mode_;
#endif
+
+ // Vector of methods to have verbose output enabled for.
+ const std::vector<std::string>* const verbose_methods_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompilerOptions);
};
} // namespace art
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 1188ec0..f48f4c3 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -748,6 +748,11 @@
break;
}
+ case Instruction::NOT_INT: {
+ Unop_12x<HNot>(instruction, Primitive::kPrimInt);
+ break;
+ }
+
case Instruction::ADD_INT: {
Binop_23x<HAdd>(instruction, Primitive::kPrimInt);
break;
@@ -793,6 +798,16 @@
break;
}
+ case Instruction::MUL_FLOAT: {
+ Binop_23x<HMul>(instruction, Primitive::kPrimFloat);
+ break;
+ }
+
+ case Instruction::MUL_DOUBLE: {
+ Binop_23x<HMul>(instruction, Primitive::kPrimDouble);
+ break;
+ }
+
case Instruction::ADD_LONG_2ADDR: {
Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
break;
@@ -828,6 +843,16 @@
break;
}
+ case Instruction::MUL_FLOAT_2ADDR: {
+ Binop_12x<HMul>(instruction, Primitive::kPrimFloat);
+ break;
+ }
+
+ case Instruction::MUL_DOUBLE_2ADDR: {
+ Binop_12x<HMul>(instruction, Primitive::kPrimDouble);
+ break;
+ }
+
case Instruction::ADD_INT_LIT16: {
Binop_22s<HAdd>(instruction, false);
break;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 792ff45..b042beb 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1219,15 +1219,16 @@
break;
}
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister());
break;
+ }
default:
- LOG(FATAL) << "Unimplemented mul type " << mul->GetResultType();
+ LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
}
}
@@ -1271,15 +1272,21 @@
__ add(out_hi, out_hi, ShifterOperand(IP));
break;
}
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
+
+ case Primitive::kPrimFloat: {
+ __ vmuls(FromDToLowS(out.As<DRegister>()),
+ FromDToLowS(first.As<DRegister>()),
+ FromDToLowS(second.As<DRegister>()));
break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ vmuld(out.As<DRegister>(), first.As<DRegister>(), second.As<DRegister>());
+ break;
+ }
default:
- LOG(FATAL) << "Unimplemented mul type " << mul->GetResultType();
+ LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
}
}
@@ -1344,17 +1351,33 @@
// Nothing to do, the parameter is already at its location.
}
-void LocationsBuilderARM::VisitNot(HNot* instruction) {
+void LocationsBuilderARM::VisitNot(HNot* not_) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
}
-void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) {
- LocationSummary* locations = instruction->GetLocations();
- __ eor(locations->Out().As<Register>(),
- locations->InAt(0).As<Register>(), ShifterOperand(1));
+void InstructionCodeGeneratorARM::VisitNot(HNot* not_) {
+ LocationSummary* locations = not_->GetLocations();
+ Location out = locations->Out();
+ Location in = locations->InAt(0);
+ switch (not_->InputAt(0)->GetType()) {
+ case Primitive::kPrimBoolean:
+ __ eor(out.As<Register>(), in.As<Register>(), ShifterOperand(1));
+ break;
+
+ case Primitive::kPrimInt:
+ __ mvn(out.As<Register>(), ShifterOperand(in.As<Register>()));
+ break;
+
+ case Primitive::kPrimLong:
+ LOG(FATAL) << "Not yet implemented type for not operation " << not_->GetResultType();
+ break;
+
+ default:
+ LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType();
+ }
}
void LocationsBuilderARM::VisitCompare(HCompare* compare) {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index acf4103..3b4b835 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1212,16 +1212,16 @@
locations->AddTemp(Location::RegisterLocation(EDX));
break;
}
-
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::SameAsFirstInput());
break;
+ }
default:
- LOG(FATAL) << "Unimplemented mul type " << mul->GetResultType();
+ LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
}
}
@@ -1283,15 +1283,18 @@
break;
}
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
+ case Primitive::kPrimFloat: {
+ __ mulss(first.As<XmmRegister>(), second.As<XmmRegister>());
break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ mulsd(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
default:
- LOG(FATAL) << "Unimplemented mul type " << mul->GetResultType();
+ LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
}
}
@@ -1353,18 +1356,34 @@
void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
}
-void LocationsBuilderX86::VisitNot(HNot* instruction) {
+void LocationsBuilderX86::VisitNot(HNot* not_) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::SameAsFirstInput());
}
-void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
- LocationSummary* locations = instruction->GetLocations();
+void InstructionCodeGeneratorX86::VisitNot(HNot* not_) {
+ LocationSummary* locations = not_->GetLocations();
+ DCHECK_EQ(locations->InAt(0).As<Register>(), locations->Out().As<Register>());
Location out = locations->Out();
DCHECK_EQ(locations->InAt(0).As<Register>(), out.As<Register>());
- __ xorl(out.As<Register>(), Immediate(1));
+ switch (not_->InputAt(0)->GetType()) {
+ case Primitive::kPrimBoolean:
+ __ xorl(out.As<Register>(), Immediate(1));
+ break;
+
+ case Primitive::kPrimInt:
+ __ notl(out.As<Register>());
+ break;
+
+ case Primitive::kPrimLong:
+ LOG(FATAL) << "Not yet implemented type for not operation " << not_->GetResultType();
+ break;
+
+ default:
+ LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType();
+ }
}
void LocationsBuilderX86::VisitCompare(HCompare* compare) {
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 58dda16..ac623f6 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1166,16 +1166,16 @@
locations->SetOut(Location::SameAsFirstInput());
break;
}
-
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::SameAsFirstInput());
break;
+ }
default:
- LOG(FATAL) << "Unimplemented mul type " << mul->GetResultType();
+ LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
}
}
@@ -1202,15 +1202,18 @@
break;
}
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
+ case Primitive::kPrimFloat: {
+ __ mulss(first.As<XmmRegister>(), second.As<XmmRegister>());
break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ mulsd(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
default:
- LOG(FATAL) << "Unimplemented mul type " << mul->GetResultType();
+ LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
}
}
@@ -1273,18 +1276,34 @@
// Nothing to do, the parameter is already at its location.
}
-void LocationsBuilderX86_64::VisitNot(HNot* instruction) {
+void LocationsBuilderX86_64::VisitNot(HNot* not_) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::SameAsFirstInput());
}
-void InstructionCodeGeneratorX86_64::VisitNot(HNot* instruction) {
- LocationSummary* locations = instruction->GetLocations();
+void InstructionCodeGeneratorX86_64::VisitNot(HNot* not_) {
+ LocationSummary* locations = not_->GetLocations();
DCHECK_EQ(locations->InAt(0).As<CpuRegister>().AsRegister(),
locations->Out().As<CpuRegister>().AsRegister());
- __ xorq(locations->Out().As<CpuRegister>(), Immediate(1));
+ Location out = locations->Out();
+ switch (not_->InputAt(0)->GetType()) {
+ case Primitive::kPrimBoolean:
+ __ xorq(out.As<CpuRegister>(), Immediate(1));
+ break;
+
+ case Primitive::kPrimInt:
+ __ notl(out.As<CpuRegister>());
+ break;
+
+ case Primitive::kPrimLong:
+ LOG(FATAL) << "Not yet implemented type for not operation " << not_->GetResultType();
+ break;
+
+ default:
+ LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType();
+ }
}
void LocationsBuilderX86_64::VisitPhi(HPhi* instruction) {
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 8bb12de..a84931a 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -135,8 +135,8 @@
const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
HGraph* graph = builder.BuildGraph(*item);
// Remove suspend checks, they cannot be executed in this context.
- RemoveSuspendChecks(graph);
ASSERT_NE(graph, nullptr);
+ RemoveSuspendChecks(graph);
RunCodeBaseline(graph, has_result, expected);
}
@@ -260,6 +260,31 @@
TestCode(data, true, 0);
}
+// Exercise bit-wise (one's complement) not-int instruction.
+#define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \
+TEST(CodegenTest, TEST_NAME) { \
+ const int32_t input = INPUT; \
+ const uint16_t input_lo = input & 0x0000FFFF; \
+ const uint16_t input_hi = input >> 16; \
+ const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( \
+ Instruction::CONST | 0 << 8, input_lo, input_hi, \
+ Instruction::NOT_INT | 1 << 8 | 0 << 12 , \
+ Instruction::RETURN | 1 << 8); \
+ \
+ TestCode(data, true, EXPECTED_OUTPUT); \
+}
+
+NOT_INT_TEST(ReturnNotIntMinus2, -2, 1)
+NOT_INT_TEST(ReturnNotIntMinus1, -1, 0)
+NOT_INT_TEST(ReturnNotInt0, 0, -1)
+NOT_INT_TEST(ReturnNotInt1, 1, -2)
+NOT_INT_TEST(ReturnNotIntINT_MIN, -2147483648, 2147483647) // (2^31) - 1
+NOT_INT_TEST(ReturnNotIntINT_MINPlus1, -2147483647, 2147483646) // (2^31) - 2
+NOT_INT_TEST(ReturnNotIntINT_MAXMinus1, 2147483646, -2147483647) // -(2^31) - 1
+NOT_INT_TEST(ReturnNotIntINT_MAX, 2147483647, -2147483648) // -(2^31)
+
+#undef NOT_INT_TEST
+
TEST(CodegenTest, ReturnAdd1) {
const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
Instruction::CONST_4 | 3 << 12 | 0,
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index db31306..badf21d 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -53,7 +53,7 @@
}
// Print detected errors on output stream `os`.
- void Dump(std::ostream& os) {
+ void Dump(std::ostream& os) const {
for (size_t i = 0, e = errors_.Size(); i < e; ++i) {
os << dump_prefix_ << errors_.Get(i) << std::endl;
}
@@ -68,7 +68,7 @@
private:
// String displayed before dumped errors.
- const char* dump_prefix_;
+ const char* const dump_prefix_;
DISALLOW_COPY_AND_ASSIGN(GraphChecker);
};
diff --git a/compiler/optimizing/graph_visualizer.h b/compiler/optimizing/graph_visualizer.h
index 05984a0..4d8bec2 100644
--- a/compiler/optimizing/graph_visualizer.h
+++ b/compiler/optimizing/graph_visualizer.h
@@ -17,6 +17,8 @@
#ifndef ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
#define ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
+#include <ostream>
+
#include "base/value_object.h"
namespace art {
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 2d9e35c..29eabe7 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -50,7 +50,7 @@
// Replace (bool_value == 0) with !bool_value
DCHECK_EQ(input2->AsIntConstant()->GetValue(), 0);
equal->GetBlock()->ReplaceAndRemoveInstructionWith(
- equal, new (GetGraph()->GetArena()) HNot(input1));
+ equal, new (GetGraph()->GetArena()) HNot(Primitive::kPrimBoolean, input1));
}
}
}
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 9b7ff88..7adb840 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -485,7 +485,7 @@
M(Local, Instruction) \
M(LongConstant, Constant) \
M(NewInstance, Instruction) \
- M(Not, Instruction) \
+ M(Not, UnaryOperation) \
M(ParameterValue, Instruction) \
M(ParallelMove, Instruction) \
M(Phi, Instruction) \
@@ -1708,15 +1708,17 @@
DISALLOW_COPY_AND_ASSIGN(HParameterValue);
};
-class HNot : public HExpression<1> {
+class HNot : public HUnaryOperation {
public:
- explicit HNot(HInstruction* input) : HExpression(Primitive::kPrimBoolean, SideEffects::None()) {
- SetRawInputAt(0, input);
- }
+ explicit HNot(Primitive::Type result_type, HInstruction* input)
+ : HUnaryOperation(result_type, input) {}
virtual bool CanBeMoved() const { return true; }
virtual bool InstructionDataEquals(HInstruction* other) const { return true; }
+ virtual int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
+ virtual int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
+
DECLARE_INSTRUCTION(Not);
private:
@@ -2123,7 +2125,7 @@
#undef DECLARE_VISIT_INSTRUCTION
private:
- HGraph* graph_;
+ HGraph* const graph_;
DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
};
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index 33dc040..ea98186 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -16,6 +16,7 @@
#include "optimization.h"
+#include "base/dumpable.h"
#include "graph_checker.h"
namespace art {
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index fc65f97..f95c4a4 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -16,6 +16,8 @@
#include "register_allocator.h"
+#include <sstream>
+
#include "base/bit_vector-inl.h"
#include "code_generator.h"
#include "ssa_liveness_analysis.h"
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 8f71848..7dda4f6 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -32,6 +32,7 @@
live_in_(allocator, number_of_ssa_values, false),
live_out_(allocator, number_of_ssa_values, false),
kill_(allocator, number_of_ssa_values, false) {
+ UNUSED(block_);
live_in_.ClearAllBits();
live_out_.ClearAllBits();
kill_.ClearAllBits();
diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h
index 5bfa462..91237ae 100644
--- a/compiler/utils/assembler_test.h
+++ b/compiler/utils/assembler_test.h
@@ -24,7 +24,6 @@
#include <cstdio>
#include <cstdlib>
#include <fstream>
-#include <iostream>
#include <iterator>
#include <sys/stat.h>
@@ -118,9 +117,8 @@
std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
for (auto reg : registers) {
for (int64_t imm : imms) {
- Imm* new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(*reg, *new_imm);
- delete new_imm;
+ Imm new_imm = CreateImmediate(imm);
+ (assembler_.get()->*f)(*reg, new_imm);
std::string base = fmt;
size_t reg_index = base.find("{reg}");
@@ -154,9 +152,8 @@
std::string str;
std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
for (int64_t imm : imms) {
- Imm* new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(*new_imm);
- delete new_imm;
+ Imm new_imm = CreateImmediate(imm);
+ (assembler_.get()->*f)(new_imm);
std::string base = fmt;
size_t imm_index = base.find("{imm}");
@@ -333,7 +330,7 @@
}
// Create an immediate from the specific value.
- virtual Imm* CreateImmediate(int64_t imm_value) = 0;
+ virtual Imm CreateImmediate(int64_t imm_value) = 0;
private:
// Driver() assembles and compares the results. If the results are not equal and we have a
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index c7eada3..b5bf31b 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -29,7 +29,7 @@
namespace art {
namespace x86 {
-class Immediate {
+class Immediate : public ValueObject {
public:
explicit Immediate(int32_t value) : value_(value) {}
@@ -47,7 +47,7 @@
};
-class Operand {
+class Operand : public ValueObject {
public:
uint8_t mod() const {
return (encoding_at(0) >> 6) & 3;
@@ -129,8 +129,6 @@
}
friend class X86Assembler;
-
- DISALLOW_COPY_AND_ASSIGN(Operand);
};
@@ -168,7 +166,6 @@
}
}
-
Address(Register index, ScaleFactor scale, int32_t disp) {
CHECK_NE(index, ESP); // Illegal addressing mode.
SetModRM(0, ESP);
@@ -205,14 +202,12 @@
private:
Address() {}
-
- DISALLOW_COPY_AND_ASSIGN(Address);
};
class X86Assembler FINAL : public Assembler {
public:
- explicit X86Assembler() {}
+ explicit X86Assembler() : cfi_cfa_offset_(0), cfi_pc_(0) {}
virtual ~X86Assembler() {}
/*
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 7e5859c..92b81ec 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -36,7 +36,7 @@
//
// Note: As we support cross-compilation, the value type must be int64_t. Please be aware of
// conversion rules in expressions regarding negation, especially size_t on 32b.
-class Immediate {
+class Immediate : public ValueObject {
public:
explicit Immediate(int64_t value) : value_(value) {}
@@ -54,12 +54,10 @@
private:
const int64_t value_;
-
- DISALLOW_COPY_AND_ASSIGN(Immediate);
};
-class Operand {
+class Operand : public ValueObject {
public:
uint8_t mod() const {
return (encoding_at(0) >> 6) & 3;
@@ -157,8 +155,6 @@
}
friend class X86_64Assembler;
-
- DISALLOW_COPY_AND_ASSIGN(Operand);
};
@@ -247,8 +243,6 @@
private:
Address() {}
-
- DISALLOW_COPY_AND_ASSIGN(Address);
};
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 37a0932..18c5cbc 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -72,8 +72,8 @@
return registers_;
}
- x86_64::Immediate* CreateImmediate(int64_t imm_value) OVERRIDE {
- return new x86_64::Immediate(imm_value);
+ x86_64::Immediate CreateImmediate(int64_t imm_value) OVERRIDE {
+ return x86_64::Immediate(imm_value);
}
private:
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 326fa72..98712cd 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -30,6 +30,10 @@
#include <sys/utsname.h>
#endif
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include "cutils/trace.h"
+
+#include "base/dumpable.h"
#include "base/stl_util.h"
#include "base/stringpiece.h"
#include "base/timing_logger.h"
@@ -832,6 +836,7 @@
int small_method_threshold = CompilerOptions::kDefaultSmallMethodThreshold;
int tiny_method_threshold = CompilerOptions::kDefaultTinyMethodThreshold;
int num_dex_methods_threshold = CompilerOptions::kDefaultNumDexMethodsThreshold;
+ std::vector<std::string> verbose_methods;
// Initialize ISA and ISA features to default values.
InstructionSet instruction_set = kRuntimeISA;
@@ -1058,6 +1063,11 @@
include_patch_information = true;
} else if (option == "--no-include-patch-information") {
include_patch_information = false;
+ } else if (option.starts_with("--verbose-methods=")) {
+ // TODO: rather than switch off compiler logging, make all VLOG(compiler) messages conditional
+ // on having verbost methods.
+ gLogVerbosity.compiler = false;
+ Split(option.substr(strlen("--verbose-methods=")).ToString(), ',', &verbose_methods);
} else {
Usage("Unknown argument %s", option.data());
}
@@ -1213,25 +1223,25 @@
PassDriverMEOpts::PrintPassOptions();
}
- std::unique_ptr<CompilerOptions> compiler_options(new CompilerOptions(compiler_filter,
- huge_method_threshold,
- large_method_threshold,
- small_method_threshold,
- tiny_method_threshold,
- num_dex_methods_threshold,
- generate_gdb_information,
- include_patch_information,
- top_k_profile_threshold,
- include_debug_symbols,
- implicit_null_checks,
- implicit_so_checks,
- implicit_suspend_checks,
- compile_pic
+ std::unique_ptr<CompilerOptions> compiler_options(
+ new CompilerOptions(compiler_filter,
+ huge_method_threshold,
+ large_method_threshold,
+ small_method_threshold,
+ tiny_method_threshold,
+ num_dex_methods_threshold,
+ generate_gdb_information,
+ include_patch_information,
+ top_k_profile_threshold,
+ include_debug_symbols,
+ implicit_null_checks,
+ implicit_so_checks,
+ implicit_suspend_checks,
+ compile_pic,
#ifdef ART_SEA_IR_MODE
- , compiler_options.sea_ir_ =
- true;
+ true,
#endif
- )); // NOLINT(whitespace/parens)
+ verbose_methods.empty() ? nullptr : &verbose_methods));
// Done with usage checks, enable watchdog if requested
WatchDog watch_dog(watch_dog_enabled);
diff --git a/disassembler/disassembler.cc b/disassembler/disassembler.cc
index c97bf64..bf68204 100644
--- a/disassembler/disassembler.cc
+++ b/disassembler/disassembler.cc
@@ -16,7 +16,7 @@
#include "disassembler.h"
-#include <iostream>
+#include <ostream>
#include "base/logging.h"
#include "base/stringprintf.h"
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index ac883fe..ee652b3 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -18,7 +18,8 @@
#include <inttypes.h>
-#include <iostream>
+#include <ostream>
+#include <sstream>
#include "base/logging.h"
#include "base/stringprintf.h"
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc
index fc1065a..229ac97 100644
--- a/disassembler/disassembler_arm64.cc
+++ b/disassembler/disassembler_arm64.cc
@@ -18,7 +18,7 @@
#include <inttypes.h>
-#include <iostream>
+#include <ostream>
#include "base/logging.h"
#include "base/stringprintf.h"
diff --git a/disassembler/disassembler_mips.cc b/disassembler/disassembler_mips.cc
index bd5fac7..97c06f1 100644
--- a/disassembler/disassembler_mips.cc
+++ b/disassembler/disassembler_mips.cc
@@ -16,7 +16,8 @@
#include "disassembler_mips.h"
-#include <iostream>
+#include <ostream>
+#include <sstream>
#include "base/logging.h"
#include "base/stringprintf.h"
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index 63a74c7..e12559f 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -16,12 +16,14 @@
#include "disassembler_x86.h"
-#include <iostream>
+#include <inttypes.h>
+
+#include <ostream>
+#include <sstream>
#include "base/logging.h"
#include "base/stringprintf.h"
#include "thread.h"
-#include <inttypes.h>
namespace art {
namespace x86 {
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index c0c96e5..8e5af53 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -24,6 +24,7 @@
#include <string>
#include <vector>
+#include "base/dumpable.h"
#include "base/scoped_flock.h"
#include "base/stringpiece.h"
#include "base/stringprintf.h"
diff --git a/runtime/Android.mk b/runtime/Android.mk
index d9b4139..0ef0fef 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -209,7 +209,6 @@
LIBART_TARGET_SRC_FILES := \
$(LIBART_COMMON_SRC_FILES) \
- base/logging_android.cc \
jdwp/jdwp_adb.cc \
monitor_android.cc \
runtime_android.cc \
@@ -282,7 +281,6 @@
LIBART_HOST_SRC_FILES := \
$(LIBART_COMMON_SRC_FILES) \
- base/logging_linux.cc \
monitor_linux.cc \
runtime_linux.cc \
thread_linux.cc
@@ -477,7 +475,7 @@
endif
endif
LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
-# LOCAL_ADDITIONAL_DEPENDENCIES += $$(LOCAL_PATH)/Android.mk
+ LOCAL_ADDITIONAL_DEPENDENCIES += $$(LOCAL_PATH)/Android.mk
ifeq ($$(art_target_or_host),target)
LOCAL_MODULE_TARGET_ARCH := $$(ART_TARGET_SUPPORTED_ARCH)
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 0fb96d7..147d434 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -1285,7 +1285,7 @@
THREE_ARG_REF_DOWNCALL art_quick_set8_instance, artSet8InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
THREE_ARG_REF_DOWNCALL art_quick_set16_instance, artSet16InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
THREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
-THREE_ARG_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
+THREE_ARG_REF_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
THREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
// This is separated out as the argument order is different.
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index ea586b8..c5a0f6c 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -1148,7 +1148,7 @@
// For some reason this does not work, as the type_idx is artificial and outside what the
// resolved types of c_obj allow...
- if (false) {
+ if ((false)) {
// Use an arbitrary method from c to use as referrer
size_t result = Invoke3(static_cast<size_t>(c->GetDexTypeIndex()), // type_idx
reinterpret_cast<size_t>(c_obj->GetVirtualMethod(0)), // arbitrary
diff --git a/runtime/base/bit_vector.cc b/runtime/base/bit_vector.cc
index 1d67962..5b8b6e2 100644
--- a/runtime/base/bit_vector.cc
+++ b/runtime/base/bit_vector.cc
@@ -16,6 +16,8 @@
#include "bit_vector.h"
+#include <sstream>
+
#include "allocator.h"
#include "bit_vector-inl.h"
diff --git a/runtime/base/dumpable.h b/runtime/base/dumpable.h
new file mode 100644
index 0000000..3c316cc
--- /dev/null
+++ b/runtime/base/dumpable.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_RUNTIME_BASE_DUMPABLE_H_
+#define ART_RUNTIME_BASE_DUMPABLE_H_
+
+#include "base/macros.h"
+
+namespace art {
+
+// A convenience to allow any class with a "Dump(std::ostream& os)" member function
+// but without an operator<< to be used as if it had an operator<<. Use like this:
+//
+// os << Dumpable<MyType>(my_type_instance);
+//
+template<typename T>
+class Dumpable FINAL {
+ public:
+ explicit Dumpable(const T& value) : value_(value) {
+ }
+
+ void Dump(std::ostream& os) const {
+ value_.Dump(os);
+ }
+
+ private:
+ const T& value_;
+
+ DISALLOW_COPY_AND_ASSIGN(Dumpable);
+};
+
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) {
+ rhs.Dump(os);
+ return os;
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_BASE_DUMPABLE_H_
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index 5af597b..46c3538 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -16,17 +16,25 @@
#include "logging.h"
+#include <sstream>
+
#include "base/mutex.h"
#include "runtime.h"
#include "thread-inl.h"
#include "utils.h"
+// Headers for LogMessage::LogLine.
+#ifdef HAVE_ANDROID_OS
+#include "cutils/log.h"
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
namespace art {
LogVerbosity gLogVerbosity;
-std::vector<std::string> gVerboseMethods;
-
unsigned int gAborting = 0;
static LogSeverity gMinimumLogSeverity = INFO;
@@ -47,14 +55,6 @@
: "art";
}
-// Configure logging based on ANDROID_LOG_TAGS environment variable.
-// We need to parse a string that looks like
-//
-// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
-//
-// The tag (or '*' for the global level) comes first, followed by a colon
-// and a letter indicating the minimum priority level we're expected to log.
-// This can be used to reveal or conceal logs with specific tags.
void InitLogging(char* argv[]) {
if (gCmdLine.get() != nullptr) {
return;
@@ -65,22 +65,22 @@
// Stash the command line for later use. We can use /proc/self/cmdline on Linux to recover this,
// but we don't have that luxury on the Mac, and there are a couple of argv[0] variants that are
// commonly used.
- if (argv != NULL) {
+ if (argv != nullptr) {
gCmdLine.reset(new std::string(argv[0]));
- for (size_t i = 1; argv[i] != NULL; ++i) {
+ for (size_t i = 1; argv[i] != nullptr; ++i) {
gCmdLine->append(" ");
gCmdLine->append(argv[i]);
}
gProgramInvocationName.reset(new std::string(argv[0]));
const char* last_slash = strrchr(argv[0], '/');
- gProgramInvocationShortName.reset(new std::string((last_slash != NULL) ? last_slash + 1
+ gProgramInvocationShortName.reset(new std::string((last_slash != nullptr) ? last_slash + 1
: argv[0]));
} else {
- // TODO: fall back to /proc/self/cmdline when argv is NULL on Linux
+ // TODO: fall back to /proc/self/cmdline when argv is NULL on Linux.
gCmdLine.reset(new std::string("<unset>"));
}
const char* tags = getenv("ANDROID_LOG_TAGS");
- if (tags == NULL) {
+ if (tags == nullptr) {
return;
}
@@ -119,47 +119,121 @@
}
}
-LogMessageData::LogMessageData(const char* file, int line, LogSeverity severity, int error)
- : file(file),
- line_number(line),
- severity(severity),
- error(error) {
- const char* last_slash = strrchr(file, '/');
- file = (last_slash == NULL) ? file : last_slash + 1;
-}
+// This indirection greatly reduces the stack impact of having
+// lots of checks/logging in a function.
+class LogMessageData {
+ public:
+ LogMessageData(const char* file, unsigned int line, LogSeverity severity, int error)
+ : file_(file),
+ line_number_(line),
+ severity_(severity),
+ error_(error) {
+ const char* last_slash = strrchr(file, '/');
+ file = (last_slash == nullptr) ? file : last_slash + 1;
+ }
+ const char * GetFile() const {
+ return file_;
+ }
+
+ unsigned int GetLineNumber() const {
+ return line_number_;
+ }
+
+ LogSeverity GetSeverity() const {
+ return severity_;
+ }
+
+ int GetError() const {
+ return error_;
+ }
+
+ std::ostream& GetBuffer() {
+ return buffer_;
+ }
+
+ std::string ToString() const {
+ return buffer_.str();
+ }
+
+ private:
+ std::ostringstream buffer_;
+ const char* const file_;
+ const unsigned int line_number_;
+ const LogSeverity severity_;
+ const int error_;
+
+ DISALLOW_COPY_AND_ASSIGN(LogMessageData);
+};
+
+
+LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, int error)
+ : data_(new LogMessageData(file, line, severity, error)) {
+}
LogMessage::~LogMessage() {
- if (data_->severity < gMinimumLogSeverity) {
+ if (data_->GetSeverity() < gMinimumLogSeverity) {
return; // No need to format something we're not going to output.
}
// Finish constructing the message.
- if (data_->error != -1) {
- data_->buffer << ": " << strerror(data_->error);
+ if (data_->GetError() != -1) {
+ data_->GetBuffer() << ": " << strerror(data_->GetError());
}
- std::string msg(data_->buffer.str());
+ std::string msg(data_->ToString());
// Do the actual logging with the lock held.
{
MutexLock mu(Thread::Current(), *Locks::logging_lock_);
if (msg.find('\n') == std::string::npos) {
- LogLine(*data_, msg.c_str());
+ LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), msg.c_str());
} else {
msg += '\n';
size_t i = 0;
while (i < msg.size()) {
size_t nl = msg.find('\n', i);
msg[nl] = '\0';
- LogLine(*data_, &msg[i]);
+ LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), &msg[i]);
i = nl + 1;
}
}
}
// Abort if necessary.
- if (data_->severity == FATAL) {
+ if (data_->GetSeverity() == FATAL) {
Runtime::Abort();
}
}
+std::ostream& LogMessage::stream() {
+ return data_->GetBuffer();
+}
+
+#ifdef HAVE_ANDROID_OS
+static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
+ ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
+ ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
+};
+COMPILE_ASSERT(arraysize(kLogSeverityToAndroidLogPriority) == INTERNAL_FATAL + 1,
+ mismatch_in_size_of_kLogSeverityToAndroidLogPriority_and_values_in_LogSeverity);
+#endif
+
+void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity log_severity,
+ const char* message) {
+#ifdef HAVE_ANDROID_OS
+ const char* tag = ProgramInvocationShortName();
+ int priority = kLogSeverityToAndroidLogPriority[log_severity];
+ if (priority == ANDROID_LOG_FATAL) {
+ LOG_PRI(priority, tag, "%s:%u] %s", file, line, message);
+ } else {
+ LOG_PRI(priority, tag, "%s", message);
+ }
+#else
+ static const char* log_characters = "VDIWEFF";
+ CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
+ char severity = log_characters[log_severity];
+ fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n",
+ ProgramInvocationShortName(), severity, getpid(), ::art::GetTid(), file, line, message);
+#endif
+}
+
} // namespace art
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
index cf3e763..baa83e3 100644
--- a/runtime/base/logging.h
+++ b/runtime/base/logging.h
@@ -17,29 +17,113 @@
#ifndef ART_RUNTIME_BASE_LOGGING_H_
#define ART_RUNTIME_BASE_LOGGING_H_
-#include <cerrno>
-#include <cstring>
-#include <iostream> // NOLINT
#include <memory>
-#include <sstream>
-#include <signal.h>
-#include <vector>
+#include <ostream>
#include "base/macros.h"
-#include "log_severity.h"
+namespace art {
+
+enum LogSeverity {
+ VERBOSE,
+ DEBUG,
+ INFO,
+ WARNING,
+ ERROR,
+ FATAL,
+ INTERNAL_FATAL, // For Runtime::Abort.
+};
+
+// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
+// and the "-verbose:" command line argument.
+struct LogVerbosity {
+ bool class_linker; // Enabled with "-verbose:class".
+ bool compiler;
+ bool gc;
+ bool heap;
+ bool jdwp;
+ bool jni;
+ bool monitor;
+ bool profiler;
+ bool signals;
+ bool startup;
+ bool third_party_jni; // Enabled with "-verbose:third-party-jni".
+ bool threads;
+ bool verifier;
+};
+
+// Global log verbosity setting, initialized by InitLogging.
+extern LogVerbosity gLogVerbosity;
+
+// 0 if not abort, non-zero if an abort is in progress. Used on fatal exit to prevents recursive
+// aborts. Global declaration allows us to disable some error checking to ensure fatal shutdown
+// makes forward progress.
+extern unsigned int gAborting;
+
+// Configure logging based on ANDROID_LOG_TAGS environment variable.
+// We need to parse a string that looks like
+//
+// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
+//
+// The tag (or '*' for the global level) comes first, followed by a colon
+// and a letter indicating the minimum priority level we're expected to log.
+// This can be used to reveal or conceal logs with specific tags.
+extern void InitLogging(char* argv[]);
+
+// Returns the command line used to invoke the current tool or nullptr if InitLogging hasn't been
+// performed.
+extern const char* GetCmdLine();
+
+// The command used to start the ART runtime, such as "/system/bin/dalvikvm". If InitLogging hasn't
+// been performed then just returns "art"
+extern const char* ProgramInvocationName();
+
+// A short version of the command used to start the ART runtime, such as "dalvikvm". If InitLogging
+// hasn't been performed then just returns "art"
+extern const char* ProgramInvocationShortName();
+
+// Logs a message to logcat on Android otherwise to stderr. If the severity is FATAL it also causes
+// an abort. For example: LOG(FATAL) << "We didn't expect to reach here";
+#define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream()
+
+// A variant of LOG that also logs the current errno value. To be used when library calls fail.
+#define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream()
+
+// Marker that code is yet to be implemented.
+#define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
+
+// Is verbose logging enabled for the given module? Where the module is defined in LogVerbosity.
+#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module)
+
+// Variant of LOG that logs when verbose logging is enabled for a module. For example,
+// VLOG(jni) << "A JNI operation was performed";
+#define VLOG(module) \
+ if (VLOG_IS_ON(module)) \
+ ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
+
+// Return the stream associated with logging for the given module.
+#define VLOG_STREAM(module) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
+
+// Check whether condition x holds and LOG(FATAL) if not. The value of the expression x is only
+// evaluated once. Extra logging can be appended using << after. For example,
+// CHECK(false == true) results in a log message of "Check failed: false == true".
#define CHECK(x) \
if (UNLIKELY(!(x))) \
- ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
+ ::art::LogMessage(__FILE__, __LINE__, ::art::FATAL, -1).stream() \
<< "Check failed: " #x << " "
+// Helper for CHECK_xx(x,y) macros.
#define CHECK_OP(LHS, RHS, OP) \
for (auto _values = ::art::MakeEagerEvaluator(LHS, RHS); \
UNLIKELY(!(_values.lhs OP _values.rhs)); /* empty */) \
- ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
+ ::art::LogMessage(__FILE__, __LINE__, ::art::FATAL, -1).stream() \
<< "Check failed: " << #LHS << " " << #OP << " " << #RHS \
<< " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") "
+
+// Check whether a condition holds between x and y, LOG(FATAL) if not. The value of the expressions
+// x and y is evaluated once. Extra logging can be appended using << after. For example,
+// CHECK_NE(0 == 1, false) results in "Check failed: false != false (0==1=false, false=false) ".
#define CHECK_EQ(x, y) CHECK_OP(x, y, ==)
#define CHECK_NE(x, y) CHECK_OP(x, y, !=)
#define CHECK_LE(x, y) CHECK_OP(x, y, <=)
@@ -47,22 +131,25 @@
#define CHECK_GE(x, y) CHECK_OP(x, y, >=)
#define CHECK_GT(x, y) CHECK_OP(x, y, >)
+// Helper for CHECK_STRxx(s1,s2) macros.
#define CHECK_STROP(s1, s2, sense) \
if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \
- LOG(FATAL) << "Check failed: " \
- << "\"" << s1 << "\"" \
- << (sense ? " == " : " != ") \
- << "\"" << s2 << "\""
+ LOG(::art::FATAL) << "Check failed: " \
+ << "\"" << s1 << "\"" \
+ << (sense ? " == " : " != ") \
+ << "\"" << s2 << "\""
+// Check for string (const char*) equality between s1 and s2, LOG(FATAL) if not.
#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)
+// Perform the pthread function call(args), LOG(FATAL) on error.
#define CHECK_PTHREAD_CALL(call, args, what) \
do { \
int rc = call args; \
if (rc != 0) { \
errno = rc; \
- PLOG(FATAL) << # call << " failed for " << what; \
+ PLOG(::art::FATAL) << # call << " failed for " << what; \
} \
} while (false)
@@ -74,81 +161,34 @@
// n / 2;
// }
#define CHECK_CONSTEXPR(x, out, dummy) \
- (UNLIKELY(!(x))) ? (LOG(FATAL) << "Check failed: " << #x out, dummy) :
+ (UNLIKELY(!(x))) ? (LOG(::art::FATAL) << "Check failed: " << #x out, dummy) :
-#ifndef NDEBUG
-#define DCHECK(x) CHECK(x)
-#define DCHECK_EQ(x, y) CHECK_EQ(x, y)
-#define DCHECK_NE(x, y) CHECK_NE(x, y)
-#define DCHECK_LE(x, y) CHECK_LE(x, y)
-#define DCHECK_LT(x, y) CHECK_LT(x, y)
-#define DCHECK_GE(x, y) CHECK_GE(x, y)
-#define DCHECK_GT(x, y) CHECK_GT(x, y)
-#define DCHECK_STREQ(s1, s2) CHECK_STREQ(s1, s2)
-#define DCHECK_STRNE(s1, s2) CHECK_STRNE(s1, s2)
-#define DCHECK_CONSTEXPR(x, out, dummy) CHECK_CONSTEXPR(x, out, dummy)
-
-#else // NDEBUG
-
-#define DCHECK(condition) \
- while (false) \
- CHECK(condition)
-
-#define DCHECK_EQ(val1, val2) \
- while (false) \
- CHECK_EQ(val1, val2)
-
-#define DCHECK_NE(val1, val2) \
- while (false) \
- CHECK_NE(val1, val2)
-
-#define DCHECK_LE(val1, val2) \
- while (false) \
- CHECK_LE(val1, val2)
-
-#define DCHECK_LT(val1, val2) \
- while (false) \
- CHECK_LT(val1, val2)
-
-#define DCHECK_GE(val1, val2) \
- while (false) \
- CHECK_GE(val1, val2)
-
-#define DCHECK_GT(val1, val2) \
- while (false) \
- CHECK_GT(val1, val2)
-
-#define DCHECK_STREQ(str1, str2) \
- while (false) \
- CHECK_STREQ(str1, str2)
-
-#define DCHECK_STRNE(str1, str2) \
- while (false) \
- CHECK_STRNE(str1, str2)
-
-#define DCHECK_CONSTEXPR(x, out, dummy) \
- (false && (x)) ? (dummy) :
-
+// DCHECKs are debug variants of CHECKs only enabled in debug builds. Generally CHECK should be
+// used unless profiling identifies a CHECK as being in performance critical code.
+#if defined(NDEBUG)
+static constexpr bool kEnableDChecks = false;
+#else
+static constexpr bool kEnableDChecks = true;
#endif
-#define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream()
-#define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream()
+#define DCHECK(x) if (::art::kEnableDChecks) CHECK(x)
+#define DCHECK_EQ(x, y) if (::art::kEnableDChecks) CHECK_EQ(x, y)
+#define DCHECK_NE(x, y) if (::art::kEnableDChecks) CHECK_NE(x, y)
+#define DCHECK_LE(x, y) if (::art::kEnableDChecks) CHECK_LE(x, y)
+#define DCHECK_LT(x, y) if (::art::kEnableDChecks) CHECK_LT(x, y)
+#define DCHECK_GE(x, y) if (::art::kEnableDChecks) CHECK_GE(x, y)
+#define DCHECK_GT(x, y) if (::art::kEnableDChecks) CHECK_GT(x, y)
+#define DCHECK_STREQ(s1, s2) if (::art::kEnableDChecks) CHECK_STREQ(s1, s2)
+#define DCHECK_STRNE(s1, s2) if (::art::kEnableDChecks) CHECK_STRNE(s1, s2)
+#if defined(NDEBUG)
+#define DCHECK_CONSTEXPR(x, out, dummy)
+#else
+#define DCHECK_CONSTEXPR(x, out, dummy) CHECK_CONSTEXPR(x, out, dummy)
+#endif
-#define LG LOG(INFO)
-
-#define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
-
-#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module)
-#define VLOG(module) if (VLOG_IS_ON(module)) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
-#define VLOG_STREAM(module) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
-
-//
-// Implementation details beyond this point.
-//
-
-namespace art {
-
+// Temporary class created to evaluate the LHS and RHS, used with MakeEagerEvaluator to infer the
+// types of LHS and RHS.
template <typename LHS, typename RHS>
struct EagerEvaluator {
EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) { }
@@ -156,10 +196,14 @@
RHS rhs;
};
-// We want char*s to be treated as pointers, not strings. If you want them treated like strings,
-// you'd need to use CHECK_STREQ and CHECK_STRNE anyway to compare the characters rather than their
-// addresses. We could express this more succinctly with std::remove_const, but this is quick and
-// easy to understand, and works before we have C++0x. We rely on signed/unsigned warnings to
+// Helper function for CHECK_xx.
+template <typename LHS, typename RHS>
+static inline EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
+ return EagerEvaluator<LHS, RHS>(lhs, rhs);
+}
+
+// Explicitly instantiate EagerEvalue for pointers so that char*s aren't treated as strings. To
+// compare strings use CHECK_STREQ and CHECK_STRNE. We rely on signed/unsigned warnings to
// protect you against combinations not explicitly listed below.
#define EAGER_PTR_EVALUATOR(T1, T2) \
template <> struct EagerEvaluator<T1, T2> { \
@@ -182,153 +226,30 @@
EAGER_PTR_EVALUATOR(signed char*, const signed char*);
EAGER_PTR_EVALUATOR(signed char*, signed char*);
-template <typename LHS, typename RHS>
-EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
- return EagerEvaluator<LHS, RHS>(lhs, rhs);
-}
+// Data for the log message, not stored in LogMessage to avoid increasing the stack size.
+class LogMessageData;
-// This indirection greatly reduces the stack impact of having
-// lots of checks/logging in a function.
-struct LogMessageData {
- public:
- LogMessageData(const char* file, int line, LogSeverity severity, int error);
- std::ostringstream buffer;
- const char* const file;
- const int line_number;
- const LogSeverity severity;
- const int error;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LogMessageData);
-};
-
+// A LogMessage is a temporarily scoped object used by LOG and the unlikely part of a CHECK. The
+// destructor will abort if the severity is FATAL.
class LogMessage {
public:
- LogMessage(const char* file, int line, LogSeverity severity, int error)
- : data_(new LogMessageData(file, line, severity, error)) {
- }
+ LogMessage(const char* file, unsigned int line, LogSeverity severity, int error);
~LogMessage(); // TODO: enable LOCKS_EXCLUDED(Locks::logging_lock_).
- std::ostream& stream() {
- return data_->buffer;
- }
+ // Returns the stream associated with the message, the LogMessage performs output when it goes
+ // out of scope.
+ std::ostream& stream();
+
+ // The routine that performs the actual logging.
+ static void LogLine(const char* file, unsigned int line, LogSeverity severity, const char* msg);
private:
- static void LogLine(const LogMessageData& data, const char*);
-
const std::unique_ptr<LogMessageData> data_;
- friend void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context);
- friend class Mutex;
DISALLOW_COPY_AND_ASSIGN(LogMessage);
};
-// A convenience to allow any class with a "Dump(std::ostream& os)" member function
-// but without an operator<< to be used as if it had an operator<<. Use like this:
-//
-// os << Dumpable<MyType>(my_type_instance);
-//
-template<typename T>
-class Dumpable {
- public:
- explicit Dumpable(T& value) : value_(value) {
- }
-
- void Dump(std::ostream& os) const {
- value_.Dump(os);
- }
-
- private:
- T& value_;
-
- DISALLOW_COPY_AND_ASSIGN(Dumpable);
-};
-
-template<typename T>
-std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) {
- rhs.Dump(os);
- return os;
-}
-
-template<typename T>
-class ConstDumpable {
- public:
- explicit ConstDumpable(const T& value) : value_(value) {
- }
-
- void Dump(std::ostream& os) const {
- value_.Dump(os);
- }
-
- private:
- const T& value_;
-
- DISALLOW_COPY_AND_ASSIGN(ConstDumpable);
-};
-
-template<typename T>
-std::ostream& operator<<(std::ostream& os, const ConstDumpable<T>& rhs) {
- rhs.Dump(os);
- return os;
-}
-
-// Helps you use operator<< in a const char*-like context such as our various 'F' methods with
-// format strings.
-template<typename T>
-class ToStr {
- public:
- explicit ToStr(const T& value) {
- std::ostringstream os;
- os << value;
- s_ = os.str();
- }
-
- const char* c_str() const {
- return s_.c_str();
- }
-
- const std::string& str() const {
- return s_;
- }
-
- private:
- std::string s_;
- DISALLOW_COPY_AND_ASSIGN(ToStr);
-};
-
-// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
-// and the "-verbose:" command line argument.
-struct LogVerbosity {
- bool class_linker; // Enabled with "-verbose:class".
- bool compiler;
- bool gc;
- bool heap;
- bool jdwp;
- bool jni;
- bool monitor;
- bool profiler;
- bool signals;
- bool startup;
- bool third_party_jni; // Enabled with "-verbose:third-party-jni".
- bool threads;
- bool verifier;
-};
-
-extern LogVerbosity gLogVerbosity;
-
-extern std::vector<std::string> gVerboseMethods;
-
-// Used on fatal exit. Prevents recursive aborts. Allows us to disable
-// some error checking to ensure fatal shutdown makes forward progress.
-extern unsigned int gAborting;
-
-extern void InitLogging(char* argv[]);
-
-extern const char* GetCmdLine();
-extern const char* ProgramInvocationName();
-extern const char* ProgramInvocationShortName();
-
} // namespace art
#endif // ART_RUNTIME_BASE_LOGGING_H_
diff --git a/runtime/base/logging_android.cc b/runtime/base/logging_android.cc
deleted file mode 100644
index 9b1ac58..0000000
--- a/runtime/base/logging_android.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2011 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 "logging.h"
-
-#include <unistd.h>
-
-#include <iostream>
-
-#include "base/stringprintf.h"
-#include "cutils/log.h"
-
-namespace art {
-
-static const int kLogSeverityToAndroidLogPriority[] = {
- ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
- ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
-};
-
-void LogMessage::LogLine(const LogMessageData& data, const char* message) {
- const char* tag = ProgramInvocationShortName();
- int priority = kLogSeverityToAndroidLogPriority[data.severity];
- if (priority == ANDROID_LOG_FATAL) {
- LOG_PRI(priority, tag, "%s:%d] %s", data.file, data.line_number, message);
- } else {
- LOG_PRI(priority, tag, "%s", message);
- }
-}
-
-} // namespace art
diff --git a/runtime/base/logging_linux.cc b/runtime/base/logging_linux.cc
deleted file mode 100644
index 0399128..0000000
--- a/runtime/base/logging_linux.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2011 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 "logging.h"
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-
-#include "base/stringprintf.h"
-#include "utils.h"
-
-namespace art {
-
-void LogMessage::LogLine(const LogMessageData& data, const char* message) {
- char severity = "VDIWEFF"[data.severity];
- fprintf(stderr, "%s %c %5d %5d %s:%d] %s\n",
- ProgramInvocationShortName(), severity, getpid(), ::art::GetTid(),
- data.file, data.line_number, message);
-}
-
-} // namespace art
diff --git a/runtime/base/macros.h b/runtime/base/macros.h
index c80d35e..febea61 100644
--- a/runtime/base/macros.h
+++ b/runtime/base/macros.h
@@ -68,22 +68,28 @@
#define ART_FRIEND_TEST(test_set_name, individual_test)\
friend class test_set_name##_##individual_test##_Test
-// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
-// It goes in the private: declarations in a class.
+// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. It goes in the private:
+// declarations in a class.
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
-// A macro to disallow all the implicit constructors, namely the
-// default constructor, copy constructor and operator= functions.
+// A macro to disallow all the implicit constructors, namely the default constructor, copy
+// constructor and operator= functions.
//
-// This should be used in the private: declarations for a class
-// that wants to prevent anyone from instantiating it. This is
-// especially useful for classes containing only static methods.
+// This should be used in the private: declarations for a class that wants to prevent anyone from
+// instantiating it. This is especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
- TypeName(); \
+ TypeName() = delete; \
DISALLOW_COPY_AND_ASSIGN(TypeName)
+// A macro to disallow new and delete operators for a class. It goes in the private: declarations.
+#define DISALLOW_ALLOCATION() \
+ public: \
+ ALWAYS_INLINE void operator delete(void*, size_t) { UNREACHABLE(); } \
+ private: \
+ void* operator new(size_t) = delete
+
// The arraysize(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
// used in defining new arrays, for example. If you use arraysize on
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index f70db35..e066787 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -21,11 +21,8 @@
#include "mutex.h"
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-
-#include "cutils/trace.h"
-
#include "base/stringprintf.h"
+#include "base/value_object.h"
#include "runtime.h"
#include "thread.h"
@@ -44,35 +41,6 @@
}
#endif // ART_USE_FUTEXES
-class ScopedContentionRecorder {
- public:
- ScopedContentionRecorder(BaseMutex* mutex, uint64_t blocked_tid, uint64_t owner_tid)
- : mutex_(kLogLockContentions ? mutex : NULL),
- blocked_tid_(kLogLockContentions ? blocked_tid : 0),
- owner_tid_(kLogLockContentions ? owner_tid : 0),
- start_nano_time_(kLogLockContentions ? NanoTime() : 0) {
- if (ATRACE_ENABLED()) {
- std::string msg = StringPrintf("Lock contention on %s (owner tid: %" PRIu64 ")",
- mutex->GetName(), owner_tid);
- ATRACE_BEGIN(msg.c_str());
- }
- }
-
- ~ScopedContentionRecorder() {
- ATRACE_END();
- if (kLogLockContentions) {
- uint64_t end_nano_time = NanoTime();
- mutex_->RecordContention(blocked_tid_, owner_tid_, end_nano_time - start_nano_time_);
- }
- }
-
- private:
- BaseMutex* const mutex_;
- const uint64_t blocked_tid_;
- const uint64_t owner_tid_;
- const uint64_t start_nano_time_;
-};
-
static inline uint64_t SafeGetTid(const Thread* self) {
if (self != NULL) {
return static_cast<uint64_t>(self->GetTid());
@@ -158,15 +126,7 @@
// Add as an extra reader.
done = state_.CompareExchangeWeakAcquire(cur_state, cur_state + 1);
} else {
- // Owner holds it exclusively, hang up.
- ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
- ++num_pending_readers_;
- if (futex(state_.Address(), FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
- if (errno != EAGAIN) {
- PLOG(FATAL) << "futex wait failed for " << name_;
- }
- }
- --num_pending_readers_;
+ HandleSharedLockContention(self, cur_state);
}
} while (!done);
#else
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 70b6f7e..6362a98 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -19,8 +19,12 @@
#include <errno.h>
#include <sys/time.h>
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include "cutils/trace.h"
+
#include "atomic.h"
#include "base/logging.h"
+#include "base/value_object.h"
#include "mutex-inl.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
@@ -106,6 +110,36 @@
const BaseMutex* const mutex_;
};
+// Scoped class that generates events at the beginning and end of lock contention.
+class ScopedContentionRecorder FINAL : public ValueObject {
+ public:
+ ScopedContentionRecorder(BaseMutex* mutex, uint64_t blocked_tid, uint64_t owner_tid)
+ : mutex_(kLogLockContentions ? mutex : NULL),
+ blocked_tid_(kLogLockContentions ? blocked_tid : 0),
+ owner_tid_(kLogLockContentions ? owner_tid : 0),
+ start_nano_time_(kLogLockContentions ? NanoTime() : 0) {
+ if (ATRACE_ENABLED()) {
+ std::string msg = StringPrintf("Lock contention on %s (owner tid: %" PRIu64 ")",
+ mutex->GetName(), owner_tid);
+ ATRACE_BEGIN(msg.c_str());
+ }
+ }
+
+ ~ScopedContentionRecorder() {
+ ATRACE_END();
+ if (kLogLockContentions) {
+ uint64_t end_nano_time = NanoTime();
+ mutex_->RecordContention(blocked_tid_, owner_tid_, end_nano_time - start_nano_time_);
+ }
+ }
+
+ private:
+ BaseMutex* const mutex_;
+ const uint64_t blocked_tid_;
+ const uint64_t owner_tid_;
+ const uint64_t start_nano_time_;
+};
+
BaseMutex::BaseMutex(const char* name, LockLevel level) : level_(level), name_(name) {
if (kLogLockContentions) {
ScopedAllMutexesLock mu(this);
@@ -428,9 +462,9 @@
if (this != Locks::logging_lock_) {
LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_;
} else {
- LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1);
- LogMessage::LogLine(data, StringPrintf("Unexpected state_ %d in unlock for %s",
- cur_state, name_).c_str());
+ LogMessage::LogLine(__FILE__, __LINE__, INTERNAL_FATAL,
+ StringPrintf("Unexpected state_ %d in unlock for %s",
+ cur_state, name_).c_str());
_exit(1);
}
}
@@ -612,6 +646,18 @@
}
#endif
+void ReaderWriterMutex::HandleSharedLockContention(Thread* self, int32_t cur_state) {
+ // Owner holds it exclusively, hang up.
+ ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
+ ++num_pending_readers_;
+ if (futex(state_.Address(), FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
+ if (errno != EAGAIN) {
+ PLOG(FATAL) << "futex wait failed for " << name_;
+ }
+ }
+ --num_pending_readers_;
+}
+
bool ReaderWriterMutex::SharedTryLock(Thread* self) {
DCHECK(self == NULL || self == Thread::Current());
#if ART_USE_FUTEXES
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 516fa07..25fdd59 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -360,6 +360,9 @@
virtual void Dump(std::ostream& os) const;
private:
+ // Out-of-inline path for handling contention for a SharedLock.
+ void HandleSharedLockContention(Thread* self, int32_t cur_state);
+
#if ART_USE_FUTEXES
// -1 implies held exclusive, +ve shared held by state_ many owners.
AtomicInteger state_;
diff --git a/runtime/base/stringpiece.cc b/runtime/base/stringpiece.cc
index 824ee48..2570bad 100644
--- a/runtime/base/stringpiece.cc
+++ b/runtime/base/stringpiece.cc
@@ -16,7 +16,7 @@
#include "stringpiece.h"
-#include <iostream>
+#include <ostream>
#include <utility>
#include "logging.h"
diff --git a/runtime/base/to_str.h b/runtime/base/to_str.h
new file mode 100644
index 0000000..6b1c84c
--- /dev/null
+++ b/runtime/base/to_str.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_RUNTIME_BASE_TO_STR_H_
+#define ART_RUNTIME_BASE_TO_STR_H_
+
+#include <sstream>
+
+namespace art {
+
+// Helps you use operator<< in a const char*-like context such as our various 'F' methods with
+// format strings.
+template<typename T>
+class ToStr {
+ public:
+ explicit ToStr(const T& value) {
+ std::ostringstream os;
+ os << value;
+ s_ = os.str();
+ }
+
+ const char* c_str() const {
+ return s_.c_str();
+ }
+
+ const std::string& str() const {
+ return s_;
+ }
+
+ private:
+ std::string s_;
+ DISALLOW_COPY_AND_ASSIGN(ToStr);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_BASE_TO_STR_H_
diff --git a/runtime/base/unix_file/mapped_file.cc b/runtime/base/unix_file/mapped_file.cc
index 63927b1..77f4d02 100644
--- a/runtime/base/unix_file/mapped_file.cc
+++ b/runtime/base/unix_file/mapped_file.cc
@@ -42,7 +42,7 @@
struct stat st;
int result = TEMP_FAILURE_RETRY(fstat(Fd(), &st));
if (result == -1) {
- PLOG(WARNING) << "Failed to stat file '" << GetPath() << "'";
+ PLOG(::art::WARNING) << "Failed to stat file '" << GetPath() << "'";
return false;
}
file_size_ = st.st_size;
@@ -50,8 +50,8 @@
mapped_file_ = mmap(NULL, file_size_, PROT_READ, MAP_PRIVATE, Fd(), 0);
} while (mapped_file_ == MAP_FAILED && errno == EINTR);
if (mapped_file_ == MAP_FAILED) {
- PLOG(WARNING) << "Failed to mmap file '" << GetPath() << "' of size "
- << file_size_ << " bytes to memory";
+ PLOG(::art::WARNING) << "Failed to mmap file '" << GetPath() << "' of size "
+ << file_size_ << " bytes to memory";
return false;
}
map_mode_ = kMapReadOnly;
@@ -67,8 +67,7 @@
int result = TEMP_FAILURE_RETRY(ftruncate(Fd(), file_size));
#endif
if (result == -1) {
- PLOG(ERROR) << "Failed to truncate file '" << GetPath()
- << "' to size " << file_size;
+ PLOG(::art::ERROR) << "Failed to truncate file '" << GetPath() << "' to size " << file_size;
return false;
}
file_size_ = file_size;
@@ -77,7 +76,7 @@
mmap(NULL, file_size_, PROT_READ | PROT_WRITE, MAP_SHARED, Fd(), 0);
} while (mapped_file_ == MAP_FAILED && errno == EINTR);
if (mapped_file_ == MAP_FAILED) {
- PLOG(WARNING) << "Failed to mmap file '" << GetPath() << "' of size "
+ PLOG(::art::WARNING) << "Failed to mmap file '" << GetPath() << "' of size "
<< file_size_ << " bytes to memory";
return false;
}
@@ -89,8 +88,7 @@
CHECK(IsMapped());
int result = TEMP_FAILURE_RETRY(munmap(mapped_file_, file_size_));
if (result == -1) {
- PLOG(WARNING) << "Failed unmap file '" << GetPath() << "' of size "
- << file_size_;
+ PLOG(::art::WARNING) << "Failed unmap file '" << GetPath() << "' of size " << file_size_;
return false;
} else {
mapped_file_ = NULL;
diff --git a/runtime/base/value_object.h b/runtime/base/value_object.h
index ee0e2a0..8c752a9 100644
--- a/runtime/base/value_object.h
+++ b/runtime/base/value_object.h
@@ -17,19 +17,13 @@
#ifndef ART_RUNTIME_BASE_VALUE_OBJECT_H_
#define ART_RUNTIME_BASE_VALUE_OBJECT_H_
-#include "base/logging.h"
+#include "base/macros.h"
namespace art {
class ValueObject {
- public:
- void* operator new(size_t size) {
- LOG(FATAL) << "UNREACHABLE";
- abort();
- }
- void operator delete(void*, size_t) {
- LOG(FATAL) << "UNREACHABLE";
- }
+ private:
+ DISALLOW_ALLOCATION();
};
} // namespace art
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index fec1824..b2df091 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -20,6 +20,7 @@
#include <zlib.h>
#include "base/logging.h"
+#include "base/to_str.h"
#include "class_linker.h"
#include "class_linker-inl.h"
#include "dex_file-inl.h"
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 8c2293f..9d2d59c 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -37,7 +37,7 @@
CHECK_EQ(GetDexPc(), DexFile::kDexNoIndex);
}
- if (!m || m->IsNative() || m->IsRuntimeMethod() || IsShadowFrame()) {
+ if (m == nullptr || m->IsNative() || m->IsRuntimeMethod() || IsShadowFrame()) {
return true;
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index bbbb9e0..f6717fb 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -17,6 +17,7 @@
#include "class_linker.h"
#include <deque>
+#include <iostream>
#include <memory>
#include <queue>
#include <string>
@@ -5110,7 +5111,7 @@
bool seen_non_ref = false;
for (size_t i = 0; i < num_fields; i++) {
mirror::ArtField* field = fields->Get(i);
- if (false) { // enable to debug field layout
+ if ((false)) { // enable to debug field layout
LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance")
<< " class=" << PrettyClass(klass.Get())
<< " field=" << PrettyField(field)
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index ea3da64..6e3ebc2 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -44,7 +44,7 @@
int main(int argc, char **argv) {
art::InitLogging(argv);
- LOG(INFO) << "Running main() from common_runtime_test.cc...";
+ LOG(::art::INFO) << "Running main() from common_runtime_test.cc...";
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index b676c62..18bbc38 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -4116,7 +4116,6 @@
HeapChunkContext(bool merge, bool native)
: buf_(16384 - 16),
type_(0),
- merge_(merge),
chunk_overhead_(0) {
Reset();
if (native) {
@@ -4327,7 +4326,6 @@
void* startOfNextMemoryChunk_;
size_t totalAllocationUnits_;
uint32_t type_;
- bool merge_;
bool needHeader_;
size_t chunk_overhead_;
@@ -4678,7 +4676,7 @@
* between the contents of these tables.
*/
jbyteArray Dbg::GetRecentAllocations() {
- if (false) {
+ if ((false)) {
DumpRecentAllocations();
}
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index f408386..78cbe58 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -23,7 +23,9 @@
#include <string.h>
#include <sys/file.h>
#include <sys/stat.h>
+
#include <memory>
+#include <sstream>
#include "base/logging.h"
#include "base/stringprintf.h"
diff --git a/runtime/dex_instruction.cc b/runtime/dex_instruction.cc
index 7e775f4..af38433 100644
--- a/runtime/dex_instruction.cc
+++ b/runtime/dex_instruction.cc
@@ -19,6 +19,7 @@
#include <inttypes.h>
#include <iomanip>
+#include <sstream>
#include "base/stringprintf.h"
#include "dex_file-inl.h"
diff --git a/runtime/dex_instruction_visitor_test.cc b/runtime/dex_instruction_visitor_test.cc
index c5e63eb..5273084 100644
--- a/runtime/dex_instruction_visitor_test.cc
+++ b/runtime/dex_instruction_visitor_test.cc
@@ -16,7 +16,6 @@
#include "dex_instruction_visitor.h"
-#include <iostream>
#include <memory>
#include "gtest/gtest.h"
diff --git a/runtime/dex_method_iterator_test.cc b/runtime/dex_method_iterator_test.cc
index b8f180b..c6f333f 100644
--- a/runtime/dex_method_iterator_test.cc
+++ b/runtime/dex_method_iterator_test.cc
@@ -38,8 +38,8 @@
const DexFile& dex_file = it.GetDexFile();
InvokeType invoke_type = it.GetInvokeType();
uint32_t method_idx = it.GetMemberIndex();
- if (false) {
- LG << invoke_type << " " << PrettyMethod(method_idx, dex_file);
+ if ((false)) {
+ LOG(INFO) << invoke_type << " " << PrettyMethod(method_idx, dex_file);
}
it.Next();
}
diff --git a/runtime/elf_utils.h b/runtime/elf_utils.h
index 676cd52..7b00bad 100644
--- a/runtime/elf_utils.h
+++ b/runtime/elf_utils.h
@@ -24,6 +24,8 @@
#include "base/logging.h"
+namespace art {
+
// Architecture dependent flags for the ELF header.
#define EF_ARM_EABI_VER5 0x05000000
#define EF_MIPS_ABI_O32 0x00001000
@@ -163,4 +165,6 @@
}
}
+} // namespace art
+
#endif // ART_RUNTIME_ELF_UTILS_H_
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index 6b3e9dc..f78273f 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -52,7 +52,7 @@
uint64_t fpr_result)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Compute address of return PC and sanity check that it currently holds 0.
- uint32_t return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, Runtime::kRefsOnly);
+ size_t return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, Runtime::kRefsOnly);
uintptr_t* return_pc = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(sp) +
return_pc_offset);
CHECK_EQ(*return_pc, 0U);
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index c239535..c1276b5 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -15,6 +15,7 @@
*/
#include "entrypoints/entrypoint_utils-inl.h"
+#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
#include "thread-inl.h"
#include "verify_object-inl.h"
diff --git a/runtime/gc/allocator/dlmalloc.cc b/runtime/gc/allocator/dlmalloc.cc
index a6a3ee7..fbeba7f 100644
--- a/runtime/gc/allocator/dlmalloc.cc
+++ b/runtime/gc/allocator/dlmalloc.cc
@@ -39,11 +39,11 @@
static void art_heap_corruption(const char* function) {
- LOG(FATAL) << "Corrupt heap detected in: " << function;
+ LOG(::art::FATAL) << "Corrupt heap detected in: " << function;
}
static void art_heap_usage_error(const char* function, void* p) {
- LOG(FATAL) << "Incorrect use of function '" << function << "' argument " << p << " not expected";
+ LOG(::art::FATAL) << "Incorrect use of function '" << function << "' argument " << p << " not expected";
}
#include "globals.h"
@@ -63,7 +63,7 @@
int rc = madvise(start, length, MADV_DONTNEED);
if (UNLIKELY(rc != 0)) {
errno = rc;
- PLOG(FATAL) << "madvise failed during heap trimming";
+ PLOG(::art::FATAL) << "madvise failed during heap trimming";
}
size_t* reclaimed = reinterpret_cast<size_t*>(arg);
*reclaimed += length;
diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc
index a3da532..fa531a7 100644
--- a/runtime/gc/allocator/rosalloc.cc
+++ b/runtime/gc/allocator/rosalloc.cc
@@ -24,6 +24,7 @@
#include <map>
#include <list>
+#include <sstream>
#include <vector>
namespace art {
@@ -1143,7 +1144,7 @@
size_t RosAlloc::BulkFree(Thread* self, void** ptrs, size_t num_ptrs) {
size_t freed_bytes = 0;
- if (false) {
+ if ((false)) {
// Used only to test Free() as GC uses only BulkFree().
for (size_t i = 0; i < num_ptrs; ++i) {
freed_bytes += FreeInternal(self, ptrs[i]);
diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index 07b61e6..9e6a800 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -18,6 +18,10 @@
#include "garbage_collector.h"
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include "cutils/trace.h"
+
+#include "base/dumpable.h"
#include "base/histogram-inl.h"
#include "base/logging.h"
#include "base/mutex-inl.h"
@@ -188,7 +192,7 @@
if (iterations == 0) {
return;
}
- os << ConstDumpable<CumulativeLogger>(logger);
+ os << Dumpable<CumulativeLogger>(logger);
const uint64_t total_ns = logger.GetTotalNs();
double seconds = NsToMs(logger.GetTotalNs()) / 1000.0;
const uint64_t freed_bytes = GetTotalFreedBytes();
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 942b556..83da063 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -21,6 +21,9 @@
#include <climits>
#include <vector>
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include "cutils/trace.h"
+
#include "base/bounded_fifo.h"
#include "base/logging.h"
#include "base/macros.h"
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 9459a3b..e141b6f 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -16,9 +16,10 @@
#include "semi_space-inl.h"
+#include <climits>
#include <functional>
#include <numeric>
-#include <climits>
+#include <sstream>
#include <vector>
#include "base/logging.h"
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b9d69d5..c2baa29 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -24,6 +24,7 @@
#include <vector>
#include "base/allocator.h"
+#include "base/dumpable.h"
#include "base/histogram-inl.h"
#include "base/stl_util.h"
#include "common_throws.h"
@@ -2178,7 +2179,7 @@
<< percent_free << "% free, " << PrettySize(current_heap_size) << "/"
<< PrettySize(total_memory) << ", " << "paused " << pause_string.str()
<< " total " << PrettyDuration((duration / 1000) * 1000);
- VLOG(heap) << ConstDumpable<TimingLogger>(*current_gc_iteration_.GetTimings());
+ VLOG(heap) << Dumpable<TimingLogger>(*current_gc_iteration_.GetTimings());
}
FinishGC(self, gc_type);
// Inform DDMS that a GC completed.
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index ba85c55..ff1e38b 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -601,9 +601,6 @@
void RemoveRememberedSet(space::Space* space);
bool IsCompilingBoot() const;
- bool RunningOnValgrind() const {
- return running_on_valgrind_;
- }
bool HasImageSpace() const;
ReferenceProcessor* GetReferenceProcessor() {
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 39d82cc..d479038 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -21,6 +21,7 @@
#include <random>
+#include "base/macros.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "base/scoped_flock.h"
diff --git a/runtime/gc/space/malloc_space.h b/runtime/gc/space/malloc_space.h
index 7230116..cfde460 100644
--- a/runtime/gc/space/malloc_space.h
+++ b/runtime/gc/space/malloc_space.h
@@ -19,7 +19,7 @@
#include "space.h"
-#include <iostream>
+#include <ostream>
#include <valgrind.h>
#include <memcheck/memcheck.h>
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index d25694a..161eba9 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -17,6 +17,9 @@
#include "rosalloc_space-inl.h"
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include "cutils/trace.h"
+
#include "gc/accounting/card_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
@@ -73,8 +76,9 @@
uint8_t* begin = mem_map->Begin();
// TODO: Fix RosAllocSpace to support valgrind. There is currently some issues with
// AllocationSize caused by redzones. b/12944686
- if (false && Runtime::Current()->GetHeap()->RunningOnValgrind()) {
- LOG(FATAL) << "Unimplemented";
+ if (Runtime::Current()->RunningOnValgrind()) {
+ UNIMPLEMENTED(FATAL);
+ UNREACHABLE();
} else {
return new RosAllocSpace(name, mem_map, rosalloc, begin, end, begin + capacity, growth_limit,
can_move_objects, starting_size, initial_size, low_memory_mode);
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index c1455fd..4d177a3 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -126,7 +126,7 @@
}
table_[index].Add(obj);
result = ToIndirectRef(index);
- if (false) {
+ if ((false)) {
LOG(INFO) << "+++ added at " << ExtractIndex(result) << " top=" << segment_state_.parts.topIndex
<< " holes=" << segment_state_.parts.numHoles;
}
@@ -193,7 +193,7 @@
int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles;
if (numHoles != 0) {
while (--topIndex > bottomIndex && numHoles != 0) {
- if (false) {
+ if ((false)) {
LOG(INFO) << "+++ checking for hole at " << topIndex - 1
<< " (cookie=" << cookie << ") val="
<< table_[topIndex - 1].GetReference()->Read<kWithoutReadBarrier>();
@@ -201,7 +201,7 @@
if (!table_[topIndex - 1].GetReference()->IsNull()) {
break;
}
- if (false) {
+ if ((false)) {
LOG(INFO) << "+++ ate hole at " << (topIndex - 1);
}
numHoles--;
@@ -210,7 +210,7 @@
segment_state_.parts.topIndex = topIndex;
} else {
segment_state_.parts.topIndex = topIndex-1;
- if (false) {
+ if ((false)) {
LOG(INFO) << "+++ ate last entry " << topIndex - 1;
}
}
@@ -228,7 +228,7 @@
*table_[idx].GetReference() = GcRoot<mirror::Object>(nullptr);
segment_state_.parts.numHoles++;
- if (false) {
+ if ((false)) {
LOG(INFO) << "+++ left hole at " << idx << ", holes=" << segment_state_.parts.numHoles;
}
}
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index adbece0..f981522 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -18,12 +18,15 @@
#include <sys/uio.h>
+#include <sstream>
+
#include "arch/context.h"
#include "atomic.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "debugger.h"
#include "dex_file-inl.h"
+#include "entrypoints/quick/quick_entrypoints.h"
#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc_root-inl.h"
@@ -34,9 +37,6 @@
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "nth_caller_visitor.h"
-#if !defined(ART_USE_PORTABLE_COMPILER)
-#include "entrypoints/quick/quick_entrypoints.h"
-#endif
#include "os.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index a8345ad..fa03fc7 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -21,6 +21,9 @@
#include <math.h>
+#include <iostream>
+#include <sstream>
+
#include "base/logging.h"
#include "class_linker-inl.h"
#include "common_throws.h"
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index fed8bf0..19e03d8 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -18,6 +18,7 @@
#include <dlfcn.h>
+#include "base/dumpable.h"
#include "base/mutex.h"
#include "base/stl_util.h"
#include "check_jni.h"
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 70754f2..ad06b85 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -2705,7 +2705,7 @@
os << "JNIWeakGlobalRefType";
return os;
default:
- LOG(FATAL) << "jobjectRefType[" << static_cast<int>(rhs) << "]";
- return os;
+ LOG(::art::FATAL) << "jobjectRefType[" << static_cast<int>(rhs) << "]";
+ UNREACHABLE();
}
}
diff --git a/runtime/log_severity.h b/runtime/log_severity.h
deleted file mode 100644
index 31682df..0000000
--- a/runtime/log_severity.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef ART_RUNTIME_LOG_SEVERITY_H_
-#define ART_RUNTIME_LOG_SEVERITY_H_
-
-typedef int LogSeverity;
-
-const int VERBOSE = 0, DEBUG = 1, INFO = 2, WARNING = 3, ERROR = 4, FATAL = 5;
-const int INTERNAL_FATAL = 6; // For Runtime::Abort.
-
-#endif // ART_RUNTIME_LOG_SEVERITY_H_
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 3144ce1..c118471 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -15,11 +15,12 @@
*/
#include "mem_map.h"
-#include "thread-inl.h"
-#include <inttypes.h>
#include <backtrace/BacktraceMap.h>
+#include <inttypes.h>
+
#include <memory>
+#include <sstream>
// See CreateStartPos below.
#ifdef __BIONIC__
@@ -28,6 +29,7 @@
#include "base/stringprintf.h"
#include "ScopedFd.h"
+#include "thread-inl.h"
#include "utils.h"
#define USE_ASHMEM 1
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 1bbcf8e..b2b2420 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -478,6 +478,7 @@
friend struct art::ObjectOffsets; // for verifying offset information
friend class CopyObjectVisitor; // for CopyObject().
friend class CopyClassVisitor; // for CopyObject().
+ DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
};
diff --git a/runtime/native/scoped_fast_native_object_access.h b/runtime/native/scoped_fast_native_object_access.h
index 606d62d..dfabff5 100644
--- a/runtime/native/scoped_fast_native_object_access.h
+++ b/runtime/native/scoped_fast_native_object_access.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_
#define ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_
-#include "mirror/art_method.h"
+#include "mirror/art_method-inl.h"
#include "scoped_thread_state_change.h"
namespace art {
diff --git a/runtime/offsets.cc b/runtime/offsets.cc
index 3691401..f59ed88 100644
--- a/runtime/offsets.cc
+++ b/runtime/offsets.cc
@@ -16,7 +16,7 @@
#include "offsets.h"
-#include <iostream> // NOLINT
+#include <ostream>
namespace art {
diff --git a/runtime/offsets.h b/runtime/offsets.h
index 72a6b0f..9d5063f 100644
--- a/runtime/offsets.h
+++ b/runtime/offsets.h
@@ -17,7 +17,8 @@
#ifndef ART_RUNTIME_OFFSETS_H_
#define ART_RUNTIME_OFFSETS_H_
-#include <iostream> // NOLINT
+#include <ostream>
+
#include "globals.h"
namespace art {
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index dcca9d3..6b64c25 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -16,6 +16,8 @@
#include "parsed_options.h"
+#include <sstream>
+
#ifdef HAVE_ANDROID_OS
#include "cutils/properties.h"
#endif
@@ -534,9 +536,6 @@
return false;
}
}
- } else if (StartsWith(option, "-verbose-methods:")) {
- gLogVerbosity.compiler = false;
- Split(option.substr(strlen("-verbose-methods:")), ',', &gVerboseMethods);
} else if (StartsWith(option, "-Xlockprofthreshold:")) {
if (!ParseUnsignedInteger(option, ':', &lock_profiling_threshold_)) {
return false;
diff --git a/runtime/profiler.cc b/runtime/profiler.cc
index 1d06d35..e399195 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -97,7 +97,7 @@
switch (profile_options.GetProfileType()) {
case kProfilerMethod: {
mirror::ArtMethod* method = thread->GetCurrentMethod(nullptr);
- if (false && method == nullptr) {
+ if ((false) && method == nullptr) {
LOG(INFO) << "No current method available";
std::ostringstream os;
thread->Dump(os);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 8e57837..c58735a 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -300,7 +300,7 @@
InstrumentationStackVisitor(Thread* self, bool is_deoptimization, size_t frame_depth)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: StackVisitor(self, nullptr),
- self_(self), frame_depth_(frame_depth),
+ frame_depth_(frame_depth),
instrumentation_frames_to_pop_(0) {
CHECK_NE(frame_depth_, kInvalidFrameDepth);
}
@@ -324,7 +324,6 @@
}
private:
- Thread* const self_;
const size_t frame_depth_;
size_t instrumentation_frames_to_pop_;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 50cdf8e..8ba098f 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -45,6 +45,7 @@
#include "arch/x86_64/registers_x86_64.h"
#include "asm_support.h"
#include "atomic.h"
+#include "base/dumpable.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "debugger.h"
@@ -208,7 +209,7 @@
}
struct AbortState {
- void Dump(std::ostream& os) {
+ void Dump(std::ostream& os) const {
if (gAborting > 1) {
os << "Runtime aborting --- recursively, so no thread-specific detail!\n";
return;
@@ -239,7 +240,7 @@
}
// No thread-safety analysis as we do explicitly test for holding the mutator lock.
- void DumpThread(std::ostream& os, Thread* self) NO_THREAD_SAFETY_ANALYSIS {
+ void DumpThread(std::ostream& os, Thread* self) const NO_THREAD_SAFETY_ANALYSIS {
DCHECK(Locks::mutator_lock_->IsExclusiveHeld(self) || Locks::mutator_lock_->IsSharedHeld(self));
self->Dump(os);
if (self->IsExceptionPending()) {
@@ -251,7 +252,7 @@
}
}
- void DumpAllThreads(std::ostream& os, Thread* self) {
+ void DumpAllThreads(std::ostream& os, Thread* self) const {
Runtime* runtime = Runtime::Current();
if (runtime != nullptr) {
ThreadList* thread_list = runtime->GetThreadList();
diff --git a/runtime/runtime_android.cc b/runtime/runtime_android.cc
index 079d7e5..33600dd 100644
--- a/runtime/runtime_android.cc
+++ b/runtime/runtime_android.cc
@@ -32,13 +32,12 @@
struct sigaction old_action;
void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context) {
- static bool handlingUnexpectedSignal = false;
- if (handlingUnexpectedSignal) {
- LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1);
- LogMessage::LogLine(data, "HandleUnexpectedSignal reentered\n");
+ static bool handling_unexpected_signal = false;
+ if (handling_unexpected_signal) {
+ LogMessage::LogLine(__FILE__, __LINE__, INTERNAL_FATAL, "HandleUnexpectedSignal reentered\n");
_exit(1);
}
- handlingUnexpectedSignal = true;
+ handling_unexpected_signal = true;
gAborting++; // set before taking any locks
MutexLock mu(Thread::Current(), *Locks::unexpected_signal_lock_);
diff --git a/runtime/runtime_linux.cc b/runtime/runtime_linux.cc
index 46ee274..1de035c 100644
--- a/runtime/runtime_linux.cc
+++ b/runtime/runtime_linux.cc
@@ -21,6 +21,9 @@
#include <sys/utsname.h>
#include <inttypes.h>
+#include <sstream>
+
+#include "base/dumpable.h"
#include "base/logging.h"
#include "base/mutex.h"
#include "base/stringprintf.h"
@@ -32,13 +35,13 @@
static constexpr bool kDumpHeapObjectOnSigsevg = false;
struct Backtrace {
- void Dump(std::ostream& os) {
+ void Dump(std::ostream& os) const {
DumpNativeStack(os, GetTid(), "\t");
}
};
struct OsInfo {
- void Dump(std::ostream& os) {
+ void Dump(std::ostream& os) const {
utsname info;
uname(&info);
// Linux 2.6.38.8-gg784 (x86_64)
@@ -132,9 +135,11 @@
}
struct UContext {
- explicit UContext(void* raw_context) : context(reinterpret_cast<ucontext_t*>(raw_context)->uc_mcontext) {}
+ explicit UContext(void* raw_context) :
+ context(reinterpret_cast<ucontext_t*>(raw_context)->uc_mcontext) {
+ }
- void Dump(std::ostream& os) {
+ void Dump(std::ostream& os) const {
// TODO: support non-x86 hosts (not urgent because this code doesn't run on targets).
#if defined(__APPLE__) && defined(__i386__)
DumpRegister32(os, "eax", context->__ss.__eax);
@@ -228,15 +233,15 @@
#endif
}
- void DumpRegister32(std::ostream& os, const char* name, uint32_t value) {
+ void DumpRegister32(std::ostream& os, const char* name, uint32_t value) const {
os << StringPrintf(" %6s: 0x%08x", name, value);
}
- void DumpRegister64(std::ostream& os, const char* name, uint64_t value) {
+ void DumpRegister64(std::ostream& os, const char* name, uint64_t value) const {
os << StringPrintf(" %6s: 0x%016" PRIx64, name, value);
}
- void DumpX86Flags(std::ostream& os, uint32_t flags) {
+ void DumpX86Flags(std::ostream& os, uint32_t flags) const {
os << " [";
if ((flags & (1 << 0)) != 0) {
os << " CF";
@@ -274,8 +279,7 @@
void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context) {
static bool handlingUnexpectedSignal = false;
if (handlingUnexpectedSignal) {
- LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1);
- LogMessage::LogLine(data, "HandleUnexpectedSignal reentered\n");
+ LogMessage::LogLine(__FILE__, __LINE__, INTERNAL_FATAL, "HandleUnexpectedSignal reentered\n");
_exit(1);
}
handlingUnexpectedSignal = true;
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index 336340e..d4ec803 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -25,6 +25,8 @@
#include <sys/types.h>
#include <unistd.h>
+#include <sstream>
+
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "gc/heap.h"
@@ -131,7 +133,7 @@
runtime->DumpForSigQuit(os);
- if (false) {
+ if ((false)) {
std::string maps;
if (ReadFileToString("/proc/self/maps", &maps)) {
os << "/proc/self/maps:\n" << maps;
diff --git a/runtime/thread.cc b/runtime/thread.cc
index f93b15b..9c04133 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -29,9 +29,11 @@
#include <cerrno>
#include <iostream>
#include <list>
+#include <sstream>
#include "arch/context.h"
#include "base/mutex.h"
+#include "base/to_str.h"
#include "class_linker-inl.h"
#include "class_linker.h"
#include "debugger.h"
diff --git a/runtime/thread_linux.cc b/runtime/thread_linux.cc
index 1254056..0284364 100644
--- a/runtime/thread_linux.cc
+++ b/runtime/thread_linux.cc
@@ -16,6 +16,8 @@
#include "thread.h"
+#include <signal.h>
+
namespace art {
void Thread::SetNativePriority(int) {
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 646830a..6e18904 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -25,6 +25,8 @@
#include <sys/types.h>
#include <unistd.h>
+#include <sstream>
+
#include "base/mutex.h"
#include "base/mutex-inl.h"
#include "base/timing_logger.h"
@@ -480,17 +482,18 @@
VLOG(threads) << "Resume(" << reinterpret_cast<void*>(thread) << ") complete";
}
-static void ThreadSuspendByPeerWarning(Thread* self, int level, const char* message, jobject peer) {
+static void ThreadSuspendByPeerWarning(Thread* self, LogSeverity severity, const char* message,
+ jobject peer) {
JNIEnvExt* env = self->GetJniEnv();
ScopedLocalRef<jstring>
scoped_name_string(env, (jstring)env->GetObjectField(peer,
WellKnownClasses::java_lang_Thread_name));
ScopedUtfChars scoped_name_chars(env, scoped_name_string.get());
if (scoped_name_chars.c_str() == NULL) {
- LOG(level) << message << ": " << peer;
+ LOG(severity) << message << ": " << peer;
env->ExceptionClear();
} else {
- LOG(level) << message << ": " << peer << ":" << scoped_name_chars.c_str();
+ LOG(severity) << message << ": " << peer << ":" << scoped_name_chars.c_str();
}
}
@@ -562,8 +565,9 @@
}
}
-static void ThreadSuspendByThreadIdWarning(int level, const char* message, uint32_t thread_id) {
- LOG(level) << StringPrintf("%s: %d", message, thread_id);
+static void ThreadSuspendByThreadIdWarning(LogSeverity severity, const char* message,
+ uint32_t thread_id) {
+ LOG(severity) << StringPrintf("%s: %d", message, thread_id);
}
Thread* ThreadList::SuspendThreadByThreadId(uint32_t thread_id, bool debug_suspension,
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 91a37fd..b3158a4 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -18,6 +18,9 @@
#include <sys/uio.h>
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include "cutils/trace.h"
+
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 4a3c3ec..fc3c879 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -18,6 +18,8 @@
#include <stdlib.h>
+#include <sstream>
+
#include "base/logging.h"
#include "mirror/class.h"
#include "ScopedLocalRef.h"
diff --git a/sigchainlib/sigchain_dummy.cc b/sigchainlib/sigchain_dummy.cc
index fbc8c3f..17bfe8f 100644
--- a/sigchainlib/sigchain_dummy.cc
+++ b/sigchainlib/sigchain_dummy.cc
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#include <stdio.h>
+#include <stdlib.h>
+
#ifdef HAVE_ANDROID_OS
#include <android/log.h>
#else
@@ -21,8 +24,6 @@
#include <iostream>
#endif
-#include <stdlib.h>
-
#include "sigchain.h"
static void log(const char* format, ...) {
diff --git a/test/115-native-bridge/run b/test/115-native-bridge/run
index e475cd6..32a9975 100644
--- a/test/115-native-bridge/run
+++ b/test/115-native-bridge/run
@@ -18,9 +18,9 @@
# Use libnativebridgetest as a native bridge, start NativeBridgeMain (Main is JniTest main file).
LIBPATH=$(echo ${ARGS} | sed -r 's/.*Djava.library.path=([^ ]*) .*/\1/')
-cp ${LIBPATH}/libnativebridgetest.so .
+ln -s ${LIBPATH}/libnativebridgetest.so .
touch libarttest.so
-cp ${LIBPATH}/libarttest.so libarttest2.so
+ln -s ${LIBPATH}/libarttest.so libarttest2.so
# pwd likely has /, so it's a pain to put that into a sed rule.
LEFT=$(echo ${ARGS} | sed -r 's/-Djava.library.path.*//')
diff --git a/test/411-optimizing-arith/src/Main.java b/test/411-optimizing-arith/src/Main.java
index ab8a83f..4de2271 100644
--- a/test/411-optimizing-arith/src/Main.java
+++ b/test/411-optimizing-arith/src/Main.java
@@ -16,7 +16,6 @@
// Note that $opt$ is a marker for the optimizing compiler to ensure
// it does compile the method.
-
public class Main {
public static void expectEquals(int expected, int result) {
@@ -31,29 +30,140 @@
}
}
+ public static void expectEquals(float expected, float result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ public static void expectEquals(double expected, double result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ public static void expectApproxEquals(float a, float b, float maxDelta) {
+ boolean aproxEquals = (a > b)
+ ? ((a - b) < maxDelta)
+ : ((b - a) < maxDelta);
+ if (!aproxEquals) {
+ throw new Error("Expected: " + a + ", found: " + b + ", with delta: " + maxDelta);
+ }
+ }
+
+ public static void expectApproxEquals(double a, double b, double maxDelta) {
+ boolean aproxEquals = (a > b)
+ ? ((a - b) < maxDelta)
+ : ((b - a) < maxDelta);
+ if (!aproxEquals) {
+ throw new Error("Expected: " + a + ", found: " + b + ", with delta: " + maxDelta);
+ }
+ }
+
+ public static void expectNaN(float a) {
+ if (a == a) {
+ throw new Error("Expected NaN: " + a);
+ }
+ }
+
+ public static void expectNaN(double a) {
+ if (a == a) {
+ throw new Error("Expected NaN: " + a);
+ }
+ }
+
public static void main(String[] args) {
mul();
neg();
}
public static void mul() {
+ mulInt();
+ mulLong();
+ mulFloat();
+ mulDouble();
+ }
+
+ private static void mulInt() {
expectEquals(15, $opt$Mul(5, 3));
+ expectEquals(0, $opt$Mul(0, 0));
expectEquals(0, $opt$Mul(0, 3));
expectEquals(0, $opt$Mul(3, 0));
expectEquals(-3, $opt$Mul(1, -3));
expectEquals(36, $opt$Mul(-12, -3));
expectEquals(33, $opt$Mul(1, 3) * 11);
expectEquals(671088645, $opt$Mul(134217729, 5)); // (2^27 + 1) * 5
+ }
+ private static void mulLong() {
expectEquals(15L, $opt$Mul(5L, 3L));
+ expectEquals(0L, $opt$Mul(0L, 0L));
expectEquals(0L, $opt$Mul(0L, 3L));
expectEquals(0L, $opt$Mul(3L, 0L));
expectEquals(-3L, $opt$Mul(1L, -3L));
expectEquals(36L, $opt$Mul(-12L, -3L));
- expectEquals(33L, $opt$Mul(1L, 3L) * 11);
+ expectEquals(33L, $opt$Mul(1L, 3L) * 11F);
expectEquals(240518168583L, $opt$Mul(34359738369L, 7L)); // (2^35 + 1) * 7
}
+ private static void mulFloat() {
+ expectApproxEquals(15F, $opt$Mul(5F, 3F), 0.0001F);
+ expectApproxEquals(0F, $opt$Mul(0F, 0F), 0.0001F);
+ expectApproxEquals(0F, $opt$Mul(0F, 3F), 0.0001F);
+ expectApproxEquals(0F, $opt$Mul(3F, 0F), 0.0001F);
+ expectApproxEquals(-3F, $opt$Mul(1F, -3F), 0.0001F);
+ expectApproxEquals(36F, $opt$Mul(-12F, -3F), 0.0001F);
+ expectApproxEquals(33F, $opt$Mul(1F, 3F) * 11F, 0.0001F);
+ expectApproxEquals(0.02F, 0.1F * 0.2F, 0.0001F);
+ expectApproxEquals(-0.1F, -0.5F * 0.2F, 0.0001F);
+
+ expectNaN($opt$Mul(0F, Float.POSITIVE_INFINITY));
+ expectNaN($opt$Mul(0F, Float.NEGATIVE_INFINITY));
+ expectNaN($opt$Mul(Float.NaN, 11F));
+ expectNaN($opt$Mul(Float.NaN, -11F));
+ expectNaN($opt$Mul(Float.NaN, Float.NEGATIVE_INFINITY));
+ expectNaN($opt$Mul(Float.NaN, Float.POSITIVE_INFINITY));
+
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Mul(2F, 3.40282346638528860e+38F));
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Mul(2F, Float.POSITIVE_INFINITY));
+ expectEquals(Float.NEGATIVE_INFINITY, $opt$Mul(-2F, Float.POSITIVE_INFINITY));
+ expectEquals(Float.NEGATIVE_INFINITY, $opt$Mul(-2F, 3.40282346638528860e+38F));
+ expectEquals(Float.NEGATIVE_INFINITY, $opt$Mul(2F, Float.NEGATIVE_INFINITY));
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Mul(-2F, Float.NEGATIVE_INFINITY));
+ expectEquals(Float.NEGATIVE_INFINITY, $opt$Mul(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY));
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Mul(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY));
+ expectEquals(Float.POSITIVE_INFINITY, $opt$Mul(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY));
+ }
+
+ private static void mulDouble() {
+ expectApproxEquals(15D, $opt$Mul(5D, 3D), 0.0001D);
+ expectApproxEquals(0D, $opt$Mul(0D, 0D), 0.0001D);
+ expectApproxEquals(0D, $opt$Mul(0D, 3D), 0.0001D);
+ expectApproxEquals(0D, $opt$Mul(3D, 0D), 0.0001D);
+ expectApproxEquals(-3D, $opt$Mul(1D, -3D), 0.0001D);
+ expectApproxEquals(36D, $opt$Mul(-12D, -3D), 0.0001D);
+ expectApproxEquals(33D, $opt$Mul(1D, 3D) * 11D, 0.0001D);
+ expectApproxEquals(0.02D, 0.1D * 0.2D, 0.0001D);
+ expectApproxEquals(-0.1D, -0.5D * 0.2D, 0.0001D);
+
+ expectNaN($opt$Mul(0D, Double.POSITIVE_INFINITY));
+ expectNaN($opt$Mul(0D, Double.NEGATIVE_INFINITY));
+ expectNaN($opt$Mul(Double.NaN, 11D));
+ expectNaN($opt$Mul(Double.NaN, -11D));
+ expectNaN($opt$Mul(Double.NaN, Double.NEGATIVE_INFINITY));
+ expectNaN($opt$Mul(Double.NaN, Double.POSITIVE_INFINITY));
+
+ expectEquals(Double.POSITIVE_INFINITY, $opt$Mul(2D, 1.79769313486231570e+308));
+ expectEquals(Double.POSITIVE_INFINITY, $opt$Mul(2D, Double.POSITIVE_INFINITY));
+ expectEquals(Double.NEGATIVE_INFINITY, $opt$Mul(-2D, Double.POSITIVE_INFINITY));
+ expectEquals(Double.NEGATIVE_INFINITY, $opt$Mul(-2D, 1.79769313486231570e+308));
+ expectEquals(Double.NEGATIVE_INFINITY, $opt$Mul(2D, Double.NEGATIVE_INFINITY));
+ expectEquals(Double.POSITIVE_INFINITY, $opt$Mul(-2D, Double.NEGATIVE_INFINITY));
+ expectEquals(Double.NEGATIVE_INFINITY, $opt$Mul(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
+ expectEquals(Double.POSITIVE_INFINITY, $opt$Mul(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
+ expectEquals(Double.POSITIVE_INFINITY, $opt$Mul(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
+ }
+
public static void neg() {
expectEquals(-1, $opt$Neg(1));
expectEquals(1, $opt$Neg(-1));
@@ -90,7 +200,16 @@
return a * b;
}
+ static float $opt$Mul(float a, float b) {
+ return a * b;
+ }
+
+ static double $opt$Mul(double a, double b) {
+ return a * b;
+ }
+
static int $opt$Neg(int a){
return -a;
}
+
}
diff --git a/test/Android.libarttest.mk b/test/Android.libarttest.mk
index fd95038..55de1f3 100644
--- a/test/Android.libarttest.mk
+++ b/test/Android.libarttest.mk
@@ -58,8 +58,7 @@
ifeq ($$(art_target_or_host),target)
$(call set-target-local-clang-vars)
$(call set-target-local-cflags-vars,debug)
- LOCAL_SHARED_LIBRARIES += libdl libcutils
- LOCAL_STATIC_LIBRARIES := libgtest
+ LOCAL_SHARED_LIBRARIES += libdl
LOCAL_MULTILIB := both
LOCAL_MODULE_PATH_32 := $(ART_TARGET_TEST_OUT)/$(ART_TARGET_ARCH_32)
LOCAL_MODULE_PATH_64 := $(ART_TARGET_TEST_OUT)/$(ART_TARGET_ARCH_64)
@@ -68,11 +67,7 @@
else # host
LOCAL_CLANG := $(ART_HOST_CLANG)
LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
- LOCAL_STATIC_LIBRARIES := libcutils
LOCAL_LDLIBS := $(ART_HOST_LDLIBS) -ldl -lpthread
- ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt
- endif
LOCAL_IS_HOST_MODULE := true
LOCAL_MULTILIB := both
include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/test/Android.libnativebridgetest.mk b/test/Android.libnativebridgetest.mk
index 5e2493c..1b20e69 100644
--- a/test/Android.libnativebridgetest.mk
+++ b/test/Android.libnativebridgetest.mk
@@ -51,7 +51,7 @@
ifeq ($$(art_target_or_host),target)
$(call set-target-local-clang-vars)
$(call set-target-local-cflags-vars,debug)
- LOCAL_SHARED_LIBRARIES += libdl libcutils
+ LOCAL_SHARED_LIBRARIES += libdl
LOCAL_STATIC_LIBRARIES := libgtest
LOCAL_MULTILIB := both
LOCAL_MODULE_PATH_32 := $(ART_TARGET_TEST_OUT)/$(ART_TARGET_ARCH_32)
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 5fff69e..427e0b1 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -66,11 +66,6 @@
########################################################################
# General rules to build and run a run-test.
-# Test rule names or of the form:
-# test-art-{1: host or target}-run-test-{2: prebuild no-prebuild no-dex2oat}-
-# {3: interpreter default optimizing}-{4: relocate no-relocate relocate-no-patchoat}-
-# {5: trace or no-trace}-{6: gcstress gcverify cms}-{7: forcecopy checkjni jni}-
-# {8: no-image or image}-{9: test name}{10: 32 or 64}
TARGET_TYPES := host target
PREBUILD_TYPES := prebuild
ifeq ($(ART_TEST_RUN_TEST_NO_PREBUILD),true)
@@ -289,8 +284,8 @@
ifneq (,$(filter default,$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
- defaut,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
- $(IMAGE_TYPES),$(TEST_ART_BROKEN_FALLBACK_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+ default,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
+ $(IMAGE_TYPES),$(TEST_ART_BROKEN_DEFAULT_RUN_TESTS),$(ALL_ADDRESS_SIZES))
endif
TEST_ART_BROKEN_DEFAULT_RUN_TESTS :=
@@ -360,7 +355,7 @@
endif
# Create a rule to build and run a tests following the form:
-# test-art-{1: host or target}-run-test-{2:debug ndebug}-{3: prebuild no-prebuild no-dex2oat}-
+# test-art-{1: host or target}-run-test-{2: debug ndebug}-{3: prebuild no-prebuild no-dex2oat}-
# {4: interpreter default optimizing}-{5: relocate no-relocate relocate-no-patchoat}-
# {6: trace or no-trace}-{7: gcstress gcverify cms}-{8: forcecopy checkjni jni}-
# {9: no-image image}-{10: test name}{11: 32 or 64}
diff --git a/test/run-test b/test/run-test
index 73ffc31..2ef3ab1 100755
--- a/test/run-test
+++ b/test/run-test
@@ -469,9 +469,6 @@
file_size_limit=5120
elif echo "$test_dir" | grep 083; then
file_size_limit=5120
-elif echo "$test_dir" | grep 115; then
-# Native bridge test copies libarttest.so into its directory, which needs 2MB already.
- file_size_limit=5120
fi
if ! ulimit -S "$file_size_limit"; then
echo "ulimit file size setting failed"