Merge "MIPS32: Implement table-based packed switch"
diff --git a/Android.bp b/Android.bp
index 77b9ac3..f7e909d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -22,11 +22,15 @@
"build",
"compiler",
"dalvikvm",
+ "dex2oat",
"dexdump",
"dexlayout",
"dexlist",
"disassembler",
+ "imgdiag",
"oatdump",
+ "patchoat",
+ "profman",
"runtime",
"sigchainlib",
"tools/cpp-define-generator",
diff --git a/Android.mk b/Android.mk
index 5a17379..d43118c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,11 +76,7 @@
########################################################################
# product rules
-include $(art_path)/dex2oat/Android.mk
include $(art_path)/oatdump/Android.mk
-include $(art_path)/imgdiag/Android.mk
-include $(art_path)/patchoat/Android.mk
-include $(art_path)/profman/Android.mk
include $(art_path)/tools/Android.mk
include $(art_path)/tools/ahat/Android.mk
include $(art_path)/tools/dexfuzz/Android.mk
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index e88d027..00d29b9 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -114,29 +114,33 @@
ART_TARGET_SHARED_LIBRARY_DEPENDENCIES += $(foreach lib,$(ART_CORE_SHARED_LIBRARIES), $(2ND_TARGET_OUT_SHARED_LIBRARIES)/$(lib).so)
endif
-ART_CORE_EXECUTABLES := \
+ART_CORE_DEBUGGABLE_EXECUTABLES := \
dex2oat \
imgdiag \
oatdump \
patchoat \
profman \
+ART_CORE_EXECUTABLES := \
+ dalvikvm \
+ dexlist \
+
# Depend on the -target or -host phony targets generated by the build system
# for each module
-ART_TARGET_EXECUTABLES := dalvikvm-target
+ART_TARGET_EXECUTABLES :=
ifneq ($(ART_BUILD_TARGET_NDEBUG),false)
-ART_TARGET_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES),$(name)-target)
+ART_TARGET_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES) $(ART_CORE_DEBUGGABLE_EXECUTABLES),$(name)-target)
endif
ifneq ($(ART_BUILD_TARGET_DEBUG),false)
-ART_TARGET_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES),$(name)d-target)
+ART_TARGET_EXECUTABLES += $(foreach name,$(ART_CORE_DEBUGGABLE_EXECUTABLES),$(name)d-target)
endif
-ART_HOST_EXECUTABLES := dalvikvm-host
+ART_HOST_EXECUTABLES :=
ifneq ($(ART_BUILD_HOST_NDEBUG),false)
-ART_HOST_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES),$(name)-host)
+ART_HOST_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES) $(ART_CORE_DEBUGGABLE_EXECUTABLES),$(name)-host)
endif
ifneq ($(ART_BUILD_HOST_DEBUG),false)
-ART_HOST_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES),$(name)d-host)
+ART_HOST_EXECUTABLES += $(foreach name,$(ART_CORE_DEBUGGABLE_EXECUTABLES),$(name)d-host)
endif
endif # ART_ANDROID_COMMON_PATH_MK
diff --git a/build/Android.executable.mk b/build/Android.executable.mk
index c35833d..f38a14d 100644
--- a/build/Android.executable.mk
+++ b/build/Android.executable.mk
@@ -249,20 +249,3 @@
)
)
endef
-
-# Note: the order is important because of static linking resolution.
-ART_STATIC_DEPENDENCIES := \
- libziparchive \
- libnativehelper \
- libnativebridge \
- libnativeloader \
- libsigchain_dummy \
- liblog \
- libz \
- libbacktrace \
- libcutils \
- libunwindbacktrace \
- libutils \
- libbase \
- liblz4 \
- liblzma
diff --git a/build/art.go b/build/art.go
index da4609d..f694505 100644
--- a/build/art.go
+++ b/build/art.go
@@ -181,6 +181,7 @@
func init() {
soong.RegisterModuleType("art_cc_library", artLibrary)
soong.RegisterModuleType("art_cc_binary", artBinary)
+ soong.RegisterModuleType("art_cc_test", artTest)
soong.RegisterModuleType("art_cc_defaults", artDefaultsFactory)
soong.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory)
}
@@ -221,6 +222,15 @@
return module, props
}
+func artTest() (blueprint.Module, []interface{}) {
+ test := cc.NewTest(android.HostAndDeviceSupported)
+ module, props := test.Init()
+
+ android.AddCustomizer(test, &artCustomLinkerCustomizer{})
+ android.AddCustomizer(test, &artPrefer32BitCustomizer{})
+ return module, props
+}
+
func envDefault(ctx android.BaseContext, key string, defaultValue string) string {
ret := ctx.AConfig().Getenv(key)
if ret == "" {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index daac7fb..53e068e 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -72,6 +72,7 @@
#include "utils/swap_space.h"
#include "verifier/method_verifier.h"
#include "verifier/method_verifier-inl.h"
+#include "verifier/verifier_log_mode.h"
namespace art {
@@ -2258,7 +2259,7 @@
class VerifyClassVisitor : public CompilationVisitor {
public:
- VerifyClassVisitor(const ParallelCompilationManager* manager, LogSeverity log_level)
+ VerifyClassVisitor(const ParallelCompilationManager* manager, verifier::HardFailLogMode log_level)
: manager_(manager), log_level_(log_level) {}
virtual void Visit(size_t class_def_index) REQUIRES(!Locks::mutator_lock_) OVERRIDE {
@@ -2329,7 +2330,7 @@
private:
const ParallelCompilationManager* const manager_;
- const LogSeverity log_level_;
+ const verifier::HardFailLogMode log_level_;
};
void CompilerDriver::VerifyDexFile(jobject class_loader,
@@ -2342,9 +2343,9 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files,
thread_pool);
- LogSeverity log_level = GetCompilerOptions().AbortOnHardVerifierFailure()
- ? LogSeverity::INTERNAL_FATAL
- : LogSeverity::WARNING;
+ verifier::HardFailLogMode log_level = GetCompilerOptions().AbortOnHardVerifierFailure()
+ ? verifier::HardFailLogMode::kLogInternalFatal
+ : verifier::HardFailLogMode::kLogWarning;
VerifyClassVisitor visitor(&context, log_level);
context.ForAll(0, dex_file.NumClassDefs(), &visitor, thread_count);
}
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 78e9ca9..24d102d 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -453,7 +453,7 @@
EXPECT_EQ(72U, sizeof(OatHeader));
EXPECT_EQ(4U, sizeof(OatMethodOffsets));
EXPECT_EQ(20U, sizeof(OatQuickMethodHeader));
- EXPECT_EQ(164 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
+ EXPECT_EQ(163 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
sizeof(QuickEntryPoints));
}
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 2087888..6732670 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -1081,13 +1081,6 @@
}
}
-bool CodeGenerator::IsImplicitNullCheckAllowed(HNullCheck* null_check) const {
- return compiler_options_.GetImplicitNullChecks() &&
- // Null checks which might throw into a catch block need to save live
- // registers and therefore cannot be done implicitly.
- !null_check->CanThrowIntoCatchBlock();
-}
-
bool CodeGenerator::CanMoveNullCheckToUser(HNullCheck* null_check) {
HInstruction* first_next_not_move = null_check->GetNextDisregardingMoves();
@@ -1096,6 +1089,10 @@
}
void CodeGenerator::MaybeRecordImplicitNullCheck(HInstruction* instr) {
+ if (!compiler_options_.GetImplicitNullChecks()) {
+ return;
+ }
+
// If we are from a static path don't record the pc as we can't throw NPE.
// NB: having the checks here makes the code much less verbose in the arch
// specific code generators.
@@ -1114,16 +1111,35 @@
// and needs to record the pc.
if (first_prev_not_move != nullptr && first_prev_not_move->IsNullCheck()) {
HNullCheck* null_check = first_prev_not_move->AsNullCheck();
- if (IsImplicitNullCheckAllowed(null_check)) {
- // TODO: The parallel moves modify the environment. Their changes need to be
- // reverted otherwise the stack maps at the throw point will not be correct.
- RecordPcInfo(null_check, null_check->GetDexPc());
- }
+ // TODO: The parallel moves modify the environment. Their changes need to be
+ // reverted otherwise the stack maps at the throw point will not be correct.
+ RecordPcInfo(null_check, null_check->GetDexPc());
}
}
+LocationSummary* CodeGenerator::CreateNullCheckLocations(HNullCheck* null_check) {
+ // Note: Using kNoCall allows the method to be treated as leaf (and eliminate the
+ // HSuspendCheck from entry block). However, it will still get a valid stack frame
+ // because the HNullCheck needs an environment.
+ LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
+ // When throwing from a try block, we may need to retrieve dalvik registers from
+ // physical registers and we also need to set up stack mask for GC. This is
+ // implicitly achieved by passing kCallOnSlowPath to the LocationSummary.
+ bool can_throw_into_catch_block = null_check->CanThrowIntoCatchBlock();
+ if (can_throw_into_catch_block) {
+ call_kind = LocationSummary::kCallOnSlowPath;
+ }
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(null_check, call_kind);
+ if (can_throw_into_catch_block && compiler_options_.GetImplicitNullChecks()) {
+ locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ }
+ locations->SetInAt(0, Location::RequiresRegister());
+ DCHECK(!null_check->HasUses());
+ return locations;
+}
+
void CodeGenerator::GenerateNullCheck(HNullCheck* instruction) {
- if (IsImplicitNullCheckAllowed(instruction)) {
+ if (compiler_options_.GetImplicitNullChecks()) {
MaybeRecordStat(kImplicitNullCheckGenerated);
GenerateImplicitNullCheck(instruction);
} else {
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 0c60a98..b4d4b9b 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -313,6 +313,7 @@
bool CanMoveNullCheckToUser(HNullCheck* null_check);
void MaybeRecordImplicitNullCheck(HInstruction* instruction);
+ LocationSummary* CreateNullCheckLocations(HNullCheck* null_check);
void GenerateNullCheck(HNullCheck* null_check);
virtual void GenerateImplicitNullCheck(HNullCheck* null_check) = 0;
virtual void GenerateExplicitNullCheck(HNullCheck* null_check) = 0;
@@ -322,12 +323,6 @@
// TODO: Replace with a catch-entering instruction that records the environment.
void RecordCatchBlockInfo();
- // Returns true if implicit null checks are allowed in the compiler options
- // and if the null check is not inside a try block. We currently cannot do
- // implicit null checks in that case because we need the NullCheckSlowPath to
- // save live registers, which may be needed by the runtime to set catch phis.
- bool IsImplicitNullCheckAllowed(HNullCheck* null_check) const;
-
// TODO: Avoid creating the `std::unique_ptr` here.
void AddSlowPath(SlowPathCode* slow_path) {
slow_paths_.push_back(std::unique_ptr<SlowPathCode>(slow_path));
@@ -713,6 +708,8 @@
bool is_leaf_;
// Whether an instruction in the graph accesses the current method.
+ // TODO: Rename: this actually indicates that some instruction in the method
+ // needs the environment including a valid stack frame.
bool requires_current_method_;
friend class OptimizingCFITest;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 3cc2598f..40c2b9c 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -4251,14 +4251,7 @@
}
void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
- locations->SetInAt(0, Location::RequiresRegister());
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
+ codegen_->CreateNullCheckLocations(instruction);
}
void CodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 179bf76..c00ab56 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4384,14 +4384,7 @@
}
void LocationsBuilderARM64::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
- locations->SetInAt(0, Location::RequiresRegister());
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
+ codegen_->CreateNullCheckLocations(instruction);
}
void CodeGeneratorARM64::GenerateImplicitNullCheck(HNullCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 306538c..b767aa5 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -5075,14 +5075,7 @@
}
void LocationsBuilderMIPS::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
- locations->SetInAt(0, Location::RequiresRegister());
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
+ codegen_->CreateNullCheckLocations(instruction);
}
void CodeGeneratorMIPS::GenerateImplicitNullCheck(HNullCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 664d498..4d87523 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -3461,14 +3461,7 @@
}
void LocationsBuilderMIPS64::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
- locations->SetInAt(0, Location::RequiresRegister());
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
+ codegen_->CreateNullCheckLocations(instruction);
}
void CodeGeneratorMIPS64::GenerateImplicitNullCheck(HNullCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index e18b366..28db29c 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4950,16 +4950,10 @@
}
void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
- Location loc = codegen_->IsImplicitNullCheckAllowed(instruction)
- ? Location::RequiresRegister()
- : Location::Any();
- locations->SetInAt(0, loc);
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
+ LocationSummary* locations = codegen_->CreateNullCheckLocations(instruction);
+ if (!codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
+ // Explicit null checks can use any location.
+ locations->SetInAt(0, Location::Any());
}
}
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 15307fe..88d98fc 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -4459,16 +4459,10 @@
}
void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
- Location loc = codegen_->IsImplicitNullCheckAllowed(instruction)
- ? Location::RequiresRegister()
- : Location::Any();
- locations->SetInAt(0, loc);
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
+ LocationSummary* locations = codegen_->CreateNullCheckLocations(instruction);
+ if (!codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
+ // Explicit null checks can use any location.
+ locations->SetInAt(0, Location::Any());
}
}
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index d00a786..d9347f6 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -74,6 +74,24 @@
namespace art {
+typedef CodeGenerator* (*CreateCodegenFn)(HGraph*, const CompilerOptions&);
+
+class CodegenTargetConfig {
+ public:
+ CodegenTargetConfig(InstructionSet isa, CreateCodegenFn create_codegen)
+ : isa_(isa), create_codegen_(create_codegen) {
+ }
+ InstructionSet GetInstructionSet() const { return isa_; }
+ CodeGenerator* CreateCodeGenerator(HGraph* graph, const CompilerOptions& compiler_options) {
+ return create_codegen_(graph, compiler_options);
+ }
+
+ private:
+ CodegenTargetConfig() {}
+ InstructionSet isa_;
+ CreateCodegenFn create_codegen_;
+};
+
#ifdef ART_ENABLE_CODEGEN_arm
// Provide our own codegen, that ensures the C calling conventions
// are preserved. Currently, ART and C do not match as R4 is caller-save
@@ -222,12 +240,7 @@
VerifyGeneratedCode(target_isa, f, has_result, expected);
}
-template <typename Expected>
-static void RunCode(CodeGenerator* codegen,
- HGraph* graph,
- std::function<void(HGraph*)> hook_before_codegen,
- bool has_result,
- Expected expected) {
+static void ValidateGraph(HGraph* graph) {
GraphChecker graph_checker(graph);
graph_checker.Run();
if (!graph_checker.IsValid()) {
@@ -236,92 +249,129 @@
}
}
ASSERT_TRUE(graph_checker.IsValid());
+}
+template <typename Expected>
+static void RunCodeNoCheck(CodeGenerator* codegen,
+ HGraph* graph,
+ std::function<void(HGraph*)> hook_before_codegen,
+ bool has_result,
+ Expected expected) {
SsaLivenessAnalysis liveness(graph, codegen);
-
PrepareForRegisterAllocation(graph).Run();
liveness.Analyze();
RegisterAllocator::Create(graph->GetArena(), codegen, liveness)->AllocateRegisters();
hook_before_codegen(graph);
-
InternalCodeAllocator allocator;
codegen->Compile(&allocator);
Run(allocator, *codegen, has_result, expected);
}
template <typename Expected>
-static void RunCode(InstructionSet target_isa,
+static void RunCode(CodeGenerator* codegen,
+ HGraph* graph,
+ std::function<void(HGraph*)> hook_before_codegen,
+ bool has_result,
+ Expected expected) {
+ ValidateGraph(graph);
+ RunCodeNoCheck(codegen, graph, hook_before_codegen, has_result, expected);
+}
+
+template <typename Expected>
+static void RunCode(CodegenTargetConfig target_config,
HGraph* graph,
std::function<void(HGraph*)> hook_before_codegen,
bool has_result,
Expected expected) {
CompilerOptions compiler_options;
-#ifdef ART_ENABLE_CODEGEN_arm
- if (target_isa == kArm || target_isa == kThumb2) {
- std::unique_ptr<const ArmInstructionSetFeatures> features_arm(
- ArmInstructionSetFeatures::FromCppDefines());
- TestCodeGeneratorARM codegenARM(graph, *features_arm.get(), compiler_options);
- RunCode(&codegenARM, graph, hook_before_codegen, has_result, expected);
- }
-#endif
-#ifdef ART_ENABLE_CODEGEN_arm64
- if (target_isa == kArm64) {
- std::unique_ptr<const Arm64InstructionSetFeatures> features_arm64(
- Arm64InstructionSetFeatures::FromCppDefines());
- arm64::CodeGeneratorARM64 codegenARM64(graph, *features_arm64.get(), compiler_options);
- RunCode(&codegenARM64, graph, hook_before_codegen, has_result, expected);
- }
-#endif
-#ifdef ART_ENABLE_CODEGEN_x86
- if (target_isa == kX86) {
- std::unique_ptr<const X86InstructionSetFeatures> features_x86(
- X86InstructionSetFeatures::FromCppDefines());
- TestCodeGeneratorX86 codegenX86(graph, *features_x86.get(), compiler_options);
- RunCode(&codegenX86, graph, hook_before_codegen, has_result, expected);
- }
-#endif
-#ifdef ART_ENABLE_CODEGEN_x86_64
- if (target_isa == kX86_64) {
- std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64(
- X86_64InstructionSetFeatures::FromCppDefines());
- x86_64::CodeGeneratorX86_64 codegenX86_64(graph, *features_x86_64.get(), compiler_options);
- RunCode(&codegenX86_64, graph, hook_before_codegen, has_result, expected);
- }
-#endif
-#ifdef ART_ENABLE_CODEGEN_mips
- if (target_isa == kMips) {
- std::unique_ptr<const MipsInstructionSetFeatures> features_mips(
- MipsInstructionSetFeatures::FromCppDefines());
- mips::CodeGeneratorMIPS codegenMIPS(graph, *features_mips.get(), compiler_options);
- RunCode(&codegenMIPS, graph, hook_before_codegen, has_result, expected);
- }
-#endif
-#ifdef ART_ENABLE_CODEGEN_mips64
- if (target_isa == kMips64) {
- std::unique_ptr<const Mips64InstructionSetFeatures> features_mips64(
- Mips64InstructionSetFeatures::FromCppDefines());
- mips64::CodeGeneratorMIPS64 codegenMIPS64(graph, *features_mips64.get(), compiler_options);
- RunCode(&codegenMIPS64, graph, hook_before_codegen, has_result, expected);
- }
-#endif
+ CodeGenerator* codegen = target_config.CreateCodeGenerator(graph, compiler_options);
+ RunCode(codegen, graph, hook_before_codegen, has_result, expected);
}
-static ::std::vector<InstructionSet> GetTargetISAs() {
- ::std::vector<InstructionSet> v;
- // Add all ISAs that are executable on hardware or on simulator.
- const ::std::vector<InstructionSet> executable_isa_candidates = {
- kArm,
- kArm64,
- kThumb2,
- kX86,
- kX86_64,
- kMips,
- kMips64
+#ifdef ART_ENABLE_CODEGEN_arm
+CodeGenerator* create_codegen_arm(HGraph* graph, const CompilerOptions& compiler_options) {
+ std::unique_ptr<const ArmInstructionSetFeatures> features_arm(
+ ArmInstructionSetFeatures::FromCppDefines());
+ return new (graph->GetArena()) TestCodeGeneratorARM(graph,
+ *features_arm.get(),
+ compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_arm64
+CodeGenerator* create_codegen_arm64(HGraph* graph, const CompilerOptions& compiler_options) {
+ std::unique_ptr<const Arm64InstructionSetFeatures> features_arm64(
+ Arm64InstructionSetFeatures::FromCppDefines());
+ return new (graph->GetArena()) arm64::CodeGeneratorARM64(graph,
+ *features_arm64.get(),
+ compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_x86
+CodeGenerator* create_codegen_x86(HGraph* graph, const CompilerOptions& compiler_options) {
+ std::unique_ptr<const X86InstructionSetFeatures> features_x86(
+ X86InstructionSetFeatures::FromCppDefines());
+ return new (graph->GetArena()) TestCodeGeneratorX86(graph, *features_x86.get(), compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_x86_64
+CodeGenerator* create_codegen_x86_64(HGraph* graph, const CompilerOptions& compiler_options) {
+ std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64(
+ X86_64InstructionSetFeatures::FromCppDefines());
+ return new (graph->GetArena())
+ x86_64::CodeGeneratorX86_64(graph, *features_x86_64.get(), compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_mips
+CodeGenerator* create_codegen_mips(HGraph* graph, const CompilerOptions& compiler_options) {
+ std::unique_ptr<const MipsInstructionSetFeatures> features_mips(
+ MipsInstructionSetFeatures::FromCppDefines());
+ return new (graph->GetArena())
+ mips::CodeGeneratorMIPS(graph, *features_mips.get(), compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_mips64
+CodeGenerator* create_codegen_mips64(HGraph* graph, const CompilerOptions& compiler_options) {
+ std::unique_ptr<const Mips64InstructionSetFeatures> features_mips64(
+ Mips64InstructionSetFeatures::FromCppDefines());
+ return new (graph->GetArena())
+ mips64::CodeGeneratorMIPS64(graph, *features_mips64.get(), compiler_options);
+}
+#endif
+
+// Return all combinations of ISA and code generator that are executable on
+// hardware, or on simulator, and that we'd like to test.
+static ::std::vector<CodegenTargetConfig> GetTargetConfigs() {
+ ::std::vector<CodegenTargetConfig> v;
+ ::std::vector<CodegenTargetConfig> test_config_candidates = {
+#ifdef ART_ENABLE_CODEGEN_arm
+ CodegenTargetConfig(kArm, create_codegen_arm),
+ CodegenTargetConfig(kThumb2, create_codegen_arm),
+#endif
+#ifdef ART_ENABLE_CODEGEN_arm64
+ CodegenTargetConfig(kArm64, create_codegen_arm64),
+#endif
+#ifdef ART_ENABLE_CODEGEN_x86
+ CodegenTargetConfig(kX86, create_codegen_x86),
+#endif
+#ifdef ART_ENABLE_CODEGEN_x86_64
+ CodegenTargetConfig(kX86_64, create_codegen_x86_64),
+#endif
+#ifdef ART_ENABLE_CODEGEN_mips
+ CodegenTargetConfig(kMips, create_codegen_mips),
+#endif
+#ifdef ART_ENABLE_CODEGEN_mips64
+ CodegenTargetConfig(kMips64, create_codegen_mips64)
+#endif
};
- for (auto target_isa : executable_isa_candidates) {
- if (CanExecute(target_isa)) {
- v.push_back(target_isa);
+ for (auto test_config : test_config_candidates) {
+ if (CanExecute(test_config.GetInstructionSet())) {
+ v.push_back(test_config);
}
}
@@ -331,26 +381,26 @@
static void TestCode(const uint16_t* data,
bool has_result = false,
int32_t expected = 0) {
- for (InstructionSet target_isa : GetTargetISAs()) {
+ for (CodegenTargetConfig target_config : GetTargetConfigs()) {
ArenaPool pool;
ArenaAllocator arena(&pool);
HGraph* graph = CreateCFG(&arena, data);
// Remove suspend checks, they cannot be executed in this context.
RemoveSuspendChecks(graph);
- RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
+ RunCode(target_config, graph, [](HGraph*) {}, has_result, expected);
}
}
static void TestCodeLong(const uint16_t* data,
bool has_result,
int64_t expected) {
- for (InstructionSet target_isa : GetTargetISAs()) {
+ for (CodegenTargetConfig target_config : GetTargetConfigs()) {
ArenaPool pool;
ArenaAllocator arena(&pool);
HGraph* graph = CreateCFG(&arena, data, Primitive::kPrimLong);
// Remove suspend checks, they cannot be executed in this context.
RemoveSuspendChecks(graph);
- RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
+ RunCode(target_config, graph, [](HGraph*) {}, has_result, expected);
}
}
@@ -667,7 +717,7 @@
}
TEST_F(CodegenTest, NonMaterializedCondition) {
- for (InstructionSet target_isa : GetTargetISAs()) {
+ for (CodegenTargetConfig target_config : GetTargetConfigs()) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
@@ -715,12 +765,12 @@
block->InsertInstructionBefore(move, block->GetLastInstruction());
};
- RunCode(target_isa, graph, hook_before_codegen, true, 0);
+ RunCode(target_config, graph, hook_before_codegen, true, 0);
}
}
TEST_F(CodegenTest, MaterializedCondition1) {
- for (InstructionSet target_isa : GetTargetISAs()) {
+ for (CodegenTargetConfig target_config : GetTargetConfigs()) {
// Check that condition are materialized correctly. A materialized condition
// should yield `1` if it evaluated to true, and `0` otherwise.
// We force the materialization of comparisons for different combinations of
@@ -762,13 +812,13 @@
HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
block->InsertInstructionBefore(move, block->GetLastInstruction());
};
- RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
+ RunCode(target_config, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
}
}
}
TEST_F(CodegenTest, MaterializedCondition2) {
- for (InstructionSet target_isa : GetTargetISAs()) {
+ for (CodegenTargetConfig target_config : GetTargetConfigs()) {
// Check that HIf correctly interprets a materialized condition.
// We force the materialization of comparisons for different combinations of
// inputs. An HIf takes the materialized combination as input and returns a
@@ -830,7 +880,7 @@
HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
block->InsertInstructionBefore(move, block->GetLastInstruction());
};
- RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
+ RunCode(target_config, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
}
}
}
@@ -859,7 +909,7 @@
int64_t i,
int64_t j,
Primitive::Type type,
- const InstructionSet target_isa) {
+ const CodegenTargetConfig target_config) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
HGraph* graph = CreateGraph(&allocator);
@@ -941,23 +991,16 @@
block->AddInstruction(new (&allocator) HReturn(comparison));
graph->BuildDominatorTree();
- RunCode(target_isa, graph, [](HGraph*) {}, true, expected_result);
+ RunCode(target_config, graph, [](HGraph*) {}, true, expected_result);
}
TEST_F(CodegenTest, ComparisonsInt) {
- for (InstructionSet target_isa : GetTargetISAs()) {
+ for (CodegenTargetConfig target_config : GetTargetConfigs()) {
for (int64_t i = -1; i <= 1; i++) {
for (int64_t j = -1; j <= 1; j++) {
- TestComparison(kCondEQ, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondNE, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondLT, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondLE, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondGT, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondGE, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondB, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondBE, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondA, i, j, Primitive::kPrimInt, target_isa);
- TestComparison(kCondAE, i, j, Primitive::kPrimInt, target_isa);
+ for (int cond = kCondFirst; cond <= kCondLast; cond++) {
+ TestComparison(static_cast<IfCondition>(cond), i, j, Primitive::kPrimInt, target_config);
+ }
}
}
}
@@ -969,23 +1012,17 @@
return;
}
- for (InstructionSet target_isa : GetTargetISAs()) {
- if (target_isa == kMips || target_isa == kMips64) {
+ for (CodegenTargetConfig target_config : GetTargetConfigs()) {
+ if ((target_config.GetInstructionSet() == kMips) ||
+ (target_config.GetInstructionSet() == kMips64)) {
continue;
}
for (int64_t i = -1; i <= 1; i++) {
for (int64_t j = -1; j <= 1; j++) {
- TestComparison(kCondEQ, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondNE, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondLT, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondLE, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondGT, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondGE, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondB, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondBE, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondA, i, j, Primitive::kPrimLong, target_isa);
- TestComparison(kCondAE, i, j, Primitive::kPrimLong, target_isa);
+ for (int cond = kCondFirst; cond <= kCondLast; cond++) {
+ TestComparison(static_cast<IfCondition>(cond), i, j, Primitive::kPrimLong, target_config);
+ }
}
}
}
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 97b7916..119b62a 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -109,6 +109,9 @@
kCondBE, // <=
kCondA, // >
kCondAE, // >=
+ // First and last aliases.
+ kCondFirst = kCondEQ,
+ kCondLast = kCondAE,
};
enum GraphAnalysisResult {
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
new file mode 100644
index 0000000..43df6ae
--- /dev/null
+++ b/dex2oat/Android.bp
@@ -0,0 +1,122 @@
+//
+// 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.
+//
+
+cc_defaults {
+ name: "dex2oat-defaults",
+ host_supported: true,
+ defaults: ["art_defaults"],
+ srcs: ["dex2oat.cc"],
+
+ target: {
+ android: {
+ // Use the 32-bit version of dex2oat on devices
+ compile_multilib: "prefer32",
+
+ sanitize: {
+ // ASan slows down dex2oat by ~3.5x, which translates into
+ // extremely slow first boot. Disabled to help speed up
+ // SANITIZE_TARGET mode.
+ // Bug: 22233158
+ address: false,
+ },
+ },
+ },
+
+
+ include_dirs: [
+ "art/cmdline",
+ ],
+}
+
+art_cc_binary {
+ name: "dex2oat",
+ defaults: [
+ "dex2oat-defaults",
+ ],
+ shared_libs: [
+ "libart",
+ "libart-compiler",
+ "libsigchain",
+ ],
+}
+
+art_cc_binary {
+ name: "dex2oatd",
+ defaults: [
+ "art_debug_defaults",
+ "dex2oat-defaults",
+ ],
+ shared_libs: [
+ "libartd",
+ "libartd-compiler",
+ "libsigchain",
+ ],
+}
+
+art_cc_binary {
+ name: "dex2oats",
+ device_supported: false,
+ static_executable: true,
+ defaults: ["dex2oat-defaults"],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ ldflags: [
+ // We need this because GC stress mode makes use of
+ // _Unwind_GetIP and _Unwind_Backtrace and the symbols are also
+ // defined in libgcc_eh.a(unwind-dw2.o)
+ // TODO: Having this is not ideal as it might obscure errors.
+ // Try to get rid of it.
+ "-z muldefs",
+ ],
+ static_libs: [
+ "libart-compiler",
+ "libart",
+ "libvixl-arm",
+ "libvixl-arm64",
+ ] + art_static_dependencies,
+}
+
+art_cc_binary {
+ name: "dex2oatds",
+ device_supported: false,
+ static_executable: true,
+ defaults: [
+ "art_debug_defaults",
+ "dex2oat-defaults",
+ ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ ldflags: [
+ // We need this because GC stress mode makes use of
+ // _Unwind_GetIP and _Unwind_Backtrace and the symbols are also
+ // defined in libgcc_eh.a(unwind-dw2.o)
+ // TODO: Having this is not ideal as it might obscure errors.
+ // Try to get rid of it.
+ "-z muldefs",
+ ],
+ static_libs: [
+ "libartd-compiler",
+ "libartd",
+ "libvixld-arm",
+ "libvixld-arm64",
+ ] + art_static_dependencies,
+}
diff --git a/dex2oat/Android.mk b/dex2oat/Android.mk
deleted file mode 100644
index 32424ca..0000000
--- a/dex2oat/Android.mk
+++ /dev/null
@@ -1,78 +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.
-#
-
-# ASan slows down dex2oat by ~3.5x, which translates into extremely slow first
-# boot. Disabled to help speed up SANITIZE_TARGET mode.
-# The supported way of using SANITIZE_TARGET is by first running a normal build,
-# followed by a SANITIZE_TARGET=address build on top of it (in the same build
-# tree). By disabling this module in SANITIZE_TARGET build, we keep the regular,
-# uninstrumented version of it.
-# Bug: 22233158
-ifeq (,$(filter address, $(SANITIZE_TARGET)))
-
-LOCAL_PATH := $(call my-dir)
-
-include art/build/Android.executable.mk
-
-DEX2OAT_SRC_FILES := \
- dex2oat.cc
-
-# TODO: Remove this when the framework (installd) supports pushing the
-# right instruction-set parameter for the primary architecture.
-ifneq ($(filter ro.zygote=zygote64,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES)),)
- dex2oat_target_arch := 64
-else
- dex2oat_target_arch := 32
-endif
-
-ifeq ($(HOST_PREFER_32_BIT),true)
- # We need to explicitly restrict the host arch to 32-bit only, as
- # giving 'both' would make build-art-executable generate a build
- # rule for a 64-bit dex2oat executable too.
- dex2oat_host_arch := 32
-else
- dex2oat_host_arch := both
-endif
-
-ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
- $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler libsigchain,art/compiler,target,ndebug,$(dex2oat_target_arch)))
-endif
-
-ifeq ($(ART_BUILD_TARGET_DEBUG),true)
- $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler libsigchain,art/compiler,target,debug,$(dex2oat_target_arch)))
-endif
-
-# We always build dex2oat and dependencies, even if the host build is
-# otherwise disabled, since they are used to cross compile for the target.
-ifeq ($(ART_BUILD_HOST_NDEBUG),true)
- $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler libsigchain libziparchive liblz4,art/compiler,host,ndebug,$(dex2oat_host_arch)))
- ifeq ($(ART_BUILD_HOST_STATIC),true)
- $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libart libart-compiler libart libvixl-arm libvixl-arm64 $(ART_STATIC_DEPENDENCIES),art/compiler,host,ndebug,$(dex2oat_host_arch),static))
- endif
-endif
-
-ifeq ($(ART_BUILD_HOST_DEBUG),true)
- $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler libsigchain libziparchive liblz4,art/compiler,host,debug,$(dex2oat_host_arch)))
- ifeq ($(ART_BUILD_HOST_STATIC),true)
- $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libartd libartd-compiler libartd libvixld-arm libvixld-arm64 $(ART_STATIC_DEPENDENCIES),art/compiler,host,debug,$(dex2oat_host_arch),static))
- endif
-endif
-
-# Clear locals now they've served their purpose.
-dex2oat_target_arch :=
-dex2oat_host_arch :=
-
-endif
diff --git a/imgdiag/Android.bp b/imgdiag/Android.bp
new file mode 100644
index 0000000..4c0772d
--- /dev/null
+++ b/imgdiag/Android.bp
@@ -0,0 +1,71 @@
+//
+// Copyright (C) 2014 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.
+//
+
+// Build variants {target,host} x {debug,ndebug} x {32,64}
+
+cc_defaults {
+ name: "imgdiag-defaults",
+ host_supported: true,
+ srcs: ["imgdiag.cc"],
+ defaults: ["art_defaults"],
+
+ // Note that this tool needs to be built for both 32-bit and 64-bit since it requires
+ // that the image it's analyzing be the same ISA as the runtime ISA.
+ compile_multilib: "both",
+
+ shared_libs: ["libbacktrace"],
+ target: {
+ android: {
+ shared_libs: ["libcutils"],
+ },
+ host: {
+ shared_libs: ["libziparchive"],
+ },
+ },
+ include_dirs: [
+ "art/cmdline",
+ ],
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+ symlink_preferred_arch: true,
+}
+
+art_cc_binary {
+ name: "imgdiag",
+ defaults: ["imgdiag-defaults"],
+ shared_libs: [
+ "libart",
+ "libart-compiler",
+ ],
+}
+
+art_cc_binary {
+ name: "imgdiagd",
+ defaults: [
+ "imgdiag-defaults",
+ "art_debug_defaults",
+ ],
+ shared_libs: [
+ "libartd",
+ "libartd-compiler",
+ ],
+}
diff --git a/imgdiag/Android.mk b/imgdiag/Android.mk
deleted file mode 100644
index 278527f..0000000
--- a/imgdiag/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include art/build/Android.executable.mk
-
-IMGDIAG_SRC_FILES := \
- imgdiag.cc
-
-# Note that this tool needs to be built for both 32-bit and 64-bit since it requires
-# that the image it's analyzing be the same ISA as the runtime ISA.
-
-# Build variants {target,host} x {debug,ndebug} x {32,64}
-#
-# Honor HOST_PREFER_32_BIT, as building a 64-bit imgdiag executable
-# when HOST_PREFER_32_BIT is true would require an unmet dependency on
-# 64-bit libbacktrace.
-$(eval $(call build-art-multi-executable,imgdiag,$(IMGDIAG_SRC_FILES),libart-compiler libbacktrace,libcutils,libziparchive,art/compiler,both,$(HOST_PREFER_32_BIT)))
diff --git a/patchoat/Android.bp b/patchoat/Android.bp
new file mode 100644
index 0000000..8d8d6d1
--- /dev/null
+++ b/patchoat/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2014 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.
+//
+
+cc_defaults {
+ name: "patchoat-defaults",
+ host_supported: true,
+ defaults: ["art_defaults"],
+ srcs: ["patchoat.cc"],
+ target: {
+ android: {
+ compile_multilib: "prefer32",
+ },
+ },
+}
+
+art_cc_binary {
+ name: "patchoat",
+ defaults: ["patchoat-defaults"],
+ shared_libs: [
+ "libart",
+ ],
+}
+
+art_cc_binary {
+ name: "patchoatd",
+ defaults: [
+ "patchoat-defaults",
+ "art_debug_defaults",
+ ],
+ shared_libs: [
+ "libartd",
+ ],
+}
diff --git a/patchoat/Android.mk b/patchoat/Android.mk
deleted file mode 100644
index 8f9ffca..0000000
--- a/patchoat/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include art/build/Android.executable.mk
-
-PATCHOAT_SRC_FILES := \
- patchoat.cc
-
-# TODO: Remove this when the framework (installd) supports pushing the
-# right instruction-set parameter for the primary architecture.
-ifneq ($(filter ro.zygote=zygote64,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES)),)
- patchoat_arch := 64
-else
- patchoat_arch := 32
-endif
-
-ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
- $(eval $(call build-art-executable,patchoat,$(PATCHOAT_SRC_FILES),libcutils libsigchain,art/compiler,target,ndebug,$(patchoat_arch)))
-endif
-ifeq ($(ART_BUILD_TARGET_DEBUG),true)
- $(eval $(call build-art-executable,patchoat,$(PATCHOAT_SRC_FILES),libcutils libsigchain,art/compiler,target,debug,$(patchoat_arch)))
-endif
-
-# We always build patchoat and dependencies, even if the host build is otherwise disabled, since they are used to cross compile for the target.
-ifeq ($(ART_BUILD_HOST_NDEBUG),true)
- $(eval $(call build-art-executable,patchoat,$(PATCHOAT_SRC_FILES),libcutils libsigchain,art/compiler,host,ndebug))
-endif
-ifeq ($(ART_BUILD_HOST_DEBUG),true)
- $(eval $(call build-art-executable,patchoat,$(PATCHOAT_SRC_FILES),libcutils libsigchain,art/compiler,host,debug))
-endif
diff --git a/profman/Android.bp b/profman/Android.bp
new file mode 100644
index 0000000..f3b4e14
--- /dev/null
+++ b/profman/Android.bp
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_defaults {
+ name: "profman-defaults",
+ host_supported: true,
+ defaults: ["art_defaults"],
+ srcs: [
+ "profman.cc",
+ "profile_assistant.cc",
+ ],
+
+ target: {
+ android: {
+ compile_multilib: "prefer32",
+ },
+ },
+
+ include_dirs: [
+ "art/cmdline",
+ ],
+}
+
+art_cc_binary {
+ name: "profman",
+ defaults: ["profman-defaults"],
+ shared_libs: [
+ "libart",
+ ],
+}
+
+art_cc_binary {
+ name: "profmand",
+ defaults: [
+ "profman-defaults",
+ "art_debug_defaults",
+ ],
+ shared_libs: [
+ "libartd",
+ ],
+}
diff --git a/profman/Android.mk b/profman/Android.mk
deleted file mode 100644
index d38d107..0000000
--- a/profman/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include art/build/Android.executable.mk
-
-PROFMAN_SRC_FILES := \
- profman.cc \
- profile_assistant.cc
-
-# TODO: Remove this when the framework (installd) supports pushing the
-# right instruction-set parameter for the primary architecture.
-ifneq ($(filter ro.zygote=zygote64,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES)),)
- profman_arch := 64
-else
- profman_arch := 32
-endif
-
-ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
- $(eval $(call build-art-executable,profman,$(PROFMAN_SRC_FILES),libcutils,art/profman,target,ndebug,$(profman_arch)))
-endif
-ifeq ($(ART_BUILD_TARGET_DEBUG),true)
- $(eval $(call build-art-executable,profman,$(PROFMAN_SRC_FILES),libcutils,art/profman,target,debug,$(profman_arch)))
-endif
-
-ifeq ($(ART_BUILD_HOST_NDEBUG),true)
- $(eval $(call build-art-executable,profman,$(PROFMAN_SRC_FILES),libcutils,art/profman,host,ndebug))
-endif
-ifeq ($(ART_BUILD_HOST_DEBUG),true)
- $(eval $(call build-art-executable,profman,$(PROFMAN_SRC_FILES),libcutils,art/profman,host,debug))
-endif
diff --git a/runtime/Android.bp b/runtime/Android.bp
index a884505..b61976c 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -155,6 +155,7 @@
"native/java_lang_reflect_Constructor.cc",
"native/java_lang_reflect_Field.cc",
"native/java_lang_reflect_Method.cc",
+ "native/java_lang_reflect_Parameter.cc",
"native/java_lang_reflect_Proxy.cc",
"native/java_util_concurrent_atomic_AtomicLong.cc",
"native/libcore_util_CharsetUtils.cc",
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
index befdd48..daa2dff 100644
--- a/runtime/arch/arm/fault_handler_arm.cc
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -122,13 +122,16 @@
struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
uint8_t* ptr = reinterpret_cast<uint8_t*>(sc->arm_pc);
-
uint32_t instr_size = GetInstructionSize(ptr);
- sc->arm_lr = (sc->arm_pc + instr_size) | 1; // LR needs to point to gc map location
+ uintptr_t gc_map_location = (sc->arm_pc + instr_size) | 1;
+
+ // Push the gc map location to the stack and pass the fault address in LR.
+ sc->arm_sp -= sizeof(uintptr_t);
+ *reinterpret_cast<uintptr_t*>(sc->arm_sp) = gc_map_location;
+ sc->arm_lr = reinterpret_cast<uintptr_t>(info->si_addr);
sc->arm_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
// Pass the faulting address as the first argument of
// art_quick_throw_null_pointer_exception_from_signal.
- sc->arm_r0 = reinterpret_cast<uintptr_t>(info->si_addr);
VLOG(signals) << "Generating null pointer exception";
return true;
}
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index a3f053b..0416988 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -173,6 +173,29 @@
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kSaveEverything)
+ * when core registers are already saved.
+ */
+.macro SETUP_SAVE_EVERYTHING_FRAME_CORE_REGS_SAVED rTemp
+ @ 14 words of callee saves and args already saved.
+ vpush {d0-d15} @ 32 words, 2 for each of the 16 saved doubles.
+ .cfi_adjust_cfa_offset 128
+ sub sp, #8 @ 2 words of space, alignment padding and Method*
+ .cfi_adjust_cfa_offset 8
+ RUNTIME_CURRENT1 \rTemp @ Load Runtime::Current into rTemp.
+ @ Load kSaveEverything Method* into rTemp.
+ ldr \rTemp, [\rTemp, #RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET]
+ str \rTemp, [sp, #0] @ Place Method* at bottom of stack.
+ str sp, [r9, #THREAD_TOP_QUICK_FRAME_OFFSET] @ Place sp in Thread::Current()->top_quick_frame.
+
+ // Ugly compile-time check, but we only have the preprocessor.
+#if (FRAME_SIZE_SAVE_EVERYTHING != 56 + 128 + 8)
+#error "FRAME_SIZE_SAVE_EVERYTHING(ARM) size not as expected."
+#endif
+.endm
+
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kSaveEverything)
*/
.macro SETUP_SAVE_EVERYTHING_FRAME rTemp
push {r0-r12, lr} @ 14 words of callee saves and args.
@@ -191,20 +214,7 @@
.cfi_rel_offset r11, 44
.cfi_rel_offset ip, 48
.cfi_rel_offset lr, 52
- vpush {d0-d15} @ 32 words, 2 for each of the 16 saved doubles.
- .cfi_adjust_cfa_offset 128
- sub sp, #8 @ 2 words of space, alignment padding and Method*
- .cfi_adjust_cfa_offset 8
- RUNTIME_CURRENT1 \rTemp @ Load Runtime::Current into rTemp.
- @ Load kSaveEverything Method* into rTemp.
- ldr \rTemp, [\rTemp, #RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET]
- str \rTemp, [sp, #0] @ Place Method* at bottom of stack.
- str sp, [r9, #THREAD_TOP_QUICK_FRAME_OFFSET] @ Place sp in Thread::Current()->top_quick_frame.
-
- // Ugly compile-time check, but we only have the preprocessor.
-#if (FRAME_SIZE_SAVE_EVERYTHING != 56 + 128 + 8)
-#error "FRAME_SIZE_SAVE_EVERYTHING(ARM) size not as expected."
-#endif
+ SETUP_SAVE_EVERYTHING_FRAME_CORE_REGS_SAVED \rTemp
.endm
.macro RESTORE_SAVE_EVERYTHING_FRAME
@@ -356,7 +366,34 @@
/*
* Call installed by a signal handler to create and deliver a NullPointerException.
*/
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
+ .extern art_quick_throw_null_pointer_exception_from_signal
+ENTRY art_quick_throw_null_pointer_exception_from_signal
+ // The fault handler pushes the gc map address, i.e. "return address", to stack
+ // and passes the fault address in LR. So we need to set up the CFI info accordingly.
+ .cfi_def_cfa_offset __SIZEOF_POINTER__
+ .cfi_rel_offset lr, 0
+ push {r0-r12} @ 13 words of callee saves and args; LR already saved.
+ .cfi_adjust_cfa_offset 52
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset r1, 4
+ .cfi_rel_offset r2, 8
+ .cfi_rel_offset r3, 12
+ .cfi_rel_offset r4, 16
+ .cfi_rel_offset r5, 20
+ .cfi_rel_offset r6, 24
+ .cfi_rel_offset r7, 28
+ .cfi_rel_offset r8, 32
+ .cfi_rel_offset r9, 36
+ .cfi_rel_offset r10, 40
+ .cfi_rel_offset r11, 44
+ .cfi_rel_offset ip, 48
+
+ @ save all registers as basis for long jump context
+ SETUP_SAVE_EVERYTHING_FRAME_CORE_REGS_SAVED r1
+ mov r0, lr @ pass the fault address stored in LR by the fault handler.
+ mov r1, r9 @ pass Thread::Current
+ b artThrowNullPointerExceptionFromSignal @ (Thread*)
+END art_quick_throw_null_pointer_exception_from_signal
/*
* Called by managed code to create and deliver an ArithmeticException.
@@ -381,11 +418,6 @@
NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
/*
- * Called by managed code to create and deliver a NoSuchMethodError.
- */
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
-
- /*
* All generated callsites for interface invokes and invocation slow paths will load arguments
* as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
* the method_idx. This wrapper will save arg1-arg3, and call the appropriate C helper.
diff --git a/runtime/arch/arm64/fault_handler_arm64.cc b/runtime/arch/arm64/fault_handler_arm64.cc
index 6724d6d..c02be87 100644
--- a/runtime/arch/arm64/fault_handler_arm64.cc
+++ b/runtime/arch/arm64/fault_handler_arm64.cc
@@ -96,12 +96,12 @@
struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
- sc->regs[30] = sc->pc + 4; // LR needs to point to gc map location
+ // Push the gc map location to the stack and pass the fault address in LR.
+ sc->sp -= sizeof(uintptr_t);
+ *reinterpret_cast<uintptr_t*>(sc->sp) = sc->pc + 4;
+ sc->regs[30] = reinterpret_cast<uintptr_t>(info->si_addr);
sc->pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
- // Pass the faulting address as the first argument of
- // art_quick_throw_null_pointer_exception_from_signal.
- sc->regs[0] = reinterpret_cast<uintptr_t>(info->si_addr);
VLOG(signals) << "Generating null pointer exception";
return true;
}
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 25aa8ce..1a8a2b2 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -265,10 +265,10 @@
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kSaveEverything)
+ * when the SP has already been decremented by FRAME_SIZE_SAVE_EVERYTHING
+ * and saving registers x29 and LR is handled elsewhere.
*/
-.macro SETUP_SAVE_EVERYTHING_FRAME
- INCREASE_FRAME 512
-
+.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_X29_LR
// Ugly compile-time check, but we only have the preprocessor.
#if (FRAME_SIZE_SAVE_EVERYTHING != 512)
#error "FRAME_SIZE_SAVE_EVERYTHING(ARM64) size not as expected."
@@ -310,7 +310,6 @@
SAVE_TWO_REGS x23, x24, 448
SAVE_TWO_REGS x25, x26, 464
SAVE_TWO_REGS x27, x28, 480
- SAVE_TWO_REGS x29, xLR, 496
// art::Runtime** xIP0 = &art::Runtime::instance_
adrp xIP0, :got:_ZN3art7Runtime9instance_E
@@ -328,6 +327,16 @@
str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
.endm
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kSaveEverything)
+ */
+.macro SETUP_SAVE_EVERYTHING_FRAME
+ INCREASE_FRAME 512
+ SAVE_TWO_REGS x29, xLR, 496
+ SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_X29_LR
+.endm
+
.macro RESTORE_SAVE_EVERYTHING_FRAME
// Restore FP registers.
// For better performance, load d0 and d31 separately, so that all LDPs are 16-byte aligned.
@@ -462,7 +471,22 @@
/*
* Call installed by a signal handler to create and deliver a NullPointerException.
*/
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
+ .extern art_quick_throw_null_pointer_exception_from_signal
+ENTRY art_quick_throw_null_pointer_exception_from_signal
+ // The fault handler pushes the gc map address, i.e. "return address", to stack
+ // and passes the fault address in LR. So we need to set up the CFI info accordingly.
+ .cfi_def_cfa_offset __SIZEOF_POINTER__
+ .cfi_rel_offset lr, 0
+ // Save all registers as basis for long jump context.
+ INCREASE_FRAME (FRAME_SIZE_SAVE_EVERYTHING - __SIZEOF_POINTER__)
+ SAVE_REG x29, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__) // LR already saved.
+ SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_X29_LR
+ mov x0, lr // pass the fault address stored in LR by the fault handler.
+ mov x1, xSELF // pass Thread::Current.
+ // TODO: Change other throwing entrypoints to use BL instead of B. http://b/31468464
+ bl artThrowNullPointerExceptionFromSignal // (arg, Thread*).
+ brk 0
+END art_quick_throw_null_pointer_exception_from_signal
/*
* Called by managed code to create and deliver an ArithmeticException.
@@ -487,11 +511,6 @@
NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
/*
- * Called by managed code to create and deliver a NoSuchMethodError.
- */
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
-
- /*
* All generated callsites for interface invokes and invocation slow paths will load arguments
* as usual - except instead of loading arg0/x0 with the target Method*, arg0/x0 will contain
* the method_idx. This wrapper will save arg1-arg3, and call the appropriate C helper.
diff --git a/runtime/arch/mips/asm_support_mips.S b/runtime/arch/mips/asm_support_mips.S
index 801f708..7955b1d 100644
--- a/runtime/arch/mips/asm_support_mips.S
+++ b/runtime/arch/mips/asm_support_mips.S
@@ -43,7 +43,7 @@
.endm
// Declare a function called name, doesn't set up $gp.
-.macro ENTRY_NO_GP name
+.macro ENTRY_NO_GP_CUSTOM_CFA name, cfa_offset
.type \name, %function
.global \name
// Cache alignment for function entry.
@@ -51,7 +51,12 @@
\name:
.cfi_startproc
// Ensure we get a sane starting CFA.
- .cfi_def_cfa $sp,0
+ .cfi_def_cfa $sp, \cfa_offset
+.endm
+
+ // Declare a function called name, doesn't set up $gp.
+.macro ENTRY_NO_GP name
+ ENTRY_NO_GP_CUSTOM_CFA \name, 0
.endm
.macro END name
diff --git a/runtime/arch/mips/entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc
index 38aa67c..e10d4e6 100644
--- a/runtime/arch/mips/entrypoints_init_mips.cc
+++ b/runtime/arch/mips/entrypoints_init_mips.cc
@@ -264,8 +264,6 @@
static_assert(!IsDirectEntrypoint(kQuickThrowArrayBounds), "Non-direct C stub marked direct.");
qpoints->pThrowDivZero = art_quick_throw_div_zero;
static_assert(!IsDirectEntrypoint(kQuickThrowDivZero), "Non-direct C stub marked direct.");
- qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
- static_assert(!IsDirectEntrypoint(kQuickThrowNoSuchMethod), "Non-direct C stub marked direct.");
qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
static_assert(!IsDirectEntrypoint(kQuickThrowNullPointer), "Non-direct C stub marked direct.");
qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
diff --git a/runtime/arch/mips/fault_handler_mips.cc b/runtime/arch/mips/fault_handler_mips.cc
index 7969a8f..b6a63ca 100644
--- a/runtime/arch/mips/fault_handler_mips.cc
+++ b/runtime/arch/mips/fault_handler_mips.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-
+#include "arch/mips/quick_method_frame_info_mips.h"
#include "fault_handler.h"
#include <sys/ucontext.h>
#include "art_method-inl.h"
@@ -82,12 +82,15 @@
struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+ // Decrement $sp by the frame size of the kSaveEverything method and store
+ // the fault address in the padding right after the ArtMethod*.
+ sc->sc_regs[mips::SP] -= mips::MipsCalleeSaveFrameSize(Runtime::kSaveEverything);
+ uintptr_t* padding = reinterpret_cast<uintptr_t*>(sc->sc_regs[mips::SP]) + /* ArtMethod* */ 1;
+ *padding = reinterpret_cast<uintptr_t>(info->si_addr);
+
sc->sc_regs[mips::RA] = sc->sc_pc + 4; // RA needs to point to gc map location
sc->sc_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
sc->sc_regs[mips::T9] = sc->sc_pc; // make sure T9 points to the function
- // Pass the faulting address as the first argument of
- // art_quick_throw_null_pointer_exception_from_signal.
- sc->sc_regs[mips::A0] = reinterpret_cast<uintptr_t>(info->si_addr);
VLOG(signals) << "Generating null pointer exception";
return true;
}
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 4bd1314..4563004 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -279,6 +279,7 @@
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kSaveEverything).
+ * when the $sp has already been decremented by FRAME_SIZE_SAVE_EVERYTHING.
* Callee-save: $at, $v0-$v1, $a0-$a3, $t0-$t7, $s0-$s7, $t8-$t9, $gp, $fp $ra, $f0-$f31;
* 28(GPR)+ 32(FPR) + 3 words for padding and 1 word for Method*
* Clobbers $t0 and $t1.
@@ -286,10 +287,7 @@
* Reserves FRAME_SIZE_SAVE_EVERYTHING + ARG_SLOT_SIZE bytes on the stack.
* This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
*/
-.macro SETUP_SAVE_EVERYTHING_FRAME
- addiu $sp, $sp, -256
- .cfi_adjust_cfa_offset 256
-
+.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
// Ugly compile-time check, but we only have the preprocessor.
#if (FRAME_SIZE_SAVE_EVERYTHING != 256)
#error "FRAME_SIZE_SAVE_EVERYTHING(MIPS) size not as expected."
@@ -388,6 +386,22 @@
.cfi_adjust_cfa_offset ARG_SLOT_SIZE
.endm
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kSaveEverything).
+ * Callee-save: $at, $v0-$v1, $a0-$a3, $t0-$t7, $s0-$s7, $t8-$t9, $gp, $fp $ra, $f0-$f31;
+ * 28(GPR)+ 32(FPR) + 3 words for padding and 1 word for Method*
+ * Clobbers $t0 and $t1.
+ * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
+ * Reserves FRAME_SIZE_SAVE_EVERYTHING + ARG_SLOT_SIZE bytes on the stack.
+ * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
+ */
+.macro SETUP_SAVE_EVERYTHING_FRAME
+ addiu $sp, $sp, -(FRAME_SIZE_SAVE_EVERYTHING)
+ .cfi_adjust_cfa_offset (FRAME_SIZE_SAVE_EVERYTHING)
+ SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
+.endm
+
.macro RESTORE_SAVE_EVERYTHING_FRAME
addiu $sp, $sp, ARG_SLOT_SIZE # remove argument slots on the stack
.cfi_adjust_cfa_offset -ARG_SLOT_SIZE
@@ -708,8 +722,10 @@
* Call installed by a signal handler to create and deliver a NullPointerException.
*/
.extern artThrowNullPointerExceptionFromSignal
-ENTRY art_quick_throw_null_pointer_exception_from_signal
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, FRAME_SIZE_SAVE_EVERYTHING
+ SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
+ # Retrieve the fault address from the padding where the signal handler stores it.
+ lw $a0, (ARG_SLOT_SIZE + __SIZEOF_POINTER__)($sp)
la $t9, artThrowNullPointerExceptionFromSignal
jalr $zero, $t9 # artThrowNullPointerExceptionFromSignal(uintptr_t, Thread*)
move $a1, rSELF # pass Thread::Current
@@ -761,17 +777,6 @@
END art_quick_throw_stack_overflow
/*
- * Called by managed code to create and deliver a NoSuchMethodError.
- */
- .extern artThrowNoSuchMethodFromCode
-ENTRY art_quick_throw_no_such_method
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
- la $t9, artThrowNoSuchMethodFromCode
- jalr $zero, $t9 # artThrowNoSuchMethodFromCode(method_idx, Thread*)
- move $a1, rSELF # pass Thread::Current
-END art_quick_throw_no_such_method
-
- /*
* All generated callsites for interface invokes and invocation slow paths will load arguments
* as usual - except instead of loading arg0/$a0 with the target Method*, arg0/$a0 will contain
* the method_idx. This wrapper will save arg1-arg3, and call the appropriate C helper.
diff --git a/runtime/arch/mips64/asm_support_mips64.S b/runtime/arch/mips64/asm_support_mips64.S
index 786e860..6c58fcf 100644
--- a/runtime/arch/mips64/asm_support_mips64.S
+++ b/runtime/arch/mips64/asm_support_mips64.S
@@ -45,8 +45,8 @@
.L\name\()_gp_set:
.endm
- // Declare a function called name, doesn't set up $gp.
-.macro ENTRY_NO_GP name
+ // Declare a function called name, doesn't set up $gp.
+.macro ENTRY_NO_GP_CUSTOM_CFA name, cfa_offset
.type \name, %function
.global \name
// Cache alignment for function entry.
@@ -54,7 +54,12 @@
\name:
.cfi_startproc
// Ensure we get a sane starting CFA.
- .cfi_def_cfa $sp,0
+ .cfi_def_cfa $sp, \cfa_offset
+.endm
+
+ // Declare a function called name, doesn't set up $gp.
+.macro ENTRY_NO_GP name
+ ENTRY_NO_GP_CUSTOM_CFA \name, 0
.endm
.macro END name
diff --git a/runtime/arch/mips64/fault_handler_mips64.cc b/runtime/arch/mips64/fault_handler_mips64.cc
index 0bbb6e1..e52dc73 100644
--- a/runtime/arch/mips64/fault_handler_mips64.cc
+++ b/runtime/arch/mips64/fault_handler_mips64.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-
+#include "arch/mips64/quick_method_frame_info_mips64.h"
#include "fault_handler.h"
#include <sys/ucontext.h>
#include "art_method-inl.h"
@@ -83,12 +83,15 @@
struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+ // Decrement $sp by the frame size of the kSaveEverything method and store
+ // the fault address in the padding right after the ArtMethod*.
+ sc->sc_regs[mips64::SP] -= mips64::Mips64CalleeSaveFrameSize(Runtime::kSaveEverything);
+ uintptr_t* padding = reinterpret_cast<uintptr_t*>(sc->sc_regs[mips64::SP]) + /* ArtMethod* */ 1;
+ *padding = reinterpret_cast<uintptr_t>(info->si_addr);
+
sc->sc_regs[mips64::RA] = sc->sc_pc + 4; // RA needs to point to gc map location
sc->sc_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
sc->sc_regs[mips64::T9] = sc->sc_pc; // make sure T9 points to the function
- // Pass the faulting address as the first argument of
- // art_quick_throw_null_pointer_exception_from_signal.
- sc->sc_regs[mips64::A0] = reinterpret_cast<uintptr_t>(info->si_addr);
VLOG(signals) << "Generating null pointer exception";
return true;
}
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index 26717ad..c16e855 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -316,14 +316,12 @@
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kSaveEverything).
+ * when the $sp has already been decremented by FRAME_SIZE_SAVE_EVERYTHING.
* callee-save: $at + $v0-$v1 + $a0-$a7 + $t0-$t3 + $s0-$s7 + $t8-$t9 + $gp + $s8 + $ra + $s8,
* $f0-$f31; 28(GPR)+ 32(FPR) + 1x8 bytes padding + method*
* This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
*/
-.macro SETUP_SAVE_EVERYTHING_FRAME
- daddiu $sp, $sp, -496
- .cfi_adjust_cfa_offset 496
-
+.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
// Ugly compile-time check, but we only have the preprocessor.
#if (FRAME_SIZE_SAVE_EVERYTHING != 496)
#error "FRAME_SIZE_SAVE_EVERYTHING(MIPS64) size not as expected."
@@ -436,6 +434,19 @@
sd $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)
.endm
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kSaveEverything).
+ * callee-save: $at + $v0-$v1 + $a0-$a7 + $t0-$t3 + $s0-$s7 + $t8-$t9 + $gp + $s8 + $ra + $s8,
+ * $f0-$f31; 28(GPR)+ 32(FPR) + 1x8 bytes padding + method*
+ * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
+ */
+.macro SETUP_SAVE_EVERYTHING_FRAME
+ daddiu $sp, $sp, -(FRAME_SIZE_SAVE_EVERYTHING)
+ .cfi_adjust_cfa_offset (FRAME_SIZE_SAVE_EVERYTHING)
+ SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
+.endm
+
.macro RESTORE_SAVE_EVERYTHING_FRAME
// Restore FP registers.
l.d $f31, 264($sp)
@@ -818,8 +829,10 @@
* Call installed by a signal handler to create and deliver a NullPointerException
*/
.extern artThrowNullPointerExceptionFromSignal
-ENTRY art_quick_throw_null_pointer_exception_from_signal
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, FRAME_SIZE_SAVE_EVERYTHING
+ SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
+ # Retrieve the fault address from the padding where the signal handler stores it.
+ ld $a0, (__SIZEOF_POINTER__)($sp)
dla $t9, artThrowNullPointerExceptionFromSignal
jalr $zero, $t9 # artThrowNullPointerExceptionFromSignal(uinptr_t, Thread*)
move $a1, rSELF # pass Thread::Current
@@ -874,17 +887,6 @@
END art_quick_throw_stack_overflow
/*
- * Called by managed code to create and deliver a NoSuchMethodError.
- */
- .extern artThrowNoSuchMethodFromCode
-ENTRY art_quick_throw_no_such_method
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
- dla $t9, artThrowNoSuchMethodFromCode
- jalr $zero, $t9 # artThrowNoSuchMethodFromCode(method_idx, Thread*)
- move $a1, rSELF # pass Thread::Current
-END art_quick_throw_no_such_method
-
- /*
* All generated callsites for interface invokes and invocation slow paths will load arguments
* as usual - except instead of loading arg0/$a0 with the target Method*, arg0/$a0 will contain
* the method_idx. This wrapper will save arg1-arg3, load the caller's Method*, align the
diff --git a/runtime/arch/x86/asm_support_x86.S b/runtime/arch/x86/asm_support_x86.S
index 3e47209..14b01c5 100644
--- a/runtime/arch/x86/asm_support_x86.S
+++ b/runtime/arch/x86/asm_support_x86.S
@@ -114,7 +114,7 @@
.balign 16
END_MACRO
-MACRO1(DEFINE_FUNCTION, c_name)
+MACRO2(DEFINE_FUNCTION_CUSTOM_CFA, c_name, cfa_offset)
FUNCTION_TYPE(SYMBOL(\c_name))
ASM_HIDDEN CALLVAR(c_name)
.globl CALLVAR(c_name)
@@ -122,7 +122,11 @@
CALLVAR(c_name):
CFI_STARTPROC
// Ensure we get a sane starting CFA.
- CFI_DEF_CFA(esp, 4)
+ CFI_DEF_CFA(esp, RAW_VAR(cfa_offset))
+END_MACRO
+
+MACRO1(DEFINE_FUNCTION, c_name)
+ DEFINE_FUNCTION_CUSTOM_CFA RAW_VAR(c_name), __SIZEOF_POINTER__
END_MACRO
MACRO1(END_FUNCTION, c_name)
diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc
index c7af249..a4d6bb4 100644
--- a/runtime/arch/x86/fault_handler_x86.cc
+++ b/runtime/arch/x86/fault_handler_x86.cc
@@ -325,21 +325,15 @@
// next instruction (this instruction + instruction size). The return address
// is on the stack at the top address of the current frame.
- // Push the return address onto the stack.
+ // Push the return address and fault address onto the stack.
uintptr_t retaddr = reinterpret_cast<uintptr_t>(pc + instr_size);
- uintptr_t* next_sp = reinterpret_cast<uintptr_t*>(sp - sizeof(uintptr_t));
- *next_sp = retaddr;
+ uintptr_t* next_sp = reinterpret_cast<uintptr_t*>(sp - 2 * sizeof(uintptr_t));
+ next_sp[1] = retaddr;
+ next_sp[0] = reinterpret_cast<uintptr_t>(sig->si_addr);
uc->CTX_ESP = reinterpret_cast<uintptr_t>(next_sp);
uc->CTX_EIP = reinterpret_cast<uintptr_t>(
art_quick_throw_null_pointer_exception_from_signal);
- // Pass the faulting address as the first argument of
- // art_quick_throw_null_pointer_exception_from_signal.
-#if defined(__x86_64__)
- uc->CTX_RDI = reinterpret_cast<uintptr_t>(sig->si_addr);
-#else
- uc->CTX_EAX = reinterpret_cast<uintptr_t>(sig->si_addr);
-#endif
VLOG(signals) << "Generating null pointer exception";
return true;
}
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 646a80c..f3793e1 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -224,10 +224,11 @@
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kSaveEverything)
+ * when EDI is already saved.
*/
-MACRO2(SETUP_SAVE_EVERYTHING_FRAME, got_reg, temp_reg)
- // Save core registers.
- PUSH edi
+MACRO2(SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED, got_reg, temp_reg)
+ // Save core registers from highest to lowest to agree with core spills bitmap.
+ // EDI, or at least a placeholder for it, is already on the stack.
PUSH esi
PUSH ebp
PUSH ebx
@@ -264,6 +265,15 @@
#endif
END_MACRO
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kSaveEverything)
+ */
+MACRO2(SETUP_SAVE_EVERYTHING_FRAME, got_reg, temp_reg)
+ PUSH edi
+ SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED RAW_VAR(got_reg), RAW_VAR(temp_reg)
+END_MACRO
+
MACRO0(RESTORE_SAVE_EVERYTHING_FRAME)
// Restore FPRs. Method and padding is still on the stack.
movsd 16(%esp), %xmm0
@@ -320,7 +330,6 @@
MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
DEFINE_FUNCTION VAR(c_name)
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save all registers as basis for long jump context
- mov %esp, %ecx
// Outgoing argument set up
subl MACRO_LITERAL(8), %esp // alignment padding
CFI_ADJUST_CFA_OFFSET(8)
@@ -354,7 +363,23 @@
/*
* Call installed by a signal handler to create and deliver a NullPointerException.
*/
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
+DEFINE_FUNCTION_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, 2 * __SIZEOF_POINTER__
+ // Fault address and return address were saved by the fault handler.
+ // Save all registers as basis for long jump context; EDI will replace fault address later.
+ SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED ebx, ebx
+ // Retrieve fault address and save EDI.
+ movl (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%esp), %eax
+ movl %edi, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%esp)
+ CFI_REL_OFFSET(%edi, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__))
+ // Outgoing argument set up
+ subl MACRO_LITERAL(8), %esp // alignment padding
+ CFI_ADJUST_CFA_OFFSET(8)
+ pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
+ CFI_ADJUST_CFA_OFFSET(4)
+ PUSH eax // pass arg1
+ call SYMBOL(artThrowNullPointerExceptionFromSignal) // (addr, self)
+ UNREACHABLE
+END_FUNCTION art_quick_throw_null_pointer_exception
/*
* Called by managed code to create and deliver an ArithmeticException.
@@ -373,11 +398,6 @@
ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
/*
- * Called by managed code to create and deliver a NoSuchMethodError.
- */
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
-
- /*
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
* index, arg2 holds limit.
*/
diff --git a/runtime/arch/x86_64/asm_support_x86_64.S b/runtime/arch/x86_64/asm_support_x86_64.S
index 0728f99..af4a6c4 100644
--- a/runtime/arch/x86_64/asm_support_x86_64.S
+++ b/runtime/arch/x86_64/asm_support_x86_64.S
@@ -110,7 +110,7 @@
// TODO: we might need to use SYMBOL() here to add the underscore prefix
// for mac builds.
-MACRO1(DEFINE_FUNCTION, c_name)
+MACRO2(DEFINE_FUNCTION_CUSTOM_CFA, c_name, cfa_offset)
FUNCTION_TYPE(SYMBOL(\c_name))
ASM_HIDDEN CALLVAR(c_name)
.globl CALLVAR(c_name)
@@ -118,7 +118,11 @@
CALLVAR(c_name):
CFI_STARTPROC
// Ensure we get a sane starting CFA.
- CFI_DEF_CFA(rsp, 8)
+ CFI_DEF_CFA(rsp, RAW_VAR(cfa_offset))
+END_MACRO
+
+MACRO1(DEFINE_FUNCTION, c_name)
+ DEFINE_FUNCTION_CUSTOM_CFA RAW_VAR(c_name), __SIZEOF_POINTER__
END_MACRO
MACRO1(END_FUNCTION, c_name)
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 5ea58af..bfba543 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -263,14 +263,15 @@
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kSaveEverything)
+ * when R15 is already saved.
*/
-MACRO0(SETUP_SAVE_EVERYTHING_FRAME)
+MACRO0(SETUP_SAVE_EVERYTHING_FRAME_R15_SAVED)
#if defined(__APPLE__)
int3
int3
#else
// Save core registers from highest to lowest to agree with core spills bitmap.
- PUSH r15
+ // R15, or at least a placeholder for it, is already on the stack.
PUSH r14
PUSH r13
PUSH r12
@@ -322,6 +323,15 @@
#endif // __APPLE__
END_MACRO
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kSaveEverything)
+ */
+MACRO0(SETUP_SAVE_EVERYTHING_FRAME)
+ PUSH r15
+ SETUP_SAVE_EVERYTHING_FRAME_R15_SAVED
+END_MACRO
+
MACRO0(RESTORE_SAVE_EVERYTHING_FRAME)
// Restore FPRs. Method and padding is still on the stack.
movq 16(%rsp), %xmm0
@@ -413,7 +423,19 @@
/*
* Call installed by a signal handler to create and deliver a NullPointerException.
*/
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
+DEFINE_FUNCTION_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, 2 * __SIZEOF_POINTER__
+ // Fault address and return address were saved by the fault handler.
+ // Save all registers as basis for long jump context; R15 will replace fault address later.
+ SETUP_SAVE_EVERYTHING_FRAME_R15_SAVED
+ // Retrieve fault address and save R15.
+ movq (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%rsp), %rdi
+ movq %r15, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%rsp)
+ CFI_REL_OFFSET(%r15, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__))
+ // Outgoing argument set up; RDI already contains the fault address.
+ movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current()
+ call SYMBOL(artThrowNullPointerExceptionFromSignal) // (addr, self)
+ UNREACHABLE
+END_FUNCTION art_quick_throw_null_pointer_exception_from_signal
/*
* Called by managed code to create and deliver an ArithmeticException.
@@ -432,11 +454,6 @@
ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
/*
- * Called by managed code to create and deliver a NoSuchMethodError.
- */
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
-
- /*
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
* index, arg2 holds limit.
*/
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index f4addf7..b8f7272 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -89,20 +89,20 @@
ADD_TEST_EQ(THREAD_SELF_OFFSET,
art::Thread::SelfOffset<POINTER_SIZE>().Int32Value())
-// Offset of field Thread::tlsPtr_.thread_local_objects.
-#define THREAD_LOCAL_OBJECTS_OFFSET (THREAD_CARD_TABLE_OFFSET + 199 * __SIZEOF_POINTER__)
-ADD_TEST_EQ(THREAD_LOCAL_OBJECTS_OFFSET,
- art::Thread::ThreadLocalObjectsOffset<POINTER_SIZE>().Int32Value())
// Offset of field Thread::tlsPtr_.thread_local_pos.
-#define THREAD_LOCAL_POS_OFFSET (THREAD_LOCAL_OBJECTS_OFFSET + __SIZEOF_SIZE_T__)
+#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 198 * __SIZEOF_POINTER__)
ADD_TEST_EQ(THREAD_LOCAL_POS_OFFSET,
art::Thread::ThreadLocalPosOffset<POINTER_SIZE>().Int32Value())
// Offset of field Thread::tlsPtr_.thread_local_end.
#define THREAD_LOCAL_END_OFFSET (THREAD_LOCAL_POS_OFFSET + __SIZEOF_POINTER__)
ADD_TEST_EQ(THREAD_LOCAL_END_OFFSET,
art::Thread::ThreadLocalEndOffset<POINTER_SIZE>().Int32Value())
+// Offset of field Thread::tlsPtr_.thread_local_objects.
+#define THREAD_LOCAL_OBJECTS_OFFSET (THREAD_LOCAL_END_OFFSET + __SIZEOF_POINTER__)
+ADD_TEST_EQ(THREAD_LOCAL_OBJECTS_OFFSET,
+ art::Thread::ThreadLocalObjectsOffset<POINTER_SIZE>().Int32Value())
// Offset of field Thread::tlsPtr_.mterp_current_ibase.
-#define THREAD_CURRENT_IBASE_OFFSET (THREAD_LOCAL_END_OFFSET + __SIZEOF_POINTER__)
+#define THREAD_CURRENT_IBASE_OFFSET (THREAD_LOCAL_OBJECTS_OFFSET + __SIZEOF_SIZE_T__)
ADD_TEST_EQ(THREAD_CURRENT_IBASE_OFFSET,
art::Thread::MterpCurrentIBaseOffset<POINTER_SIZE>().Int32Value())
// Offset of field Thread::tlsPtr_.mterp_default_ibase.
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index 529c391..e00e62d 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -187,7 +187,7 @@
LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, int error)
: data_(new LogMessageData(file, line, severity, error)) {
if (PrintDirectly(severity)) {
- static constexpr char kLogCharacters[] = { 'N', 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
+ static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
"Wrong character array size");
stream() << ProgramInvocationShortName() << " " << kLogCharacters[static_cast<size_t>(severity)]
@@ -198,7 +198,7 @@
if (PrintDirectly(data_->GetSeverity())) {
// Add newline at the end to match the not printing directly behavior.
std::cerr << '\n';
- } else if (data_->GetSeverity() != LogSeverity::NONE) {
+ } else {
if (data_->GetSeverity() < gMinimumLogSeverity) {
return; // No need to format something we're not going to output.
}
@@ -242,7 +242,6 @@
#ifdef ART_TARGET_ANDROID
static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
- ANDROID_LOG_VERBOSE, // NONE, use verbose as stand-in, will never be printed.
ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
};
@@ -252,10 +251,6 @@
void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity log_severity,
const char* message) {
- if (log_severity == LogSeverity::NONE) {
- return;
- }
-
#ifdef ART_TARGET_ANDROID
const char* tag = ProgramInvocationShortName();
int priority = kLogSeverityToAndroidLogPriority[static_cast<size_t>(log_severity)];
@@ -265,7 +260,7 @@
LOG_PRI(priority, tag, "%s", message);
}
#else
- static const char* log_characters = "NVDIWEFF";
+ 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",
@@ -275,10 +270,6 @@
void LogMessage::LogLineLowStack(const char* file, unsigned int line, LogSeverity log_severity,
const char* message) {
- if (log_severity == LogSeverity::NONE) {
- return;
- }
-
#ifdef ART_TARGET_ANDROID
// Use android_writeLog() to avoid stack-based buffers used by android_printLog().
const char* tag = ProgramInvocationShortName();
@@ -300,7 +291,7 @@
android_writeLog(priority, tag, message);
}
#else
- static constexpr char kLogCharacters[] = { 'N', 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
+ static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
"Wrong character array size");
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
index f43cb8b..185aa0e 100644
--- a/runtime/base/logging.h
+++ b/runtime/base/logging.h
@@ -24,7 +24,6 @@
namespace art {
enum LogSeverity {
- NONE, // Fake level, don't log at all.
VERBOSE,
DEBUG,
INFO,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 8edb1b4..4d252e1 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3848,7 +3848,9 @@
return false;
}
-void ClassLinker::VerifyClass(Thread* self, Handle<mirror::Class> klass, LogSeverity log_level) {
+void ClassLinker::VerifyClass(Thread* self,
+ Handle<mirror::Class> klass,
+ verifier::HardFailLogMode log_level) {
{
// TODO: assert that the monitor on the Class is held
ObjectLock<mirror::Class> lock(self, klass);
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 4bd1bd2..5e4ae03 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -36,6 +36,7 @@
#include "jni.h"
#include "oat_file.h"
#include "object_callbacks.h"
+#include "verifier/verifier_log_mode.h"
namespace art {
@@ -460,7 +461,7 @@
void VerifyClass(Thread* self,
Handle<mirror::Class> klass,
- LogSeverity log_level = LogSeverity::NONE)
+ verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!dex_lock_);
bool VerifyClassUsingOatFile(const DexFile& dex_file,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 3be39a1..5e0ee6f 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -697,6 +697,9 @@
struct ExecutableOffsets : public CheckOffsets<mirror::Executable> {
ExecutableOffsets() : CheckOffsets<mirror::Executable>(
false, "Ljava/lang/reflect/Executable;") {
+ addOffset(OFFSETOF_MEMBER(mirror::Executable, has_real_parameter_data_),
+ "hasRealParameterData");
+ addOffset(OFFSETOF_MEMBER(mirror::Executable, parameters_), "parameters");
};
};
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 77362a5..1e4c772 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -357,16 +357,6 @@
ThrowException("Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
}
-void ThrowNoSuchMethodError(uint32_t method_idx) {
- ArtMethod* method = Thread::Current()->GetCurrentMethod(nullptr);
- mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
- const DexFile& dex_file = *dex_cache->GetDexFile();
- std::ostringstream msg;
- msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
- ThrowException("Ljava/lang/NoSuchMethodError;",
- method->GetDeclaringClass(), msg.str().c_str());
-}
-
// NullPointerException
void ThrowNullPointerExceptionForFieldAccess(ArtField* field, bool is_read) {
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index ab25543..945dc2d 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -178,9 +178,6 @@
const Signature& signature)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowNoSuchMethodError(uint32_t method_idx)
- REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
-
// NullPointerException
void ThrowNullPointerExceptionForFieldAccess(ArtField* field,
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index ebadd79..76cd348 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -1431,6 +1431,34 @@
return ProcessAnnotationSetRefList(method_class, set_ref_list, size);
}
+mirror::Object* DexFile::GetAnnotationForMethodParameter(ArtMethod* method,
+ uint32_t parameter_idx,
+ Handle<mirror::Class> annotation_class)
+ const {
+ const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method);
+ if (parameter_annotations == nullptr) {
+ return nullptr;
+ }
+ const AnnotationSetRefList* set_ref_list =
+ GetParameterAnnotationSetRefList(parameter_annotations);
+ if (set_ref_list == nullptr) {
+ return nullptr;
+ }
+
+ if (parameter_idx >= set_ref_list->size_) {
+ return nullptr;
+ }
+ const AnnotationSetRefItem* annotation_set_ref = &set_ref_list->list_[parameter_idx];
+ const AnnotationSetItem* annotation_set = GetSetRefItemItem(annotation_set_ref);
+
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+ return GetAnnotationObjectFromAnnotationSet(method_class,
+ annotation_set,
+ kDexVisibilityRuntime,
+ annotation_class);
+}
+
mirror::ObjectArray<mirror::String>* DexFile::GetSignatureAnnotationForMethod(ArtMethod* method)
const {
const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index ebbde0a..23676bd 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -953,6 +953,10 @@
REQUIRES_SHARED(Locks::mutator_lock_);
mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle<mirror::Class> annotation_class)
const REQUIRES_SHARED(Locks::mutator_lock_);
+ mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method,
+ uint32_t parameter_idx,
+ Handle<mirror::Class> annotation_class) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method) const
REQUIRES_SHARED(Locks::mutator_lock_);
mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method) const
diff --git a/runtime/entrypoints/quick/quick_default_externs.h b/runtime/entrypoints/quick/quick_default_externs.h
index 86fb881..cfa5325 100644
--- a/runtime/entrypoints/quick/quick_default_externs.h
+++ b/runtime/entrypoints/quick/quick_default_externs.h
@@ -118,7 +118,6 @@
extern "C" void art_quick_deliver_exception(art::mirror::Object*);
extern "C" void art_quick_throw_array_bounds(int32_t index, int32_t limit);
extern "C" void art_quick_throw_div_zero();
-extern "C" void art_quick_throw_no_such_method(int32_t method_idx);
extern "C" void art_quick_throw_null_pointer_exception();
extern "C" void art_quick_throw_null_pointer_exception_from_signal(uintptr_t address);
extern "C" void art_quick_throw_stack_overflow(void*);
diff --git a/runtime/entrypoints/quick/quick_default_init_entrypoints.h b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
index 2a206c2..1ee1f81 100644
--- a/runtime/entrypoints/quick/quick_default_init_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
@@ -113,7 +113,6 @@
qpoints->pDeliverException = art_quick_deliver_exception;
qpoints->pThrowArrayBounds = art_quick_throw_array_bounds;
qpoints->pThrowDivZero = art_quick_throw_div_zero;
- qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
qpoints->pThrowStringBounds = art_quick_throw_string_bounds;
diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h
index 74c928a..e402919 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_list.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_list.h
@@ -139,7 +139,6 @@
V(DeliverException, void, mirror::Object*) \
V(ThrowArrayBounds, void, int32_t, int32_t) \
V(ThrowDivZero, void, void) \
- V(ThrowNoSuchMethod, void, int32_t) \
V(ThrowNullPointer, void, void) \
V(ThrowStackOverflow, void, void*) \
V(ThrowStringBounds, void, int32_t, int32_t) \
diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
index 67cae8a..a205b17 100644
--- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
@@ -101,13 +101,6 @@
self->QuickDeliverException();
}
-extern "C" NO_RETURN void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- ScopedQuickEntrypointChecks sqec(self);
- ThrowNoSuchMethodError(method_idx);
- self->QuickDeliverException();
-}
-
extern "C" NO_RETURN void artThrowClassCastException(mirror::Class* dest_type,
mirror::Class* src_type,
Thread* self)
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index b102334..03254ab 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -122,10 +122,10 @@
// Skip across the entrypoints structures.
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_start, thread_local_objects, sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_objects, thread_local_pos, sizeof(size_t));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_start, thread_local_pos, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_pos, thread_local_end, sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_end, mterp_current_ibase, sizeof(void*));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_end, thread_local_objects, sizeof(void*));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_objects, mterp_current_ibase, sizeof(size_t));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, mterp_current_ibase, mterp_default_ibase, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, mterp_default_ibase, mterp_alt_ibase, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, mterp_alt_ibase, rosalloc_runs, sizeof(void*));
@@ -288,8 +288,7 @@
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pDeliverException, pThrowArrayBounds, sizeof(void*));
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowArrayBounds, pThrowDivZero, sizeof(void*));
- EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowDivZero, pThrowNoSuchMethod, sizeof(void*));
- EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowNoSuchMethod, pThrowNullPointer, sizeof(void*));
+ EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowDivZero, pThrowNullPointer, sizeof(void*));
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowNullPointer, pThrowStackOverflow, sizeof(void*));
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowStackOverflow, pThrowStringBounds, sizeof(void*));
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowStringBounds, pDeoptimize, sizeof(void*));
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 975ac36..e534369 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -2087,7 +2087,8 @@
to_ref = reinterpret_cast<mirror::Object*>(old_lock_word.ForwardingAddress());
CHECK(to_ref != nullptr);
CHECK_NE(to_ref, lost_fwd_ptr);
- CHECK(region_space_->IsInToSpace(to_ref) || heap_->non_moving_space_->HasAddress(to_ref));
+ CHECK(region_space_->IsInToSpace(to_ref) || heap_->non_moving_space_->HasAddress(to_ref))
+ << "to_ref=" << to_ref << " " << heap_->DumpSpaces();
CHECK_NE(to_ref->GetLockWord(false).GetState(), LockWord::kForwardingAddress);
return to_ref;
}
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
index 22a3ea8..9c20613 100644
--- a/runtime/mirror/abstract_method.h
+++ b/runtime/mirror/abstract_method.h
@@ -63,8 +63,8 @@
HeapReference<mirror::Class> declaring_class_;
HeapReference<mirror::Class> declaring_class_of_overridden_method_;
- uint32_t access_flags_;
uint64_t art_method_;
+ uint32_t access_flags_;
uint32_t dex_method_index_;
friend struct art::AbstractMethodOffsets; // for verifying offset information
diff --git a/runtime/mirror/accessible_object.h b/runtime/mirror/accessible_object.h
index 1d934a8..2581ac2 100644
--- a/runtime/mirror/accessible_object.h
+++ b/runtime/mirror/accessible_object.h
@@ -47,9 +47,8 @@
private:
uint8_t flag_;
- // Padding required for now since "packed" will cause reflect.Field fields to not be aligned
- // otherwise.
- uint8_t padding_[3];
+ // Padding required for correct alignment of subclasses like Executable, Field, etc.
+ uint8_t padding_[1];
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessibleObject);
};
diff --git a/runtime/mirror/executable.h b/runtime/mirror/executable.h
index 8786657..232fce8 100644
--- a/runtime/mirror/executable.h
+++ b/runtime/mirror/executable.h
@@ -33,6 +33,9 @@
// C++ mirror of java.lang.reflect.Executable.
class MANAGED Executable : public AccessibleObject {
private:
+ uint16_t has_real_parameter_data_;
+ HeapReference<mirror::Array> parameters_;
+
friend struct art::ExecutableOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(Executable);
};
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index 7eb9da4..f378568 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -99,6 +99,9 @@
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
private:
+ // Padding required for matching alignment with the Java peer.
+ uint8_t padding_[2];
+
HeapReference<mirror::Class> declaring_class_;
HeapReference<mirror::Class> type_;
int32_t access_flags_;
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index 86e5139..aea6ff1 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -245,8 +245,9 @@
template <bool kIsInstrumented>
inline String* String::AllocEmptyString(Thread* self, gc::AllocatorType allocator_type) {
- SetStringCountVisitor visitor(0);
- return Alloc<kIsInstrumented>(self, 0, allocator_type, visitor);
+ const int32_t length_with_flag = String::GetFlaggedCount(0);
+ SetStringCountVisitor visitor(length_with_flag);
+ return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor);
}
template <bool kIsInstrumented>
diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc
new file mode 100644
index 0000000..8fe3bb5
--- /dev/null
+++ b/runtime/native/java_lang_reflect_Parameter.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "java_lang_reflect_Parameter.h"
+
+#include "art_method-inl.h"
+#include "common_throws.h"
+#include "dex_file-inl.h"
+#include "jni_internal.h"
+#include "scoped_fast_native_object_access.h"
+#include "utils.h"
+
+namespace art {
+
+static jobject Parameter_getAnnotationNative(JNIEnv* env,
+ jclass,
+ jobject javaMethod,
+ jint parameterIndex,
+ jclass annotationType) {
+ ScopedFastNativeObjectAccess soa(env);
+ if (UNLIKELY(javaMethod == nullptr)) {
+ ThrowNullPointerException("javaMethod == null");
+ return nullptr;
+ }
+
+ ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
+ if (method->IsProxyMethod()) {
+ return nullptr;
+ }
+
+ uint32_t parameter_count = method->GetParameterTypeList()->Size();
+ if (UNLIKELY(parameterIndex < 0 || static_cast<uint32_t>(parameterIndex) >= parameter_count)) {
+ ThrowIllegalArgumentException(
+ StringPrintf("Illegal parameterIndex %d for %s, parameter_count is %d",
+ parameterIndex,
+ PrettyMethod(method).c_str(),
+ parameter_count).c_str());
+ return nullptr;
+ }
+
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+ return soa.AddLocalReference<jobject>(
+ method->GetDexFile()->GetAnnotationForMethodParameter(method, parameterIndex, klass));
+}
+
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(Parameter,
+ getAnnotationNative,
+ "!(Ljava/lang/reflect/Executable;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;"),
+};
+
+void register_java_lang_reflect_Parameter(JNIEnv* env) {
+ REGISTER_NATIVE_METHODS("java/lang/reflect/Parameter");
+}
+
+} // namespace art
diff --git a/runtime/native/java_lang_reflect_Parameter.h b/runtime/native/java_lang_reflect_Parameter.h
new file mode 100644
index 0000000..f6322b1
--- /dev/null
+++ b/runtime/native/java_lang_reflect_Parameter.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_PARAMETER_H_
+#define ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_PARAMETER_H_
+
+#include <jni.h>
+
+namespace art {
+
+void register_java_lang_reflect_Parameter(JNIEnv* env);
+
+} // namespace art
+
+#endif // ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_PARAMETER_H_
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 339c457..d3561c1 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -32,6 +32,7 @@
#include <jni.h>
#include "openjdkjvmti/jvmti.h"
+#include "art_jvmti.h"
#include "gc_root-inl.h"
#include "globals.h"
#include "jni_env_ext-inl.h"
@@ -44,25 +45,6 @@
namespace openjdkjvmti {
-extern const jvmtiInterface_1 gJvmtiInterface;
-
-// A structure that is a jvmtiEnv with additional information for the runtime.
-struct ArtJvmTiEnv : public jvmtiEnv {
- art::JavaVMExt* art_vm;
- void* local_data;
-
- explicit ArtJvmTiEnv(art::JavaVMExt* runtime) : art_vm(runtime), local_data(nullptr) {
- functions = &gJvmtiInterface;
- }
-};
-
-// Macro and constexpr to make error values less annoying to write.
-#define ERR(e) JVMTI_ERROR_ ## e
-static constexpr jvmtiError OK = JVMTI_ERROR_NONE;
-
-// Special error code for unimplemented functions in JVMTI
-static constexpr jvmtiError ERR(NOT_IMPLEMENTED) = JVMTI_ERROR_NOT_AVAILABLE;
-
class JvmtiFunctions {
private:
static bool IsValidEnv(jvmtiEnv* env) {
diff --git a/runtime/openjdkjvmti/art_jvmti.h b/runtime/openjdkjvmti/art_jvmti.h
new file mode 100644
index 0000000..a2c6882
--- /dev/null
+++ b/runtime/openjdkjvmti/art_jvmti.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h. The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_
+#define ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_
+
+#include <jni.h>
+
+#include "java_vm_ext.h"
+#include "jni_env_ext.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+extern const jvmtiInterface_1 gJvmtiInterface;
+
+// A structure that is a jvmtiEnv with additional information for the runtime.
+struct ArtJvmTiEnv : public jvmtiEnv {
+ art::JavaVMExt* art_vm;
+ void* local_data;
+
+ explicit ArtJvmTiEnv(art::JavaVMExt* runtime) : art_vm(runtime), local_data(nullptr) {
+ functions = &gJvmtiInterface;
+ }
+};
+
+// Macro and constexpr to make error values less annoying to write.
+#define ERR(e) JVMTI_ERROR_ ## e
+static constexpr jvmtiError OK = JVMTI_ERROR_NONE;
+
+// Special error code for unimplemented functions in JVMTI
+static constexpr jvmtiError ERR(NOT_IMPLEMENTED) = JVMTI_ERROR_NOT_AVAILABLE;
+
+static inline JNIEnv* GetJniEnv(jvmtiEnv* env) {
+ JNIEnv* ret_value = nullptr;
+ jint res = reinterpret_cast<ArtJvmTiEnv*>(env)->art_vm->GetEnv(
+ reinterpret_cast<void**>(&ret_value), JNI_VERSION_1_1);
+ if (res != JNI_OK) {
+ return nullptr;
+ }
+ return ret_value;
+}
+
+} // namespace openjdkjvmti
+
+#endif // ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 561ada4..97911d4 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -113,6 +113,7 @@
#include "native/java_lang_reflect_Constructor.h"
#include "native/java_lang_reflect_Field.h"
#include "native/java_lang_reflect_Method.h"
+#include "native/java_lang_reflect_Parameter.h"
#include "native/java_lang_reflect_Proxy.h"
#include "native/java_util_concurrent_atomic_AtomicLong.h"
#include "native/libcore_util_CharsetUtils.h"
@@ -1425,6 +1426,7 @@
register_java_lang_reflect_Constructor(env);
register_java_lang_reflect_Field(env);
register_java_lang_reflect_Method(env);
+ register_java_lang_reflect_Parameter(env);
register_java_lang_reflect_Proxy(env);
register_java_lang_ref_Reference(env);
register_java_lang_String(env);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 43ef1cb..a860c7a 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2548,7 +2548,6 @@
QUICK_ENTRY_POINT_INFO(pDeliverException)
QUICK_ENTRY_POINT_INFO(pThrowArrayBounds)
QUICK_ENTRY_POINT_INFO(pThrowDivZero)
- QUICK_ENTRY_POINT_INFO(pThrowNoSuchMethod)
QUICK_ENTRY_POINT_INFO(pThrowNullPointer)
QUICK_ENTRY_POINT_INFO(pThrowStackOverflow)
QUICK_ENTRY_POINT_INFO(pDeoptimize)
diff --git a/runtime/thread.h b/runtime/thread.h
index d248123..b53cc2e 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -1363,12 +1363,12 @@
instrumentation_stack(nullptr), debug_invoke_req(nullptr), single_step_control(nullptr),
stacked_shadow_frame_record(nullptr), deoptimization_context_stack(nullptr),
frame_id_to_shadow_frame(nullptr), name(nullptr), pthread_self(0),
- last_no_thread_suspension_cause(nullptr), thread_local_start(nullptr),
- thread_local_objects(0), thread_local_pos(nullptr), thread_local_end(nullptr),
- mterp_current_ibase(nullptr), mterp_default_ibase(nullptr), mterp_alt_ibase(nullptr),
- thread_local_alloc_stack_top(nullptr), thread_local_alloc_stack_end(nullptr),
- nested_signal_state(nullptr), flip_function(nullptr), method_verifier(nullptr),
- thread_local_mark_stack(nullptr) {
+ last_no_thread_suspension_cause(nullptr), checkpoint_function(nullptr),
+ thread_local_start(nullptr), thread_local_pos(nullptr), thread_local_end(nullptr),
+ thread_local_objects(0), mterp_current_ibase(nullptr), mterp_default_ibase(nullptr),
+ mterp_alt_ibase(nullptr), thread_local_alloc_stack_top(nullptr),
+ thread_local_alloc_stack_end(nullptr), nested_signal_state(nullptr),
+ flip_function(nullptr), method_verifier(nullptr), thread_local_mark_stack(nullptr) {
std::fill(held_mutexes, held_mutexes + kLockLevelCount, nullptr);
}
@@ -1480,11 +1480,11 @@
// Thread-local allocation pointer.
uint8_t* thread_local_start;
- size_t thread_local_objects;
// thread_local_pos and thread_local_end must be consecutive for ldrd and are 8 byte aligned for
// potentially better performance.
uint8_t* thread_local_pos;
uint8_t* thread_local_end;
+ size_t thread_local_objects;
// Mterp jump table bases.
void* mterp_current_ibase;
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 589e71c..6b1170b 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -123,7 +123,7 @@
mirror::Class* klass,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- LogSeverity log_level,
+ HardFailLogMode log_level,
std::string* error) {
if (klass->IsVerified()) {
return kNoFailure;
@@ -196,7 +196,7 @@
Handle<mirror::ClassLoader> class_loader,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- LogSeverity log_level,
+ HardFailLogMode log_level,
bool need_precise_constants,
std::string* error_string) {
DCHECK(it != nullptr);
@@ -267,7 +267,7 @@
const DexFile::ClassDef& class_def,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- LogSeverity log_level,
+ HardFailLogMode log_level,
std::string* error) {
ScopedTrace trace(__FUNCTION__);
@@ -360,7 +360,7 @@
uint32_t method_access_flags,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- LogSeverity log_level,
+ HardFailLogMode log_level,
bool need_precise_constants,
std::string* hard_failure_msg) {
MethodVerifier::FailureData result;
@@ -420,11 +420,26 @@
} else {
CHECK(verifier.have_pending_hard_failure_);
if (VLOG_IS_ON(verifier)) {
- log_level = LogSeverity::VERBOSE;
+ log_level = std::max(HardFailLogMode::kLogVerbose, log_level);
}
- if (log_level > LogSeverity::VERBOSE) {
- verifier.DumpFailures(LOG(log_level) << "Verification error in "
- << PrettyMethod(method_idx, *dex_file) << "\n");
+ if (log_level >= HardFailLogMode::kLogVerbose) {
+ LogSeverity severity;
+ switch (log_level) {
+ case HardFailLogMode::kLogVerbose:
+ severity = LogSeverity::VERBOSE;
+ break;
+ case HardFailLogMode::kLogWarning:
+ severity = LogSeverity::WARNING;
+ break;
+ case HardFailLogMode::kLogInternalFatal:
+ severity = LogSeverity::INTERNAL_FATAL;
+ break;
+ default:
+ LOG(FATAL) << "Unsupported log-level " << static_cast<uint32_t>(log_level);
+ UNREACHABLE();
+ }
+ verifier.DumpFailures(LOG(severity) << "Verification error in "
+ << PrettyMethod(method_idx, *dex_file) << "\n");
}
if (hard_failure_msg != nullptr) {
CHECK(!verifier.failure_messages_.empty());
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index d4e12f7..c4b1c6e 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -32,6 +32,7 @@
#include "method_reference.h"
#include "register_line.h"
#include "reg_type_cache.h"
+#include "verifier_log_mode.h"
namespace art {
@@ -152,7 +153,7 @@
mirror::Class* klass,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- LogSeverity log_level,
+ HardFailLogMode log_level,
std::string* error)
REQUIRES_SHARED(Locks::mutator_lock_);
static FailureKind VerifyClass(Thread* self,
@@ -162,7 +163,7 @@
const DexFile::ClassDef& class_def,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- LogSeverity log_level,
+ HardFailLogMode log_level,
std::string* error)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -336,7 +337,7 @@
Handle<mirror::ClassLoader> class_loader,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- LogSeverity log_level,
+ HardFailLogMode log_level,
bool need_precise_constants,
std::string* error_string)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -362,7 +363,7 @@
uint32_t method_access_flags,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- LogSeverity log_level,
+ HardFailLogMode log_level,
bool need_precise_constants,
std::string* hard_failure_msg)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index 4fd581d..646987a 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -23,6 +23,7 @@
#include "common_runtime_test.h"
#include "dex_file.h"
#include "scoped_thread_state_change.h"
+#include "verifier_log_mode.h"
namespace art {
namespace verifier {
@@ -37,12 +38,8 @@
// Verify the class
std::string error_msg;
- MethodVerifier::FailureKind failure = MethodVerifier::VerifyClass(self,
- klass,
- nullptr,
- true,
- LogSeverity::WARNING,
- &error_msg);
+ MethodVerifier::FailureKind failure = MethodVerifier::VerifyClass(
+ self, klass, nullptr, true, HardFailLogMode::kLogWarning, &error_msg);
ASSERT_TRUE(failure == MethodVerifier::kNoFailure) << error_msg;
}
diff --git a/runtime/verifier/verifier_log_mode.h b/runtime/verifier/verifier_log_mode.h
new file mode 100644
index 0000000..3744b9b
--- /dev/null
+++ b/runtime/verifier/verifier_log_mode.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
+#define ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
+
+namespace art {
+namespace verifier {
+
+enum class HardFailLogMode {
+ kLogNone, // Don't log hard failures at all.
+ kLogVerbose, // Log with severity VERBOSE.
+ kLogWarning, // Log with severity WARNING.
+ kLogInternalFatal, // Log with severity INTERNAL_FATAL
+};
+
+} // namespace verifier
+} // namespace art
+
+#endif // ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
diff --git a/test/439-npe/expected.txt b/test/439-npe/expected.txt
index 34855ee..b4fd6bb 100644
--- a/test/439-npe/expected.txt
+++ b/test/439-npe/expected.txt
@@ -52,3 +52,73 @@
$opt$noinline$getBooleanElement
$opt$noinline$getCharElement
$opt$noinline$getShortElement
+i0=4
+i1=8
+i2=12
+i3=16
+i4=20
+i5=24
+i6=28
+i7=32
+i8=36
+i9=40
+i10=44
+i11=48
+i12=52
+i13=56
+i14=44
+i15=57
+l0=84
+l1=88
+l2=92
+l3=96
+l4=100
+l5=104
+l6=108
+l7=112
+l8=116
+l9=120
+l10=124
+l11=128
+l12=132
+l13=136
+l14=104
+l15=146
+f0=164.0
+f1=168.0
+f2=172.0
+f3=176.0
+f4=180.0
+f5=184.0
+f6=188.0
+f7=192.0
+f8=196.0
+f9=200.0
+f10=204.0
+f11=208.0
+f12=212.0
+f13=216.0
+f14=164.0
+f15=55.5
+d0=244.0
+d1=248.0
+d2=252.0
+d3=256.0
+d4=260.0
+d5=264.0
+d6=268.0
+d7=272.0
+d8=276.0
+d9=280.0
+d10=284.0
+d11=288.0
+d12=292.0
+d13=296.0
+d14=224.0
+d15=75.125
+addInt=42
+addLong=111
+addFloat=0.5
+addDouble=0.125
+m=null
+i=2
diff --git a/test/439-npe/src/Main.java b/test/439-npe/src/Main.java
index 8f66da0..bc044a4 100644
--- a/test/439-npe/src/Main.java
+++ b/test/439-npe/src/Main.java
@@ -634,12 +634,246 @@
} catch (NullPointerException npe) {
check(npe, thisLine += 6, methodLine += 5, "$opt$noinline$getShortElement");
}
+
+ $opt$noinline$testRegisterRetrieval();
}
- static void check(NullPointerException npe, int mainLine, int medthodLine, String methodName) {
+ static void $opt$noinline$testRegisterRetrieval() {
+ Main[] array = $noinline$PrepareArray();
+ int i0 = 0;
+ int i1 = 1;
+ int i2 = 2;
+ int i3 = 3;
+ int i4 = 4;
+ int i5 = 5;
+ int i6 = 6;
+ int i7 = 7;
+ int i8 = 8;
+ int i9 = 9;
+ int i10 = 10;
+ int i11 = 11;
+ int i12 = 12;
+ int i13 = 13;
+ int i14 = 14;
+ int i15 = 15;
+ long l0 = 20L;
+ long l1 = 21L;
+ long l2 = 22L;
+ long l3 = 23L;
+ long l4 = 24L;
+ long l5 = 25L;
+ long l6 = 26L;
+ long l7 = 27L;
+ long l8 = 28L;
+ long l9 = 29L;
+ long l10 = 30L;
+ long l11 = 31L;
+ long l12 = 32L;
+ long l13 = 33L;
+ long l14 = 34L;
+ long l15 = 35L;
+ float f0 = 40.0f;
+ float f1 = 41.0f;
+ float f2 = 42.0f;
+ float f3 = 43.0f;
+ float f4 = 44.0f;
+ float f5 = 45.0f;
+ float f6 = 46.0f;
+ float f7 = 47.0f;
+ float f8 = 48.0f;
+ float f9 = 49.0f;
+ float f10 = 50.0f;
+ float f11 = 51.0f;
+ float f12 = 52.0f;
+ float f13 = 53.0f;
+ float f14 = 54.0f;
+ float f15 = 55.0f;
+ double d0 = 60.0;
+ double d1 = 61.0;
+ double d2 = 62.0;
+ double d3 = 63.0;
+ double d4 = 64.0;
+ double d5 = 65.0;
+ double d6 = 66.0;
+ double d7 = 67.0;
+ double d8 = 68.0;
+ double d9 = 69.0;
+ double d10 = 70.0;
+ double d11 = 71.0;
+ double d12 = 72.0;
+ double d13 = 73.0;
+ double d14 = 74.0;
+ double d15 = 75.0;
+ int addInt = -1;
+ long addLong = -2L;
+ float addFloat = -3.0f;
+ double addDouble = -4.0;
+ Main m = null;
+ int i = 0;
+ try {
+ for (i = 0; i < array.length; ++i) {
+ m = array[i];
+ // We have 16 ints, 16 longs, 16 floats, 16 doubles and a few helper variables here,
+ // none of them anonymous. Hopefully, all available physical registers will be allocated
+ // to these variables, so that when `m.intField` throws NPE during the third iteration,
+ // we will fully test retrieval of values from all physical registers.
+ addInt = m.intField;
+ addLong = m.longField;
+ addFloat = m.floatField;
+ addDouble = m.doubleField;
+ i0 += i1;
+ i1 += i2;
+ i2 += i3;
+ i3 += i4;
+ i4 += i5;
+ i5 += i6;
+ i6 += i7;
+ i7 += i8;
+ i8 += i9;
+ i9 += i10;
+ i10 += i11;
+ i11 += i12;
+ i12 += i13;
+ i13 += i14;
+ i14 += i15;
+ i15 += addInt;
+ l0 += l1;
+ l1 += l2;
+ l2 += l3;
+ l3 += l4;
+ l4 += l5;
+ l5 += l6;
+ l6 += l7;
+ l7 += l8;
+ l8 += l9;
+ l9 += l10;
+ l10 += l11;
+ l11 += l12;
+ l12 += l13;
+ l13 += l14;
+ l14 += l15;
+ l15 += addLong;
+ f0 += f1;
+ f1 += f2;
+ f2 += f3;
+ f3 += f4;
+ f4 += f5;
+ f5 += f6;
+ f6 += f7;
+ f7 += f8;
+ f8 += f9;
+ f9 += f10;
+ f10 += f11;
+ f11 += f12;
+ f12 += f13;
+ f13 += f14;
+ f14 += f15;
+ f15 += addFloat;
+ d0 += d1;
+ d1 += d2;
+ d2 += d3;
+ d3 += d4;
+ d4 += d5;
+ d5 += d6;
+ d6 += d7;
+ d7 += d8;
+ d8 += d9;
+ d9 += d10;
+ d10 += d11;
+ d11 += d12;
+ d12 += d13;
+ d13 += d14;
+ d14 += d15;
+ d15 += addDouble;
+ }
+ } catch (NullPointerException npe) {
+ System.out.println("i0=" + i0);
+ System.out.println("i1=" + i1);
+ System.out.println("i2=" + i2);
+ System.out.println("i3=" + i3);
+ System.out.println("i4=" + i4);
+ System.out.println("i5=" + i5);
+ System.out.println("i6=" + i6);
+ System.out.println("i7=" + i7);
+ System.out.println("i8=" + i8);
+ System.out.println("i9=" + i9);
+ System.out.println("i10=" + i10);
+ System.out.println("i11=" + i11);
+ System.out.println("i12=" + i12);
+ System.out.println("i13=" + i13);
+ System.out.println("i14=" + i14);
+ System.out.println("i15=" + i15);
+ System.out.println("l0=" + l0);
+ System.out.println("l1=" + l1);
+ System.out.println("l2=" + l2);
+ System.out.println("l3=" + l3);
+ System.out.println("l4=" + l4);
+ System.out.println("l5=" + l5);
+ System.out.println("l6=" + l6);
+ System.out.println("l7=" + l7);
+ System.out.println("l8=" + l8);
+ System.out.println("l9=" + l9);
+ System.out.println("l10=" + l10);
+ System.out.println("l11=" + l11);
+ System.out.println("l12=" + l12);
+ System.out.println("l13=" + l13);
+ System.out.println("l14=" + l14);
+ System.out.println("l15=" + l15);
+ System.out.println("f0=" + f0);
+ System.out.println("f1=" + f1);
+ System.out.println("f2=" + f2);
+ System.out.println("f3=" + f3);
+ System.out.println("f4=" + f4);
+ System.out.println("f5=" + f5);
+ System.out.println("f6=" + f6);
+ System.out.println("f7=" + f7);
+ System.out.println("f8=" + f8);
+ System.out.println("f9=" + f9);
+ System.out.println("f10=" + f10);
+ System.out.println("f11=" + f11);
+ System.out.println("f12=" + f12);
+ System.out.println("f13=" + f13);
+ System.out.println("f14=" + f14);
+ System.out.println("f15=" + f15);
+ System.out.println("d0=" + d0);
+ System.out.println("d1=" + d1);
+ System.out.println("d2=" + d2);
+ System.out.println("d3=" + d3);
+ System.out.println("d4=" + d4);
+ System.out.println("d5=" + d5);
+ System.out.println("d6=" + d6);
+ System.out.println("d7=" + d7);
+ System.out.println("d8=" + d8);
+ System.out.println("d9=" + d9);
+ System.out.println("d10=" + d10);
+ System.out.println("d11=" + d11);
+ System.out.println("d12=" + d12);
+ System.out.println("d13=" + d13);
+ System.out.println("d14=" + d14);
+ System.out.println("d15=" + d15);
+ System.out.println("addInt=" + addInt);
+ System.out.println("addLong=" + addLong);
+ System.out.println("addFloat=" + addFloat);
+ System.out.println("addDouble=" + addDouble);
+ System.out.println("m=" + m);
+ System.out.println("i=" + i);
+ }
+ }
+
+ static Main[] $noinline$PrepareArray() {
+ if (doThrow) { throw new Error(); }
+ Main[] array = new Main[] { new Main(), new Main(), null, new Main() };
+ array[1].intField = 42;
+ array[1].longField = 111L;
+ array[1].floatField = 0.5f;
+ array[1].doubleField = 0.125;
+ return array;
+ }
+
+ static void check(NullPointerException npe, int mainLine, int methodLine, String methodName) {
System.out.println(methodName);
StackTraceElement[] trace = npe.getStackTrace();
- checkElement(trace[0], "Main", methodName, "Main.java", medthodLine);
+ checkElement(trace[0], "Main", methodName, "Main.java", methodLine);
checkElement(trace[1], "Main", "main", "Main.java", mainLine);
}
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
index 12e0338..5ef66d1 100755
--- a/tools/buildbot-build.sh
+++ b/tools/buildbot-build.sh
@@ -45,6 +45,16 @@
fi
done
+# Workaround for repo incompatibilities on the Chromium buildbot.
+# TODO: Remove this workaround once https://bugs.chromium.org/p/chromium/issues/detail?id=646329
+# is addressed.
+repo=$(which repo)
+if [[ $repo == *"depot_tools"* ]]; then
+ ln -s build/soong/root.bp Android.bp
+ ln -s build/soong/bootstrap.bash bootstrap.bash
+ echo "include build/core/main.mk" > Makefile
+fi
+
if [[ $mode == "host" ]]; then
make_command="make $j_arg $showcommands build-art-host-tests $common_targets"
make_command+=" ${out_dir}/host/linux-x86/lib/libjavacoretests.so "