summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/buffered_output_stream.cc2
-rw-r--r--compiler/buffered_output_stream.h2
-rw-r--r--compiler/compiled_method.cc53
-rw-r--r--compiler/compiled_method.h33
-rw-r--r--compiler/dex/arena_allocator.cc3
-rw-r--r--compiler/dex/quick/gen_invoke.cc8
-rw-r--r--compiler/driver/compiler_driver.cc34
-rw-r--r--compiler/driver/compiler_driver.h4
-rw-r--r--compiler/driver/compiler_driver_test.cc6
-rw-r--r--compiler/elf_fixup.cc12
-rw-r--r--compiler/file_output_stream.cc2
-rw-r--r--compiler/file_output_stream.h2
-rw-r--r--compiler/image_writer.cc132
-rw-r--r--compiler/image_writer.h24
-rw-r--r--compiler/jni/jni_compiler_test.cc47
-rw-r--r--compiler/llvm/compiler_llvm.cc2
-rw-r--r--compiler/llvm/gbc_expander.cc4
-rw-r--r--compiler/llvm/llvm_compilation_unit.cc4
-rw-r--r--compiler/llvm/llvm_compilation_unit.h4
-rw-r--r--compiler/oat_test.cc61
-rw-r--r--compiler/oat_writer.cc154
-rw-r--r--compiler/oat_writer.h6
-rw-r--r--compiler/output_stream.h2
-rw-r--r--compiler/utils/dedupe_set.h4
-rw-r--r--compiler/utils/mips/assembler_mips.cc12
-rw-r--r--compiler/utils/x86/assembler_x86.cc20
-rw-r--r--compiler/utils/x86/assembler_x86.h3
-rw-r--r--compiler/vector_output_stream.h2
-rw-r--r--dex2oat/dex2oat.cc14
-rw-r--r--disassembler/disassembler_arm.cc4
-rw-r--r--oatdump/oatdump.cc206
-rw-r--r--runtime/Android.mk24
-rw-r--r--runtime/arch/arm/context_arm.h2
-rw-r--r--runtime/arch/arm/portable_entrypoints_arm.S2
-rw-r--r--runtime/arch/arm/quick_entrypoints_arm.S2
-rw-r--r--runtime/arch/context.cc7
-rw-r--r--runtime/arch/context.h5
-rw-r--r--runtime/arch/mips/context_mips.h2
-rw-r--r--runtime/arch/mips/portable_entrypoints_mips.S68
-rw-r--r--runtime/arch/mips/quick_entrypoints_mips.S8
-rw-r--r--runtime/arch/x86/context_x86.cc8
-rw-r--r--runtime/arch/x86/context_x86.h2
-rw-r--r--runtime/arch/x86/jni_entrypoints_x86.S2
-rw-r--r--runtime/arch/x86/portable_entrypoints_x86.S2
-rw-r--r--runtime/arch/x86/quick_entrypoints_x86.S2
-rw-r--r--runtime/arch/x86_64/asm_support_x86_64.S146
-rw-r--r--runtime/arch/x86_64/asm_support_x86_64.h31
-rw-r--r--runtime/arch/x86_64/context_x86_64.cc76
-rw-r--r--runtime/arch/x86_64/context_x86_64.h69
-rw-r--r--runtime/arch/x86_64/entrypoints_init_x86_64.cc224
-rw-r--r--runtime/arch/x86_64/jni_entrypoints_x86_64.S22
-rw-r--r--runtime/arch/x86_64/portable_entrypoints_x86_64.S28
-rw-r--r--runtime/arch/x86_64/quick_entrypoints_x86_64.S401
-rw-r--r--runtime/arch/x86_64/registers_x86_64.cc38
-rw-r--r--runtime/arch/x86_64/registers_x86_64.h54
-rw-r--r--runtime/arch/x86_64/thread_x86_64.cc69
-rw-r--r--runtime/asm_support.h3
-rw-r--r--runtime/atomic.cc2
-rw-r--r--runtime/atomic.h71
-rw-r--r--runtime/atomic_integer.h86
-rw-r--r--runtime/barrier_test.cc2
-rw-r--r--runtime/base/bit_vector_test.cc4
-rw-r--r--runtime/base/mutex.cc6
-rw-r--r--runtime/base/mutex.h2
-rw-r--r--runtime/base/unix_file/fd_file.cc16
-rw-r--r--runtime/base/unix_file/fd_file.h4
-rw-r--r--runtime/base/unix_file/mapped_file.cc6
-rw-r--r--runtime/base/unix_file/mapped_file_test.cc13
-rw-r--r--runtime/base/unix_file/null_file_test.cc6
-rw-r--r--runtime/base/unix_file/random_access_file_test.h24
-rw-r--r--runtime/check_jni.cc174
-rw-r--r--runtime/class_linker-inl.h10
-rw-r--r--runtime/class_linker.cc175
-rw-r--r--runtime/class_linker.h37
-rw-r--r--runtime/class_linker_test.cc37
-rw-r--r--runtime/common_test.h79
-rw-r--r--runtime/common_throws.cc33
-rw-r--r--runtime/common_throws.h31
-rw-r--r--runtime/debugger.cc45
-rw-r--r--runtime/debugger.h4
-rw-r--r--runtime/dex_file-inl.h2
-rw-r--r--runtime/dex_file.cc2
-rw-r--r--runtime/dex_file.h2
-rw-r--r--runtime/elf_file.cc3
-rw-r--r--runtime/entrypoints/entrypoint_utils.h55
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.cc18
-rw-r--r--runtime/entrypoints/portable/portable_cast_entrypoints.cc12
-rw-r--r--runtime/entrypoints/portable/portable_field_entrypoints.cc16
-rw-r--r--runtime/entrypoints/portable/portable_fillarray_entrypoints.cc2
-rw-r--r--runtime/entrypoints/portable/portable_invoke_entrypoints.cc2
-rw-r--r--runtime/entrypoints/portable/portable_throw_entrypoints.cc2
-rw-r--r--runtime/entrypoints/portable/portable_trampoline_entrypoints.cc32
-rw-r--r--runtime/entrypoints/quick/quick_cast_entrypoints.cc3
-rw-r--r--runtime/entrypoints/quick/quick_dexcache_entrypoints.cc6
-rw-r--r--runtime/entrypoints/quick/quick_field_entrypoints.cc38
-rw-r--r--runtime/entrypoints/quick/quick_fillarray_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_invoke_entrypoints.cc24
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc12
-rw-r--r--runtime/exception_test.cc95
-rw-r--r--runtime/gc/accounting/atomic_stack.h4
-rw-r--r--runtime/gc/accounting/card_table.cc6
-rw-r--r--runtime/gc/accounting/mod_union_table.cc41
-rw-r--r--runtime/gc/accounting/mod_union_table.h11
-rw-r--r--runtime/gc/accounting/space_bitmap-inl.h13
-rw-r--r--runtime/gc/accounting/space_bitmap.cc2
-rw-r--r--runtime/gc/accounting/space_bitmap.h4
-rw-r--r--runtime/gc/collector/mark_sweep-inl.h14
-rw-r--r--runtime/gc/collector/mark_sweep.h2
-rw-r--r--runtime/gc/collector/semi_space.cc6
-rw-r--r--runtime/gc/collector/semi_space.h2
-rw-r--r--runtime/gc/heap.cc66
-rw-r--r--runtime/gc/heap.h35
-rw-r--r--runtime/gc/reference_queue.cc11
-rw-r--r--runtime/gc/reference_queue.h4
-rw-r--r--runtime/gc/space/bump_pointer_space.cc4
-rw-r--r--runtime/gc/space/bump_pointer_space.h6
-rw-r--r--runtime/gc/space/dlmalloc_space.cc2
-rw-r--r--runtime/gc/space/dlmalloc_space.h10
-rw-r--r--runtime/gc/space/image_space.cc6
-rw-r--r--runtime/gc/space/image_space.h2
-rw-r--r--runtime/gc/space/large_object_space.cc10
-rw-r--r--runtime/gc/space/large_object_space.h5
-rw-r--r--runtime/gc/space/malloc_space.cc2
-rw-r--r--runtime/gc/space/malloc_space.h27
-rw-r--r--runtime/gc/space/rosalloc_space.cc2
-rw-r--r--runtime/gc/space/rosalloc_space.h10
-rw-r--r--runtime/gc/space/space.h2
-rw-r--r--runtime/gc/space/space_test.cc72
-rw-r--r--runtime/gc/space/zygote_space.h2
-rw-r--r--runtime/globals.h2
-rw-r--r--runtime/hprof/hprof.cc180
-rw-r--r--runtime/instruction_set.h1
-rw-r--r--runtime/instrumentation.cc112
-rw-r--r--runtime/instrumentation.h29
-rw-r--r--runtime/interpreter/interpreter.cc2
-rw-r--r--runtime/interpreter/interpreter_common.cc21
-rw-r--r--runtime/interpreter/interpreter_common.h6
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc2
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc2
-rw-r--r--runtime/invoke_arg_array_builder.h16
-rw-r--r--runtime/jdwp/jdwp.h2
-rw-r--r--runtime/jni_internal.cc16
-rw-r--r--runtime/jni_internal_test.cc62
-rw-r--r--runtime/lock_word-inl.h7
-rw-r--r--runtime/lock_word.h2
-rw-r--r--runtime/mem_map.cc8
-rw-r--r--runtime/mem_map.h2
-rw-r--r--runtime/mem_map_test.cc143
-rw-r--r--runtime/mirror/array-inl.h117
-rw-r--r--runtime/mirror/array.cc4
-rw-r--r--runtime/mirror/array.h59
-rw-r--r--runtime/mirror/art_field-inl.h60
-rw-r--r--runtime/mirror/art_field.h104
-rw-r--r--runtime/mirror/art_method-inl.h77
-rw-r--r--runtime/mirror/art_method.cc67
-rw-r--r--runtime/mirror/art_method.h310
-rw-r--r--runtime/mirror/class-inl.h130
-rw-r--r--runtime/mirror/class.cc60
-rw-r--r--runtime/mirror/class.h328
-rw-r--r--runtime/mirror/class_loader.h6
-rw-r--r--runtime/mirror/dex_cache-inl.h2
-rw-r--r--runtime/mirror/dex_cache.h60
-rw-r--r--runtime/mirror/iftable.h9
-rw-r--r--runtime/mirror/object-inl.h165
-rw-r--r--runtime/mirror/object.cc9
-rw-r--r--runtime/mirror/object.h149
-rw-r--r--runtime/mirror/object_array-inl.h162
-rw-r--r--runtime/mirror/object_array.h24
-rw-r--r--runtime/mirror/object_reference.h91
-rw-r--r--runtime/mirror/object_test.cc7
-rw-r--r--runtime/mirror/proxy.h18
-rw-r--r--runtime/mirror/stack_trace_element.h29
-rw-r--r--runtime/mirror/string.cc28
-rw-r--r--runtime/mirror/string.h34
-rw-r--r--runtime/mirror/throwable.cc12
-rw-r--r--runtime/mirror/throwable.h22
-rw-r--r--runtime/modifiers.h1
-rw-r--r--runtime/monitor.cc18
-rw-r--r--runtime/monitor.h17
-rw-r--r--runtime/monitor_pool.cc56
-rw-r--r--runtime/monitor_pool.h94
-rw-r--r--runtime/native/dalvik_system_DexFile.cc2
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc5
-rw-r--r--runtime/native/dalvik_system_VMStack.cc2
-rw-r--r--runtime/native/dalvik_system_Zygote.cc2
-rw-r--r--runtime/native/java_lang_System.cc342
-rw-r--r--runtime/native/sun_misc_Unsafe.cc58
-rw-r--r--runtime/oat_file.cc61
-rw-r--r--runtime/oat_file.h26
-rw-r--r--runtime/object_utils.h89
-rw-r--r--runtime/offsets.h8
-rw-r--r--runtime/primitive.h3
-rw-r--r--runtime/profiler.cc4
-rw-r--r--runtime/reference_table.cc12
-rw-r--r--runtime/runtime.cc115
-rw-r--r--runtime/runtime.h6
-rw-r--r--runtime/runtime_linux.cc6
-rw-r--r--runtime/sirt_ref.h12
-rw-r--r--runtime/stack.cc36
-rw-r--r--runtime/stack.h99
-rw-r--r--runtime/stack_indirect_reference_table.h15
-rw-r--r--runtime/thread.cc40
-rw-r--r--runtime/thread.h14
-rw-r--r--runtime/thread_pool.cc2
-rw-r--r--runtime/thread_pool_test.cc2
-rw-r--r--runtime/trace.cc20
-rw-r--r--runtime/trace.h10
-rw-r--r--runtime/utf.cc2
-rw-r--r--runtime/utf.h2
-rw-r--r--runtime/utils.cc30
-rw-r--r--runtime/utils.h44
-rw-r--r--runtime/verifier/method_verifier.cc11
-rw-r--r--runtime/verifier/method_verifier.h3
-rw-r--r--runtime/verifier/reg_type.h2
-rw-r--r--runtime/well_known_classes.cc2
-rw-r--r--runtime/zip_archive.cc2
216 files changed, 4850 insertions, 2924 deletions
diff --git a/compiler/buffered_output_stream.cc b/compiler/buffered_output_stream.cc
index 81a58f6..0940a80 100644
--- a/compiler/buffered_output_stream.cc
+++ b/compiler/buffered_output_stream.cc
@@ -23,7 +23,7 @@ namespace art {
BufferedOutputStream::BufferedOutputStream(OutputStream* out)
: OutputStream(out->GetLocation()), out_(out), used_(0) {}
-bool BufferedOutputStream::WriteFully(const void* buffer, int64_t byte_count) {
+bool BufferedOutputStream::WriteFully(const void* buffer, size_t byte_count) {
if (byte_count > kBufferSize) {
Flush();
return out_->WriteFully(buffer, byte_count);
diff --git a/compiler/buffered_output_stream.h b/compiler/buffered_output_stream.h
index 7d874fb..75a3f24 100644
--- a/compiler/buffered_output_stream.h
+++ b/compiler/buffered_output_stream.h
@@ -31,7 +31,7 @@ class BufferedOutputStream : public OutputStream {
delete out_;
}
- virtual bool WriteFully(const void* buffer, int64_t byte_count);
+ virtual bool WriteFully(const void* buffer, size_t byte_count);
virtual off_t Seek(off_t offset, Whence whence);
diff --git a/compiler/compiled_method.cc b/compiler/compiled_method.cc
index 29ff390..f6d724a 100644
--- a/compiler/compiled_method.cc
+++ b/compiler/compiled_method.cc
@@ -20,14 +20,16 @@
namespace art {
CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
- const std::vector<uint8_t>& code)
- : compiler_driver_(compiler_driver), instruction_set_(instruction_set), code_(nullptr) {
- SetCode(code);
+ const std::vector<uint8_t>& quick_code)
+ : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
+ portable_code_(nullptr), quick_code_(nullptr) {
+ SetCode(&quick_code, nullptr);
}
CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
const std::string& elf_object, const std::string& symbol)
- : compiler_driver_(compiler_driver), instruction_set_(instruction_set), symbol_(symbol) {
+ : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
+ portable_code_(nullptr), quick_code_(nullptr), symbol_(symbol) {
CHECK_NE(elf_object.size(), 0U);
CHECK_NE(symbol.size(), 0U);
std::vector<uint8_t> temp_code(elf_object.size());
@@ -38,12 +40,41 @@ CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instr
// change to have different kinds of compiled methods. This is
// being deferred until we work on hybrid execution or at least
// until we work on batch compilation.
- SetCode(temp_code);
+ SetCode(nullptr, &temp_code);
}
-void CompiledCode::SetCode(const std::vector<uint8_t>& code) {
- CHECK(!code.empty());
- code_ = compiler_driver_->DeduplicateCode(code);
+void CompiledCode::SetCode(const std::vector<uint8_t>* quick_code,
+ const std::vector<uint8_t>* portable_code) {
+ if (portable_code != nullptr) {
+ CHECK(!portable_code->empty());
+ portable_code_ = compiler_driver_->DeduplicateCode(*portable_code);
+ }
+ if (quick_code != nullptr) {
+ CHECK(!quick_code->empty());
+ quick_code_ = compiler_driver_->DeduplicateCode(*quick_code);
+ }
+}
+
+bool CompiledCode::operator==(const CompiledCode& rhs) const {
+ if (quick_code_ != nullptr) {
+ if (rhs.quick_code_ == nullptr) {
+ return false;
+ } else if (quick_code_->size() != rhs.quick_code_->size()) {
+ return false;
+ } else {
+ return std::equal(quick_code_->begin(), quick_code_->end(), rhs.quick_code_->begin());
+ }
+ } else if (portable_code_ != nullptr) {
+ if (rhs.portable_code_ == nullptr) {
+ return false;
+ } else if (portable_code_->size() != rhs.portable_code_->size()) {
+ return false;
+ } else {
+ return std::equal(portable_code_->begin(), portable_code_->end(),
+ rhs.portable_code_->begin());
+ }
+ }
+ return (rhs.quick_code_ == nullptr) && (rhs.portable_code_ == nullptr);
}
uint32_t CompiledCode::AlignCode(uint32_t offset) const {
@@ -100,7 +131,6 @@ const void* CompiledCode::CodePointer(const void* code_pointer,
}
}
-#if defined(ART_USE_PORTABLE_COMPILER)
const std::string& CompiledCode::GetSymbol() const {
CHECK_NE(0U, symbol_.size());
return symbol_;
@@ -114,18 +144,17 @@ const std::vector<uint32_t>& CompiledCode::GetOatdataOffsetsToCompliledCodeOffse
void CompiledCode::AddOatdataOffsetToCompliledCodeOffset(uint32_t offset) {
oatdata_offsets_to_compiled_code_offset_.push_back(offset);
}
-#endif
CompiledMethod::CompiledMethod(CompilerDriver& driver,
InstructionSet instruction_set,
- const std::vector<uint8_t>& code,
+ const std::vector<uint8_t>& quick_code,
const size_t frame_size_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
const std::vector<uint8_t>& mapping_table,
const std::vector<uint8_t>& vmap_table,
const std::vector<uint8_t>& native_gc_map)
- : CompiledCode(&driver, instruction_set, code), frame_size_in_bytes_(frame_size_in_bytes),
+ : CompiledCode(&driver, instruction_set, quick_code), frame_size_in_bytes_(frame_size_in_bytes),
core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask),
mapping_table_(driver.DeduplicateMappingTable(mapping_table)),
vmap_table_(driver.DeduplicateVMapTable(vmap_table)),
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index e4fedf1..6112305 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -36,7 +36,7 @@ class CompiledCode {
public:
// For Quick to supply an code blob
CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
- const std::vector<uint8_t>& code);
+ const std::vector<uint8_t>& quick_code);
// For Portable to supply an ELF object
CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
@@ -46,16 +46,18 @@ class CompiledCode {
return instruction_set_;
}
- const std::vector<uint8_t>& GetCode() const {
- return *code_;
+ const std::vector<uint8_t>* GetPortableCode() const {
+ return portable_code_;
}
- void SetCode(const std::vector<uint8_t>& code);
-
- bool operator==(const CompiledCode& rhs) const {
- return (code_ == rhs.code_);
+ const std::vector<uint8_t>* GetQuickCode() const {
+ return quick_code_;
}
+ void SetCode(const std::vector<uint8_t>* quick_code, const std::vector<uint8_t>* portable_code);
+
+ bool operator==(const CompiledCode& rhs) const;
+
// To align an offset from a page-aligned value to make it suitable
// for code storage. For example on ARM, to ensure that PC relative
// valu computations work out as expected.
@@ -72,19 +74,20 @@ class CompiledCode {
static const void* CodePointer(const void* code_pointer,
InstructionSet instruction_set);
-#if defined(ART_USE_PORTABLE_COMPILER)
const std::string& GetSymbol() const;
const std::vector<uint32_t>& GetOatdataOffsetsToCompliledCodeOffset() const;
void AddOatdataOffsetToCompliledCodeOffset(uint32_t offset);
-#endif
private:
- CompilerDriver* compiler_driver_;
+ CompilerDriver* const compiler_driver_;
const InstructionSet instruction_set_;
- // Used to store the PIC code for Quick and an ELF image for portable.
- std::vector<uint8_t>* code_;
+ // The ELF image for portable.
+ std::vector<uint8_t>* portable_code_;
+
+ // Used to store the PIC code for Quick.
+ std::vector<uint8_t>* quick_code_;
// Used for the Portable ELF symbol name.
const std::string symbol_;
@@ -101,7 +104,7 @@ class CompiledMethod : public CompiledCode {
// Constructs a CompiledMethod for the non-LLVM compilers.
CompiledMethod(CompilerDriver& driver,
InstructionSet instruction_set,
- const std::vector<uint8_t>& code,
+ const std::vector<uint8_t>& quick_code,
const size_t frame_size_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
@@ -109,10 +112,10 @@ class CompiledMethod : public CompiledCode {
const std::vector<uint8_t>& vmap_table,
const std::vector<uint8_t>& native_gc_map);
- // Constructs a CompiledMethod for the JniCompiler.
+ // Constructs a CompiledMethod for the QuickJniCompiler.
CompiledMethod(CompilerDriver& driver,
InstructionSet instruction_set,
- const std::vector<uint8_t>& code,
+ const std::vector<uint8_t>& quick_code,
const size_t frame_size_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask);
diff --git a/compiler/dex/arena_allocator.cc b/compiler/dex/arena_allocator.cc
index 132831c..8d24439 100644
--- a/compiler/dex/arena_allocator.cc
+++ b/compiler/dex/arena_allocator.cc
@@ -52,7 +52,8 @@ Arena::Arena(size_t size)
next_(nullptr) {
if (kUseMemMap) {
std::string error_msg;
- map_ = MemMap::MapAnonymous("dalvik-arena", NULL, size, PROT_READ | PROT_WRITE, &error_msg);
+ map_ = MemMap::MapAnonymous("dalvik-arena", NULL, size, PROT_READ | PROT_WRITE, false,
+ &error_msg);
CHECK(map_ != nullptr) << error_msg;
memory_ = map_->Begin();
size_ = map_->Size();
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 6382dd6..6aaad66 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -453,7 +453,7 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
if (cu->instruction_set != kX86) {
if (direct_code == 0) {
cg->LoadWordDisp(cg->TargetReg(kArg0),
- mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value(),
cg->TargetReg(kInvokeTgt));
}
break;
@@ -506,7 +506,7 @@ static int NextVCallInsn(CompilationUnit* cu, CallInfo* info,
case 4: // Get the compiled code address [uses kArg0, sets kInvokeTgt]
if (cu->instruction_set != kX86) {
cg->LoadWordDisp(cg->TargetReg(kArg0),
- mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value(),
cg->TargetReg(kInvokeTgt));
break;
}
@@ -561,7 +561,7 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state,
case 5: // Get the compiled code address [use kArg0, set kInvokeTgt]
if (cu->instruction_set != kX86) {
cg->LoadWordDisp(cg->TargetReg(kArg0),
- mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value(),
cg->TargetReg(kInvokeTgt));
break;
}
@@ -1437,7 +1437,7 @@ void Mir2Lir::GenInvoke(CallInfo* info) {
} else {
if (fast_path) {
call_inst = OpMem(kOpBlx, TargetReg(kArg0),
- mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value());
+ mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value());
} else {
ThreadOffset trampoline(-1);
switch (info->type) {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 37b668f..9f48351 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -556,12 +556,15 @@ static DexToDexCompilationLevel GetDexToDexCompilationlevel(
}
}
-void CompilerDriver::CompileOne(const mirror::ArtMethod* method, TimingLogger& timings) {
+void CompilerDriver::CompileOne(mirror::ArtMethod* method, TimingLogger& timings) {
DCHECK(!Runtime::Current()->IsStarted());
Thread* self = Thread::Current();
jobject jclass_loader;
const DexFile* dex_file;
uint16_t class_def_idx;
+ uint32_t method_idx = method->GetDexMethodIndex();
+ uint32_t access_flags = method->GetAccessFlags();
+ InvokeType invoke_type = method->GetInvokeType();
{
ScopedObjectAccessUnchecked soa(self);
ScopedLocalRef<jobject>
@@ -573,6 +576,7 @@ void CompilerDriver::CompileOne(const mirror::ArtMethod* method, TimingLogger& t
dex_file = &mh.GetDexFile();
class_def_idx = mh.GetClassDefIndex();
}
+ const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
self->TransitionFromRunnableToSuspended(kNative);
std::vector<const DexFile*> dex_files;
@@ -581,8 +585,6 @@ void CompilerDriver::CompileOne(const mirror::ArtMethod* method, TimingLogger& t
UniquePtr<ThreadPool> thread_pool(new ThreadPool("Compiler driver thread pool", 0U));
PreCompile(jclass_loader, dex_files, *thread_pool.get(), timings);
- uint32_t method_idx = method->GetDexMethodIndex();
- const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
// Can we run DEX-to-DEX compiler on this class ?
DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile;
{
@@ -592,8 +594,8 @@ void CompilerDriver::CompileOne(const mirror::ArtMethod* method, TimingLogger& t
soa.Decode<mirror::ClassLoader*>(jclass_loader));
dex_to_dex_compilation_level = GetDexToDexCompilationlevel(class_loader, *dex_file, class_def);
}
- CompileMethod(code_item, method->GetAccessFlags(), method->GetInvokeType(),
- class_def_idx, method_idx, jclass_loader, *dex_file, dex_to_dex_compilation_level);
+ CompileMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, jclass_loader,
+ *dex_file, dex_to_dex_compilation_level);
self->GetJniEnv()->DeleteGlobalRef(jclass_loader);
@@ -1009,7 +1011,7 @@ bool CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompi
if (referrer_class != NULL) {
mirror::Class* fields_class = resolved_field->GetDeclaringClass();
bool access_ok = referrer_class->CanAccessResolvedField(fields_class, resolved_field,
- *dex_cache, field_idx);
+ dex_cache.get(), field_idx);
bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal() &&
fields_class != referrer_class;
if (access_ok && !is_write_to_final_from_wrong_class) {
@@ -1056,7 +1058,7 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila
return true; // fast path
} else {
bool access_ok = referrer_class->CanAccessResolvedField(fields_class, resolved_field,
- *dex_cache, field_idx);
+ dex_cache.get(), field_idx);
bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal();
if (access_ok && !is_write_to_final_from_wrong_class) {
// We have the resolved field, we must make it into a index for the referrer
@@ -1198,13 +1200,23 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType
CHECK(!method->IsAbstract());
*type = sharp_type;
*direct_method = reinterpret_cast<uintptr_t>(method);
- *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromCompiledCode());
+ if (compiler_backend_ == kQuick) {
+ *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
+ } else {
+ CHECK_EQ(compiler_backend_, kPortable);
+ *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
+ }
target_method->dex_file = method->GetDeclaringClass()->GetDexCache()->GetDexFile();
target_method->dex_method_index = method->GetDexMethodIndex();
} else if (!must_use_direct_pointers) {
// Set the code and rely on the dex cache for the method.
*type = sharp_type;
- *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromCompiledCode());
+ if (compiler_backend_ == kQuick) {
+ *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
+ } else {
+ CHECK_EQ(compiler_backend_, kPortable);
+ *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
+ }
} else {
// Direct pointers were required but none were available.
VLOG(compiler) << "Dex cache devirtualization failed for: " << PrettyMethod(method);
@@ -1239,8 +1251,8 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui
bool icce = resolved_method->CheckIncompatibleClassChange(*invoke_type);
if (referrer_class != NULL && !icce) {
mirror::Class* methods_class = resolved_method->GetDeclaringClass();
- if (referrer_class->CanAccessResolvedMethod(methods_class, resolved_method,
- *dex_cache, target_method->dex_method_index)) {
+ if (referrer_class->CanAccessResolvedMethod(methods_class, resolved_method, dex_cache.get(),
+ target_method->dex_method_index)) {
const bool enableFinalBasedSharpening = enable_devirtualization;
// Sharpen a virtual call into a direct call when the target is known not to have been
// overridden (ie is final).
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index a8110e7..4307212 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -106,8 +106,8 @@ class CompilerDriver {
TimingLogger& timings)
LOCKS_EXCLUDED(Locks::mutator_lock_);
- // Compile a single Method
- void CompileOne(const mirror::ArtMethod* method, TimingLogger& timings)
+ // Compile a single Method.
+ void CompileOne(mirror::ArtMethod* method, TimingLogger& timings)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
VerificationResults* GetVerificationResults() const {
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index a5eb94f..0d0c204 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -122,7 +122,11 @@ TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
EXPECT_TRUE(method != NULL) << "method_idx=" << i
<< " " << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
<< " " << dex->GetMethodName(dex->GetMethodId(i));
- EXPECT_TRUE(method->GetEntryPointFromCompiledCode() != NULL) << "method_idx=" << i
+ EXPECT_TRUE(method->GetEntryPointFromQuickCompiledCode() != NULL) << "method_idx=" << i
+ << " "
+ << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
+ << " " << dex->GetMethodName(dex->GetMethodId(i));
+ EXPECT_TRUE(method->GetEntryPointFromPortableCompiledCode() != NULL) << "method_idx=" << i
<< " "
<< dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
<< " " << dex->GetMethodName(dex->GetMethodId(i));
diff --git a/compiler/elf_fixup.cc b/compiler/elf_fixup.cc
index c571288..66c8da1 100644
--- a/compiler/elf_fixup.cc
+++ b/compiler/elf_fixup.cc
@@ -177,7 +177,7 @@ bool ElfFixup::FixupDynamic(ElfFile& elf_file, uintptr_t base_address) {
if (elf_dyn_needs_fixup) {
uint32_t d_ptr = elf_dyn.d_un.d_ptr;
if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Dyn[%d] from 0x%08x to 0x%08x",
+ LOG(INFO) << StringPrintf("In %s moving Elf32_Dyn[%d] from 0x%08x to 0x%08" PRIxPTR,
elf_file.GetFile().GetPath().c_str(), i,
d_ptr, d_ptr + base_address);
}
@@ -196,7 +196,7 @@ bool ElfFixup::FixupSectionHeaders(ElfFile& elf_file, uintptr_t base_address) {
continue;
}
if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Shdr[%d] from 0x%08x to 0x%08x",
+ LOG(INFO) << StringPrintf("In %s moving Elf32_Shdr[%d] from 0x%08x to 0x%08" PRIxPTR,
elf_file.GetFile().GetPath().c_str(), i,
sh.sh_addr, sh.sh_addr + base_address);
}
@@ -213,7 +213,7 @@ bool ElfFixup::FixupProgramHeaders(ElfFile& elf_file, uintptr_t base_address) {
CHECK((ph.p_align == 0) || (0 == ((ph.p_vaddr - ph.p_offset) & (ph.p_align - 1))))
<< elf_file.GetFile().GetPath() << " i=" << i;
if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Phdr[%d] from 0x%08x to 0x%08x",
+ LOG(INFO) << StringPrintf("In %s moving Elf32_Phdr[%d] from 0x%08x to 0x%08" PRIxPTR,
elf_file.GetFile().GetPath().c_str(), i,
ph.p_vaddr, ph.p_vaddr + base_address);
}
@@ -238,7 +238,7 @@ bool ElfFixup::FixupSymbols(ElfFile& elf_file, uintptr_t base_address, bool dyna
::llvm::ELF::Elf32_Sym& symbol = elf_file.GetSymbol(section_type, i);
if (symbol.st_value != 0) {
if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Sym[%d] from 0x%08x to 0x%08x",
+ LOG(INFO) << StringPrintf("In %s moving Elf32_Sym[%d] from 0x%08x to 0x%08" PRIxPTR,
elf_file.GetFile().GetPath().c_str(), i,
symbol.st_value, symbol.st_value + base_address);
}
@@ -255,7 +255,7 @@ bool ElfFixup::FixupRelocations(ElfFile& elf_file, uintptr_t base_address) {
for (uint32_t i = 0; i < elf_file.GetRelNum(sh); i++) {
llvm::ELF::Elf32_Rel& rel = elf_file.GetRel(sh, i);
if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Rel[%d] from 0x%08x to 0x%08x",
+ LOG(INFO) << StringPrintf("In %s moving Elf32_Rel[%d] from 0x%08x to 0x%08" PRIxPTR,
elf_file.GetFile().GetPath().c_str(), i,
rel.r_offset, rel.r_offset + base_address);
}
@@ -265,7 +265,7 @@ bool ElfFixup::FixupRelocations(ElfFile& elf_file, uintptr_t base_address) {
for (uint32_t i = 0; i < elf_file.GetRelaNum(sh); i++) {
llvm::ELF::Elf32_Rela& rela = elf_file.GetRela(sh, i);
if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Rela[%d] from 0x%08x to 0x%08x",
+ LOG(INFO) << StringPrintf("In %s moving Elf32_Rela[%d] from 0x%08x to 0x%08" PRIxPTR,
elf_file.GetFile().GetPath().c_str(), i,
rela.r_offset, rela.r_offset + base_address);
}
diff --git a/compiler/file_output_stream.cc b/compiler/file_output_stream.cc
index 0e4a294..3ee16f5 100644
--- a/compiler/file_output_stream.cc
+++ b/compiler/file_output_stream.cc
@@ -25,7 +25,7 @@ namespace art {
FileOutputStream::FileOutputStream(File* file) : OutputStream(file->GetPath()), file_(file) {}
-bool FileOutputStream::WriteFully(const void* buffer, int64_t byte_count) {
+bool FileOutputStream::WriteFully(const void* buffer, size_t byte_count) {
return file_->WriteFully(buffer, byte_count);
}
diff --git a/compiler/file_output_stream.h b/compiler/file_output_stream.h
index bde9e68..76b00fe 100644
--- a/compiler/file_output_stream.h
+++ b/compiler/file_output_stream.h
@@ -29,7 +29,7 @@ class FileOutputStream : public OutputStream {
virtual ~FileOutputStream() {}
- virtual bool WriteFully(const void* buffer, int64_t byte_count);
+ virtual bool WriteFully(const void* buffer, size_t byte_count);
virtual off_t Seek(off_t offset, Whence whence);
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 09bb70c..67cd51b 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -208,12 +208,12 @@ void ImageWriter::AssignImageOffset(mirror::Object* object) {
DCHECK_LT(image_end_, image_->Size());
}
-bool ImageWriter::IsImageOffsetAssigned(const mirror::Object* object) const {
+bool ImageWriter::IsImageOffsetAssigned(mirror::Object* object) const {
DCHECK(object != nullptr);
return object->GetLockWord().GetState() == LockWord::kForwardingAddress;
}
-size_t ImageWriter::GetImageOffset(const mirror::Object* object) const {
+size_t ImageWriter::GetImageOffset(mirror::Object* object) const {
DCHECK(object != nullptr);
DCHECK(IsImageOffsetAssigned(object));
LockWord lock_word = object->GetLockWord();
@@ -226,7 +226,7 @@ bool ImageWriter::AllocMemory() {
size_t length = RoundUp(Runtime::Current()->GetHeap()->GetTotalMemory(), kPageSize);
std::string error_msg;
image_.reset(MemMap::MapAnonymous("image writer image", NULL, length, PROT_READ | PROT_WRITE,
- &error_msg));
+ true, &error_msg));
if (UNLIKELY(image_.get() == nullptr)) {
LOG(ERROR) << "Failed to allocate memory for image file generation: " << error_msg;
return false;
@@ -281,7 +281,7 @@ void ImageWriter::ComputeEagerResolvedStrings() SHARED_LOCKS_REQUIRED(Locks::mut
Runtime::Current()->GetHeap()->VisitObjects(ComputeEagerResolvedStringsCallback, this);
}
-bool ImageWriter::IsImageClass(const Class* klass) {
+bool ImageWriter::IsImageClass(Class* klass) {
return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor());
}
@@ -447,7 +447,7 @@ void ImageWriter::WalkInstanceFields(mirror::Object* obj, mirror::Class* klass)
for (size_t i = 0; i < num_reference_fields; ++i) {
mirror::ArtField* field = sirt_class->GetInstanceField(i);
MemberOffset field_offset = field->GetOffset();
- mirror::Object* value = obj->GetFieldObject<mirror::Object*>(field_offset, false);
+ mirror::Object* value = obj->GetFieldObject<mirror::Object>(field_offset, false);
if (value != nullptr) {
WalkFieldsInOrder(value);
}
@@ -470,7 +470,7 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) {
for (size_t i = 0; i < num_static_fields; ++i) {
mirror::ArtField* field = klass->GetStaticField(i);
MemberOffset field_offset = field->GetOffset();
- mirror::Object* value = sirt_obj->GetFieldObject<mirror::Object*>(field_offset, false);
+ mirror::Object* value = sirt_obj->GetFieldObject<mirror::Object>(field_offset, false);
if (value != nullptr) {
WalkFieldsInOrder(value);
}
@@ -527,16 +527,16 @@ void ImageWriter::CalculateNewObjectOffsets(size_t oat_loaded_size, size_t oat_d
const size_t heap_bytes_per_bitmap_byte = kBitsPerByte * gc::accounting::SpaceBitmap::kAlignment;
const size_t bitmap_bytes = RoundUp(image_end_, heap_bytes_per_bitmap_byte) /
heap_bytes_per_bitmap_byte;
- ImageHeader image_header(reinterpret_cast<uint32_t>(image_begin_),
+ ImageHeader image_header(PointerToLowMemUInt32(image_begin_),
static_cast<uint32_t>(image_end_),
RoundUp(image_end_, kPageSize),
RoundUp(bitmap_bytes, kPageSize),
- reinterpret_cast<uint32_t>(GetImageAddress(image_roots.get())),
+ PointerToLowMemUInt32(GetImageAddress(image_roots.get())),
oat_file_->GetOatHeader().GetChecksum(),
- reinterpret_cast<uint32_t>(oat_file_begin),
- reinterpret_cast<uint32_t>(oat_data_begin_),
- reinterpret_cast<uint32_t>(oat_data_end),
- reinterpret_cast<uint32_t>(oat_file_end));
+ PointerToLowMemUInt32(oat_file_begin),
+ PointerToLowMemUInt32(oat_data_begin_),
+ PointerToLowMemUInt32(oat_data_end),
+ PointerToLowMemUInt32(oat_file_end));
memcpy(image_->Begin(), &image_header, sizeof(image_header));
// Note that image_end_ is left at end of used space
@@ -578,7 +578,7 @@ void ImageWriter::CopyAndFixupObjectsCallback(Object* obj, void* arg) {
image_writer->FixupObject(obj, copy);
}
-void ImageWriter::FixupObject(const Object* orig, Object* copy) {
+void ImageWriter::FixupObject(Object* orig, Object* copy) {
DCHECK(orig != NULL);
DCHECK(copy != NULL);
copy->SetClass(down_cast<Class*>(GetImageAddress(orig->GetClass())));
@@ -594,12 +594,12 @@ void ImageWriter::FixupObject(const Object* orig, Object* copy) {
}
}
-void ImageWriter::FixupClass(const Class* orig, Class* copy) {
+void ImageWriter::FixupClass(Class* orig, Class* copy) {
FixupInstanceFields(orig, copy);
FixupStaticFields(orig, copy);
}
-void ImageWriter::FixupMethod(const ArtMethod* orig, ArtMethod* copy) {
+void ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) {
FixupInstanceFields(orig, copy);
// OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
@@ -607,43 +607,36 @@ void ImageWriter::FixupMethod(const ArtMethod* orig, ArtMethod* copy) {
// The resolution method has a special trampoline to call.
if (UNLIKELY(orig == Runtime::Current()->GetResolutionMethod())) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_));
-#else
- copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_));
-#endif
+ copy->SetEntryPointFromPortableCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_));
+ copy->SetEntryPointFromQuickCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_));
} else if (UNLIKELY(orig == Runtime::Current()->GetImtConflictMethod())) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_imt_conflict_trampoline_offset_));
-#else
- copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_imt_conflict_trampoline_offset_));
-#endif
+ copy->SetEntryPointFromPortableCompiledCode(GetOatAddress(portable_imt_conflict_trampoline_offset_));
+ copy->SetEntryPointFromQuickCompiledCode(GetOatAddress(quick_imt_conflict_trampoline_offset_));
} else {
// We assume all methods have code. If they don't currently then we set them to the use the
// resolution trampoline. Abstract methods never have code and so we need to make sure their
// use results in an AbstractMethodError. We use the interpreter to achieve this.
if (UNLIKELY(orig->IsAbstract())) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_to_interpreter_bridge_offset_));
-#else
- copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_to_interpreter_bridge_offset_));
-#endif
+ copy->SetEntryPointFromPortableCompiledCode(GetOatAddress(portable_to_interpreter_bridge_offset_));
+ copy->SetEntryPointFromQuickCompiledCode(GetOatAddress(quick_to_interpreter_bridge_offset_));
copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*>
- (const_cast<byte*>(GetOatAddress(interpreter_to_interpreter_bridge_offset_))));
+ (const_cast<byte*>(GetOatAddress(interpreter_to_interpreter_bridge_offset_))));
} else {
copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*>
- (const_cast<byte*>(GetOatAddress(interpreter_to_compiled_code_bridge_offset_))));
+ (const_cast<byte*>(GetOatAddress(interpreter_to_compiled_code_bridge_offset_))));
// Use original code if it exists. Otherwise, set the code pointer to the resolution
// trampoline.
- const byte* code = GetOatAddress(orig->GetOatCodeOffset());
- if (code != NULL) {
- copy->SetEntryPointFromCompiledCode(code);
+ const byte* quick_code = GetOatAddress(orig->GetQuickOatCodeOffset());
+ if (quick_code != nullptr) {
+ copy->SetEntryPointFromQuickCompiledCode(quick_code);
} else {
-#if defined(ART_USE_PORTABLE_COMPILER)
- copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_));
-#else
- copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_));
-#endif
+ copy->SetEntryPointFromQuickCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_));
+ }
+ const byte* portable_code = GetOatAddress(orig->GetPortableOatCodeOffset());
+ if (portable_code != nullptr) {
+ copy->SetEntryPointFromPortableCompiledCode(portable_code);
+ } else {
+ copy->SetEntryPointFromPortableCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_));
}
if (orig->IsNative()) {
// The native method's pointer is set to a stub to lookup via dlsym.
@@ -667,14 +660,14 @@ void ImageWriter::FixupMethod(const ArtMethod* orig, ArtMethod* copy) {
}
}
-void ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
+void ImageWriter::FixupObjectArray(ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
for (int32_t i = 0; i < orig->GetLength(); ++i) {
- const Object* element = orig->Get(i);
- copy->SetPtrWithoutChecks(i, GetImageAddress(element));
+ Object* element = orig->Get(i);
+ copy->SetWithoutChecksAndWriteBarrier(i, GetImageAddress(element));
}
}
-void ImageWriter::FixupInstanceFields(const Object* orig, Object* copy) {
+void ImageWriter::FixupInstanceFields(Object* orig, Object* copy) {
DCHECK(orig != NULL);
DCHECK(copy != NULL);
Class* klass = orig->GetClass();
@@ -682,13 +675,13 @@ void ImageWriter::FixupInstanceFields(const Object* orig, Object* copy) {
FixupFields(orig, copy, klass->GetReferenceInstanceOffsets(), false);
}
-void ImageWriter::FixupStaticFields(const Class* orig, Class* copy) {
+void ImageWriter::FixupStaticFields(Class* orig, Class* copy) {
DCHECK(orig != NULL);
DCHECK(copy != NULL);
FixupFields(orig, copy, orig->GetReferenceStaticOffsets(), true);
}
-void ImageWriter::FixupFields(const Object* orig,
+void ImageWriter::FixupFields(Object* orig,
Object* copy,
uint32_t ref_offsets,
bool is_static) {
@@ -697,9 +690,10 @@ void ImageWriter::FixupFields(const Object* orig,
while (ref_offsets != 0) {
size_t right_shift = CLZ(ref_offsets);
MemberOffset byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
- const Object* ref = orig->GetFieldObject<const Object*>(byte_offset, false);
- // Use SetFieldPtr to avoid card marking since we are writing to the image.
- copy->SetFieldPtr(byte_offset, GetImageAddress(ref), false);
+ Object* ref = orig->GetFieldObject<Object>(byte_offset, false);
+ // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the
+ // image.
+ copy->SetFieldObjectWithoutWriteBarrier(byte_offset, GetImageAddress(ref), false);
ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
}
} else {
@@ -707,7 +701,7 @@ void ImageWriter::FixupFields(const Object* orig,
// walk up the class inheritance hierarchy and find reference
// offsets the hard way. In the static case, just consider this
// class.
- for (const Class *klass = is_static ? orig->AsClass() : orig->GetClass();
+ for (Class *klass = is_static ? orig->AsClass() : orig->GetClass();
klass != NULL;
klass = is_static ? NULL : klass->GetSuperClass()) {
size_t num_reference_fields = (is_static
@@ -718,9 +712,10 @@ void ImageWriter::FixupFields(const Object* orig,
? klass->GetStaticField(i)
: klass->GetInstanceField(i));
MemberOffset field_offset = field->GetOffset();
- const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false);
- // Use SetFieldPtr to avoid card marking since we are writing to the image.
- copy->SetFieldPtr(field_offset, GetImageAddress(ref), false);
+ Object* ref = orig->GetFieldObject<Object>(field_offset, false);
+ // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the
+ // image.
+ copy->SetFieldObjectWithoutWriteBarrier(field_offset, GetImageAddress(ref), false);
}
}
}
@@ -728,9 +723,10 @@ void ImageWriter::FixupFields(const Object* orig,
// Fix-up referent, that isn't marked as an object field, for References.
ArtField* field = orig->GetClass()->FindInstanceField("referent", "Ljava/lang/Object;");
MemberOffset field_offset = field->GetOffset();
- const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false);
- // Use SetFieldPtr to avoid card marking since we are writing to the image.
- copy->SetFieldPtr(field_offset, GetImageAddress(ref), false);
+ Object* ref = orig->GetFieldObject<Object>(field_offset, false);
+ // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the
+ // image.
+ copy->SetFieldObjectWithoutWriteBarrier(field_offset, GetImageAddress(ref), false);
}
}
@@ -786,17 +782,17 @@ void ImageWriter::PatchOatCodeAndMethods() {
for (size_t i = 0; i < code_to_patch.size(); i++) {
const CompilerDriver::CallPatchInformation* patch = code_to_patch[i];
ArtMethod* target = GetTargetMethod(patch);
- uint32_t code = reinterpret_cast<uint32_t>(class_linker->GetOatCodeFor(target));
- uint32_t code_base = reinterpret_cast<uint32_t>(&oat_file_->GetOatHeader());
- uint32_t code_offset = code - code_base;
- SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetOatAddress(code_offset)));
+ uintptr_t quick_code = reinterpret_cast<uintptr_t>(class_linker->GetQuickOatCodeFor(target));
+ uintptr_t code_base = reinterpret_cast<uintptr_t>(&oat_file_->GetOatHeader());
+ uintptr_t code_offset = quick_code - code_base;
+ SetPatchLocation(patch, PointerToLowMemUInt32(GetOatAddress(code_offset)));
}
const CallPatches& methods_to_patch = compiler_driver_.GetMethodsToPatch();
for (size_t i = 0; i < methods_to_patch.size(); i++) {
const CompilerDriver::CallPatchInformation* patch = methods_to_patch[i];
ArtMethod* target = GetTargetMethod(patch);
- SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target)));
+ SetPatchLocation(patch, PointerToLowMemUInt32(GetImageAddress(target)));
}
const std::vector<const CompilerDriver::TypePatchInformation*>& classes_to_patch =
@@ -804,7 +800,7 @@ void ImageWriter::PatchOatCodeAndMethods() {
for (size_t i = 0; i < classes_to_patch.size(); i++) {
const CompilerDriver::TypePatchInformation* patch = classes_to_patch[i];
Class* target = GetTargetType(patch);
- SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target)));
+ SetPatchLocation(patch, PointerToLowMemUInt32(GetImageAddress(target)));
}
// Update the image header with the new checksum after patching
@@ -815,18 +811,18 @@ void ImageWriter::PatchOatCodeAndMethods() {
void ImageWriter::SetPatchLocation(const CompilerDriver::PatchInformation* patch, uint32_t value) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- const void* oat_code = class_linker->GetOatCodeFor(patch->GetDexFile(),
- patch->GetReferrerClassDefIdx(),
- patch->GetReferrerMethodIdx());
+ const void* quick_oat_code = class_linker->GetQuickOatCodeFor(patch->GetDexFile(),
+ patch->GetReferrerClassDefIdx(),
+ patch->GetReferrerMethodIdx());
OatHeader& oat_header = const_cast<OatHeader&>(oat_file_->GetOatHeader());
// TODO: make this Thumb2 specific
- uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(oat_code) & ~0x1);
+ uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(quick_oat_code) & ~0x1);
uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset());
if (kIsDebugBuild) {
if (patch->IsCall()) {
const CompilerDriver::CallPatchInformation* cpatch = patch->AsCall();
const DexFile::MethodId& id = cpatch->GetDexFile().GetMethodId(cpatch->GetTargetMethodIdx());
- uint32_t expected = reinterpret_cast<uint32_t>(&id);
+ uintptr_t expected = reinterpret_cast<uintptr_t>(&id);
uint32_t actual = *patch_location;
CHECK(actual == expected || actual == value) << std::hex
<< "actual=" << actual
@@ -836,7 +832,7 @@ void ImageWriter::SetPatchLocation(const CompilerDriver::PatchInformation* patch
if (patch->IsType()) {
const CompilerDriver::TypePatchInformation* tpatch = patch->AsType();
const DexFile::TypeId& id = tpatch->GetDexFile().GetTypeId(tpatch->GetTargetTypeIdx());
- uint32_t expected = reinterpret_cast<uint32_t>(&id);
+ uintptr_t expected = reinterpret_cast<uintptr_t>(&id);
uint32_t actual = *patch_location;
CHECK(actual == expected || actual == value) << std::hex
<< "actual=" << actual
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 695f59b..a1504ee 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -66,17 +66,17 @@ class ImageWriter {
void AssignImageOffset(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetImageOffset(mirror::Object* object, size_t offset)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsImageOffsetAssigned(const mirror::Object* object) const;
- size_t GetImageOffset(const mirror::Object* object) const;
+ bool IsImageOffsetAssigned(mirror::Object* object) const;
+ size_t GetImageOffset(mirror::Object* object) const;
- mirror::Object* GetImageAddress(const mirror::Object* object) const {
+ mirror::Object* GetImageAddress(mirror::Object* object) const {
if (object == NULL) {
return NULL;
}
return reinterpret_cast<mirror::Object*>(image_begin_ + GetImageOffset(object));
}
- mirror::Object* GetLocalAddress(const mirror::Object* object) const {
+ mirror::Object* GetLocalAddress(mirror::Object* object) const {
size_t offset = GetImageOffset(object);
byte* dst = image_->Begin() + offset;
return reinterpret_cast<mirror::Object*>(dst);
@@ -96,7 +96,7 @@ class ImageWriter {
}
// Returns true if the class was in the original requested image classes list.
- bool IsImageClass(const mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsImageClass(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Debug aid that list of requested image classes.
void DumpImageClasses();
@@ -141,20 +141,20 @@ class ImageWriter {
void CopyAndFixupObjects();
static void CopyAndFixupObjectsCallback(mirror::Object* obj, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupClass(const mirror::Class* orig, mirror::Class* copy)
+ void FixupClass(mirror::Class* orig, mirror::Class* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupMethod(const mirror::ArtMethod* orig, mirror::ArtMethod* copy)
+ void FixupMethod(mirror::ArtMethod* orig, mirror::ArtMethod* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupObject(const mirror::Object* orig, mirror::Object* copy)
+ void FixupObject(mirror::Object* orig, mirror::Object* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupObjectArray(const mirror::ObjectArray<mirror::Object>* orig,
+ void FixupObjectArray(mirror::ObjectArray<mirror::Object>* orig,
mirror::ObjectArray<mirror::Object>* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupInstanceFields(const mirror::Object* orig, mirror::Object* copy)
+ void FixupInstanceFields(mirror::Object* orig, mirror::Object* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupStaticFields(const mirror::Class* orig, mirror::Class* copy)
+ void FixupStaticFields(mirror::Class* orig, mirror::Class* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupFields(const mirror::Object* orig, mirror::Object* copy, uint32_t ref_offsets,
+ void FixupFields(mirror::Object* orig, mirror::Object* copy, uint32_t ref_offsets,
bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 1c8714a..c77d319 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -58,11 +58,14 @@ class JniCompilerTest : public CommonTest {
method = c->FindVirtualMethod(method_name, method_sig);
}
ASSERT_TRUE(method != NULL) << method_name << " " << method_sig;
- if (method->GetEntryPointFromCompiledCode() != NULL) {
- return;
+ if (method->GetEntryPointFromQuickCompiledCode() == nullptr) {
+ ASSERT_TRUE(method->GetEntryPointFromPortableCompiledCode() == nullptr);
+ CompileMethod(method);
+ ASSERT_TRUE(method->GetEntryPointFromQuickCompiledCode() != nullptr)
+ << method_name << " " << method_sig;
+ ASSERT_TRUE(method->GetEntryPointFromPortableCompiledCode() != nullptr)
+ << method_name << " " << method_sig;
}
- CompileMethod(method);
- ASSERT_TRUE(method->GetEntryPointFromCompiledCode() != NULL) << method_name << " " << method_sig;
}
void SetUpForTest(bool direct, const char* method_name, const char* method_sig,
@@ -122,19 +125,19 @@ jobject JniCompilerTest::class_loader_;
int gJava_MyClassNatives_foo_calls = 0;
void Java_MyClassNatives_foo(JNIEnv* env, jobject thisObj) {
// 1 = thisObj
- EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
Locks::mutator_lock_->AssertNotHeld(Thread::Current());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
gJava_MyClassNatives_foo_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
}
TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
TEST_DISABLED_FOR_PORTABLE();
- SetUpForTest(false, "foo", "()V",
- reinterpret_cast<void*>(&Java_MyClassNatives_foo));
+ SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
EXPECT_EQ(0, gJava_MyClassNatives_foo_calls);
env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
@@ -178,12 +181,13 @@ TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) {
int gJava_MyClassNatives_fooI_calls = 0;
jint Java_MyClassNatives_fooI(JNIEnv* env, jobject thisObj, jint x) {
// 1 = thisObj
- EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
gJava_MyClassNatives_fooI_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
return x;
}
@@ -204,12 +208,13 @@ TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
int gJava_MyClassNatives_fooII_calls = 0;
jint Java_MyClassNatives_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
// 1 = thisObj
- EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
gJava_MyClassNatives_fooII_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
return x - y; // non-commutative operator
}
@@ -231,12 +236,13 @@ TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
int gJava_MyClassNatives_fooJJ_calls = 0;
jlong Java_MyClassNatives_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
// 1 = thisObj
- EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
gJava_MyClassNatives_fooJJ_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
return x - y; // non-commutative operator
}
@@ -259,12 +265,13 @@ TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
int gJava_MyClassNatives_fooDD_calls = 0;
jdouble Java_MyClassNatives_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
// 1 = thisObj
- EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
gJava_MyClassNatives_fooDD_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
return x - y; // non-commutative operator
}
@@ -288,12 +295,13 @@ TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
int gJava_MyClassNatives_fooJJ_synchronized_calls = 0;
jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
// 1 = thisObj
- EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
gJava_MyClassNatives_fooJJ_synchronized_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
return x | y;
}
@@ -314,12 +322,13 @@ int gJava_MyClassNatives_fooIOO_calls = 0;
jobject Java_MyClassNatives_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
jobject z) {
// 3 = this + y + z
- EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
gJava_MyClassNatives_fooIOO_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
switch (x) {
case 1:
return y;
@@ -365,12 +374,13 @@ TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
int gJava_MyClassNatives_fooSII_calls = 0;
jint Java_MyClassNatives_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
// 1 = klass
- EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(klass != NULL);
EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
gJava_MyClassNatives_fooSII_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
return x + y;
}
@@ -388,12 +398,13 @@ TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
int gJava_MyClassNatives_fooSDD_calls = 0;
jdouble Java_MyClassNatives_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
// 1 = klass
- EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(klass != NULL);
EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
gJava_MyClassNatives_fooSDD_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
return x - y; // non-commutative operator
}
@@ -417,12 +428,13 @@ int gJava_MyClassNatives_fooSIOO_calls = 0;
jobject Java_MyClassNatives_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
jobject z) {
// 3 = klass + y + z
- EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(klass != NULL);
EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
gJava_MyClassNatives_fooSIOO_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
switch (x) {
case 1:
return y;
@@ -469,12 +481,13 @@ TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
int gJava_MyClassNatives_fooSSIOO_calls = 0;
jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) {
// 3 = klass + y + z
- EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
EXPECT_EQ(kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(klass != NULL);
EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
gJava_MyClassNatives_fooSSIOO_calls++;
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
switch (x) {
case 1:
return y;
diff --git a/compiler/llvm/compiler_llvm.cc b/compiler/llvm/compiler_llvm.cc
index 94408bb..6563eb5 100644
--- a/compiler/llvm/compiler_llvm.cc
+++ b/compiler/llvm/compiler_llvm.cc
@@ -126,7 +126,7 @@ LlvmCompilationUnit* CompilerLLVM::AllocateCompilationUnit() {
MutexLock GUARD(Thread::Current(), next_cunit_id_lock_);
LlvmCompilationUnit* cunit = new LlvmCompilationUnit(this, next_cunit_id_++);
if (!bitcode_filename_.empty()) {
- cunit->SetBitcodeFileName(StringPrintf("%s-%zu",
+ cunit->SetBitcodeFileName(StringPrintf("%s-%u",
bitcode_filename_.c_str(),
cunit->GetCompilationUnitId()));
}
diff --git a/compiler/llvm/gbc_expander.cc b/compiler/llvm/gbc_expander.cc
index 6423cd7..8f22a97 100644
--- a/compiler/llvm/gbc_expander.cc
+++ b/compiler/llvm/gbc_expander.cc
@@ -897,7 +897,7 @@ llvm::Value* GBCExpanderPass::EmitInvoke(llvm::CallInst& call_inst) {
} else {
code_addr =
irb_.LoadFromObjectOffset(callee_method_object_addr,
- art::mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ art::mirror::ArtMethod::EntryPointFromPortableCompiledCodeOffset().Int32Value(),
func_type->getPointerTo(), kTBAARuntimeInfo);
}
@@ -1234,7 +1234,7 @@ llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
llvm::Value* code_addr =
irb_.LoadFromObjectOffset(callee_method_object_addr,
- art::mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ art::mirror::ArtMethod::EntryPointFromPortableCompiledCodeOffset().Int32Value(),
callee_method_type->getPointerTo(),
kTBAARuntimeInfo);
diff --git a/compiler/llvm/llvm_compilation_unit.cc b/compiler/llvm/llvm_compilation_unit.cc
index 038f5dc..d23706d 100644
--- a/compiler/llvm/llvm_compilation_unit.cc
+++ b/compiler/llvm/llvm_compilation_unit.cc
@@ -151,7 +151,7 @@ static std::string DumpDirectory() {
void LlvmCompilationUnit::DumpBitcodeToFile() {
std::string bitcode;
DumpBitcodeToString(bitcode);
- std::string filename(StringPrintf("%s/Art%u.bc", DumpDirectory().c_str(), cunit_id_));
+ std::string filename(StringPrintf("%s/Art%zu.bc", DumpDirectory().c_str(), cunit_id_));
UniquePtr<File> output(OS::CreateEmptyFile(filename.c_str()));
output->WriteFully(bitcode.data(), bitcode.size());
LOG(INFO) << ".bc file written successfully: " << filename;
@@ -178,7 +178,7 @@ bool LlvmCompilationUnit::Materialize() {
const bool kDumpELF = false;
if (kDumpELF) {
// Dump the ELF image for debugging
- std::string filename(StringPrintf("%s/Art%u.o", DumpDirectory().c_str(), cunit_id_));
+ std::string filename(StringPrintf("%s/Art%zu.o", DumpDirectory().c_str(), cunit_id_));
UniquePtr<File> output(OS::CreateEmptyFile(filename.c_str()));
output->WriteFully(elf_object_.data(), elf_object_.size());
LOG(INFO) << ".o file written successfully: " << filename;
diff --git a/compiler/llvm/llvm_compilation_unit.h b/compiler/llvm/llvm_compilation_unit.h
index ced9f81..58aa6fd 100644
--- a/compiler/llvm/llvm_compilation_unit.h
+++ b/compiler/llvm/llvm_compilation_unit.h
@@ -101,10 +101,10 @@ class LlvmCompilationUnit {
private:
LlvmCompilationUnit(const CompilerLLVM* compiler_llvm,
- uint32_t cunit_id);
+ size_t cunit_id);
const CompilerLLVM* compiler_llvm_;
- const uint32_t cunit_id_;
+ const size_t cunit_id_;
UniquePtr< ::llvm::LLVMContext> context_;
UniquePtr<IRBuilder> irb_;
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index fc45412..b3070b6 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -39,29 +39,42 @@ class OatTest : public CommonTest {
method->GetDexMethodIndex()));
if (compiled_method == NULL) {
- EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " "
- << oat_method.GetCode();
-#if !defined(ART_USE_PORTABLE_COMPILER)
- EXPECT_EQ(oat_method.GetFrameSizeInBytes(), kCompile ? kStackAlignment : 0);
+ EXPECT_TRUE(oat_method.GetQuickCode() == NULL) << PrettyMethod(method) << " "
+ << oat_method.GetQuickCode();
+ EXPECT_TRUE(oat_method.GetPortableCode() == NULL) << PrettyMethod(method) << " "
+ << oat_method.GetPortableCode();
+ EXPECT_EQ(oat_method.GetFrameSizeInBytes(), 0U);
EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
-#endif
} else {
- const void* oat_code = oat_method.GetCode();
- EXPECT_TRUE(oat_code != NULL) << PrettyMethod(method);
- uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
- oat_code = reinterpret_cast<const void*>(oat_code_aligned);
-
- const std::vector<uint8_t>& code = compiled_method->GetCode();
- size_t code_size = code.size() * sizeof(code[0]);
- EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
- << PrettyMethod(method) << " " << code_size;
- CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
-#if !defined(ART_USE_PORTABLE_COMPILER)
- EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
- EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
- EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
-#endif
+ const void* quick_oat_code = oat_method.GetQuickCode();
+ if (quick_oat_code != nullptr) {
+ EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
+ EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
+ EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
+ uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(quick_oat_code), 2);
+ quick_oat_code = reinterpret_cast<const void*>(oat_code_aligned);
+ const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode();
+ EXPECT_TRUE(quick_code != nullptr);
+ size_t code_size = quick_code->size() * sizeof(quick_code[0]);
+ EXPECT_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size))
+ << PrettyMethod(method) << " " << code_size;
+ CHECK_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size));
+ } else {
+ const void* portable_oat_code = oat_method.GetPortableCode();
+ EXPECT_TRUE(portable_oat_code != nullptr) << PrettyMethod(method);
+ EXPECT_EQ(oat_method.GetFrameSizeInBytes(), 0U);
+ EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
+ EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
+ uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(portable_oat_code), 2);
+ portable_oat_code = reinterpret_cast<const void*>(oat_code_aligned);
+ const std::vector<uint8_t>* portable_code = compiled_method->GetPortableCode();
+ EXPECT_TRUE(portable_code != nullptr);
+ size_t code_size = portable_code->size() * sizeof(portable_code[0]);
+ EXPECT_EQ(0, memcmp(quick_oat_code, &portable_code[0], code_size))
+ << PrettyMethod(method) << " " << code_size;
+ CHECK_EQ(0, memcmp(quick_oat_code, &portable_code[0], code_size));
+ }
}
}
};
@@ -70,12 +83,8 @@ TEST_F(OatTest, WriteRead) {
TimingLogger timings("CommonTest::WriteRead", false, false);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- // TODO: make selectable
-#if defined(ART_USE_PORTABLE_COMPILER)
- CompilerBackend compiler_backend = kPortable;
-#else
- CompilerBackend compiler_backend = kQuick;
-#endif
+ // TODO: make selectable.
+ CompilerBackend compiler_backend = kUsePortableCompiler ? kPortable : kQuick;
InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
InstructionSetFeatures insn_features;
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 7a902d8..7c5669a 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -39,7 +39,7 @@ namespace art {
OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
uint32_t image_file_location_oat_checksum,
- uint32_t image_file_location_oat_begin,
+ uintptr_t image_file_location_oat_begin,
const std::string& image_file_location,
const CompilerDriver* compiler,
TimingLogger* timings)
@@ -348,8 +348,8 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
bool __attribute__((unused)) is_native,
InvokeType invoke_type,
uint32_t method_idx, const DexFile& dex_file) {
- // derived from CompiledMethod if available
- uint32_t code_offset = 0;
+ // Derived from CompiledMethod if available.
+ uint32_t quick_code_offset = 0;
uint32_t frame_size_in_bytes = kStackAlignment;
uint32_t core_spill_mask = 0;
uint32_t fp_spill_mask = 0;
@@ -358,36 +358,38 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
uint32_t gc_map_offset = 0;
OatClass* oat_class = oat_classes_[oat_class_index];
-#if defined(ART_USE_PORTABLE_COMPILER)
- size_t oat_method_offsets_offset =
- oat_class->GetOatMethodOffsetsOffsetFromOatHeader(class_def_method_index);
-#endif
-
CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+
if (compiled_method != NULL) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- compiled_method->AddOatdataOffsetToCompliledCodeOffset(
- oat_method_offsets_offset + OFFSETOF_MEMBER(OatMethodOffsets, code_offset_));
-#else
- const std::vector<uint8_t>& code = compiled_method->GetCode();
- offset = compiled_method->AlignCode(offset);
- DCHECK_ALIGNED(offset, kArmAlignment);
- uint32_t code_size = code.size() * sizeof(code[0]);
- CHECK_NE(code_size, 0U);
- uint32_t thumb_offset = compiled_method->CodeDelta();
- code_offset = offset + sizeof(code_size) + thumb_offset;
-
- // Deduplicate code arrays
- SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
- if (code_iter != code_offsets_.end()) {
- code_offset = code_iter->second;
+ const std::vector<uint8_t>* portable_code = compiled_method->GetPortableCode();
+ const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode();
+ if (portable_code != nullptr) {
+ CHECK(quick_code == nullptr);
+ size_t oat_method_offsets_offset =
+ oat_class->GetOatMethodOffsetsOffsetFromOatHeader(class_def_method_index);
+ compiled_method->AddOatdataOffsetToCompliledCodeOffset(
+ oat_method_offsets_offset + OFFSETOF_MEMBER(OatMethodOffsets, code_offset_));
} else {
- code_offsets_.Put(&code, code_offset);
- offset += sizeof(code_size); // code size is prepended before code
- offset += code_size;
- oat_header_->UpdateChecksum(&code[0], code_size);
+ CHECK(quick_code != nullptr);
+ offset = compiled_method->AlignCode(offset);
+ DCHECK_ALIGNED(offset, kArmAlignment);
+ uint32_t code_size = quick_code->size() * sizeof(uint8_t);
+ CHECK_NE(code_size, 0U);
+ uint32_t thumb_offset = compiled_method->CodeDelta();
+ quick_code_offset = offset + sizeof(code_size) + thumb_offset;
+
+ // Deduplicate code arrays
+ SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter =
+ code_offsets_.find(quick_code);
+ if (code_iter != code_offsets_.end()) {
+ quick_code_offset = code_iter->second;
+ } else {
+ code_offsets_.Put(quick_code, quick_code_offset);
+ offset += sizeof(code_size); // code size is prepended before code
+ offset += code_size;
+ oat_header_->UpdateChecksum(&(*quick_code)[0], code_size);
+ }
}
-#endif
frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
core_spill_mask = compiled_method->GetCoreSpillMask();
fp_spill_mask = compiled_method->GetFpSpillMask();
@@ -456,7 +458,7 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
}
oat_class->method_offsets_[*method_offsets_index] =
- OatMethodOffsets(code_offset,
+ OatMethodOffsets(quick_code_offset,
frame_size_in_bytes,
core_spill_mask,
fp_spill_mask,
@@ -483,9 +485,11 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
// Don't overwrite static method trampoline
if (!method->IsStatic() || method->IsConstructor() ||
method->GetDeclaringClass()->IsInitialized()) {
- method->SetOatCodeOffset(code_offset);
+ // TODO: record portable code offsets: method->SetPortableOatCodeOffset(portable_code_offset);
+ method->SetQuickOatCodeOffset(quick_code_offset);
} else {
- method->SetEntryPointFromCompiledCode(NULL);
+ method->SetEntryPointFromPortableCompiledCode(nullptr);
+ method->SetEntryPointFromQuickCompiledCode(nullptr);
}
method->SetOatVmapTableOffset(vmap_table_offset);
method->SetOatNativeGcMapOffset(gc_map_offset);
@@ -753,52 +757,52 @@ size_t OatWriter::WriteCodeMethod(OutputStream& out, const size_t file_offset,
if (compiled_method != NULL) { // ie. not an abstract method
const OatMethodOffsets method_offsets = oat_class->method_offsets_[*method_offsets_index];
(*method_offsets_index)++;
-
-#if !defined(ART_USE_PORTABLE_COMPILER)
- uint32_t aligned_offset = compiled_method->AlignCode(relative_offset);
- uint32_t aligned_code_delta = aligned_offset - relative_offset;
- if (aligned_code_delta != 0) {
- off_t new_offset = out.Seek(aligned_code_delta, kSeekCurrent);
- size_code_alignment_ += aligned_code_delta;
- uint32_t expected_offset = file_offset + aligned_offset;
- if (static_cast<uint32_t>(new_offset) != expected_offset) {
- PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
- << " Expected: " << expected_offset << " File: " << out.GetLocation();
- return 0;
+ const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode();
+ if (quick_code != nullptr) {
+ CHECK(compiled_method->GetPortableCode() == nullptr);
+ uint32_t aligned_offset = compiled_method->AlignCode(relative_offset);
+ uint32_t aligned_code_delta = aligned_offset - relative_offset;
+ if (aligned_code_delta != 0) {
+ off_t new_offset = out.Seek(aligned_code_delta, kSeekCurrent);
+ size_code_alignment_ += aligned_code_delta;
+ uint32_t expected_offset = file_offset + aligned_offset;
+ if (static_cast<uint32_t>(new_offset) != expected_offset) {
+ PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
+ << " Expected: " << expected_offset << " File: " << out.GetLocation();
+ return 0;
+ }
+ relative_offset += aligned_code_delta;
+ DCHECK_OFFSET();
}
- relative_offset += aligned_code_delta;
- DCHECK_OFFSET();
- }
- DCHECK_ALIGNED(relative_offset, kArmAlignment);
- const std::vector<uint8_t>& code = compiled_method->GetCode();
- uint32_t code_size = code.size() * sizeof(code[0]);
- CHECK_NE(code_size, 0U);
-
- // Deduplicate code arrays
- size_t code_offset = relative_offset + sizeof(code_size) + compiled_method->CodeDelta();
- SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
- if (code_iter != code_offsets_.end() && code_offset != method_offsets.code_offset_) {
- DCHECK(code_iter->second == method_offsets.code_offset_)
- << PrettyMethod(method_idx, dex_file);
- } else {
- DCHECK(code_offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
- if (!out.WriteFully(&code_size, sizeof(code_size))) {
- ReportWriteFailure("method code size", method_idx, dex_file, out);
- return 0;
+ DCHECK_ALIGNED(relative_offset, kArmAlignment);
+ uint32_t code_size = quick_code->size() * sizeof(uint8_t);
+ CHECK_NE(code_size, 0U);
+
+ // Deduplicate code arrays
+ size_t code_offset = relative_offset + sizeof(code_size) + compiled_method->CodeDelta();
+ SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter =
+ code_offsets_.find(quick_code);
+ if (code_iter != code_offsets_.end() && code_offset != method_offsets.code_offset_) {
+ DCHECK(code_iter->second == method_offsets.code_offset_)
+ << PrettyMethod(method_idx, dex_file);
+ } else {
+ DCHECK(code_offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
+ if (!out.WriteFully(&code_size, sizeof(code_size))) {
+ ReportWriteFailure("method code size", method_idx, dex_file, out);
+ return 0;
+ }
+ size_code_size_ += sizeof(code_size);
+ relative_offset += sizeof(code_size);
+ DCHECK_OFFSET();
+ if (!out.WriteFully(&(*quick_code)[0], code_size)) {
+ ReportWriteFailure("method code", method_idx, dex_file, out);
+ return 0;
+ }
+ size_code_ += code_size;
+ relative_offset += code_size;
}
- size_code_size_ += sizeof(code_size);
- relative_offset += sizeof(code_size);
DCHECK_OFFSET();
- if (!out.WriteFully(&code[0], code_size)) {
- ReportWriteFailure("method code", method_idx, dex_file, out);
- return 0;
- }
- size_code_ += code_size;
- relative_offset += code_size;
}
- DCHECK_OFFSET();
-#endif
-
const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable();
size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
@@ -994,7 +998,6 @@ OatWriter::OatClass::~OatClass() {
delete compiled_methods_;
}
-#if defined(ART_USE_PORTABLE_COMPILER)
size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatHeader(
size_t class_def_method_index_) const {
uint32_t method_offset = GetOatMethodOffsetsOffsetFromOatClass(class_def_method_index_);
@@ -1008,7 +1011,6 @@ size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatClass(
size_t class_def_method_index_) const {
return oat_method_offsets_offsets_from_oat_class_[class_def_method_index_];
}
-#endif
size_t OatWriter::OatClass::SizeOf() const {
return sizeof(status_)
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 64275e6..067c789 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -65,7 +65,7 @@ class OatWriter {
public:
OatWriter(const std::vector<const DexFile*>& dex_files,
uint32_t image_file_location_oat_checksum,
- uint32_t image_file_location_oat_begin,
+ uintptr_t image_file_location_oat_begin,
const std::string& image_file_location,
const CompilerDriver* compiler,
TimingLogger* timings);
@@ -150,10 +150,8 @@ class OatWriter {
uint32_t num_non_null_compiled_methods,
mirror::Class::Status status);
~OatClass();
-#if defined(ART_USE_PORTABLE_COMPILER)
size_t GetOatMethodOffsetsOffsetFromOatHeader(size_t class_def_method_index_) const;
size_t GetOatMethodOffsetsOffsetFromOatClass(size_t class_def_method_index_) const;
-#endif
size_t SizeOf() const;
void UpdateChecksum(OatHeader& oat_header) const;
bool Write(OatWriter* oat_writer, OutputStream& out, const size_t file_offset) const;
@@ -217,7 +215,7 @@ class OatWriter {
// dependencies on the image.
uint32_t image_file_location_oat_checksum_;
- uint32_t image_file_location_oat_begin_;
+ uintptr_t image_file_location_oat_begin_;
std::string image_file_location_;
// data to write
diff --git a/compiler/output_stream.h b/compiler/output_stream.h
index 112dcfc..478a854 100644
--- a/compiler/output_stream.h
+++ b/compiler/output_stream.h
@@ -41,7 +41,7 @@ class OutputStream {
return location_;
}
- virtual bool WriteFully(const void* buffer, int64_t byte_count) = 0;
+ virtual bool WriteFully(const void* buffer, size_t byte_count) = 0;
virtual off_t Seek(off_t offset, Whence whence) = 0;
diff --git a/compiler/utils/dedupe_set.h b/compiler/utils/dedupe_set.h
index 638e0ec..7cc253c 100644
--- a/compiler/utils/dedupe_set.h
+++ b/compiler/utils/dedupe_set.h
@@ -62,7 +62,9 @@ class DedupeSet {
explicit DedupeSet(const char* set_name) {
for (HashType i = 0; i < kShard; ++i) {
- lock_name_[i] = StringPrintf("%s lock %d", set_name, i);
+ std::ostringstream oss;
+ oss << set_name << " lock " << i;
+ lock_name_[i] = oss.str();
lock_[i].reset(new Mutex(lock_name_[i].c_str()));
}
}
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index 2be3d56..fdd2bab 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -23,18 +23,6 @@
namespace art {
namespace mips {
-#if 0
-class DirectCallRelocation : public AssemblerFixup {
- public:
- void Process(const MemoryRegion& region, int position) {
- // Direct calls are relative to the following instruction on mips.
- int32_t pointer = region.Load<int32_t>(position);
- int32_t start = reinterpret_cast<int32_t>(region.start());
- int32_t delta = start + position + sizeof(int32_t);
- region.Store<int32_t>(position, pointer - delta);
- }
-};
-#endif
std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
if (rhs >= D0 && rhs < kNumberOfDRegisters) {
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 9095180..136d248 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -24,17 +24,6 @@
namespace art {
namespace x86 {
-class DirectCallRelocation : public AssemblerFixup {
- public:
- void Process(const MemoryRegion& region, int position) {
- // Direct calls are relative to the following instruction on x86.
- int32_t pointer = region.Load<int32_t>(position);
- int32_t start = reinterpret_cast<int32_t>(region.start());
- int32_t delta = start + position + sizeof(int32_t);
- region.Store<int32_t>(position, pointer - delta);
- }
-};
-
std::ostream& operator<<(std::ostream& os, const XmmRegister& reg) {
return os << "XMM" << static_cast<int>(reg);
}
@@ -1304,15 +1293,6 @@ void X86Assembler::Bind(Label* label) {
}
-void X86Assembler::Stop(const char* message) {
- // Emit the message address as immediate operand in the test rax instruction,
- // followed by the int3 instruction.
- // Execution can be resumed with the 'cont' command in gdb.
- testl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
- int3();
-}
-
-
void X86Assembler::EmitOperand(int reg_or_opcode, const Operand& operand) {
CHECK_GE(reg_or_opcode, 0);
CHECK_LT(reg_or_opcode, 8);
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 4ba03d1..0fa8e00 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -452,9 +452,6 @@ class X86Assembler : public Assembler {
void Align(int alignment, int offset);
void Bind(Label* label);
- // Debugging and bringup support.
- void Stop(const char* message);
-
//
// Overridden common assembler high-level functionality
//
diff --git a/compiler/vector_output_stream.h b/compiler/vector_output_stream.h
index a3f8226..09daa12 100644
--- a/compiler/vector_output_stream.h
+++ b/compiler/vector_output_stream.h
@@ -31,7 +31,7 @@ class VectorOutputStream : public OutputStream {
virtual ~VectorOutputStream() {}
- bool WriteFully(const void* buffer, int64_t byte_count) {
+ bool WriteFully(const void* buffer, size_t byte_count) {
if (static_cast<size_t>(offset_) == vector_.size()) {
const uint8_t* start = reinterpret_cast<const uint8_t*>(buffer);
vector_.insert(vector_.end(), &start[0], &start[byte_count]);
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 582a0e9..5ac01f2 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -291,13 +291,13 @@ class Dex2Oat {
timings.NewSplit("dex2oat OatWriter");
std::string image_file_location;
uint32_t image_file_location_oat_checksum = 0;
- uint32_t image_file_location_oat_data_begin = 0;
+ uintptr_t image_file_location_oat_data_begin = 0;
if (!driver->IsImage()) {
TimingLogger::ScopedSplit split("Loading image checksum", &timings);
gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace();
image_file_location_oat_checksum = image_space->GetImageHeader().GetOatChecksum();
image_file_location_oat_data_begin =
- reinterpret_cast<uint32_t>(image_space->GetImageHeader().GetOatDataBegin());
+ reinterpret_cast<uintptr_t>(image_space->GetImageHeader().GetOatDataBegin());
image_file_location = image_space->GetImageFilename();
if (host_prefix != NULL && StartsWith(image_file_location, host_prefix->c_str())) {
image_file_location = image_file_location.substr(host_prefix->size());
@@ -683,11 +683,7 @@ static int dex2oat(int argc, char** argv) {
std::string android_root;
std::vector<const char*> runtime_args;
int thread_count = sysconf(_SC_NPROCESSORS_CONF);
-#if defined(ART_USE_PORTABLE_COMPILER)
- CompilerBackend compiler_backend = kPortable;
-#else
- CompilerBackend compiler_backend = kQuick;
-#endif
+ CompilerBackend compiler_backend = kUsePortableCompiler ? kPortable : kQuick;
// Take the default set of instruction features from the build.
InstructionSetFeatures instruction_set_features =
@@ -700,7 +696,7 @@ static int dex2oat(int argc, char** argv) {
#elif defined(__mips__)
InstructionSet instruction_set = kMips;
#else
-#error "Unsupported architecture"
+ InstructionSet instruction_set = kNone;
#endif
@@ -777,6 +773,8 @@ static int dex2oat(int argc, char** argv) {
instruction_set = kMips;
} else if (instruction_set_str == "x86") {
instruction_set = kX86;
+ } else if (instruction_set_str == "x86_64") {
+ instruction_set = kX86_64;
}
} else if (option.starts_with("--instruction-set-features=")) {
StringPiece str = option.substr(strlen("--instruction-set-features=")).data();
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index 68626f6..3e6e33f 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -16,6 +16,8 @@
#include "disassembler_arm.h"
+#include <inttypes.h>
+
#include <iostream>
#include "base/logging.h"
@@ -711,7 +713,7 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
if (Rn.r == 15 && U == 1) {
intptr_t lit_adr = reinterpret_cast<intptr_t>(instr_ptr);
lit_adr = RoundDown(lit_adr, 4) + 4 + (imm8 << 2);
- args << StringPrintf(" ; 0x%llx", *reinterpret_cast<int64_t*>(lit_adr));
+ args << StringPrintf(" ; 0x%" PRIx64, *reinterpret_cast<int64_t*>(lit_adr));
}
} else if (Rn.r == 13 && W == 1 && U == L) { // VPUSH/VPOP
opcode << (L == 1 ? "vpop" : "vpush");
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 9bde30d..53b07f9 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -49,6 +49,7 @@
#include "runtime.h"
#include "safe_map.h"
#include "scoped_thread_state_change.h"
+#include "verifier/dex_gc_map.h"
#include "verifier/method_verifier.h"
#include "vmap_table.h"
@@ -162,12 +163,11 @@ class OatDumper {
reinterpret_cast<const byte*>(oat_data) > oat_file_.End()) {
return 0; // Address not in oat file
}
- uint32_t begin_offset = reinterpret_cast<size_t>(oat_data) -
- reinterpret_cast<size_t>(oat_file_.Begin());
- typedef std::set<uint32_t>::iterator It;
- It it = offsets_.upper_bound(begin_offset);
+ uintptr_t begin_offset = reinterpret_cast<uintptr_t>(oat_data) -
+ reinterpret_cast<uintptr_t>(oat_file_.Begin());
+ auto it = offsets_.upper_bound(begin_offset);
CHECK(it != offsets_.end());
- uint32_t end_offset = *it;
+ uintptr_t end_offset = *it;
return end_offset - begin_offset;
}
@@ -175,7 +175,7 @@ class OatDumper {
return oat_file_.GetOatHeader().GetInstructionSet();
}
- const void* GetOatCode(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ const void* GetQuickOatCode(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
MethodHelper mh(m);
for (size_t i = 0; i < oat_dex_files_.size(); i++) {
const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
@@ -193,7 +193,7 @@ class OatDumper {
const OatFile::OatClass* oat_class = oat_dex_file->GetOatClass(class_def_index);
CHECK(oat_class != NULL);
size_t method_index = m->GetMethodIndex();
- return oat_class->GetOatMethod(method_index).GetCode();
+ return oat_class->GetOatMethod(method_index).GetQuickCode();
}
}
}
@@ -216,7 +216,7 @@ class OatDumper {
<< "': " << error_msg;
continue;
}
- offsets_.insert(reinterpret_cast<uint32_t>(&dex_file->GetHeader()));
+ offsets_.insert(reinterpret_cast<uintptr_t>(&dex_file->GetHeader()));
for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) {
const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index));
@@ -240,7 +240,7 @@ class OatDumper {
// If the last thing in the file is code for a method, there won't be an offset for the "next"
// thing. Instead of having a special case in the upper_bound code, let's just add an entry
// for the end of the file.
- offsets_.insert(static_cast<uint32_t>(oat_file_.Size()));
+ offsets_.insert(oat_file_.Size());
}
void AddOffsets(const OatFile::OatMethod& oat_method) {
@@ -374,11 +374,17 @@ class OatDumper {
}
}
{
+ const void* code = oat_method.GetQuickCode();
+ uint32_t code_size = oat_method.GetQuickCodeSize();
+ if (code == nullptr) {
+ code = oat_method.GetPortableCode();
+ code_size = oat_method.GetPortableCodeSize();
+ }
indent1_os << StringPrintf("CODE: %p (offset=0x%08x size=%d)%s\n",
- oat_method.GetCode(),
+ code,
oat_method.GetCodeOffset(),
- oat_method.GetCodeSize(),
- oat_method.GetCode() != NULL ? "..." : "");
+ code_size,
+ code != nullptr ? "..." : "");
Indenter indent2_filter(indent1_os.rdbuf(), kIndentChar, kIndentBy1Count);
std::ostream indent2_os(&indent2_filter);
@@ -468,42 +474,60 @@ class OatDumper {
}
}
+ void DumpGcMapRegisters(std::ostream& os, const OatFile::OatMethod& oat_method,
+ const DexFile::CodeItem* code_item,
+ size_t num_regs, const uint8_t* reg_bitmap) {
+ bool first = true;
+ for (size_t reg = 0; reg < num_regs; reg++) {
+ if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
+ if (first) {
+ os << " v" << reg << " (";
+ DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
+ os << ")";
+ first = false;
+ } else {
+ os << ", v" << reg << " (";
+ DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
+ os << ")";
+ }
+ }
+ }
+ if (first) {
+ os << "No registers in GC map\n";
+ } else {
+ os << "\n";
+ }
+ }
void DumpGcMap(std::ostream& os, const OatFile::OatMethod& oat_method,
const DexFile::CodeItem* code_item) {
const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
- if (gc_map_raw == NULL) {
- return;
+ if (gc_map_raw == nullptr) {
+ return; // No GC map.
}
- NativePcOffsetToReferenceMap map(gc_map_raw);
- const void* code = oat_method.GetCode();
- for (size_t entry = 0; entry < map.NumEntries(); entry++) {
- const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code) +
- map.GetNativePcOffset(entry);
- os << StringPrintf("%p", native_pc);
- size_t num_regs = map.RegWidth() * 8;
- const uint8_t* reg_bitmap = map.GetBitMap(entry);
- bool first = true;
- for (size_t reg = 0; reg < num_regs; reg++) {
- if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
- if (first) {
- os << " v" << reg << " (";
- DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
- os << ")";
- first = false;
- } else {
- os << ", v" << reg << " (";
- DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
- os << ")";
- }
- }
+ const void* quick_code = oat_method.GetQuickCode();
+ if (quick_code != nullptr) {
+ NativePcOffsetToReferenceMap map(gc_map_raw);
+ for (size_t entry = 0; entry < map.NumEntries(); entry++) {
+ const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(quick_code) +
+ map.GetNativePcOffset(entry);
+ os << StringPrintf("%p", native_pc);
+ DumpGcMapRegisters(os, oat_method, code_item, map.RegWidth() * 8, map.GetBitMap(entry));
+ }
+ } else {
+ const void* portable_code = oat_method.GetPortableCode();
+ CHECK(portable_code != nullptr);
+ verifier::DexPcToReferenceMap map(gc_map_raw);
+ for (size_t entry = 0; entry < map.NumEntries(); entry++) {
+ uint32_t dex_pc = map.GetDexPc(entry);
+ os << StringPrintf("0x%08x", dex_pc);
+ DumpGcMapRegisters(os, oat_method, code_item, map.RegWidth() * 8, map.GetBitMap(entry));
}
- os << "\n";
}
}
void DumpMappingTable(std::ostream& os, const OatFile::OatMethod& oat_method) {
- const void* code = oat_method.GetCode();
- if (code == NULL) {
+ const void* quick_code = oat_method.GetQuickCode();
+ if (quick_code == nullptr) {
return;
}
MappingTable table(oat_method.GetMappingTable());
@@ -645,31 +669,37 @@ class OatDumper {
void DumpCode(std::ostream& os, verifier::MethodVerifier* verifier,
const OatFile::OatMethod& oat_method, const DexFile::CodeItem* code_item) {
- const void* code = oat_method.GetCode();
- size_t code_size = oat_method.GetCodeSize();
- if (code == NULL || code_size == 0) {
+ const void* portable_code = oat_method.GetPortableCode();
+ const void* quick_code = oat_method.GetQuickCode();
+
+ size_t code_size = oat_method.GetQuickCodeSize();
+ if ((code_size == 0) || ((portable_code == nullptr) && (quick_code == nullptr))) {
os << "NO CODE!\n";
return;
- }
- const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code);
- size_t offset = 0;
- while (offset < code_size) {
- DumpMappingAtOffset(os, oat_method, offset, false);
- offset += disassembler_->Dump(os, native_pc + offset);
- uint32_t dex_pc = DumpMappingAtOffset(os, oat_method, offset, true);
- if (dex_pc != DexFile::kDexNoIndex) {
- DumpGcMapAtNativePcOffset(os, oat_method, code_item, offset);
- if (verifier != nullptr) {
- DumpVRegsAtDexPc(os, verifier, oat_method, code_item, dex_pc);
+ } else if (quick_code != nullptr) {
+ const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
+ size_t offset = 0;
+ while (offset < code_size) {
+ DumpMappingAtOffset(os, oat_method, offset, false);
+ offset += disassembler_->Dump(os, quick_native_pc + offset);
+ uint32_t dex_pc = DumpMappingAtOffset(os, oat_method, offset, true);
+ if (dex_pc != DexFile::kDexNoIndex) {
+ DumpGcMapAtNativePcOffset(os, oat_method, code_item, offset);
+ if (verifier != nullptr) {
+ DumpVRegsAtDexPc(os, verifier, oat_method, code_item, dex_pc);
+ }
}
}
+ } else {
+ CHECK(portable_code != nullptr);
+ CHECK_EQ(code_size, 0U); // TODO: disassembly of portable is currently not supported.
}
}
const std::string host_prefix_;
const OatFile& oat_file_;
std::vector<const OatFile::OatDexFile*> oat_dex_files_;
- std::set<uint32_t> offsets_;
+ std::set<uintptr_t> offsets_;
UniquePtr<Disassembler> disassembler_;
};
@@ -856,7 +886,7 @@ class ImageDumper {
if (descriptor[0] != 'L' && descriptor[0] != '[') {
mirror::Class* type = fh.GetType();
if (type->IsPrimitiveLong()) {
- os << StringPrintf("%lld (0x%llx)\n", field->Get64(obj), field->Get64(obj));
+ os << StringPrintf("%" PRId64 " (0x%" PRIx64 ")\n", field->Get64(obj), field->Get64(obj));
} else if (type->IsPrimitiveDouble()) {
os << StringPrintf("%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
} else if (type->IsPrimitiveFloat()) {
@@ -902,34 +932,34 @@ class ImageDumper {
return image_space_.Contains(object);
}
- const void* GetOatCodeBegin(mirror::ArtMethod* m)
+ const void* GetQuickOatCodeBegin(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const void* code = m->GetEntryPointFromCompiledCode();
- if (code == GetResolutionTrampoline(Runtime::Current()->GetClassLinker())) {
- code = oat_dumper_->GetOatCode(m);
+ const void* quick_code = m->GetEntryPointFromQuickCompiledCode();
+ if (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker())) {
+ quick_code = oat_dumper_->GetQuickOatCode(m);
}
if (oat_dumper_->GetInstructionSet() == kThumb2) {
- code = reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) & ~0x1);
+ quick_code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(quick_code) & ~0x1);
}
- return code;
+ return quick_code;
}
- uint32_t GetOatCodeSize(mirror::ArtMethod* m)
+ uint32_t GetQuickOatCodeSize(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetOatCodeBegin(m));
- if (oat_code_begin == NULL) {
+ const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetQuickOatCodeBegin(m));
+ if (oat_code_begin == nullptr) {
return 0;
}
return oat_code_begin[-1];
}
- const void* GetOatCodeEnd(mirror::ArtMethod* m)
+ const void* GetQuickOatCodeEnd(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetOatCodeBegin(m));
+ const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetQuickOatCodeBegin(m));
if (oat_code_begin == NULL) {
return NULL;
}
- return oat_code_begin + GetOatCodeSize(m);
+ return oat_code_begin + GetQuickOatCodeSize(m);
}
static void Callback(mirror::Object* obj, void* arg)
@@ -1006,17 +1036,18 @@ class ImageDumper {
} else if (obj->IsArtMethod()) {
mirror::ArtMethod* method = obj->AsArtMethod();
if (method->IsNative()) {
- DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method);
- DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
+ // TODO: portable dumping.
+ DCHECK(method->GetNativeGcMap() == nullptr) << PrettyMethod(method);
+ DCHECK(method->GetMappingTable() == nullptr) << PrettyMethod(method);
bool first_occurrence;
- const void* oat_code = state->GetOatCodeBegin(method);
- uint32_t oat_code_size = state->GetOatCodeSize(method);
- state->ComputeOatSize(oat_code, &first_occurrence);
+ const void* quick_oat_code = state->GetQuickOatCodeBegin(method);
+ uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
+ state->ComputeOatSize(quick_oat_code, &first_occurrence);
if (first_occurrence) {
- state->stats_.native_to_managed_code_bytes += oat_code_size;
+ state->stats_.native_to_managed_code_bytes += quick_oat_code_size;
}
- if (oat_code != method->GetEntryPointFromCompiledCode()) {
- indent_os << StringPrintf("OAT CODE: %p\n", oat_code);
+ if (quick_oat_code != method->GetEntryPointFromQuickCompiledCode()) {
+ indent_os << StringPrintf("OAT CODE: %p\n", quick_oat_code);
}
} else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
method->IsResolutionMethod() || method->IsImtConflictMethod() ||
@@ -1050,33 +1081,34 @@ class ImageDumper {
state->stats_.vmap_table_bytes += vmap_table_bytes;
}
- const void* oat_code_begin = state->GetOatCodeBegin(method);
- const void* oat_code_end = state->GetOatCodeEnd(method);
- uint32_t oat_code_size = state->GetOatCodeSize(method);
- state->ComputeOatSize(oat_code_begin, &first_occurrence);
+ // TODO: portable dumping.
+ const void* quick_oat_code_begin = state->GetQuickOatCodeBegin(method);
+ const void* quick_oat_code_end = state->GetQuickOatCodeEnd(method);
+ uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
+ state->ComputeOatSize(quick_oat_code_begin, &first_occurrence);
if (first_occurrence) {
- state->stats_.managed_code_bytes += oat_code_size;
+ state->stats_.managed_code_bytes += quick_oat_code_size;
if (method->IsConstructor()) {
if (method->IsStatic()) {
- state->stats_.class_initializer_code_bytes += oat_code_size;
+ state->stats_.class_initializer_code_bytes += quick_oat_code_size;
} else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
- state->stats_.large_initializer_code_bytes += oat_code_size;
+ state->stats_.large_initializer_code_bytes += quick_oat_code_size;
}
} else if (dex_instruction_bytes > kLargeMethodDexBytes) {
- state->stats_.large_method_code_bytes += oat_code_size;
+ state->stats_.large_method_code_bytes += quick_oat_code_size;
}
}
- state->stats_.managed_code_bytes_ignoring_deduplication += oat_code_size;
+ state->stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;
- indent_os << StringPrintf("OAT CODE: %p-%p\n", oat_code_begin, oat_code_end);
+ indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end);
indent_os << StringPrintf("SIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes);
size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes +
- vmap_table_bytes + oat_code_size + object_bytes;
+ vmap_table_bytes + quick_oat_code_size + object_bytes;
double expansion =
- static_cast<double>(oat_code_size) / static_cast<double>(dex_instruction_bytes);
+ static_cast<double>(quick_oat_code_size) / static_cast<double>(dex_instruction_bytes);
state->stats_.ComputeOutliers(total_size, expansion, method);
}
}
diff --git a/runtime/Android.mk b/runtime/Android.mk
index d735051..223ae7c 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -215,12 +215,13 @@ LIBART_LDFLAGS += -Wl,--no-fatal-warnings
else # TARGET_ARCH != x86
ifeq ($(TARGET_ARCH),x86_64)
LIBART_TARGET_SRC_FILES += \
- arch/x86/context_x86.cc \
- arch/x86/entrypoints_init_x86.cc \
- arch/x86/jni_entrypoints_x86.S \
- arch/x86/portable_entrypoints_x86.S \
- arch/x86/quick_entrypoints_x86.S \
- arch/x86/thread_x86.cc
+ arch/x86_64/context_x86_64.cc \
+ arch/x86_64/entrypoints_init_x86_64.cc \
+ arch/x86_64/jni_entrypoints_x86_64.S \
+ arch/x86_64/portable_entrypoints_x86_64.S \
+ arch/x86_64/quick_entrypoints_x86_64.S \
+ arch/x86_64/thread_x86_64.cc \
+ monitor_pool.cc
LIBART_LDFLAGS += -Wl,--no-fatal-warnings
else # TARGET_ARCH != x86_64
ifeq ($(TARGET_ARCH),mips)
@@ -255,6 +256,16 @@ LIBART_HOST_SRC_FILES := \
thread_linux.cc
ifeq ($(HOST_ARCH),x86)
+ifneq ($(BUILD_HOST_64bit),)
+LIBART_HOST_SRC_FILES += \
+ arch/x86_64/context_x86_64.cc \
+ arch/x86_64/entrypoints_init_x86_64.cc \
+ arch/x86_64/jni_entrypoints_x86_64.S \
+ arch/x86_64/portable_entrypoints_x86_64.S \
+ arch/x86_64/quick_entrypoints_x86_64.S \
+ arch/x86_64/thread_x86_64.cc \
+ monitor_pool.cc
+else
LIBART_HOST_SRC_FILES += \
arch/x86/context_x86.cc \
arch/x86/entrypoints_init_x86.cc \
@@ -262,6 +273,7 @@ LIBART_HOST_SRC_FILES += \
arch/x86/portable_entrypoints_x86.S \
arch/x86/quick_entrypoints_x86.S \
arch/x86/thread_x86.cc
+endif
else # HOST_ARCH != x86
$(error unsupported HOST_ARCH=$(HOST_ARCH))
endif # HOST_ARCH != x86
diff --git a/runtime/arch/arm/context_arm.h b/runtime/arch/arm/context_arm.h
index 00651ff..020cae0 100644
--- a/runtime/arch/arm/context_arm.h
+++ b/runtime/arch/arm/context_arm.h
@@ -35,7 +35,7 @@ class ArmContext : public Context {
virtual void Reset();
- virtual void FillCalleeSaves(const StackVisitor& fr);
+ virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void SetSP(uintptr_t new_sp) {
SetGPR(SP, new_sp);
diff --git a/runtime/arch/arm/portable_entrypoints_arm.S b/runtime/arch/arm/portable_entrypoints_arm.S
index ac519d5..98d17dc 100644
--- a/runtime/arch/arm/portable_entrypoints_arm.S
+++ b/runtime/arch/arm/portable_entrypoints_arm.S
@@ -53,7 +53,7 @@ ENTRY art_portable_invoke_stub
mov ip, #0 @ set ip to 0
str ip, [sp] @ store NULL for method* at bottom of frame
add sp, #16 @ first 4 args are not passed on stack for portable
- ldr ip, [r0, #METHOD_CODE_OFFSET] @ get pointer to the code
+ ldr ip, [r0, #METHOD_PORTABLE_CODE_OFFSET] @ get pointer to the code
blx ip @ call the method
mov sp, r11 @ restore the stack pointer
ldr ip, [sp, #24] @ load the result pointer
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 34de93f..0e5c60a 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -302,7 +302,7 @@ ENTRY art_quick_invoke_stub
ldr r3, [sp, #12] @ copy arg value for r3
mov ip, #0 @ set ip to 0
str ip, [sp] @ store NULL for method* at bottom of frame
- ldr ip, [r0, #METHOD_CODE_OFFSET] @ get pointer to the code
+ ldr ip, [r0, #METHOD_QUICK_CODE_OFFSET] @ get pointer to the code
blx ip @ call the method
mov sp, r11 @ restore the stack pointer
ldr ip, [sp, #24] @ load the result pointer
diff --git a/runtime/arch/context.cc b/runtime/arch/context.cc
index 7075e42..5eaf809 100644
--- a/runtime/arch/context.cc
+++ b/runtime/arch/context.cc
@@ -22,6 +22,10 @@
#include "mips/context_mips.h"
#elif defined(__i386__)
#include "x86/context_x86.h"
+#elif defined(__x86_64__)
+#include "x86_64/context_x86_64.h"
+#else
+#include "base/logging.h"
#endif
namespace art {
@@ -33,8 +37,11 @@ Context* Context::Create() {
return new mips::MipsContext();
#elif defined(__i386__)
return new x86::X86Context();
+#elif defined(__x86_64__)
+ return new x86_64::X86_64Context();
#else
UNIMPLEMENTED(FATAL);
+ return nullptr;
#endif
}
diff --git a/runtime/arch/context.h b/runtime/arch/context.h
index 91e0cd6..3d11178 100644
--- a/runtime/arch/context.h
+++ b/runtime/arch/context.h
@@ -20,6 +20,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "locks.h"
+
namespace art {
class StackVisitor;
@@ -38,7 +40,8 @@ class Context {
// Read values from callee saves in the given frame. The frame also holds
// the method that holds the layout.
- virtual void FillCalleeSaves(const StackVisitor& fr) = 0;
+ virtual void FillCalleeSaves(const StackVisitor& fr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Set the stack pointer value
virtual void SetSP(uintptr_t new_sp) = 0;
diff --git a/runtime/arch/mips/context_mips.h b/runtime/arch/mips/context_mips.h
index 5595f86..4145cd3 100644
--- a/runtime/arch/mips/context_mips.h
+++ b/runtime/arch/mips/context_mips.h
@@ -33,7 +33,7 @@ class MipsContext : public Context {
virtual void Reset();
- virtual void FillCalleeSaves(const StackVisitor& fr);
+ virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void SetSP(uintptr_t new_sp) {
SetGPR(SP, new_sp);
diff --git a/runtime/arch/mips/portable_entrypoints_mips.S b/runtime/arch/mips/portable_entrypoints_mips.S
index 9208a8a..7545ce0 100644
--- a/runtime/arch/mips/portable_entrypoints_mips.S
+++ b/runtime/arch/mips/portable_entrypoints_mips.S
@@ -61,5 +61,73 @@ ENTRY art_portable_proxy_invoke_handler
.cfi_adjust_cfa_offset -64
END art_portable_proxy_invoke_handler
+ /*
+ * Invocation stub for portable code.
+ * On entry:
+ * a0 = method pointer
+ * a1 = argument array or NULL for no argument methods
+ * a2 = size of argument array in bytes
+ * a3 = (managed) thread pointer
+ * [sp + 16] = JValue* result
+ * [sp + 20] = result type char
+ */
+ENTRY art_portable_invoke_stub
+ GENERATE_GLOBAL_POINTER
+ sw $a0, 0($sp) # save out a0
+ addiu $sp, $sp, -16 # spill s0, s1, fp, ra
+ .cfi_adjust_cfa_offset 16
+ sw $ra, 12($sp)
+ .cfi_rel_offset 31, 12
+ sw $fp, 8($sp)
+ .cfi_rel_offset 30, 8
+ sw $s1, 4($sp)
+ .cfi_rel_offset 17, 4
+ sw $s0, 0($sp)
+ .cfi_rel_offset 16, 0
+ move $fp, $sp # save sp in fp
+ .cfi_def_cfa_register 30
+ move $s1, $a3 # move managed thread pointer into s1
+ addiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset s0 to suspend check interval
+ addiu $t0, $a2, 16 # create space for method pointer in frame
+ srl $t0, $t0, 3 # shift the frame size right 3
+ sll $t0, $t0, 3 # shift the frame size left 3 to align to 16 bytes
+ subu $sp, $sp, $t0 # reserve stack space for argument array
+ addiu $a0, $sp, 4 # pass stack pointer + method ptr as dest for memcpy
+ jal memcpy # (dest, src, bytes)
+ addiu $sp, $sp, -16 # make space for argument slots for memcpy
+ addiu $sp, $sp, 16 # restore stack after memcpy
+ lw $a0, 16($fp) # restore method*
+ lw $a1, 4($sp) # copy arg value for a1
+ lw $a2, 8($sp) # copy arg value for a2
+ lw $a3, 12($sp) # copy arg value for a3
+ lw $t9, METHOD_PORTABLE_CODE_OFFSET($a0) # get pointer to the code
+ jalr $t9 # call the method
+ sw $zero, 0($sp) # store NULL for method* at bottom of frame
+ move $sp, $fp # restore the stack
+ lw $s0, 0($sp)
+ .cfi_restore 16
+ lw $s1, 4($sp)
+ .cfi_restore 17
+ lw $fp, 8($sp)
+ .cfi_restore 30
+ lw $ra, 12($sp)
+ .cfi_restore 31
+ addiu $sp, $sp, 16
+ .cfi_adjust_cfa_offset -16
+ lw $t0, 16($sp) # get result pointer
+ lw $t1, 20($sp) # get result type char
+ li $t2, 68 # put char 'D' into t2
+ beq $t1, $t2, 1f # branch if result type char == 'D'
+ li $t3, 70 # put char 'F' into t3
+ beq $t1, $t3, 1f # branch if result type char == 'F'
+ sw $v0, 0($t0) # store the result
+ jr $ra
+ sw $v1, 4($t0) # store the other half of the result
+1:
+ s.s $f0, 0($t0) # store floating point result
+ jr $ra
+ s.s $f1, 4($t0) # store other half of floating point result
+END art_portable_invoke_stub
+
UNIMPLEMENTED art_portable_resolution_trampoline
UNIMPLEMENTED art_portable_to_interpreter_bridge
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 2d1e87a..c60bca0 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -449,7 +449,7 @@ INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvoke
INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
/*
- * Common invocation stub for portable and quick.
+ * Invocation stub for quick code.
* On entry:
* a0 = method pointer
* a1 = argument array or NULL for no argument methods
@@ -458,9 +458,6 @@ INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvo
* [sp + 16] = JValue* result
* [sp + 20] = result type char
*/
- .type art_portable_invoke_stub, %function
- .global art_portable_invoke_stub
-art_portable_invoke_stub:
ENTRY art_quick_invoke_stub
GENERATE_GLOBAL_POINTER
sw $a0, 0($sp) # save out a0
@@ -490,7 +487,7 @@ ENTRY art_quick_invoke_stub
lw $a1, 4($sp) # copy arg value for a1
lw $a2, 8($sp) # copy arg value for a2
lw $a3, 12($sp) # copy arg value for a3
- lw $t9, METHOD_CODE_OFFSET($a0) # get pointer to the code
+ lw $t9, METHOD_QUICK_CODE_OFFSET($a0) # get pointer to the code
jalr $t9 # call the method
sw $zero, 0($sp) # store NULL for method* at bottom of frame
move $sp, $fp # restore the stack
@@ -518,7 +515,6 @@ ENTRY art_quick_invoke_stub
jr $ra
s.s $f1, 4($t0) # store other half of floating point result
END art_quick_invoke_stub
- .size art_portable_invoke_stub, .-art_portable_invoke_stub
/*
* Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
diff --git a/runtime/arch/x86/context_x86.cc b/runtime/arch/x86/context_x86.cc
index 66a51f7..d7dca64 100644
--- a/runtime/arch/x86/context_x86.cc
+++ b/runtime/arch/x86/context_x86.cc
@@ -23,7 +23,7 @@
namespace art {
namespace x86 {
-static const uint32_t gZero = 0;
+static const uintptr_t gZero = 0;
void X86Context::Reset() {
for (int i = 0; i < kNumberOfCpuRegisters; i++) {
@@ -55,8 +55,8 @@ void X86Context::FillCalleeSaves(const StackVisitor& fr) {
void X86Context::SmashCallerSaves() {
// This needs to be 0 because we want a null/zero return value.
- gprs_[EAX] = const_cast<uint32_t*>(&gZero);
- gprs_[EDX] = const_cast<uint32_t*>(&gZero);
+ gprs_[EAX] = const_cast<uintptr_t*>(&gZero);
+ gprs_[EDX] = const_cast<uintptr_t*>(&gZero);
gprs_[ECX] = NULL;
gprs_[EBX] = NULL;
}
@@ -89,7 +89,7 @@ void X86Context::DoLongJump() {
: "g"(&gprs[0]) // input.
:); // clobber.
#else
- UNIMPLEMENTED(FATAL);
+ UNIMPLEMENTED(FATAL);
#endif
}
diff --git a/runtime/arch/x86/context_x86.h b/runtime/arch/x86/context_x86.h
index d7d2210..598314d 100644
--- a/runtime/arch/x86/context_x86.h
+++ b/runtime/arch/x86/context_x86.h
@@ -33,7 +33,7 @@ class X86Context : public Context {
virtual void Reset();
- virtual void FillCalleeSaves(const StackVisitor& fr);
+ virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void SetSP(uintptr_t new_sp) {
SetGPR(ESP, new_sp);
diff --git a/runtime/arch/x86/jni_entrypoints_x86.S b/runtime/arch/x86/jni_entrypoints_x86.S
index 72047d5..2eb5ada 100644
--- a/runtime/arch/x86/jni_entrypoints_x86.S
+++ b/runtime/arch/x86/jni_entrypoints_x86.S
@@ -17,7 +17,7 @@
#include "asm_support_x86.S"
/*
- * Portable resolution trampoline.
+ * Jni dlsym lookup stub.
*/
DEFINE_FUNCTION art_jni_dlsym_lookup_stub
subl LITERAL(4), %esp // align stack
diff --git a/runtime/arch/x86/portable_entrypoints_x86.S b/runtime/arch/x86/portable_entrypoints_x86.S
index 48de7c1..4bd6173 100644
--- a/runtime/arch/x86/portable_entrypoints_x86.S
+++ b/runtime/arch/x86/portable_entrypoints_x86.S
@@ -46,7 +46,7 @@ DEFINE_FUNCTION art_portable_invoke_stub
addl LITERAL(12), %esp // pop arguments to memcpy
mov 12(%ebp), %eax // move method pointer into eax
mov %eax, (%esp) // push method pointer onto stack
- call *METHOD_CODE_OFFSET(%eax) // call the method
+ call *METHOD_PORTABLE_CODE_OFFSET(%eax) // call the method
mov %ebp, %esp // restore stack pointer
POP ebx // pop ebx
POP ebp // pop ebp
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 74ec761..9c3eb30 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -275,7 +275,7 @@ DEFINE_FUNCTION art_quick_invoke_stub
mov 4(%esp), %ecx // copy arg1 into ecx
mov 8(%esp), %edx // copy arg2 into edx
mov 12(%esp), %ebx // copy arg3 into ebx
- call *METHOD_CODE_OFFSET(%eax) // call the method
+ call *METHOD_QUICK_CODE_OFFSET(%eax) // call the method
mov %ebp, %esp // restore stack pointer
CFI_DEF_CFA_REGISTER(esp)
POP ebx // pop ebx
diff --git a/runtime/arch/x86_64/asm_support_x86_64.S b/runtime/arch/x86_64/asm_support_x86_64.S
new file mode 100644
index 0000000..b59c0cb
--- /dev/null
+++ b/runtime/arch/x86_64/asm_support_x86_64.S
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2013 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_ARCH_X86_64_ASM_SUPPORT_X86_64_S_
+#define ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_S_
+
+#include "asm_support_x86_64.h"
+
+#if defined(__APPLE__)
+ // Mac OS' as(1) doesn't let you name macro parameters.
+ #define MACRO0(macro_name) .macro macro_name
+ #define MACRO1(macro_name, macro_arg1) .macro macro_name
+ #define MACRO2(macro_name, macro_arg1, macro_args2) .macro macro_name
+ #define MACRO3(macro_name, macro_arg1, macro_args2, macro_args3) .macro macro_name
+ #define END_MACRO .endmacro
+
+ // Mac OS' as(1) uses $0, $1, and so on for macro arguments, and function names
+ // are mangled with an extra underscore prefix. The use of $x for arguments
+ // mean that literals need to be represented with $$x in macros.
+ #define SYMBOL(name) _ ## name
+ #define PLT_SYMBOL(name) _ ## name
+ #define VAR(name,index) SYMBOL($index)
+ #define PLT_VAR(name, index) SYMBOL($index)
+ #define REG_VAR(name,index) %$index
+ #define CALL_MACRO(name,index) $index
+ #define LITERAL(value) $value
+ #define MACRO_LITERAL(value) $$value
+
+ // Mac OS' doesn't like cfi_* directives
+ #define CFI_STARTPROC
+ #define CFI_ENDPROC
+ #define CFI_ADJUST_CFA_OFFSET(size)
+ #define CFI_DEF_CFA(reg,size)
+ #define CFI_DEF_CFA_REGISTER(reg)
+ #define CFI_RESTORE(reg)
+ #define CFI_REL_OFFSET(reg,size)
+
+ // Mac OS' doesn't support certain directives
+ #define FUNCTION_TYPE(name)
+ #define SIZE(name)
+#else
+ // Regular gas(1) lets you name macro parameters.
+ #define MACRO0(macro_name) .macro macro_name
+ #define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1
+ #define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2
+ #define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3
+ #define END_MACRO .endm
+
+ // Regular gas(1) uses \argument_name for macro arguments.
+ // We need to turn on alternate macro syntax so we can use & instead or the preprocessor
+ // will screw us by inserting a space between the \ and the name. Even in this mode there's
+ // no special meaning to $, so literals are still just $x. The use of altmacro means % is a
+ // special character meaning care needs to be taken when passing registers as macro arguments.
+ .altmacro
+ #define SYMBOL(name) name
+ #define PLT_SYMBOL(name) name@PLT
+ #define VAR(name,index) name&
+ #define PLT_VAR(name, index) name&@PLT
+ #define REG_VAR(name,index) %name
+ #define CALL_MACRO(name,index) name&
+ #define LITERAL(value) $value
+ #define MACRO_LITERAL(value) $value
+
+ // CFI support
+ #define CFI_STARTPROC .cfi_startproc
+ #define CFI_ENDPROC .cfi_endproc
+ #define CFI_ADJUST_CFA_OFFSET(size) .cfi_adjust_cfa_offset size
+ #define CFI_DEF_CFA(reg,size) .cfi_def_cfa reg,size
+ #define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
+ #define CFI_RESTORE(reg) .cfi_restore reg
+ #define CFI_REL_OFFSET(reg,size) .cfi_rel_offset reg,size
+
+ #define FUNCTION_TYPE(name) .type name&, @function
+ #define SIZE(name) .size name, .-name
+#endif
+
+ /* Cache alignment for function entry */
+MACRO0(ALIGN_FUNCTION_ENTRY)
+ .balign 16
+END_MACRO
+
+MACRO1(DEFINE_FUNCTION, c_name)
+ FUNCTION_TYPE(\c_name)
+ .globl VAR(c_name, 0)
+ ALIGN_FUNCTION_ENTRY
+VAR(c_name, 0):
+ CFI_STARTPROC
+END_MACRO
+
+MACRO1(END_FUNCTION, c_name)
+ CFI_ENDPROC
+ SIZE(\c_name)
+END_MACRO
+
+MACRO1(PUSH, reg)
+ pushq REG_VAR(reg, 0)
+ CFI_ADJUST_CFA_OFFSET(8)
+ CFI_REL_OFFSET(REG_VAR(reg, 0), 0)
+END_MACRO
+
+MACRO1(POP, reg)
+ popq REG_VAR(reg,0)
+ CFI_ADJUST_CFA_OFFSET(-8)
+ CFI_RESTORE(REG_VAR(reg,0))
+END_MACRO
+
+MACRO1(UNIMPLEMENTED,name)
+ FUNCTION_TYPE(\name)
+ .globl VAR(name, 0)
+ ALIGN_FUNCTION_ENTRY
+VAR(name, 0):
+ CFI_STARTPROC
+ int3
+ int3
+ CFI_ENDPROC
+ SIZE(\name)
+END_MACRO
+
+MACRO0(SETUP_GOT_NOSAVE)
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+END_MACRO
+
+MACRO0(SETUP_GOT)
+ PUSH ebx
+ SETUP_GOT_NOSAVE
+END_MACRO
+
+MACRO0(UNDO_SETUP_GOT)
+ POP ebx
+END_MACRO
+
+#endif // ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_S_
diff --git a/runtime/arch/x86_64/asm_support_x86_64.h b/runtime/arch/x86_64/asm_support_x86_64.h
new file mode 100644
index 0000000..d425ed8
--- /dev/null
+++ b/runtime/arch/x86_64/asm_support_x86_64.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 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_ARCH_X86_64_ASM_SUPPORT_X86_64_H_
+#define ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_H_
+
+#include "asm_support.h"
+
+// Offset of field Thread::self_ verified in InitCpu
+#define THREAD_SELF_OFFSET 72
+// Offset of field Thread::card_table_ verified in InitCpu
+#define THREAD_CARD_TABLE_OFFSET 8
+// Offset of field Thread::exception_ verified in InitCpu
+#define THREAD_EXCEPTION_OFFSET 16
+// Offset of field Thread::thin_lock_thread_id_ verified in InitCpu
+#define THREAD_ID_OFFSET 112
+
+#endif // ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_H_
diff --git a/runtime/arch/x86_64/context_x86_64.cc b/runtime/arch/x86_64/context_x86_64.cc
new file mode 100644
index 0000000..4d1131c
--- /dev/null
+++ b/runtime/arch/x86_64/context_x86_64.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "context_x86_64.h"
+
+#include "mirror/art_method.h"
+#include "mirror/object-inl.h"
+#include "stack.h"
+
+namespace art {
+namespace x86_64 {
+
+static const uintptr_t gZero = 0;
+
+void X86_64Context::Reset() {
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ gprs_[i] = NULL;
+ }
+ gprs_[RSP] = &rsp_;
+ // Initialize registers with easy to spot debug values.
+ rsp_ = X86_64Context::kBadGprBase + RSP;
+ rip_ = X86_64Context::kBadGprBase + kNumberOfCpuRegisters;
+}
+
+void X86_64Context::FillCalleeSaves(const StackVisitor& fr) {
+ mirror::ArtMethod* method = fr.GetMethod();
+ uint32_t core_spills = method->GetCoreSpillMask();
+ size_t spill_count = __builtin_popcount(core_spills);
+ DCHECK_EQ(method->GetFpSpillMask(), 0u);
+ size_t frame_size = method->GetFrameSizeInBytes();
+ if (spill_count > 0) {
+ // Lowest number spill is farthest away, walk registers and fill into context.
+ int j = 2; // Offset j to skip return address spill.
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ if (((core_spills >> i) & 1) != 0) {
+ gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size);
+ j++;
+ }
+ }
+ }
+}
+
+void X86_64Context::SmashCallerSaves() {
+ // This needs to be 0 because we want a null/zero return value.
+ gprs_[RAX] = const_cast<uintptr_t*>(&gZero);
+ gprs_[RDX] = const_cast<uintptr_t*>(&gZero);
+ gprs_[RCX] = nullptr;
+ gprs_[RBX] = nullptr;
+}
+
+void X86_64Context::SetGPR(uint32_t reg, uintptr_t value) {
+ CHECK_LT(reg, static_cast<uint32_t>(kNumberOfCpuRegisters));
+ CHECK_NE(gprs_[reg], &gZero);
+ CHECK(gprs_[reg] != NULL);
+ *gprs_[reg] = value;
+}
+
+void X86_64Context::DoLongJump() {
+ UNIMPLEMENTED(FATAL);
+}
+
+} // namespace x86_64
+} // namespace art
diff --git a/runtime/arch/x86_64/context_x86_64.h b/runtime/arch/x86_64/context_x86_64.h
new file mode 100644
index 0000000..3e49165
--- /dev/null
+++ b/runtime/arch/x86_64/context_x86_64.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_64_CONTEXT_X86_64_H_
+#define ART_RUNTIME_ARCH_X86_64_CONTEXT_X86_64_H_
+
+#include "arch/context.h"
+#include "base/logging.h"
+#include "registers_x86_64.h"
+
+namespace art {
+namespace x86_64 {
+
+class X86_64Context : public Context {
+ public:
+ X86_64Context() {
+ Reset();
+ }
+ virtual ~X86_64Context() {}
+
+ virtual void Reset();
+
+ virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ virtual void SetSP(uintptr_t new_sp) {
+ SetGPR(RSP, new_sp);
+ }
+
+ virtual void SetPC(uintptr_t new_pc) {
+ rip_ = new_pc;
+ }
+
+ virtual uintptr_t GetGPR(uint32_t reg) {
+ const uint32_t kNumberOfCpuRegisters = 8;
+ DCHECK_LT(reg, kNumberOfCpuRegisters);
+ return *gprs_[reg];
+ }
+
+ virtual void SetGPR(uint32_t reg, uintptr_t value);
+
+ virtual void SmashCallerSaves();
+ virtual void DoLongJump();
+
+ private:
+ // Pointers to register locations, floating point registers are all caller save. Values are
+ // initialized to NULL or the special registers below.
+ uintptr_t* gprs_[kNumberOfCpuRegisters];
+ // Hold values for rsp and rip if they are not located within a stack frame. RIP is somewhat
+ // special in that it cannot be encoded normally as a register operand to an instruction (except
+ // in 64bit addressing modes).
+ uintptr_t rsp_, rip_;
+};
+} // namespace x86_64
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_X86_64_CONTEXT_X86_64_H_
diff --git a/runtime/arch/x86_64/entrypoints_init_x86_64.cc b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
new file mode 100644
index 0000000..589c7d9
--- /dev/null
+++ b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2012 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 "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_entrypoints.h"
+#include "entrypoints/entrypoint_utils.h"
+
+namespace art {
+
+// Interpreter entrypoints.
+extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+
+// Portable entrypoints.
+extern "C" void art_portable_resolution_trampoline(mirror::ArtMethod*);
+extern "C" void art_portable_to_interpreter_bridge(mirror::ArtMethod*);
+
+// Cast entrypoints.
+extern "C" uint32_t art_quick_is_assignable(const mirror::Class* klass,
+ const mirror::Class* ref_class);
+extern "C" void art_quick_check_cast(void*, void*);
+
+// DexCache entrypoints.
+extern "C" void* art_quick_initialize_static_storage(uint32_t, void*);
+extern "C" void* art_quick_initialize_type(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_and_verify_access(uint32_t, void*);
+extern "C" void* art_quick_resolve_string(void*, uint32_t);
+
+// Field entrypoints.
+extern "C" int art_quick_set32_instance(uint32_t, void*, int32_t);
+extern "C" int art_quick_set32_static(uint32_t, int32_t);
+extern "C" int art_quick_set64_instance(uint32_t, void*, int64_t);
+extern "C" int art_quick_set64_static(uint32_t, int64_t);
+extern "C" int art_quick_set_obj_instance(uint32_t, void*, void*);
+extern "C" int art_quick_set_obj_static(uint32_t, void*);
+extern "C" int32_t art_quick_get32_instance(uint32_t, void*);
+extern "C" int32_t art_quick_get32_static(uint32_t);
+extern "C" int64_t art_quick_get64_instance(uint32_t, void*);
+extern "C" int64_t art_quick_get64_static(uint32_t);
+extern "C" void* art_quick_get_obj_instance(uint32_t, void*);
+extern "C" void* art_quick_get_obj_static(uint32_t);
+
+// Array entrypoints.
+extern "C" void art_quick_aput_obj_with_null_and_bound_check(void*, uint32_t, void*);
+extern "C" void art_quick_aput_obj_with_bound_check(void*, uint32_t, void*);
+extern "C" void art_quick_aput_obj(void*, uint32_t, void*);
+extern "C" void art_quick_handle_fill_data(void*, void*);
+
+// Lock entrypoints.
+extern "C" void art_quick_lock_object(void*);
+extern "C" void art_quick_unlock_object(void*);
+
+// Math entrypoints.
+extern "C" double art_quick_fmod(double, double);
+extern "C" float art_quick_fmodf(float, float);
+extern "C" double art_quick_l2d(int64_t);
+extern "C" float art_quick_l2f(int64_t);
+extern "C" int64_t art_quick_d2l(double);
+extern "C" int64_t art_quick_f2l(float);
+extern "C" int32_t art_quick_idivmod(int32_t, int32_t);
+extern "C" int64_t art_quick_ldiv(int64_t, int64_t);
+extern "C" int64_t art_quick_lmod(int64_t, int64_t);
+extern "C" int64_t art_quick_lmul(int64_t, int64_t);
+extern "C" uint64_t art_quick_lshl(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_lshr(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_lushr(uint64_t, uint32_t);
+
+// Intrinsic entrypoints.
+extern "C" int32_t art_quick_memcmp16(void*, void*, int32_t);
+extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_quick_string_compareto(void*, void*);
+extern "C" void* art_quick_memcpy(void*, const void*, size_t);
+
+// Invoke entrypoints.
+extern "C" void art_quick_imt_conflict_trampoline(mirror::ArtMethod*);
+extern "C" void art_quick_resolution_trampoline(mirror::ArtMethod*);
+extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*);
+extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
+
+// Thread entrypoints.
+extern void CheckSuspendFromCode(Thread* thread);
+extern "C" void art_quick_test_suspend();
+
+// Throw entrypoints.
+extern "C" void art_quick_deliver_exception(void*);
+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_stack_overflow(void*);
+
+extern void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints);
+
+void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
+ PortableEntryPoints* ppoints, QuickEntryPoints* qpoints) {
+ // Interpreter
+ ipoints->pInterpreterToInterpreterBridge = artInterpreterToInterpreterBridge;
+ ipoints->pInterpreterToCompiledCodeBridge = artInterpreterToCompiledCodeBridge;
+
+ // JNI
+ jpoints->pDlsymLookup = art_jni_dlsym_lookup_stub;
+
+ // Portable
+ ppoints->pPortableResolutionTrampoline = art_portable_resolution_trampoline;
+ ppoints->pPortableToInterpreterBridge = art_portable_to_interpreter_bridge;
+
+ // Alloc
+ ResetQuickAllocEntryPoints(qpoints);
+
+ // Cast
+ qpoints->pInstanceofNonTrivial = art_quick_is_assignable;
+ qpoints->pCheckCast = art_quick_check_cast;
+
+ // DexCache
+ qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage;
+ qpoints->pInitializeTypeAndVerifyAccess = art_quick_initialize_type_and_verify_access;
+ qpoints->pInitializeType = art_quick_initialize_type;
+ qpoints->pResolveString = art_quick_resolve_string;
+
+ // Field
+ qpoints->pSet32Instance = art_quick_set32_instance;
+ qpoints->pSet32Static = art_quick_set32_static;
+ qpoints->pSet64Instance = art_quick_set64_instance;
+ qpoints->pSet64Static = art_quick_set64_static;
+ qpoints->pSetObjInstance = art_quick_set_obj_instance;
+ qpoints->pSetObjStatic = art_quick_set_obj_static;
+ qpoints->pGet32Instance = art_quick_get32_instance;
+ qpoints->pGet64Instance = art_quick_get64_instance;
+ qpoints->pGetObjInstance = art_quick_get_obj_instance;
+ qpoints->pGet32Static = art_quick_get32_static;
+ qpoints->pGet64Static = art_quick_get64_static;
+ qpoints->pGetObjStatic = art_quick_get_obj_static;
+
+ // Array
+ qpoints->pAputObjectWithNullAndBoundCheck = art_quick_aput_obj_with_null_and_bound_check;
+ qpoints->pAputObjectWithBoundCheck = art_quick_aput_obj_with_bound_check;
+ qpoints->pAputObject = art_quick_aput_obj;
+ qpoints->pHandleFillArrayData = art_quick_handle_fill_data;
+
+ // JNI
+ qpoints->pJniMethodStart = JniMethodStart;
+ qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronized;
+ qpoints->pJniMethodEnd = JniMethodEnd;
+ qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized;
+ qpoints->pJniMethodEndWithReference = JniMethodEndWithReference;
+ qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
+
+ // Locks
+ qpoints->pLockObject = art_quick_lock_object;
+ qpoints->pUnlockObject = art_quick_unlock_object;
+
+ // Math
+ // points->pCmpgDouble = NULL; // Not needed on x86.
+ // points->pCmpgFloat = NULL; // Not needed on x86.
+ // points->pCmplDouble = NULL; // Not needed on x86.
+ // points->pCmplFloat = NULL; // Not needed on x86.
+ qpoints->pFmod = art_quick_fmod;
+ // qpoints->pSqrt = NULL; // Not needed on x86.
+ qpoints->pL2d = art_quick_l2d;
+ qpoints->pFmodf = art_quick_fmodf;
+ qpoints->pL2f = art_quick_l2f;
+ // points->pD2iz = NULL; // Not needed on x86.
+ // points->pF2iz = NULL; // Not needed on x86.
+ qpoints->pIdivmod = art_quick_idivmod;
+ qpoints->pD2l = art_quick_d2l;
+ qpoints->pF2l = art_quick_f2l;
+ qpoints->pLdiv = art_quick_ldiv;
+ qpoints->pLmod = art_quick_lmod;
+ qpoints->pLmul = art_quick_lmul;
+ qpoints->pShlLong = art_quick_lshl;
+ qpoints->pShrLong = art_quick_lshr;
+ qpoints->pUshrLong = art_quick_lushr;
+
+ // Intrinsics
+ qpoints->pIndexOf = art_quick_indexof;
+ qpoints->pMemcmp16 = art_quick_memcmp16;
+ qpoints->pStringCompareTo = art_quick_string_compareto;
+ qpoints->pMemcpy = art_quick_memcpy;
+
+ // Invocation
+ qpoints->pQuickImtConflictTrampoline = art_quick_imt_conflict_trampoline;
+ qpoints->pQuickResolutionTrampoline = art_quick_resolution_trampoline;
+ qpoints->pQuickToInterpreterBridge = art_quick_to_interpreter_bridge;
+ qpoints->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
+ qpoints->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
+ qpoints->pInvokeStaticTrampolineWithAccessCheck = art_quick_invoke_static_trampoline_with_access_check;
+ qpoints->pInvokeSuperTrampolineWithAccessCheck = art_quick_invoke_super_trampoline_with_access_check;
+ qpoints->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
+
+ // Thread
+ qpoints->pCheckSuspend = CheckSuspendFromCode;
+ qpoints->pTestSuspend = art_quick_test_suspend;
+
+ // Throws
+ 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;
+};
+
+} // namespace art
diff --git a/runtime/arch/x86_64/jni_entrypoints_x86_64.S b/runtime/arch/x86_64/jni_entrypoints_x86_64.S
new file mode 100644
index 0000000..35fcccb
--- /dev/null
+++ b/runtime/arch/x86_64/jni_entrypoints_x86_64.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 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 "asm_support_x86_64.S"
+
+ /*
+ * Jni dlsym lookup stub.
+ */
+UNIMPLEMENTED art_jni_dlsym_lookup_stub
diff --git a/runtime/arch/x86_64/portable_entrypoints_x86_64.S b/runtime/arch/x86_64/portable_entrypoints_x86_64.S
new file mode 100644
index 0000000..2e9d19a
--- /dev/null
+++ b/runtime/arch/x86_64/portable_entrypoints_x86_64.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 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 "asm_support_x86_64.S"
+
+ /*
+ * Portable invocation stub.
+ */
+UNIMPLEMENTED art_portable_invoke_stub
+
+UNIMPLEMENTED art_portable_proxy_invoke_handler
+
+UNIMPLEMENTED art_portable_resolution_trampoline
+
+UNIMPLEMENTED art_portable_to_interpreter_bridge
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
new file mode 100644
index 0000000..e01a31b
--- /dev/null
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2012 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 "asm_support_x86_64.S"
+
+// For x86, the CFA is esp+4, the address above the pushed return address on the stack.
+
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kSaveAll)
+ */
+MACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME)
+ int3
+ int3
+END_MACRO
+
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kRefsOnly)
+ */
+MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME)
+ int3
+ int3
+END_MACRO
+
+MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME)
+ int3
+ int3
+END_MACRO
+
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
+ */
+MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME)
+ int3
+ int3
+END_MACRO
+
+MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME)
+ int3
+END_MACRO
+
+ /*
+ * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
+ * exception is Thread::Current()->exception_.
+ */
+MACRO0(DELIVER_PENDING_EXCEPTION)
+ int3
+ int3
+END_MACRO
+
+MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+ /*
+ * Called by managed code to create and deliver a NullPointerException.
+ */
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
+
+ /*
+ * Called by managed code to create and deliver an ArithmeticException.
+ */
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
+
+ /*
+ * Called by managed code to create and deliver a StackOverflowError.
+ */
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
+
+ /*
+ * Called by managed code, saves callee saves and then calls artThrowException
+ * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
+ */
+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.
+ */
+TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
+
+ /*
+ * 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, load the caller's Method*, align the
+ * stack and call the appropriate C helper.
+ * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
+ *
+ * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
+ * of the target Method* in r0 and method->code_ in r1.
+ *
+ * If unsuccessful, the helper will return NULL/NULL. There will bea pending exception in the
+ * thread and we branch to another stub to deliver it.
+ *
+ * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
+ * pointing back to the original caller.
+ */
+MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline
+INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
+
+INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
+
+ /*
+ * Quick invocation stub.
+ */
+DEFINE_FUNCTION art_quick_invoke_stub
+ int3
+ int3
+END_FUNCTION art_quick_invoke_stub
+
+MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO0(RETURN_IF_RESULT_IS_NON_ZERO)
+ int3
+ testl %eax, %eax // eax == 0 ?
+ jz 1f // if eax == 0 goto 1
+ ret // return
+1: // deliver exception on current thread
+ DELIVER_PENDING_EXCEPTION
+END_MACRO
+
+MACRO0(RETURN_IF_EAX_ZERO)
+ int3
+ testl %eax, %eax // eax == 0 ?
+ jnz 1f // if eax != 0 goto 1
+ ret // return
+1: // deliver exception on current thread
+ DELIVER_PENDING_EXCEPTION
+END_MACRO
+
+MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION)
+ int3
+ int3
+ DELIVER_PENDING_EXCEPTION
+END_MACRO
+
+// Generate the allocation entrypoints for each allocator.
+// TODO: use arch/quick_alloc_entrypoints.S. Currently we don't as we need to use concatenation
+// macros to work around differences between OS/X's as and binutils as (OS/X lacks named arguments
+// to macros and the VAR macro won't concatenate arguments properly), this also breaks having
+// multi-line macros that use each other (hence using 1 macro per newline below).
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(c_suffix, cxx_suffix) \
+ TWO_ARG_DOWNCALL art_quick_alloc_object ## c_suffix, artAllocObjectFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(c_suffix, cxx_suffix) \
+ TWO_ARG_DOWNCALL art_quick_alloc_object_resolved ## c_suffix, artAllocObjectFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(c_suffix, cxx_suffix) \
+ TWO_ARG_DOWNCALL art_quick_alloc_object_initialized ## c_suffix, artAllocObjectFromCodeInitialized ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
+ TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check ## c_suffix, artAllocObjectFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_alloc_array ## c_suffix, artAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_alloc_array_resolved ## c_suffix, artAllocArrayFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check ## c_suffix, artAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_check_and_alloc_array ## c_suffix, artCheckAndAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check ## c_suffix, artCheckAndAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
+
+TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO
+
+TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
+
+DEFINE_FUNCTION art_quick_lock_object
+ int3
+ int3
+END_FUNCTION art_quick_lock_object
+
+DEFINE_FUNCTION art_quick_unlock_object
+ int3
+ int3
+END_FUNCTION art_quick_unlock_object
+
+DEFINE_FUNCTION art_quick_is_assignable
+ int3
+ int3
+END_FUNCTION art_quick_is_assignable
+
+DEFINE_FUNCTION art_quick_check_cast
+ int3
+ int3
+END_FUNCTION art_quick_check_cast
+
+ /*
+ * Entry from managed code for array put operations of objects where the value being stored
+ * needs to be checked for compatibility.
+ * eax = array, ecx = index, edx = value
+ */
+UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check
+UNIMPLEMENTED art_quick_aput_obj_with_bound_check
+UNIMPLEMENTED art_quick_aput_obj
+UNIMPLEMENTED art_quick_memcpy
+
+NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
+
+UNIMPLEMENTED art_quick_fmod
+UNIMPLEMENTED art_quick_fmodf
+UNIMPLEMENTED art_quick_l2d
+UNIMPLEMENTED art_quick_l2f
+UNIMPLEMENTED art_quick_d2l
+UNIMPLEMENTED art_quick_f2l
+UNIMPLEMENTED art_quick_idivmod
+UNIMPLEMENTED art_quick_ldiv
+UNIMPLEMENTED art_quick_lmod
+UNIMPLEMENTED art_quick_lmul
+UNIMPLEMENTED art_quick_lshl
+UNIMPLEMENTED art_quick_lshr
+UNIMPLEMENTED art_quick_lushr
+UNIMPLEMENTED art_quick_set32_instance
+UNIMPLEMENTED art_quick_set64_instance
+UNIMPLEMENTED art_quick_set_obj_instance
+UNIMPLEMENTED art_quick_get32_instance
+UNIMPLEMENTED art_quick_get64_instance
+UNIMPLEMENTED art_quick_get_obj_instance
+UNIMPLEMENTED art_quick_set32_static
+UNIMPLEMENTED art_quick_set64_static
+UNIMPLEMENTED art_quick_set_obj_static
+UNIMPLEMENTED art_quick_get32_static
+UNIMPLEMENTED art_quick_get64_static
+UNIMPLEMENTED art_quick_get_obj_static
+UNIMPLEMENTED art_quick_proxy_invoke_handler
+
+ /*
+ * Called to resolve an imt conflict.
+ */
+UNIMPLEMENTED art_quick_imt_conflict_trampoline
+UNIMPLEMENTED art_quick_resolution_trampoline
+UNIMPLEMENTED art_quick_to_interpreter_bridge
+
+ /*
+ * Routine that intercepts method calls and returns.
+ */
+UNIMPLEMENTED art_quick_instrumentation_entry
+UNIMPLEMENTED art_quick_instrumentation_exit
+
+ /*
+ * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
+ * will long jump to the upcall with a special exception of -1.
+ */
+UNIMPLEMENTED art_quick_deoptimize
+
+UNIMPLEMENTED art_quick_indexof
+UNIMPLEMENTED art_quick_string_compareto
+UNIMPLEMENTED art_quick_memcmp16
diff --git a/runtime/arch/x86_64/registers_x86_64.cc b/runtime/arch/x86_64/registers_x86_64.cc
new file mode 100644
index 0000000..38f3494
--- /dev/null
+++ b/runtime/arch/x86_64/registers_x86_64.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "registers_x86_64.h"
+
+#include <ostream>
+
+namespace art {
+namespace x86_64 {
+
+static const char* kRegisterNames[] = {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+};
+std::ostream& operator<<(std::ostream& os, const Register& rhs) {
+ if (rhs >= RAX && rhs <= R15) {
+ os << kRegisterNames[rhs];
+ } else {
+ os << "Register[" << static_cast<int>(rhs) << "]";
+ }
+ return os;
+}
+
+} // namespace x86_64
+} // namespace art
diff --git a/runtime/arch/x86_64/registers_x86_64.h b/runtime/arch/x86_64/registers_x86_64.h
new file mode 100644
index 0000000..9808d91
--- /dev/null
+++ b/runtime/arch/x86_64/registers_x86_64.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_64_REGISTERS_X86_64_H_
+#define ART_RUNTIME_ARCH_X86_64_REGISTERS_X86_64_H_
+
+#include <iosfwd>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "globals.h"
+
+namespace art {
+namespace x86_64 {
+
+enum Register {
+ RAX = 0,
+ RCX = 1,
+ RDX = 2,
+ RBX = 3,
+ RSP = 4,
+ RBP = 5,
+ RSI = 6,
+ RDI = 7,
+ R8 = 8,
+ R9 = 9,
+ R10 = 10,
+ R11 = 11,
+ R12 = 12,
+ R13 = 13,
+ R14 = 14,
+ R15 = 15,
+ kNumberOfCpuRegisters = 16,
+ kNoRegister = -1 // Signals an illegal register.
+};
+std::ostream& operator<<(std::ostream& os, const Register& rhs);
+
+} // namespace x86_64
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_X86_64_REGISTERS_X86_64_H_
diff --git a/runtime/arch/x86_64/thread_x86_64.cc b/runtime/arch/x86_64/thread_x86_64.cc
new file mode 100644
index 0000000..9e45a72
--- /dev/null
+++ b/runtime/arch/x86_64/thread_x86_64.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "thread.h"
+
+#include "asm_support_x86_64.h"
+#include "base/macros.h"
+#include "thread-inl.h"
+#include "thread_list.h"
+
+#include <asm/prctl.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+
+namespace art {
+
+static void arch_prctl(int code, void* val) {
+ syscall(__NR_arch_prctl, code, val);
+}
+void Thread::InitCpu() {
+ static Mutex modify_ldt_lock("modify_ldt lock");
+ MutexLock mu(Thread::Current(), modify_ldt_lock);
+ arch_prctl(ARCH_SET_GS, this);
+
+ // Allow easy indirection back to Thread*.
+ self_ = this;
+
+ // Sanity check that reads from %gs point to this Thread*.
+ Thread* self_check;
+ CHECK_EQ(THREAD_SELF_OFFSET, OFFSETOF_MEMBER(Thread, self_));
+ __asm__ __volatile__("movq %%gs:(%1), %0"
+ : "=r"(self_check) // output
+ : "r"(THREAD_SELF_OFFSET) // input
+ :); // clobber
+ CHECK_EQ(self_check, this);
+
+ // Sanity check other offsets.
+ CHECK_EQ(THREAD_EXCEPTION_OFFSET, OFFSETOF_MEMBER(Thread, exception_));
+ CHECK_EQ(THREAD_CARD_TABLE_OFFSET, OFFSETOF_MEMBER(Thread, card_table_));
+ CHECK_EQ(THREAD_ID_OFFSET, OFFSETOF_MEMBER(Thread, thin_lock_thread_id_));
+}
+
+void Thread::CleanupCpu() {
+ // Sanity check that reads from %gs point to this Thread*.
+ Thread* self_check;
+ CHECK_EQ(THREAD_SELF_OFFSET, OFFSETOF_MEMBER(Thread, self_));
+ __asm__ __volatile__("movq %%gs:(%1), %0"
+ : "=r"(self_check) // output
+ : "r"(THREAD_SELF_OFFSET) // input
+ :); // clobber
+ CHECK_EQ(self_check, this);
+
+ // Do nothing.
+}
+
+} // namespace art
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 06c7b53..4c42099 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -40,6 +40,7 @@
// Offsets within java.lang.Method.
#define METHOD_DEX_CACHE_METHODS_OFFSET 12
-#define METHOD_CODE_OFFSET 36
+#define METHOD_PORTABLE_CODE_OFFSET 40
+#define METHOD_QUICK_CODE_OFFSET 48
#endif // ART_RUNTIME_ASM_SUPPORT_H_
diff --git a/runtime/atomic.cc b/runtime/atomic.cc
index bac0a99..63f2cf8 100644
--- a/runtime/atomic.cc
+++ b/runtime/atomic.cc
@@ -24,7 +24,7 @@ namespace art {
std::vector<Mutex*>* QuasiAtomic::gSwapMutexes = nullptr;
Mutex* QuasiAtomic::GetSwapMutex(const volatile int64_t* addr) {
- return (*gSwapMutexes)[(reinterpret_cast<unsigned>(addr) >> 3U) % kSwapMutexCount];
+ return (*gSwapMutexes)[(reinterpret_cast<uintptr_t>(addr) >> 3U) % kSwapMutexCount];
}
void QuasiAtomic::Startup() {
diff --git a/runtime/atomic.h b/runtime/atomic.h
index b1e9870..2a47e46 100644
--- a/runtime/atomic.h
+++ b/runtime/atomic.h
@@ -26,6 +26,69 @@ namespace art {
class Mutex;
+template<typename T>
+class Atomic {
+ public:
+ Atomic<T>() : value_(0) { }
+
+ explicit Atomic<T>(T value) : value_(value) { }
+
+ Atomic<T>& operator=(T desired) {
+ Store(desired);
+ return *this;
+ }
+
+ T Load() const {
+ return value_;
+ }
+
+ operator T() const {
+ return Load();
+ }
+
+ T FetchAndAdd(const T value) {
+ return __sync_fetch_and_add(&value_, value); // Return old_value.
+ }
+
+ T FetchAndSub(const T value) {
+ return __sync_fetch_and_sub(&value_, value); // Return old value.
+ }
+
+ T operator++() { // Prefix operator.
+ return __sync_add_and_fetch(&value_, 1); // Return new value.
+ }
+
+ T operator++(int) { // Postfix operator.
+ return __sync_fetch_and_add(&value_, 1); // Return old value.
+ }
+
+ T operator--() { // Prefix operator.
+ return __sync_sub_and_fetch(&value_, 1); // Return new value.
+ }
+
+ T operator--(int) { // Postfix operator.
+ return __sync_fetch_and_sub(&value_, 1); // Return old value.
+ }
+
+ bool CompareAndSwap(T expected_value, T desired_value) {
+ return __sync_bool_compare_and_swap(&value_, expected_value, desired_value);
+ }
+
+ volatile T* Address() {
+ return &value_;
+ }
+
+ private:
+ // Unsafe = operator for non atomic operations on the integer.
+ void Store(T desired) {
+ value_ = desired;
+ }
+
+ volatile T value_;
+};
+
+typedef Atomic<int32_t> AtomicInteger;
+
// NOTE: Two "quasiatomic" operations on the exact same memory address
// are guaranteed to operate atomically with respect to each other,
// but no guarantees are made about quasiatomic operations mixed with
@@ -80,7 +143,7 @@ class QuasiAtomic {
static void MembarLoadStore() {
#if defined(__arm__)
__asm__ __volatile__("dmb ish" : : : "memory");
- #elif defined(__i386__)
+ #elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("" : : : "memory");
#elif defined(__mips__)
__asm__ __volatile__("sync" : : : "memory");
@@ -92,7 +155,7 @@ class QuasiAtomic {
static void MembarLoadLoad() {
#if defined(__arm__)
__asm__ __volatile__("dmb ish" : : : "memory");
- #elif defined(__i386__)
+ #elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("" : : : "memory");
#elif defined(__mips__)
__asm__ __volatile__("sync" : : : "memory");
@@ -104,7 +167,7 @@ class QuasiAtomic {
static void MembarStoreStore() {
#if defined(__arm__)
__asm__ __volatile__("dmb ishst" : : : "memory");
- #elif defined(__i386__)
+ #elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("" : : : "memory");
#elif defined(__mips__)
__asm__ __volatile__("sync" : : : "memory");
@@ -116,7 +179,7 @@ class QuasiAtomic {
static void MembarStoreLoad() {
#if defined(__arm__)
__asm__ __volatile__("dmb ish" : : : "memory");
- #elif defined(__i386__)
+ #elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("mfence" : : : "memory");
#elif defined(__mips__)
__asm__ __volatile__("sync" : : : "memory");
diff --git a/runtime/atomic_integer.h b/runtime/atomic_integer.h
deleted file mode 100644
index 651ca4a..0000000
--- a/runtime/atomic_integer.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2012 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_ATOMIC_INTEGER_H_
-#define ART_RUNTIME_ATOMIC_INTEGER_H_
-
-#include <stdint.h>
-
-namespace art {
-
-class AtomicInteger {
- public:
- AtomicInteger() : value_(0) { }
-
- explicit AtomicInteger(int32_t value) : value_(value) { }
-
- AtomicInteger& operator=(int32_t desired) {
- Store(desired);
- return *this;
- }
-
- int32_t Load() const {
- return value_;
- }
-
- operator int32_t() const {
- return Load();
- }
-
- int32_t FetchAndAdd(const int32_t value) {
- return __sync_fetch_and_add(&value_, value); // Return old_value.
- }
-
- int32_t FetchAndSub(const int32_t value) {
- return __sync_fetch_and_sub(&value_, value); // Return old value.
- }
-
- int32_t operator++() { // Prefix operator.
- return __sync_add_and_fetch(&value_, 1); // Return new value.
- }
-
- int32_t operator++(int32_t) { // Postfix operator.
- return __sync_fetch_and_add(&value_, 1); // Return old value.
- }
-
- int32_t operator--() { // Prefix operator.
- return __sync_sub_and_fetch(&value_, 1); // Return new value.
- }
-
- int32_t operator--(int32_t) { // Postfix operator.
- return __sync_fetch_and_sub(&value_, 1); // Return old value.
- }
-
- bool CompareAndSwap(int32_t expected_value, int32_t desired_value) {
- return __sync_bool_compare_and_swap(&value_, expected_value, desired_value);
- }
-
- volatile int32_t* Address() {
- return &value_;
- }
-
- private:
- // Unsafe = operator for non atomic operations on the integer.
- void Store(int32_t desired) {
- value_ = desired;
- }
-
- volatile int32_t value_;
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_ATOMIC_INTEGER_H_
diff --git a/runtime/barrier_test.cc b/runtime/barrier_test.cc
index 91fc143..69951c5 100644
--- a/runtime/barrier_test.cc
+++ b/runtime/barrier_test.cc
@@ -18,7 +18,7 @@
#include <string>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "common_test.h"
#include "mirror/object_array-inl.h"
#include "thread_pool.h"
diff --git a/runtime/base/bit_vector_test.cc b/runtime/base/bit_vector_test.cc
index d99d059..3fc9b86 100644
--- a/runtime/base/bit_vector_test.cc
+++ b/runtime/base/bit_vector_test.cc
@@ -25,7 +25,7 @@ TEST(BitVector, Test) {
BitVector bv(kBits, false, Allocator::GetMallocAllocator());
EXPECT_EQ(1U, bv.GetStorageSize());
- EXPECT_EQ(kWordSize, bv.GetSizeOf());
+ EXPECT_EQ(sizeof(uint32_t), bv.GetSizeOf());
EXPECT_FALSE(bv.IsExpandable());
EXPECT_EQ(0U, bv.NumSetBits());
@@ -70,7 +70,7 @@ TEST(BitVector, NoopAllocator) {
BitVector bv(0U, false, Allocator::GetNoopAllocator(), kWords, bits);
EXPECT_EQ(kWords, bv.GetStorageSize());
- EXPECT_EQ(kWords * kWordSize, bv.GetSizeOf());
+ EXPECT_EQ(kWords * sizeof(uint32_t), bv.GetSizeOf());
EXPECT_EQ(bits, bv.GetRawStorage());
EXPECT_EQ(0U, bv.NumSetBits());
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 05e3a83..ff72d16 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -47,7 +47,7 @@ static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, co
struct AllMutexData {
// A guard for all_mutexes_ that's not a mutex (Mutexes must CAS to acquire and busy wait).
- AtomicInteger all_mutexes_guard;
+ Atomic<const BaseMutex*> all_mutexes_guard;
// All created mutexes guarded by all_mutexes_guard_.
std::set<BaseMutex*>* all_mutexes;
AllMutexData() : all_mutexes(NULL) {}
@@ -57,12 +57,12 @@ static struct AllMutexData gAllMutexData[kAllMutexDataSize];
class ScopedAllMutexesLock {
public:
explicit ScopedAllMutexesLock(const BaseMutex* mutex) : mutex_(mutex) {
- while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(0, reinterpret_cast<int32_t>(mutex))) {
+ while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(0, mutex)) {
NanoSleep(100);
}
}
~ScopedAllMutexesLock() {
- while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(reinterpret_cast<int32_t>(mutex_), 0)) {
+ while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(mutex_, 0)) {
NanoSleep(100);
}
}
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 1c1dcaf..63ed6cb 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -23,7 +23,7 @@
#include <iosfwd>
#include <string>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/logging.h"
#include "base/macros.h"
#include "globals.h"
diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc
index f48c76d..87d1c06 100644
--- a/runtime/base/unix_file/fd_file.cc
+++ b/runtime/base/unix_file/fd_file.cc
@@ -102,11 +102,11 @@ bool FdFile::IsOpened() const {
return fd_ >= 0;
}
-bool FdFile::ReadFully(void* buffer, int64_t byte_count) {
+bool FdFile::ReadFully(void* buffer, size_t byte_count) {
char* ptr = static_cast<char*>(buffer);
while (byte_count > 0) {
- int bytes_read = TEMP_FAILURE_RETRY(read(fd_, ptr, byte_count));
- if (bytes_read <= 0) {
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd_, ptr, byte_count));
+ if (bytes_read == -1) {
return false;
}
byte_count -= bytes_read; // Reduce the number of remaining bytes.
@@ -115,15 +115,15 @@ bool FdFile::ReadFully(void* buffer, int64_t byte_count) {
return true;
}
-bool FdFile::WriteFully(const void* buffer, int64_t byte_count) {
+bool FdFile::WriteFully(const void* buffer, size_t byte_count) {
const char* ptr = static_cast<const char*>(buffer);
while (byte_count > 0) {
- int bytes_read = TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count));
- if (bytes_read < 0) {
+ ssize_t bytes_written = TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count));
+ if (bytes_written == -1) {
return false;
}
- byte_count -= bytes_read; // Reduce the number of remaining bytes.
- ptr += bytes_read; // Move the buffer forward.
+ byte_count -= bytes_written; // Reduce the number of remaining bytes.
+ ptr += bytes_written; // Move the buffer forward.
}
return true;
}
diff --git a/runtime/base/unix_file/fd_file.h b/runtime/base/unix_file/fd_file.h
index 19e3511..01f4ca2 100644
--- a/runtime/base/unix_file/fd_file.h
+++ b/runtime/base/unix_file/fd_file.h
@@ -61,8 +61,8 @@ class FdFile : public RandomAccessFile {
return file_path_;
}
void DisableAutoClose();
- bool ReadFully(void* buffer, int64_t byte_count);
- bool WriteFully(const void* buffer, int64_t byte_count);
+ bool ReadFully(void* buffer, size_t byte_count);
+ bool WriteFully(const void* buffer, size_t byte_count);
private:
int fd_;
diff --git a/runtime/base/unix_file/mapped_file.cc b/runtime/base/unix_file/mapped_file.cc
index b63fdd3..bc23a74 100644
--- a/runtime/base/unix_file/mapped_file.cc
+++ b/runtime/base/unix_file/mapped_file.cc
@@ -101,7 +101,8 @@ int64_t MappedFile::Read(char* buf, int64_t byte_count, int64_t offset) const {
errno = EINVAL;
return -errno;
}
- int64_t read_size = std::max(0LL, std::min(byte_count, file_size_ - offset));
+ int64_t read_size = std::max(static_cast<int64_t>(0),
+ std::min(byte_count, file_size_ - offset));
if (read_size > 0) {
memcpy(buf, data() + offset, read_size);
}
@@ -136,7 +137,8 @@ int64_t MappedFile::Write(const char* buf, int64_t byte_count, int64_t offset) {
errno = EINVAL;
return -errno;
}
- int64_t write_size = std::max(0LL, std::min(byte_count, file_size_ - offset));
+ int64_t write_size = std::max(static_cast<int64_t>(0),
+ std::min(byte_count, file_size_ - offset));
if (write_size > 0) {
memcpy(data() + offset, buf, write_size);
}
diff --git a/runtime/base/unix_file/mapped_file_test.cc b/runtime/base/unix_file/mapped_file_test.cc
index 3dda02f..49750f4 100644
--- a/runtime/base/unix_file/mapped_file_test.cc
+++ b/runtime/base/unix_file/mapped_file_test.cc
@@ -65,7 +65,7 @@ TEST_F(MappedFileTest, OpenClose) {
ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
EXPECT_GE(file.Fd(), 0);
EXPECT_TRUE(file.IsOpened());
- EXPECT_EQ(kContent.size(), file.size());
+ EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size()));
EXPECT_EQ(0, file.Close());
EXPECT_EQ(-1, file.Fd());
EXPECT_FALSE(file.IsOpened());
@@ -86,7 +86,7 @@ TEST_F(MappedFileTest, CanUseAfterMapReadOnly) {
EXPECT_FALSE(file.IsMapped());
EXPECT_TRUE(file.MapReadOnly());
EXPECT_TRUE(file.IsMapped());
- EXPECT_EQ(kContent.size(), file.size());
+ EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size()));
ASSERT_TRUE(file.data());
EXPECT_EQ(0, memcmp(kContent.c_str(), file.data(), file.size()));
EXPECT_EQ(0, file.Flush());
@@ -113,7 +113,7 @@ TEST_F(MappedFileTest, CanWriteNewData) {
ASSERT_TRUE(file.Open(new_path, MappedFile::kReadWriteMode));
EXPECT_TRUE(file.MapReadWrite(kContent.size()));
EXPECT_TRUE(file.IsMapped());
- EXPECT_EQ(kContent.size(), file.size());
+ EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size()));
ASSERT_TRUE(file.data());
memcpy(file.data(), kContent.c_str(), kContent.size());
EXPECT_EQ(0, file.Close());
@@ -200,15 +200,16 @@ TEST_F(MappedFileTest, WriteMappedReadWrite) {
// A zero-length write is a no-op.
EXPECT_EQ(0, file.Write(kContent.c_str(), 0, 0));
// But the file size is as given when mapped.
- EXPECT_EQ(kContent.size(), file.GetLength());
+ EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.GetLength()));
// Data written past the end are discarded.
EXPECT_EQ(kContent.size() - 1,
- file.Write(kContent.c_str(), kContent.size(), 1));
+ static_cast<uint64_t>(file.Write(kContent.c_str(), kContent.size(), 1)));
EXPECT_EQ(0, memcmp(kContent.c_str(), file.data() + 1, kContent.size() - 1));
// Data can be overwritten.
- EXPECT_EQ(kContent.size(), file.Write(kContent.c_str(), kContent.size(), 0));
+ EXPECT_EQ(kContent.size(),
+ static_cast<uint64_t>(file.Write(kContent.c_str(), kContent.size(), 0)));
EXPECT_EQ(0, memcmp(kContent.c_str(), file.data(), kContent.size()));
}
diff --git a/runtime/base/unix_file/null_file_test.cc b/runtime/base/unix_file/null_file_test.cc
index 0f20acd..410fdfc 100644
--- a/runtime/base/unix_file/null_file_test.cc
+++ b/runtime/base/unix_file/null_file_test.cc
@@ -48,7 +48,7 @@ TEST_F(NullFileTest, GetLength) {
NullFile f;
// The length is always 0.
ASSERT_EQ(0, f.GetLength());
- ASSERT_EQ(content.size(), f.Write(content.data(), content.size(), 0));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(f.Write(content.data(), content.size(), 0)));
ASSERT_EQ(0, f.GetLength());
}
@@ -58,8 +58,8 @@ TEST_F(NullFileTest, Write) {
// You can't write at a negative offset...
ASSERT_EQ(-EINVAL, f.Write(content.data(), content.size(), -128));
// But you can write anywhere else...
- ASSERT_EQ(content.size(), f.Write(content.data(), content.size(), 0));
- ASSERT_EQ(content.size(), f.Write(content.data(), content.size(), 128));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(f.Write(content.data(), content.size(), 0)));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(f.Write(content.data(), content.size(), 128)));
// ...though the file will remain empty.
ASSERT_EQ(0, f.GetLength());
}
diff --git a/runtime/base/unix_file/random_access_file_test.h b/runtime/base/unix_file/random_access_file_test.h
index 9d8550d..3152788 100644
--- a/runtime/base/unix_file/random_access_file_test.h
+++ b/runtime/base/unix_file/random_access_file_test.h
@@ -71,7 +71,7 @@ class RandomAccessFileTest : public testing::Test {
ASSERT_EQ(0, file->Read(buf, 123, 0));
const std::string content("hello");
- ASSERT_EQ(content.size(), file->Write(content.data(), content.size(), 0));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
TestReadContent(content, file.get());
}
@@ -83,21 +83,21 @@ class RandomAccessFileTest : public testing::Test {
ASSERT_EQ(-EINVAL, file->Read(buf.get(), 0, -123));
// Reading too much gets us just what's in the file.
- ASSERT_EQ(content.size(), file->Read(buf.get(), buf_size, 0));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Read(buf.get(), buf_size, 0)));
ASSERT_EQ(std::string(buf.get(), content.size()), content);
// We only get as much as we ask for.
const size_t short_request = 2;
ASSERT_LT(short_request, content.size());
- ASSERT_EQ(short_request, file->Read(buf.get(), short_request, 0));
+ ASSERT_EQ(short_request, static_cast<uint64_t>(file->Read(buf.get(), short_request, 0)));
ASSERT_EQ(std::string(buf.get(), short_request),
content.substr(0, short_request));
// We don't have to start at the beginning.
const int non_zero_offset = 2;
ASSERT_GT(non_zero_offset, 0);
- ASSERT_EQ(short_request,
- file->Read(buf.get(), short_request, non_zero_offset));
+ ASSERT_EQ(short_request, static_cast<uint64_t>(file->Read(buf.get(), short_request,
+ non_zero_offset)));
ASSERT_EQ(std::string(buf.get(), short_request),
content.substr(non_zero_offset, short_request));
@@ -109,8 +109,8 @@ class RandomAccessFileTest : public testing::Test {
void TestSetLength() {
const std::string content("hello");
UniquePtr<RandomAccessFile> file(MakeTestFile());
- ASSERT_EQ(content.size(), file->Write(content.data(), content.size(), 0));
- ASSERT_EQ(content.size(), file->GetLength());
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->GetLength()));
// Can't give a file a negative length.
ASSERT_EQ(-EINVAL, file->SetLength(-123));
@@ -143,20 +143,20 @@ class RandomAccessFileTest : public testing::Test {
ASSERT_EQ(0, file->GetLength());
// We can write data.
- ASSERT_EQ(content.size(), file->Write(content.data(), content.size(), 0));
- ASSERT_EQ(content.size(), file->GetLength());
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->GetLength()));
std::string new_content;
ASSERT_TRUE(ReadString(file.get(), &new_content));
ASSERT_EQ(new_content, content);
// We can read it back.
char buf[256];
- ASSERT_EQ(content.size(), file->Read(buf, sizeof(buf), 0));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Read(buf, sizeof(buf), 0)));
ASSERT_EQ(std::string(buf, content.size()), content);
// We can append data past the end.
- ASSERT_EQ(content.size(),
- file->Write(content.data(), content.size(), file->GetLength() + 1));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(),
+ file->GetLength() + 1)));
int64_t new_length = 2*content.size() + 1;
ASSERT_EQ(file->GetLength(), new_length);
ASSERT_TRUE(ReadString(file.get(), &new_content));
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 1b79ee0..960c26d 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -40,23 +40,23 @@ namespace art {
static void JniAbort(const char* jni_function_name, const char* msg) {
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
- mirror::ArtMethod* current_method = self->GetCurrentMethod(NULL);
+ mirror::ArtMethod* current_method = self->GetCurrentMethod(nullptr);
std::ostringstream os;
os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
- if (jni_function_name != NULL) {
+ if (jni_function_name != nullptr) {
os << "\n in call to " << jni_function_name;
}
// TODO: is this useful given that we're about to dump the calling thread's stack?
- if (current_method != NULL) {
+ if (current_method != nullptr) {
os << "\n from " << PrettyMethod(current_method);
}
os << "\n";
self->Dump(os);
JavaVMExt* vm = Runtime::Current()->GetJavaVM();
- if (vm->check_jni_abort_hook != NULL) {
+ if (vm->check_jni_abort_hook != nullptr) {
vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str());
} else {
// Ensure that we get a native stack trace for this thread.
@@ -118,10 +118,10 @@ static const char* gBuiltInPrefixes[] = {
"Ljavax/",
"Llibcore/",
"Lorg/apache/harmony/",
- NULL
+ nullptr
};
-static bool ShouldTrace(JavaVMExt* vm, const mirror::ArtMethod* method)
+static bool ShouldTrace(JavaVMExt* vm, mirror::ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
// when a native method that matches the -Xjnitrace argument calls a JNI function
@@ -135,7 +135,7 @@ static bool ShouldTrace(JavaVMExt* vm, const mirror::ArtMethod* method)
if (VLOG_IS_ON(third_party_jni)) {
// Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
// like part of Android.
- for (size_t i = 0; gBuiltInPrefixes[i] != NULL; ++i) {
+ for (size_t i = 0; gBuiltInPrefixes[i] != nullptr; ++i) {
if (StartsWith(class_name, gBuiltInPrefixes[i])) {
return false;
}
@@ -192,15 +192,16 @@ class ScopedCheck {
*
* Works for both static and instance fields.
*/
- void CheckFieldType(jobject java_object, jfieldID fid, char prim, bool isStatic)
+ void CheckFieldType(jvalue value, jfieldID fid, char prim, bool isStatic)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* f = CheckFieldID(fid);
- if (f == NULL) {
+ if (f == nullptr) {
return;
}
mirror::Class* field_type = FieldHelper(f).GetType();
if (!field_type->IsPrimitive()) {
- if (java_object != NULL) {
+ jobject java_object = value.l;
+ if (java_object != nullptr) {
mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
// If java_object is a weak global ref whose referent has been cleared,
// obj will be NULL. Otherwise, obj should always be non-NULL
@@ -242,7 +243,7 @@ class ScopedCheck {
void CheckInstanceFieldID(jobject java_object, jfieldID fid)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
- if (o == NULL || !Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
+ if (o == nullptr || !Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "field operation on invalid %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
@@ -250,12 +251,12 @@ class ScopedCheck {
}
mirror::ArtField* f = CheckFieldID(fid);
- if (f == NULL) {
+ if (f == nullptr) {
return;
}
mirror::Class* c = o->GetClass();
FieldHelper fh(f);
- if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == NULL) {
+ if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == nullptr) {
JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s",
PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
}
@@ -265,7 +266,7 @@ class ScopedCheck {
* Verify that the pointer value is non-NULL.
*/
void CheckNonNull(const void* ptr) {
- if (ptr == NULL) {
+ if (ptr == nullptr) {
JniAbortF(function_name_, "non-nullable argument was NULL");
}
}
@@ -277,7 +278,7 @@ class ScopedCheck {
void CheckSig(jmethodID mid, const char* expectedType, bool isStatic)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* m = CheckMethodID(mid);
- if (m == NULL) {
+ if (m == nullptr) {
return;
}
if (*expectedType != MethodHelper(m).GetShorty()[0]) {
@@ -303,8 +304,8 @@ class ScopedCheck {
void CheckStaticFieldID(jclass java_class, jfieldID fid)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
- const mirror::ArtField* f = CheckFieldID(fid);
- if (f == NULL) {
+ mirror::ArtField* f = CheckFieldID(fid);
+ if (f == nullptr) {
return;
}
if (f->GetDeclaringClass() != c) {
@@ -324,8 +325,8 @@ class ScopedCheck {
*/
void CheckStaticMethod(jclass java_class, jmethodID mid)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const mirror::ArtMethod* m = CheckMethodID(mid);
- if (m == NULL) {
+ mirror::ArtMethod* m = CheckMethodID(mid);
+ if (m == nullptr) {
return;
}
mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
@@ -344,8 +345,8 @@ class ScopedCheck {
*/
void CheckVirtualMethod(jobject java_object, jmethodID mid)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const mirror::ArtMethod* m = CheckMethodID(mid);
- if (m == NULL) {
+ mirror::ArtMethod* m = CheckMethodID(mid);
+ if (m == nullptr) {
return;
}
mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
@@ -394,17 +395,18 @@ class ScopedCheck {
void Check(bool entry, const char* fmt0, ...) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
va_list ap;
- const mirror::ArtMethod* traceMethod = NULL;
+ mirror::ArtMethod* traceMethod = nullptr;
if (has_method_ && (!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni))) {
// We need to guard some of the invocation interface's calls: a bad caller might
// use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Thread* self = Thread::Current();
- if ((flags_ & kFlag_Invocation) == 0 || self != NULL) {
- traceMethod = self->GetCurrentMethod(NULL);
+ if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
+ traceMethod = self->GetCurrentMethod(nullptr);
}
}
- if (((flags_ & kFlag_ForceTrace) != 0) || (traceMethod != NULL && ShouldTrace(soa_.Vm(), traceMethod))) {
+ if (((flags_ & kFlag_ForceTrace) != 0) ||
+ (traceMethod != nullptr && ShouldTrace(soa_.Vm(), traceMethod))) {
va_start(ap, fmt0);
std::string msg;
for (const char* fmt = fmt0; *fmt;) {
@@ -428,7 +430,7 @@ class ScopedCheck {
} else if (ch == 'I' || ch == 'S') { // jint, jshort
StringAppendF(&msg, "%d", va_arg(ap, int));
} else if (ch == 'J') { // jlong
- StringAppendF(&msg, "%lld", va_arg(ap, jlong));
+ StringAppendF(&msg, "%" PRId64, va_arg(ap, jlong));
} else if (ch == 'Z') { // jboolean
StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
} else if (ch == 'V') { // void
@@ -442,7 +444,7 @@ class ScopedCheck {
} else if (ch == 'L' || ch == 'a' || ch == 's') { // jobject, jarray, jstring
// For logging purposes, these are identical.
jobject o = va_arg(ap, jobject);
- if (o == NULL) {
+ if (o == nullptr) {
msg += "NULL";
} else {
StringAppendF(&msg, "%p", o);
@@ -453,7 +455,7 @@ class ScopedCheck {
} else if (ch == 'c') { // jclass
jclass jc = va_arg(ap, jclass);
mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc));
- if (c == NULL) {
+ if (c == nullptr) {
msg += "NULL";
} else if (c == kInvalidIndirectRefObject ||
!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
@@ -488,7 +490,7 @@ class ScopedCheck {
}
} else if (ch == 'p') { // void* ("pointer")
void* p = va_arg(ap, void*);
- if (p == NULL) {
+ if (p == nullptr) {
msg += "NULL";
} else {
StringAppendF(&msg, "(void*) %p", p);
@@ -506,7 +508,7 @@ class ScopedCheck {
}
} else if (ch == 'u') { // const char* (Modified UTF-8)
const char* utf = va_arg(ap, const char*);
- if (utf == NULL) {
+ if (utf == nullptr) {
msg += "NULL";
} else {
StringAppendF(&msg, "\"%s\"", utf);
@@ -563,7 +565,7 @@ class ScopedCheck {
}
} else if (ch == 'z') {
CheckLengthPositive(va_arg(ap, jsize));
- } else if (strchr("BCISZbfmpEv", ch) != NULL) {
+ } else if (strchr("BCISZbfmpEv", ch) != nullptr) {
va_arg(ap, uint32_t); // Skip this argument.
} else if (ch == 'D' || ch == 'F') {
va_arg(ap, double); // Skip this argument.
@@ -595,7 +597,7 @@ class ScopedCheck {
*/
bool CheckInstance(InstanceKind kind, jobject java_object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const char* what = NULL;
+ const char* what = nullptr;
switch (kind) {
case kClass:
what = "jclass";
@@ -616,7 +618,7 @@ class ScopedCheck {
LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
}
- if (java_object == NULL) {
+ if (java_object == nullptr) {
JniAbortF(function_name_, "%s received null %s", function_name_, what);
return false;
}
@@ -670,7 +672,7 @@ class ScopedCheck {
* Since we're dealing with objects, switch to "running" mode.
*/
void CheckArray(jarray java_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (java_array == NULL) {
+ if (java_array == nullptr) {
JniAbortF(function_name_, "jarray was NULL");
return;
}
@@ -692,29 +694,29 @@ class ScopedCheck {
}
mirror::ArtField* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (fid == NULL) {
+ if (fid == nullptr) {
JniAbortF(function_name_, "jfieldID was NULL");
- return NULL;
+ return nullptr;
}
mirror::ArtField* f = soa_.DecodeField(fid);
if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "invalid jfieldID: %p", fid);
- return NULL;
+ return nullptr;
}
return f;
}
mirror::ArtMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (mid == NULL) {
+ if (mid == nullptr) {
JniAbortF(function_name_, "jmethodID was NULL");
- return NULL;
+ return nullptr;
}
mirror::ArtMethod* m = soa_.DecodeMethod(mid);
if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "invalid jmethodID: %p", mid);
- return NULL;
+ return nullptr;
}
return m;
}
@@ -727,7 +729,7 @@ class ScopedCheck {
*/
void CheckObject(jobject java_object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (java_object == NULL) {
+ if (java_object == nullptr) {
return;
}
@@ -752,7 +754,7 @@ class ScopedCheck {
void CheckThread(int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Thread* self = Thread::Current();
- if (self == NULL) {
+ if (self == nullptr) {
JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid());
return;
}
@@ -813,7 +815,7 @@ class ScopedCheck {
// Verifies that "bytes" points to valid Modified UTF-8 data.
void CheckUtfString(const char* bytes, bool nullable) {
- if (bytes == NULL) {
+ if (bytes == nullptr) {
if (!nullable) {
JniAbortF(function_name_, "non-nullable const char* was NULL");
return;
@@ -821,9 +823,9 @@ class ScopedCheck {
return;
}
- const char* errorKind = NULL;
+ const char* errorKind = nullptr;
uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
- if (errorKind != NULL) {
+ if (errorKind != nullptr) {
JniAbortF(function_name_,
"input is not valid Modified UTF-8: illegal %s byte %#x\n"
" string: '%s'", errorKind, utf8, bytes);
@@ -998,7 +1000,7 @@ struct GuardedCopy {
const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf);
for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
if (pat[i] != kGuardPattern) {
- JniAbortF(functionName, "guard pattern(1) disturbed at %p +%d", fullBuf, i*2);
+ JniAbortF(functionName, "guard pattern(1) disturbed at %p +%zd", fullBuf, i*2);
}
}
@@ -1018,7 +1020,7 @@ struct GuardedCopy {
pat = reinterpret_cast<const uint16_t*>(fullBuf + offset);
for (size_t i = 0; i < kGuardLen / 4; i++) {
if (pat[i] != kGuardPattern) {
- JniAbortF(functionName, "guard pattern(2) disturbed at %p +%d", fullBuf, offset + i*2);
+ JniAbortF(functionName, "guard pattern(2) disturbed at %p +%zd", fullBuf, offset + i*2);
}
}
@@ -1037,7 +1039,7 @@ struct GuardedCopy {
private:
static uint8_t* DebugAlloc(size_t len) {
- void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+ void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
if (result == MAP_FAILED) {
PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
}
@@ -1081,8 +1083,8 @@ static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean*
mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
size_t component_size = a->GetClass()->GetComponentSize();
size_t byte_count = a->GetLength() * component_size;
- void* result = GuardedCopy::Create(a->GetRawData(component_size), byte_count, true);
- if (isCopy != NULL) {
+ void* result = GuardedCopy::Create(a->GetRawData(component_size, 0), byte_count, true);
+ if (isCopy != nullptr) {
*isCopy = JNI_TRUE;
}
return result;
@@ -1100,7 +1102,7 @@ static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf,
if (mode != JNI_ABORT) {
size_t len = GuardedCopy::FromData(dataBuf)->original_length;
- memcpy(a->GetRawData(a->GetClass()->GetComponentSize()), dataBuf, len);
+ memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), dataBuf, len);
}
if (mode != JNI_COMMIT) {
GuardedCopy::Destroy(dataBuf);
@@ -1223,7 +1225,7 @@ class CheckJNI {
static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
- if (globalRef != NULL && GetIndirectRefKind(globalRef) != kGlobal) {
+ if (globalRef != nullptr && GetIndirectRefKind(globalRef) != kGlobal) {
JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef);
} else {
@@ -1234,7 +1236,7 @@ class CheckJNI {
static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
- if (weakGlobalRef != NULL && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
+ if (weakGlobalRef != nullptr && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef);
} else {
@@ -1245,7 +1247,7 @@ class CheckJNI {
static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
- if (localRef != NULL && GetIndirectRefKind(localRef) != kLocal && !IsSirtLocalRef(env, localRef)) {
+ if (localRef != nullptr && GetIndirectRefKind(localRef) != kLocal && !IsSirtLocalRef(env, localRef)) {
JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef);
} else {
@@ -1318,7 +1320,7 @@ class CheckJNI {
return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig));
}
-#define FIELD_ACCESSORS(_ctype, _jname, _type) \
+#define FIELD_ACCESSORS(_ctype, _jname, _jvalue_type, _type) \
static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \
CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \
sc.CheckStaticFieldID(c, fid); \
@@ -1333,7 +1335,9 @@ class CheckJNI {
CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \
sc.CheckStaticFieldID(c, fid); \
/* "value" arg only used when type == ref */ \
- sc.CheckFieldType((jobject)(uint32_t)value, fid, _type[0], true); \
+ jvalue java_type_value; \
+ java_type_value._jvalue_type = value; \
+ sc.CheckFieldType(java_type_value, fid, _type[0], true); \
baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \
CHECK_JNI_EXIT_VOID(); \
} \
@@ -1341,20 +1345,22 @@ class CheckJNI {
CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
sc.CheckInstanceFieldID(obj, fid); \
/* "value" arg only used when type == ref */ \
- sc.CheckFieldType((jobject)(uint32_t) value, fid, _type[0], false); \
+ jvalue java_type_value; \
+ java_type_value._jvalue_type = value; \
+ sc.CheckFieldType(java_type_value, fid, _type[0], false); \
baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
CHECK_JNI_EXIT_VOID(); \
}
-FIELD_ACCESSORS(jobject, Object, "L");
-FIELD_ACCESSORS(jboolean, Boolean, "Z");
-FIELD_ACCESSORS(jbyte, Byte, "B");
-FIELD_ACCESSORS(jchar, Char, "C");
-FIELD_ACCESSORS(jshort, Short, "S");
-FIELD_ACCESSORS(jint, Int, "I");
-FIELD_ACCESSORS(jlong, Long, "J");
-FIELD_ACCESSORS(jfloat, Float, "F");
-FIELD_ACCESSORS(jdouble, Double, "D");
+FIELD_ACCESSORS(jobject, Object, l, "L");
+FIELD_ACCESSORS(jboolean, Boolean, z, "Z");
+FIELD_ACCESSORS(jbyte, Byte, b, "B");
+FIELD_ACCESSORS(jchar, Char, c, "C");
+FIELD_ACCESSORS(jshort, Short, s, "S");
+FIELD_ACCESSORS(jint, Int, i, "I");
+FIELD_ACCESSORS(jlong, Long, j, "J");
+FIELD_ACCESSORS(jfloat, Float, f, "F");
+FIELD_ACCESSORS(jdouble, Double, d, "D");
#define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
/* Virtual... */ \
@@ -1484,11 +1490,11 @@ CALL(void, Void, , , VOID_RETURN, "V");
static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
- if (sc.ForceCopy() && result != NULL) {
+ if (sc.ForceCopy() && result != nullptr) {
mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
int byteCount = s->GetLength() * 2;
result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
- if (isCopy != NULL) {
+ if (isCopy != nullptr) {
*isCopy = JNI_TRUE;
}
}
@@ -1519,9 +1525,9 @@ CALL(void, Void, , , VOID_RETURN, "V");
static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
- if (sc.ForceCopy() && result != NULL) {
+ if (sc.ForceCopy() && result != nullptr) {
result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false);
- if (isCopy != NULL) {
+ if (isCopy != nullptr) {
*isCopy = JNI_TRUE;
}
}
@@ -1578,7 +1584,7 @@ struct ForceCopyGetChecker {
ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
force_copy = sc.ForceCopy();
no_copy = 0;
- if (force_copy && isCopy != NULL) {
+ if (force_copy && isCopy != nullptr) {
// Capture this before the base call tramples on it.
no_copy = *reinterpret_cast<uint32_t*>(isCopy);
}
@@ -1586,7 +1592,7 @@ struct ForceCopyGetChecker {
template<typename ResultT>
ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
- if (force_copy && result != NULL) {
+ if (force_copy && result != nullptr) {
result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
}
return result;
@@ -1690,7 +1696,7 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
- if (sc.ForceCopy() && result != NULL) {
+ if (sc.ForceCopy() && result != nullptr) {
result = CreateGuardedPACopy(env, array, isCopy);
}
return CHECK_JNI_EXIT("p", result);
@@ -1709,11 +1715,11 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
- if (sc.ForceCopy() && result != NULL) {
+ if (sc.ForceCopy() && result != nullptr) {
mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
int byteCount = s->GetLength() * 2;
result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
- if (isCopy != NULL) {
+ if (isCopy != nullptr) {
*isCopy = JNI_TRUE;
}
}
@@ -1751,11 +1757,11 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
- if (address == NULL) {
+ if (address == nullptr) {
JniAbortF(__FUNCTION__, "non-nullable address is NULL");
}
if (capacity < 0) {
- JniAbortF(__FUNCTION__, "capacity must be non-negative: %lld", capacity);
+ JniAbortF(__FUNCTION__, "capacity must be non-negative: %" PRId64, capacity);
}
return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
}
@@ -1779,10 +1785,10 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
};
const JNINativeInterface gCheckNativeInterface = {
- NULL, // reserved0.
- NULL, // reserved1.
- NULL, // reserved2.
- NULL, // reserved3.
+ nullptr, // reserved0.
+ nullptr, // reserved1.
+ nullptr, // reserved2.
+ nullptr, // reserved3.
CheckJNI::GetVersion,
CheckJNI::DefineClass,
CheckJNI::FindClass,
@@ -2057,9 +2063,9 @@ class CheckJII {
};
const JNIInvokeInterface gCheckInvokeInterface = {
- NULL, // reserved0
- NULL, // reserved1
- NULL, // reserved2
+ nullptr, // reserved0
+ nullptr, // reserved1
+ nullptr, // reserved2
CheckJII::DestroyJavaVM,
CheckJII::AttachCurrentThread,
CheckJII::DetachCurrentThread,
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 0436435..66c24b5 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -28,7 +28,7 @@
namespace art {
inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx,
- const mirror::ArtMethod* referrer) {
+ mirror::ArtMethod* referrer) {
mirror::String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx);
if (UNLIKELY(resolved_string == NULL)) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
@@ -40,7 +40,7 @@ inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx,
}
inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx,
- const mirror::ArtMethod* referrer) {
+ mirror::ArtMethod* referrer) {
mirror::Class* resolved_type = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
if (UNLIKELY(resolved_type == NULL)) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
@@ -53,7 +53,7 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx,
return resolved_type;
}
-inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, const mirror::ArtField* referrer) {
+inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, mirror::ArtField* referrer) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache();
mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx);
@@ -68,7 +68,7 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, const mirror::
}
inline mirror::ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
InvokeType type) {
mirror::ArtMethod* resolved_method =
referrer->GetDexCacheResolvedMethods()->Get(method_idx);
@@ -84,7 +84,7 @@ inline mirror::ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
}
inline mirror::ArtField* ClassLinker::ResolveField(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
bool is_static) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
mirror::ArtField* resolved_field =
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f1f5905..978c99b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -712,11 +712,11 @@ const DexFile* ClassLinker::FindDexFileInOatLocation(const char* dex_location,
return nullptr;
}
- uint32_t expected_image_oat_offset = reinterpret_cast<uint32_t>(image_header.GetOatDataBegin());
+ uintptr_t expected_image_oat_offset = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin());
uint32_t actual_image_oat_offset = oat_file->GetOatHeader().GetImageFileLocationOatDataBegin();
if (expected_image_oat_offset != actual_image_oat_offset) {
- *error_msg = StringPrintf("Failed to find oat file at '%s' with expected image oat offset %ud, "
- "found %ud", oat_location, expected_image_oat_offset,
+ *error_msg = StringPrintf("Failed to find oat file at '%s' with expected image oat offset %"
+ PRIuPTR ", found %ud", oat_location, expected_image_oat_offset,
actual_image_oat_offset);
return nullptr;
}
@@ -858,7 +858,7 @@ bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
Runtime* runtime = Runtime::Current();
const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
uint32_t image_oat_checksum = image_header.GetOatChecksum();
- uint32_t image_oat_data_begin = reinterpret_cast<uint32_t>(image_header.GetOatDataBegin());
+ uintptr_t image_oat_data_begin = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin());
bool image_check = ((oat_file->GetOatHeader().GetImageFileLocationOatChecksum() == image_oat_checksum)
&& (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin() == image_oat_data_begin));
@@ -885,7 +885,7 @@ bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
ScopedObjectAccess soa(Thread::Current());
mirror::String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString();
std::string image_file(oat_location->ToModifiedUtf8());
- *error_msg = StringPrintf("oat file '%s' mismatch (0x%x, %d) with '%s' (0x%x, %d)",
+ *error_msg = StringPrintf("oat file '%s' mismatch (0x%x, %d) with '%s' (0x%x, %" PRIdPTR ")",
oat_file->GetLocation().c_str(),
oat_file->GetOatHeader().GetImageFileLocationOatChecksum(),
oat_file->GetOatHeader().GetImageFileLocationOatDataBegin(),
@@ -1023,7 +1023,8 @@ static void InitFromImageInterpretOnlyCallback(mirror::Object* obj, void* arg)
if (!method->IsNative()) {
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
if (method != Runtime::Current()->GetResolutionMethod()) {
- method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToInterpreterBridge());
}
}
}
@@ -1572,7 +1573,7 @@ static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16
return 0;
}
-const OatFile::OatMethod ClassLinker::GetOatMethodFor(const mirror::ArtMethod* method) {
+const OatFile::OatMethod ClassLinker::GetOatMethodFor(mirror::ArtMethod* method) {
// Although we overwrite the trampoline of non-static methods, we may get here via the resolution
// method for direct methods (or virtual methods made direct).
mirror::Class* declaring_class = method->GetDeclaringClass();
@@ -1608,35 +1609,68 @@ const OatFile::OatMethod ClassLinker::GetOatMethodFor(const mirror::ArtMethod* m
}
// Special case to get oat code without overwriting a trampoline.
-const void* ClassLinker::GetOatCodeFor(const mirror::ArtMethod* method) {
+const void* ClassLinker::GetQuickOatCodeFor(mirror::ArtMethod* method) {
CHECK(!method->IsAbstract()) << PrettyMethod(method);
if (method->IsProxyMethod()) {
-#if !defined(ART_USE_PORTABLE_COMPILER)
- return reinterpret_cast<void*>(art_quick_proxy_invoke_handler);
-#else
- return reinterpret_cast<void*>(art_portable_proxy_invoke_handler);
-#endif
+ return GetQuickProxyInvokeHandler();
+ }
+ const void* result = GetOatMethodFor(method).GetQuickCode();
+ if (result == nullptr) {
+ if (method->IsPortableCompiled()) {
+ // No code? Do we expect portable code?
+ result = GetQuickToPortableBridge();
+ } else {
+ // No code? You must mean to go into the interpreter.
+ result = GetQuickToInterpreterBridge();
+ }
}
- const void* result = GetOatMethodFor(method).GetCode();
- if (result == NULL) {
- // No code? You must mean to go into the interpreter.
- result = GetCompiledCodeToInterpreterBridge();
+ return result;
+}
+
+const void* ClassLinker::GetPortableOatCodeFor(mirror::ArtMethod* method,
+ bool* have_portable_code) {
+ CHECK(!method->IsAbstract()) << PrettyMethod(method);
+ *have_portable_code = false;
+ if (method->IsProxyMethod()) {
+ return GetPortableProxyInvokeHandler();
+ }
+ const void* result = GetOatMethodFor(method).GetPortableCode();
+ if (result == nullptr) {
+ if (GetOatMethodFor(method).GetQuickCode() == nullptr) {
+ // No code? You must mean to go into the interpreter.
+ result = GetPortableToInterpreterBridge();
+ } else {
+ // No code? But there's quick code, so use a bridge.
+ result = GetPortableToQuickBridge();
+ }
+ } else {
+ *have_portable_code = true;
}
return result;
}
-const void* ClassLinker::GetOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
- uint32_t method_idx) {
+const void* ClassLinker::GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
+ uint32_t method_idx) {
UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, class_def_idx));
CHECK(oat_class.get() != nullptr);
uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx);
- return oat_class->GetOatMethod(oat_method_idx).GetCode();
+ return oat_class->GetOatMethod(oat_method_idx).GetQuickCode();
+}
+
+const void* ClassLinker::GetPortableOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
+ uint32_t method_idx) {
+ UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, class_def_idx));
+ CHECK(oat_class.get() != nullptr);
+ uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx);
+ return oat_class->GetOatMethod(oat_method_idx).GetPortableCode();
}
// Returns true if the method must run with interpreter, false otherwise.
-static bool NeedsInterpreter(const mirror::ArtMethod* method, const void* code) {
- if (code == NULL) {
+static bool NeedsInterpreter(mirror::ArtMethod* method, const void* quick_code,
+ const void* portable_code) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if ((quick_code == nullptr) && (portable_code == nullptr)) {
// No code: need interpreter.
+ DCHECK(!method->IsNative());
return true;
}
#ifdef ART_SEA_IR_MODE
@@ -1684,13 +1718,26 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
// Only update static methods.
continue;
}
- const void* code = oat_class->GetOatMethod(method_index).GetCode();
- const bool enter_interpreter = NeedsInterpreter(method, code);
+ const void* portable_code = oat_class->GetOatMethod(method_index).GetPortableCode();
+ const void* quick_code = oat_class->GetOatMethod(method_index).GetQuickCode();
+ const bool enter_interpreter = NeedsInterpreter(method, quick_code, portable_code);
+ bool have_portable_code = false;
if (enter_interpreter) {
// Use interpreter entry point.
- code = GetCompiledCodeToInterpreterBridge();
+ portable_code = GetPortableToInterpreterBridge();
+ quick_code = GetQuickToInterpreterBridge();
+ } else {
+ if (portable_code == nullptr) {
+ portable_code = GetPortableToQuickBridge();
+ } else {
+ have_portable_code = true;
+ }
+ if (quick_code == nullptr) {
+ quick_code = GetQuickToPortableBridge();
+ }
}
- runtime->GetInstrumentation()->UpdateMethodsCode(method, code);
+ runtime->GetInstrumentation()->UpdateMethodsCode(method, quick_code, portable_code,
+ have_portable_code);
}
// Ignore virtual methods on the iterator.
}
@@ -1699,7 +1746,8 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
uint32_t method_index)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Method shouldn't have already been linked.
- DCHECK(method->GetEntryPointFromCompiledCode() == NULL);
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
+ DCHECK(method->GetEntryPointFromPortableCompiledCode() == nullptr);
// Every kind of method should at least get an invoke stub from the oat_method.
// non-abstract methods also get their code pointers.
const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
@@ -1707,7 +1755,9 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
// Install entry point from interpreter.
Runtime* runtime = Runtime::Current();
- bool enter_interpreter = NeedsInterpreter(method.get(), method->GetEntryPointFromCompiledCode());
+ bool enter_interpreter = NeedsInterpreter(method.get(),
+ method->GetEntryPointFromQuickCompiledCode(),
+ method->GetEntryPointFromPortableCompiledCode());
if (enter_interpreter) {
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
} else {
@@ -1715,18 +1765,29 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
}
if (method->IsAbstract()) {
- method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToInterpreterBridge());
return;
}
+ bool have_portable_code = false;
if (method->IsStatic() && !method->IsConstructor()) {
// For static methods excluding the class initializer, install the trampoline.
// It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines
// after initializing class (see ClassLinker::InitializeClass method).
- method->SetEntryPointFromCompiledCode(GetResolutionTrampoline(runtime->GetClassLinker()));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline(runtime->GetClassLinker()));
+ method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline(runtime->GetClassLinker()));
} else if (enter_interpreter) {
// Set entry point from compiled code if there's no code or in interpreter only mode.
- method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToInterpreterBridge());
+ } else if (method->GetEntryPointFromPortableCompiledCode() != nullptr) {
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
+ have_portable_code = true;
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToPortableBridge());
+ } else {
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() != nullptr);
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToQuickBridge());
}
if (method->IsNative()) {
@@ -1736,7 +1797,9 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
// Allow instrumentation its chance to hijack code.
runtime->GetInstrumentation()->UpdateMethodsCode(method.get(),
- method->GetEntryPointFromCompiledCode());
+ method->GetEntryPointFromQuickCompiledCode(),
+ method->GetEntryPointFromPortableCompiledCode(),
+ have_portable_code);
}
void ClassLinker::LoadClass(const DexFile& dex_file,
@@ -2803,15 +2866,15 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccess& soa, jstring na
return klass.get();
}
-std::string ClassLinker::GetDescriptorForProxy(const mirror::Class* proxy_class) {
+std::string ClassLinker::GetDescriptorForProxy(mirror::Class* proxy_class) {
DCHECK(proxy_class->IsProxyClass());
mirror::String* name = proxy_class->GetName();
DCHECK(name != NULL);
return DotToDescriptor(name->ToModifiedUtf8().c_str());
}
-mirror::ArtMethod* ClassLinker::FindMethodForProxy(const mirror::Class* proxy_class,
- const mirror::ArtMethod* proxy_method) {
+mirror::ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class,
+ mirror::ArtMethod* proxy_method) {
DCHECK(proxy_class->IsProxyClass());
DCHECK(proxy_method->IsProxyMethod());
// Locate the dex cache of the original interface/Object
@@ -2892,7 +2955,8 @@ mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self,
method->SetCoreSpillMask(refs_and_args->GetCoreSpillMask());
method->SetFpSpillMask(refs_and_args->GetFpSpillMask());
method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes());
- method->SetEntryPointFromCompiledCode(GetProxyInvokeHandler());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableProxyInvokeHandler());
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
return method;
@@ -3175,7 +3239,7 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& kl
klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
SirtRef<mirror::Class> super(self, klass->GetSuperClass());
for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) {
- const mirror::ArtMethod* method = klass->GetVTable()->Get(i);
+ mirror::ArtMethod* method = klass->GetVTable()->Get(i);
if (method != super->GetVTable()->Get(i) &&
!IsSameMethodSignatureInDifferentClassContexts(method, super.get(), klass.get())) {
ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in superclass %s",
@@ -3189,7 +3253,7 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& kl
SirtRef<mirror::Class> interface(self, klass->GetIfTable()->GetInterface(i));
if (klass->GetClassLoader() != interface->GetClassLoader()) {
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
- const mirror::ArtMethod* method = klass->GetIfTable()->GetMethodArray(i)->Get(j);
+ mirror::ArtMethod* method = klass->GetIfTable()->GetMethodArray(i)->Get(j);
if (!IsSameMethodSignatureInDifferentClassContexts(method, interface.get(),
method->GetDeclaringClass())) {
ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in interface %s",
@@ -3206,9 +3270,9 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& kl
// Returns true if classes referenced by the signature of the method are the
// same classes in klass1 as they are in klass2.
-bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const mirror::ArtMethod* method,
- const mirror::Class* klass1,
- const mirror::Class* klass2) {
+bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMethod* method,
+ mirror::Class* klass1,
+ mirror::Class* klass2) {
if (klass1 == klass2) {
return true;
}
@@ -3790,23 +3854,24 @@ struct LinkFieldsComparator {
explicit LinkFieldsComparator() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
}
// No thread safety analysis as will be called from STL. Checked lock held in constructor.
- bool operator()(const mirror::ArtField* field1, const mirror::ArtField* field2)
+ bool operator()(mirror::ArtField* field1, mirror::ArtField* field2)
NO_THREAD_SAFETY_ANALYSIS {
// First come reference fields, then 64-bit, and finally 32-bit
FieldHelper fh1(field1);
Primitive::Type type1 = fh1.GetTypeAsPrimitiveType();
FieldHelper fh2(field2);
Primitive::Type type2 = fh2.GetTypeAsPrimitiveType();
- bool isPrimitive1 = type1 != Primitive::kPrimNot;
- bool isPrimitive2 = type2 != Primitive::kPrimNot;
- bool is64bit1 = isPrimitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
- bool is64bit2 = isPrimitive2 && (type2 == Primitive::kPrimLong || type2 == Primitive::kPrimDouble);
- int order1 = (!isPrimitive1 ? 0 : (is64bit1 ? 1 : 2));
- int order2 = (!isPrimitive2 ? 0 : (is64bit2 ? 1 : 2));
- if (order1 != order2) {
- return order1 < order2;
+ if (type1 != type2) {
+ bool is_primitive1 = type1 != Primitive::kPrimNot;
+ bool is_primitive2 = type2 != Primitive::kPrimNot;
+ bool is64bit1 = is_primitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
+ bool is64bit2 = is_primitive2 && (type2 == Primitive::kPrimLong || type2 == Primitive::kPrimDouble);
+ int order1 = !is_primitive1 ? 0 : (is64bit1 ? 1 : 2);
+ int order2 = !is_primitive2 ? 0 : (is64bit2 ? 1 : 2);
+ if (order1 != order2) {
+ return order1 < order2;
+ }
}
-
// same basic group? then sort by string.
const char* name1 = fh1.GetName();
const char* name2 = fh2.GetName();
@@ -3996,14 +4061,14 @@ void ClassLinker::CreateReferenceOffsets(const SirtRef<mirror::Class>& klass, bo
size_t num_reference_fields =
is_static ? klass->NumReferenceStaticFieldsDuringLinking()
: klass->NumReferenceInstanceFieldsDuringLinking();
- const mirror::ObjectArray<mirror::ArtField>* fields =
+ mirror::ObjectArray<mirror::ArtField>* fields =
is_static ? klass->GetSFields() : klass->GetIFields();
// All of the fields that contain object references are guaranteed
// to be at the beginning of the fields list.
for (size_t i = 0; i < num_reference_fields; ++i) {
// Note that byte_offset is the offset from the beginning of
// object, not the offset into instance data
- const mirror::ArtField* field = fields->Get(i);
+ mirror::ArtField* field = fields->Get(i);
MemberOffset byte_offset = field->GetOffsetDuringLinking();
CHECK_EQ(byte_offset.Uint32Value() & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
if (CLASS_CAN_ENCODE_OFFSET(byte_offset.Uint32Value())) {
@@ -4038,7 +4103,7 @@ mirror::String* ClassLinker::ResolveString(const DexFile& dex_file, uint32_t str
}
mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_idx,
- const mirror::Class* referrer) {
+ mirror::Class* referrer) {
Thread* self = Thread::Current();
SirtRef<mirror::DexCache> dex_cache(self, referrer->GetDexCache());
SirtRef<mirror::ClassLoader> class_loader(self, referrer->GetClassLoader());
@@ -4081,7 +4146,7 @@ mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
uint32_t method_idx,
const SirtRef<mirror::DexCache>& dex_cache,
const SirtRef<mirror::ClassLoader>& class_loader,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
InvokeType type) {
DCHECK(dex_cache.get() != NULL);
// Check for hit in the dex cache.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 8722de3..7e31356 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -121,7 +121,7 @@ class ClassLinker {
// Resolve a String with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identify the
// target DexCache and ClassLoader to use for resolution.
- mirror::String* ResolveString(uint32_t string_idx, const mirror::ArtMethod* referrer)
+ mirror::String* ResolveString(uint32_t string_idx, mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Resolve a String with the given index from the DexFile, storing the
@@ -133,17 +133,16 @@ class ClassLinker {
// Resolve a Type with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identity the
// target DexCache and ClassLoader to use for resolution.
- mirror::Class* ResolveType(const DexFile& dex_file, uint16_t type_idx,
- const mirror::Class* referrer)
+ mirror::Class* ResolveType(const DexFile& dex_file, uint16_t type_idx, mirror::Class* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Resolve a Type with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identify the
// target DexCache and ClassLoader to use for resolution.
- mirror::Class* ResolveType(uint16_t type_idx, const mirror::ArtMethod* referrer)
+ mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::Class* ResolveType(uint16_t type_idx, const mirror::ArtField* referrer)
+ mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtField* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Resolve a type with the given ID from the DexFile, storing the
@@ -164,15 +163,15 @@ class ClassLinker {
uint32_t method_idx,
const SirtRef<mirror::DexCache>& dex_cache,
const SirtRef<mirror::ClassLoader>& class_loader,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtMethod* ResolveMethod(uint32_t method_idx, const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* ResolveMethod(uint32_t method_idx, mirror::ArtMethod* referrer,
InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtField* ResolveField(uint32_t field_idx, const mirror::ArtMethod* referrer,
+ mirror::ArtField* ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer,
bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -319,19 +318,23 @@ class ClassLinker {
mirror::Class* CreateProxyClass(ScopedObjectAccess& soa, jstring name, jobjectArray interfaces,
jobject loader, jobjectArray methods, jobjectArray throws)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- std::string GetDescriptorForProxy(const mirror::Class* proxy_class)
+ std::string GetDescriptorForProxy(mirror::Class* proxy_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtMethod* FindMethodForProxy(const mirror::Class* proxy_class,
- const mirror::ArtMethod* proxy_method)
+ mirror::ArtMethod* FindMethodForProxy(mirror::Class* proxy_class,
+ mirror::ArtMethod* proxy_method)
LOCKS_EXCLUDED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get the oat code for a method when its class isn't yet initialized
- const void* GetOatCodeFor(const mirror::ArtMethod* method)
+ const void* GetQuickOatCodeFor(mirror::ArtMethod* method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const void* GetPortableOatCodeFor(mirror::ArtMethod* method, bool* have_portable_code)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get the oat code for a method from a method index.
- const void* GetOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
+ const void* GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const void* GetPortableOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
pid_t GetClassesLockOwner(); // For SignalCatcher.
@@ -368,7 +371,7 @@ class ClassLinker {
mirror::ArtMethod* AllocArtMethod(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
- const OatFile::OatMethod GetOatMethodFor(const mirror::ArtMethod* method)
+ const OatFile::OatMethod GetOatMethodFor(mirror::ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
OatFile& GetImageOatFile(gc::space::ImageSpace* space)
@@ -451,9 +454,9 @@ class ClassLinker {
SirtRef<mirror::ClassLoader>& class_loader2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSameMethodSignatureInDifferentClassContexts(const mirror::ArtMethod* method,
- const mirror::Class* klass1,
- const mirror::Class* klass2)
+ bool IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMethod* method,
+ mirror::Class* klass1,
+ mirror::Class* klass2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool LinkClass(Thread* self, const SirtRef<mirror::Class>& klass,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 1744050..fb979c2 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -55,7 +55,7 @@ class ClassLinkerTest : public CommonTest {
AssertPrimitiveClass(descriptor, class_linker_->FindSystemClass(descriptor.c_str()));
}
- void AssertPrimitiveClass(const std::string& descriptor, const mirror::Class* primitive)
+ void AssertPrimitiveClass(const std::string& descriptor, mirror::Class* primitive)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ClassHelper primitive_ch(primitive);
ASSERT_TRUE(primitive != NULL);
@@ -212,7 +212,7 @@ class ClassLinkerTest : public CommonTest {
}
}
EXPECT_EQ(klass->IsInterface(), klass->GetVTable() == NULL);
- const mirror::IfTable* iftable = klass->GetIfTable();
+ mirror::IfTable* iftable = klass->GetIfTable();
for (int i = 0; i < klass->GetIfTableCount(); i++) {
mirror::Class* interface = iftable->GetInterface(i);
ASSERT_TRUE(interface != NULL);
@@ -469,20 +469,23 @@ struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> {
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_), "dexCacheResolvedTypes"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_strings_), "dexCacheStrings"));
+ // alphabetical 64-bit
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_interpreter_), "entryPointFromInterpreter"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_jni_), "entryPointFromJni"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_portable_compiled_code_), "entryPointFromPortableCompiledCode"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_quick_compiled_code_), "entryPointFromQuickCompiledCode"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, gc_map_), "gcMap"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_mapping_table_), "quickMappingTable"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_vmap_table_), "quickVmapTable"));
+
// alphabetical 32-bit
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, code_item_offset_), "codeItemOffset"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, core_spill_mask_), "coreSpillMask"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_compiled_code_), "entryPointFromCompiledCode"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_interpreter_), "entryPointFromInterpreter"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, fp_spill_mask_), "fpSpillMask"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, frame_size_in_bytes_), "frameSizeInBytes"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, gc_map_), "gcMap"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, mapping_table_), "mappingTable"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_dex_index_), "methodDexIndex"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, native_method_), "nativeMethod"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, vmap_table_), "vmapTable"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_core_spill_mask_), "quickCoreSpillMask"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_fp_spill_mask_), "quickFpSpillMask"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_frame_size_in_bytes_), "quickFrameSizeInBytes"));
};
};
@@ -762,10 +765,10 @@ TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) {
mirror::Class* array_class = class_linker_->FindSystemClass("[Ljava/lang/String;");
mirror::ObjectArray<mirror::String>* array =
mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), array_class, 0);
- uint32_t array_offset = reinterpret_cast<uint32_t>(array);
- uint32_t data_offset =
- array_offset + mirror::ObjectArray<mirror::String>::DataOffset(sizeof(mirror::String*)).Uint32Value();
- if (sizeof(mirror::String*) == sizeof(int32_t)) {
+ uintptr_t data_offset =
+ reinterpret_cast<uintptr_t>(array->GetRawData(sizeof(mirror::HeapReference<mirror::String>),
+ 0));
+ if (sizeof(mirror::HeapReference<mirror::String>) == sizeof(int32_t)) {
EXPECT_TRUE(IsAligned<4>(data_offset)); // Check 4 byte alignment.
} else {
EXPECT_TRUE(IsAligned<8>(data_offset)); // Check 8 byte alignment.
diff --git a/runtime/common_test.h b/runtime/common_test.h
index fce3f3f..ddaf52a 100644
--- a/runtime/common_test.h
+++ b/runtime/common_test.h
@@ -48,6 +48,7 @@
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
#include "thread.h"
+#include "utils.h"
#include "UniquePtr.h"
#include "verifier/method_verifier.h"
#include "verifier/method_verifier-inl.h"
@@ -262,11 +263,6 @@ static InstructionSetFeatures ParseFeatureList(std::string str) {
class CommonTest : public testing::Test {
public:
- static void MakeExecutable(const mirror::ByteArray* code_array) {
- CHECK(code_array != NULL);
- MakeExecutable(code_array->GetData(), code_array->GetLength());
- }
-
static void MakeExecutable(const std::vector<uint8_t>& code) {
CHECK_NE(code.size(), 0U);
MakeExecutable(&code[0], code.size());
@@ -280,31 +276,39 @@ class CommonTest : public testing::Test {
const uint8_t* mapping_table,
const uint8_t* vmap_table,
const uint8_t* gc_map) {
- return OatFile::OatMethod(NULL,
- reinterpret_cast<uint32_t>(code),
- frame_size_in_bytes,
- core_spill_mask,
- fp_spill_mask,
- reinterpret_cast<uint32_t>(mapping_table),
- reinterpret_cast<uint32_t>(vmap_table),
- reinterpret_cast<uint32_t>(gc_map));
+ const byte* base = nullptr; // Base of data in oat file, ie 0.
+ uint32_t code_offset = PointerToLowMemUInt32(code);
+ uint32_t mapping_table_offset = PointerToLowMemUInt32(mapping_table);
+ uint32_t vmap_table_offset = PointerToLowMemUInt32(vmap_table);
+ uint32_t gc_map_offset = PointerToLowMemUInt32(gc_map);
+ return OatFile::OatMethod(base,
+ code_offset,
+ frame_size_in_bytes,
+ core_spill_mask,
+ fp_spill_mask,
+ mapping_table_offset,
+ vmap_table_offset,
+ gc_map_offset);
}
void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(method != NULL);
+ CHECK(method != nullptr);
- const CompiledMethod* compiled_method = NULL;
+ const CompiledMethod* compiled_method = nullptr;
if (!method->IsAbstract()) {
- const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
+ mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
const DexFile& dex_file = *dex_cache->GetDexFile();
compiled_method =
compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
method->GetDexMethodIndex()));
}
- if (compiled_method != NULL) {
- const std::vector<uint8_t>& code = compiled_method->GetCode();
- MakeExecutable(code);
- const void* method_code = CompiledMethod::CodePointer(&code[0],
+ if (compiled_method != nullptr) {
+ const std::vector<uint8_t>* code = compiled_method->GetQuickCode();
+ if (code == nullptr) {
+ code = compiled_method->GetPortableCode();
+ }
+ MakeExecutable(*code);
+ const void* method_code = CompiledMethod::CodePointer(&(*code)[0],
compiled_method->GetInstructionSet());
LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
@@ -317,9 +321,9 @@ class CommonTest : public testing::Test {
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
} else {
- const void* method_code;
// No code? You must mean to go into the interpreter.
- method_code = GetCompiledCodeToInterpreterBridge();
+ const void* method_code = kUsePortableCompiler ? GetPortableToInterpreterBridge()
+ : GetQuickToInterpreterBridge();
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
kStackAlignment,
0,
@@ -330,6 +334,14 @@ class CommonTest : public testing::Test {
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
}
+ // Create bridges to transition between different kinds of compiled bridge.
+ if (method->GetEntryPointFromPortableCompiledCode() == nullptr) {
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToQuickBridge());
+ } else {
+ CHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToPortableBridge());
+ method->SetIsPortableCompiled();
+ }
}
static void MakeExecutable(const void* code_start, size_t code_length) {
@@ -415,11 +427,7 @@ class CommonTest : public testing::Test {
std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
// TODO: make selectable
-#if defined(ART_USE_PORTABLE_COMPILER)
- CompilerBackend compiler_backend = kPortable;
-#else
- CompilerBackend compiler_backend = kQuick;
-#endif
+ CompilerBackend compiler_backend = kUsePortableCompiler ? kPortable : kQuick;
verification_results_.reset(new VerificationResults);
method_inliner_map_.reset(compiler_backend == kQuick ? new DexFileToMethodInlinerMap : nullptr);
@@ -460,6 +468,8 @@ class CommonTest : public testing::Test {
instruction_set = kMips;
#elif defined(__i386__)
instruction_set = kX86;
+#elif defined(__x86_64__)
+ instruction_set = kX86_64;
#endif
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
@@ -640,7 +650,9 @@ class CommonTest : public testing::Test {
image_reservation_.reset(MemMap::MapAnonymous("image reservation",
reinterpret_cast<byte*>(ART_BASE_ADDRESS),
(size_t)100 * 1024 * 1024, // 100MB
- PROT_NONE, &error_msg));
+ PROT_NONE,
+ false /* no need for 4gb flag with fixed mmap*/,
+ &error_msg));
CHECK(image_reservation_.get() != nullptr) << error_msg;
}
@@ -733,11 +745,12 @@ class CheckJniAbortCatcher {
// MCLinker link LLVM ELF output because we no longer just have code
// blobs in memory. We'll need to dlopen to load and relocate
// temporary output to resurrect these tests.
-#if defined(ART_USE_PORTABLE_COMPILER)
-#define TEST_DISABLED_FOR_PORTABLE() printf("WARNING: TEST DISABLED FOR PORTABLE\n"); return
-#else
-#define TEST_DISABLED_FOR_PORTABLE()
-#endif
+#define TEST_DISABLED_FOR_PORTABLE() \
+ if (kUsePortableCompiler) { \
+ printf("WARNING: TEST DISABLED FOR PORTABLE\n"); \
+ return; \
+ }
+
} // namespace art
namespace std {
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index dd832df..24d16c4 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -33,7 +33,7 @@
namespace art {
-static void AddReferrerLocation(std::ostream& os, const mirror::Class* referrer)
+static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (referrer != NULL) {
ClassHelper kh(referrer);
@@ -46,7 +46,7 @@ static void AddReferrerLocation(std::ostream& os, const mirror::Class* referrer)
}
static void ThrowException(const ThrowLocation* throw_location, const char* exception_descriptor,
- const mirror::Class* referrer, const char* fmt, va_list* args = NULL)
+ mirror::Class* referrer, const char* fmt, va_list* args = NULL)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::ostringstream msg;
if (args != NULL) {
@@ -68,7 +68,7 @@ static void ThrowException(const ThrowLocation* throw_location, const char* exce
// AbstractMethodError
-void ThrowAbstractMethodError(const mirror::ArtMethod* method) {
+void ThrowAbstractMethodError(mirror::ArtMethod* method) {
ThrowException(NULL, "Ljava/lang/AbstractMethodError;", NULL,
StringPrintf("abstract method \"%s\"",
PrettyMethod(method).c_str()).c_str());
@@ -89,8 +89,7 @@ void ThrowArrayIndexOutOfBoundsException(int index, int length) {
// ArrayStoreException
-void ThrowArrayStoreException(const mirror::Class* element_class,
- const mirror::Class* array_class) {
+void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class) {
ThrowException(NULL, "Ljava/lang/ArrayStoreException;", NULL,
StringPrintf("%s cannot be stored in an array of type %s",
PrettyDescriptor(element_class).c_str(),
@@ -99,7 +98,7 @@ void ThrowArrayStoreException(const mirror::Class* element_class,
// ClassCastException
-void ThrowClassCastException(const mirror::Class* dest_type, const mirror::Class* src_type) {
+void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) {
ThrowException(NULL, "Ljava/lang/ClassCastException;", NULL,
StringPrintf("%s cannot be cast to %s",
PrettyDescriptor(src_type).c_str(),
@@ -120,7 +119,7 @@ void ThrowClassCircularityError(mirror::Class* c) {
// ClassFormatError
-void ThrowClassFormatError(const mirror::Class* referrer, const char* fmt, ...) {
+void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
ThrowException(NULL, "Ljava/lang/ClassFormatError;", referrer, fmt, &args);
@@ -136,7 +135,7 @@ void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* access
}
void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
- const mirror::ArtMethod* called,
+ mirror::ArtMethod* called,
InvokeType type) {
std::ostringstream msg;
msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
@@ -159,7 +158,7 @@ void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* acc
ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
}
-void ThrowIllegalAccessErrorFinalField(const mirror::ArtMethod* referrer,
+void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer,
mirror::ArtField* accessed) {
std::ostringstream msg;
msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
@@ -187,7 +186,7 @@ void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const ch
void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
mirror::ArtMethod* method,
- const mirror::ArtMethod* referrer) {
+ mirror::ArtMethod* referrer) {
std::ostringstream msg;
msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
<< expected_type << " but instead was found to be of type " << found_type;
@@ -196,9 +195,9 @@ void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType foun
msg.str().c_str());
}
-void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::ArtMethod* interface_method,
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
mirror::Object* this_object,
- const mirror::ArtMethod* referrer) {
+ mirror::ArtMethod* referrer) {
// Referrer is calling interface_method on this_object, however, the interface_method isn't
// implemented by this_object.
CHECK(this_object != NULL);
@@ -212,8 +211,8 @@ void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::Ar
msg.str().c_str());
}
-void ThrowIncompatibleClassChangeErrorField(const mirror::ArtField* resolved_field, bool is_static,
- const mirror::ArtMethod* referrer) {
+void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
+ mirror::ArtMethod* referrer) {
std::ostringstream msg;
msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
<< (is_static ? "static" : "instance") << " field" << " rather than a "
@@ -222,7 +221,7 @@ void ThrowIncompatibleClassChangeErrorField(const mirror::ArtField* resolved_fie
msg.str().c_str());
}
-void ThrowIncompatibleClassChangeError(const mirror::Class* referrer, const char* fmt, ...) {
+void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args);
@@ -240,7 +239,7 @@ void ThrowIOException(const char* fmt, ...) {
// LinkageError
-void ThrowLinkageError(const mirror::Class* referrer, const char* fmt, ...) {
+void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
ThrowException(NULL, "Ljava/lang/LinkageError;", referrer, fmt, &args);
@@ -486,7 +485,7 @@ void ThrowRuntimeException(const char* fmt, ...) {
// VerifyError
-void ThrowVerifyError(const mirror::Class* referrer, const char* fmt, ...) {
+void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
ThrowException(NULL, "Ljava/lang/VerifyError;", referrer, fmt, &args);
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index 7f13891..792cdef 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -33,7 +33,7 @@ class ThrowLocation;
// AbstractMethodError
-void ThrowAbstractMethodError(const mirror::ArtMethod* method)
+void ThrowAbstractMethodError(mirror::ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
// ArithmeticException
@@ -47,8 +47,7 @@ void ThrowArrayIndexOutOfBoundsException(int index, int length)
// ArrayStoreException
-void ThrowArrayStoreException(const mirror::Class* element_class,
- const mirror::Class* array_class)
+void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
// ClassCircularityError
@@ -58,7 +57,7 @@ void ThrowClassCircularityError(mirror::Class* c)
// ClassCastException
-void ThrowClassCastException(const mirror::Class* dest_type, const mirror::Class* src_type)
+void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
void ThrowClassCastException(const ThrowLocation* throw_location, const char* msg)
@@ -66,7 +65,7 @@ void ThrowClassCastException(const ThrowLocation* throw_location, const char* ms
// ClassFormatError
-void ThrowClassFormatError(const mirror::Class* referrer, const char* fmt, ...)
+void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3)))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
@@ -76,7 +75,7 @@ void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* access
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
- const mirror::ArtMethod* called,
+ mirror::ArtMethod* called,
InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
@@ -86,8 +85,7 @@ void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* a
void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowIllegalAccessErrorFinalField(const mirror::ArtMethod* referrer,
- mirror::ArtField* accessed)
+void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, mirror::ArtField* accessed)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...)
@@ -102,20 +100,19 @@ void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const ch
// IncompatibleClassChangeError
void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
- mirror::ArtMethod* method,
- const mirror::ArtMethod* referrer)
+ mirror::ArtMethod* method, mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::ArtMethod* interface_method,
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
mirror::Object* this_object,
- const mirror::ArtMethod* referrer)
+ mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowIncompatibleClassChangeErrorField(const mirror::ArtField* resolved_field, bool is_static,
- const mirror::ArtMethod* referrer)
+void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
+ mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowIncompatibleClassChangeError(const mirror::Class* referrer, const char* fmt, ...)
+void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3)))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
@@ -126,7 +123,7 @@ void ThrowIOException(const char* fmt, ...) __attribute__((__format__(__printf__
// LinkageError
-void ThrowLinkageError(const mirror::Class* referrer, const char* fmt, ...)
+void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3)))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
@@ -185,7 +182,7 @@ void ThrowRuntimeException(const char* fmt, ...)
// VerifyError
-void ThrowVerifyError(const mirror::Class* referrer, const char* fmt, ...)
+void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3)))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 2141997..9cc7cb4 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -101,7 +101,7 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
virtual ~DebugInstrumentationListener() {}
virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (method->IsNative()) {
// TODO: post location events is a suspension point and native method entry stubs aren't.
@@ -111,7 +111,7 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
}
virtual void MethodExited(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc, const JValue& return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (method->IsNative()) {
@@ -122,7 +122,7 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
}
virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// We're not recorded to listen to this kind of event, so complain.
LOG(ERROR) << "Unexpected method unwind event in debugger " << PrettyMethod(method)
@@ -130,7 +130,7 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
}
virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc)
+ mirror::ArtMethod* method, uint32_t new_dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Dbg::UpdateDebugger(thread, this_object, method, new_dex_pc);
}
@@ -303,7 +303,7 @@ static JDWP::JdwpTag TagFromClass(mirror::Class* c)
*
* Null objects are tagged JT_OBJECT.
*/
-static JDWP::JdwpTag TagFromObject(const mirror::Object* o)
+static JDWP::JdwpTag TagFromObject(mirror::Object* o)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(o->GetClass());
}
@@ -1054,16 +1054,16 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count,
size_t width = GetTagWidth(tag);
uint8_t* dst = expandBufAddSpace(pReply, count * width);
if (width == 8) {
- const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t)));
+ const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t), 0));
for (int i = 0; i < count; ++i) JDWP::Write8BE(&dst, src8[offset + i]);
} else if (width == 4) {
- const uint32_t* src4 = reinterpret_cast<uint32_t*>(a->GetRawData(sizeof(uint32_t)));
+ const uint32_t* src4 = reinterpret_cast<uint32_t*>(a->GetRawData(sizeof(uint32_t), 0));
for (int i = 0; i < count; ++i) JDWP::Write4BE(&dst, src4[offset + i]);
} else if (width == 2) {
- const uint16_t* src2 = reinterpret_cast<uint16_t*>(a->GetRawData(sizeof(uint16_t)));
+ const uint16_t* src2 = reinterpret_cast<uint16_t*>(a->GetRawData(sizeof(uint16_t), 0));
for (int i = 0; i < count; ++i) JDWP::Write2BE(&dst, src2[offset + i]);
} else {
- const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData(sizeof(uint8_t)));
+ const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData(sizeof(uint8_t), 0));
memcpy(dst, &src[offset * width], count * width);
}
} else {
@@ -1079,10 +1079,13 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count,
return JDWP::ERR_NONE;
}
-template <typename T> void CopyArrayData(mirror::Array* a, JDWP::Request& src, int offset, int count) {
+template <typename T>
+static void CopyArrayData(mirror::Array* a, JDWP::Request& src, int offset, int count)
+ NO_THREAD_SAFETY_ANALYSIS {
+ // TODO: fix when annotalysis correctly handles non-member functions.
DCHECK(a->GetClass()->IsPrimitiveArray());
- T* dst = &(reinterpret_cast<T*>(a->GetRawData(sizeof(T)))[offset * sizeof(T)]);
+ T* dst = reinterpret_cast<T*>(a->GetRawData(sizeof(T), offset));
for (int i = 0; i < count; ++i) {
*dst++ = src.ReadValue(sizeof(T));
}
@@ -1926,7 +1929,7 @@ JDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_fram
JDWP::FrameId frame_id(GetFrameId());
JDWP::JdwpLocation location;
SetLocation(location, GetMethod(), GetDexPc());
- VLOG(jdwp) << StringPrintf(" Frame %3zd: id=%3lld ", depth_, frame_id) << location;
+ VLOG(jdwp) << StringPrintf(" Frame %3zd: id=%3" PRIu64 " ", depth_, frame_id) << location;
expandBufAdd8BE(buf_, frame_id);
expandBufAddLocation(buf_, location);
}
@@ -2283,7 +2286,7 @@ void Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl
visitor.WalkStack();
}
-void Dbg::PostLocationEvent(const mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object,
+void Dbg::PostLocationEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object,
int event_flags, const JValue* return_value) {
mirror::Class* c = m->GetDeclaringClass();
@@ -2338,7 +2341,7 @@ void Dbg::PostClassPrepare(mirror::Class* c) {
}
void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* m, uint32_t dex_pc) {
+ mirror::ArtMethod* m, uint32_t dex_pc) {
if (!IsDebuggerActive() || dex_pc == static_cast<uint32_t>(-2) /* fake method exit */) {
return;
}
@@ -2630,7 +2633,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize
if (!m->IsRuntimeMethod()) {
++single_step_control_->stack_depth;
if (single_step_control_->method == NULL) {
- const mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache();
+ mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache();
single_step_control_->method = m;
*line_number_ = -1;
if (dex_cache != NULL) {
@@ -2699,7 +2702,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize
uint32_t last_pc;
};
single_step_control->dex_pcs.clear();
- const mirror::ArtMethod* m = single_step_control->method;
+ mirror::ArtMethod* m = single_step_control->method;
if (!m->IsNative()) {
DebugCallbackContext context(single_step_control, line_number);
MethodHelper mh(m);
@@ -3062,7 +3065,7 @@ bool Dbg::DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pRep
// Run through and find all chunks. [Currently just find the first.]
ScopedByteArrayRO contents(env, dataArray.get());
if (length != request_length) {
- LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%d)", length, request_length);
+ LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%zd)", length, request_length);
return false;
}
@@ -3454,7 +3457,7 @@ class HeapChunkContext {
Flush();
}
}
- const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(start);
+ mirror::Object* obj = reinterpret_cast<mirror::Object*>(start);
// Determine the type of this chunk.
// OLD-TODO: if context.merge, see if this chunk is different from the last chunk.
@@ -3497,8 +3500,8 @@ class HeapChunkContext {
*p_++ = length - 1;
}
- uint8_t ExamineObject(const mirror::Object* o, bool is_native_heap)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
+ uint8_t ExamineObject(mirror::Object* o, bool is_native_heap)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
if (o == NULL) {
return HPSG_STATE(SOLIDITY_FREE, 0);
}
@@ -3751,7 +3754,7 @@ void Dbg::DumpRecentAllocations() {
<< PrettyClass(record->type);
for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) {
- const mirror::ArtMethod* m = record->stack[stack_frame].method;
+ mirror::ArtMethod* m = record->stack[stack_frame].method;
if (m == NULL) {
break;
}
diff --git a/runtime/debugger.h b/runtime/debugger.h
index a3f8b9c..328c9cd 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -366,7 +366,7 @@ class Dbg {
kMethodEntry = 0x04,
kMethodExit = 0x08,
};
- static void PostLocationEvent(const mirror::ArtMethod* method, int pcOffset,
+ static void PostLocationEvent(mirror::ArtMethod* method, int pcOffset,
mirror::Object* thisPtr, int eventFlags,
const JValue* return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -382,7 +382,7 @@ class Dbg {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void UpdateDebugger(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc)
+ mirror::ArtMethod* method, uint32_t new_dex_pc)
LOCKS_EXCLUDED(Locks::breakpoint_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h
index 3b2135c..a459308 100644
--- a/runtime/dex_file-inl.h
+++ b/runtime/dex_file-inl.h
@@ -44,7 +44,7 @@ inline const Signature DexFile::GetMethodSignature(const MethodId& method_id) co
inline const DexFile::TryItem* DexFile::GetTryItems(const CodeItem& code_item, uint32_t offset) {
const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_];
return reinterpret_cast<const TryItem*>
- (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
+ (RoundUp(reinterpret_cast<uintptr_t>(insns_end_), 4)) + offset;
}
static inline bool DexFileStringEquals(const DexFile* df1, uint32_t sidx1,
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index d28d986..eaba7eb 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -621,7 +621,7 @@ const Signature DexFile::CreateSignature(const StringPiece& signature) const {
return Signature(this, *proto_id);
}
-int32_t DexFile::GetLineNumFromPC(const mirror::ArtMethod* method, uint32_t rel_pc) const {
+int32_t DexFile::GetLineNumFromPC(mirror::ArtMethod* method, uint32_t rel_pc) const {
// For native method, lineno should be -2 to indicate it is native. Note that
// "line number == -2" is how libcore tells from StackTraceElement.
if (method->GetCodeItemOffset() == 0) {
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index bc2bfde..46df455 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -794,7 +794,7 @@ class DexFile {
// Returns -2 for native methods (as expected in exception traces).
//
// This is used by runtime; therefore use art::Method not art::DexFile::Method.
- int32_t GetLineNumFromPC(const mirror::ArtMethod* method, uint32_t rel_pc) const
+ int32_t GetLineNumFromPC(mirror::ArtMethod* method, uint32_t rel_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 2f7c38a..261c217 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -646,7 +646,8 @@ bool ElfFile::Load(bool executable, std::string* error_msg) {
reservation_name += file_->GetPath();
std::string error_msg;
UniquePtr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
- NULL, GetLoadedSize(), PROT_NONE, &error_msg));
+ NULL, GetLoadedSize(), PROT_NONE, false,
+ &error_msg));
CHECK(reserve.get() != NULL) << file_->GetPath() << ": " << error_msg;
base_address_ = reserve->Begin();
segments_.push_back(reserve.release());
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index f478366..20532f4 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -282,7 +282,7 @@ enum FindFieldType {
};
template<FindFieldType type, bool access_check>
-static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer,
+static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
Thread* self, size_t expected_size) {
bool is_primitive;
bool is_set;
@@ -321,8 +321,7 @@ static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirr
return nullptr; // Failure.
} else {
FieldHelper fh(resolved_field);
- if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
- fh.FieldSize() != expected_size)) {
+ if (UNLIKELY(fh.IsPrimitiveType() != is_primitive || fh.FieldSize() != expected_size)) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
DCHECK(throw_location.GetMethod() == referrer);
self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
@@ -358,7 +357,7 @@ static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirr
#define EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \
template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \
mirror::ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \
- const mirror::ArtMethod* referrer, \
+ mirror::ArtMethod* referrer, \
Thread* self, size_t expected_size) \
#define EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \
@@ -496,7 +495,7 @@ EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kInterface);
// Fast path field resolution that can't initialize classes or throw exceptions.
static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
FindFieldType type, size_t expected_size)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* resolved_field =
@@ -552,7 +551,7 @@ static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
// Fast path method resolution that can't throw exceptions.
static inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx,
mirror::Object* this_object,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
bool access_check, InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
bool is_direct = type == kStatic || type == kDirect;
@@ -593,7 +592,7 @@ static inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx,
}
static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, bool can_run_clinit,
bool verify_access)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -630,7 +629,7 @@ static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-static inline mirror::String* ResolveStringFromCode(const mirror::ArtMethod* referrer,
+static inline mirror::String* ResolveStringFromCode(mirror::ArtMethod* referrer,
uint32_t string_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -719,21 +718,21 @@ static inline const void* GetPortableToInterpreterBridge() {
return reinterpret_cast<void*>(art_portable_to_interpreter_bridge);
}
+static inline const void* GetPortableToQuickBridge() {
+ // TODO: portable to quick bridge. Bug: 8196384
+ return GetPortableToInterpreterBridge();
+}
+
extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*);
static inline const void* GetQuickToInterpreterBridge() {
return reinterpret_cast<void*>(art_quick_to_interpreter_bridge);
}
-// Return address of interpreter stub.
-static inline const void* GetCompiledCodeToInterpreterBridge() {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableToInterpreterBridge();
-#else
+static inline const void* GetQuickToPortableBridge() {
+ // TODO: quick to portable bridge. Bug: 8196384
return GetQuickToInterpreterBridge();
-#endif
}
-
static inline const void* GetPortableResolutionTrampoline(ClassLinker* class_linker) {
return class_linker->GetPortableResolutionTrampoline();
}
@@ -742,15 +741,6 @@ static inline const void* GetQuickResolutionTrampoline(ClassLinker* class_linker
return class_linker->GetQuickResolutionTrampoline();
}
-// Return address of resolution trampoline stub for defined compiler.
-static inline const void* GetResolutionTrampoline(ClassLinker* class_linker) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableResolutionTrampoline(class_linker);
-#else
- return GetQuickResolutionTrampoline(class_linker);
-#endif
-}
-
static inline const void* GetPortableImtConflictTrampoline(ClassLinker* class_linker) {
return class_linker->GetPortableImtConflictTrampoline();
}
@@ -759,15 +749,6 @@ static inline const void* GetQuickImtConflictTrampoline(ClassLinker* class_linke
return class_linker->GetQuickImtConflictTrampoline();
}
-// Return address of imt conflict trampoline stub for defined compiler.
-static inline const void* GetImtConflictTrampoline(ClassLinker* class_linker) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableImtConflictTrampoline(class_linker);
-#else
- return GetQuickImtConflictTrampoline(class_linker);
-#endif
-}
-
extern "C" void art_portable_proxy_invoke_handler();
static inline const void* GetPortableProxyInvokeHandler() {
return reinterpret_cast<void*>(art_portable_proxy_invoke_handler);
@@ -778,14 +759,6 @@ static inline const void* GetQuickProxyInvokeHandler() {
return reinterpret_cast<void*>(art_quick_proxy_invoke_handler);
}
-static inline const void* GetProxyInvokeHandler() {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableProxyInvokeHandler();
-#else
- return GetQuickProxyInvokeHandler();
-#endif
-}
-
extern "C" void* art_jni_dlsym_lookup_stub(JNIEnv*, jobject);
static inline void* GetJniDlsymLookupStub() {
return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub);
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index 0df00c2..8a2ce51 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -45,15 +45,15 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& m
}
}
uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
-#if defined(ART_USE_PORTABLE_COMPILER)
- ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
- arg_array.BuildArgArrayFromFrame(shadow_frame, arg_offset);
- method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
-#else
- method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
- (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
- result, mh.GetShorty()[0]);
-#endif
+ if (kUsePortableCompiler) {
+ ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
+ arg_array.BuildArgArrayFromFrame(shadow_frame, arg_offset);
+ method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
+ } else {
+ method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
+ (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
+ result, mh.GetShorty()[0]);
+ }
}
} // namespace art
diff --git a/runtime/entrypoints/portable/portable_cast_entrypoints.cc b/runtime/entrypoints/portable/portable_cast_entrypoints.cc
index d343c5d..a553a22 100644
--- a/runtime/entrypoints/portable/portable_cast_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_cast_entrypoints.cc
@@ -20,16 +20,16 @@
namespace art {
-extern "C" int32_t art_portable_is_assignable_from_code(const mirror::Class* dest_type,
- const mirror::Class* src_type)
+extern "C" int32_t art_portable_is_assignable_from_code(mirror::Class* dest_type,
+ mirror::Class* src_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(dest_type != NULL);
DCHECK(src_type != NULL);
return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
}
-extern "C" void art_portable_check_cast_from_code(const mirror::Class* dest_type,
- const mirror::Class* src_type)
+extern "C" void art_portable_check_cast_from_code(mirror::Class* dest_type,
+ mirror::Class* src_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
DCHECK(src_type->IsClass()) << PrettyClass(src_type);
@@ -38,8 +38,8 @@ extern "C" void art_portable_check_cast_from_code(const mirror::Class* dest_type
}
}
-extern "C" void art_portable_check_put_array_element_from_code(const mirror::Object* element,
- const mirror::Object* array)
+extern "C" void art_portable_check_put_array_element_from_code(mirror::Object* element,
+ mirror::Object* array)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (element == NULL) {
return;
diff --git a/runtime/entrypoints/portable/portable_field_entrypoints.cc b/runtime/entrypoints/portable/portable_field_entrypoints.cc
index 095e99e..0b54b9c 100644
--- a/runtime/entrypoints/portable/portable_field_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_field_entrypoints.cc
@@ -65,13 +65,13 @@ extern "C" int32_t art_portable_set_obj_static_from_code(uint32_t field_idx,
mirror::Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(field->GetDeclaringClass(), new_value);
return 0;
}
field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, Thread::Current(),
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(field->GetDeclaringClass(), new_value);
return 0;
@@ -113,12 +113,12 @@ extern "C" mirror::Object* art_portable_get_obj_static_from_code(uint32_t field_
mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(field->GetDeclaringClass());
}
field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, Thread::Current(),
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(field->GetDeclaringClass());
}
@@ -167,13 +167,13 @@ extern "C" int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx,
mirror::Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(obj, new_value);
return 0;
}
field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, Thread::Current(),
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(obj, new_value);
return 0;
@@ -218,12 +218,12 @@ extern "C" mirror::Object* art_portable_get_obj_instance_from_code(uint32_t fiel
mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(obj);
}
field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, Thread::Current(),
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(obj);
}
diff --git a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
index 8cf4eed..1005d0e 100644
--- a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
@@ -44,7 +44,7 @@ extern "C" void art_portable_fill_array_data_from_code(mirror::ArtMethod* method
return; // Error
}
uint32_t size_in_bytes = payload->element_count * payload->element_width;
- memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+ memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
}
} // namespace art
diff --git a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
index 47ccbb1..d34b097 100644
--- a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
@@ -34,7 +34,7 @@ mirror::ArtMethod* FindMethodHelper(uint32_t method_idx, mirror::Object* this_ob
}
}
DCHECK(!thread->IsExceptionPending());
- const void* code = method->GetEntryPointFromCompiledCode();
+ const void* code = method->GetEntryPointFromPortableCompiledCode();
// When we return, the caller will branch to this address, so it had better not be 0!
if (UNLIKELY(code == NULL)) {
diff --git a/runtime/entrypoints/portable/portable_throw_entrypoints.cc b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
index 2a0df9b..1fdb832 100644
--- a/runtime/entrypoints/portable/portable_throw_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
@@ -75,7 +75,7 @@ extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* cu
ThrowLocation throw_location;
mirror::Throwable* exception = self->GetException(&throw_location);
// Check for special deoptimization exception.
- if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) {
+ if (UNLIKELY(reinterpret_cast<intptr_t>(exception) == -1)) {
return -1;
}
mirror::Class* exception_type = exception->GetClass();
diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
index 2162dcc..55fd301 100644
--- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
@@ -47,6 +47,11 @@ class PortableArgumentVisitor {
#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
#define PORTABLE_STACK_ARG_SKIP 4
+#elif defined(__x86_64__)
+// TODO: implement and check these.
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 16
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 96
+#define PORTABLE_STACK_ARG_SKIP 0
#else
#error "Unsupported architecture"
#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
@@ -387,43 +392,42 @@ extern "C" const void* artPortableResolutionTrampoline(mirror::ArtMethod* called
// Incompatible class change should have been handled in resolve method.
CHECK(!called->CheckIncompatibleClassChange(invoke_type));
}
- const void* code = NULL;
+ const void* code = nullptr;
if (LIKELY(!thread->IsExceptionPending())) {
// Ensure that the called method's class is initialized.
SirtRef<mirror::Class> called_class(thread, called->GetDeclaringClass());
linker->EnsureInitialized(called_class, true, true);
if (LIKELY(called_class->IsInitialized())) {
- code = called->GetEntryPointFromCompiledCode();
+ code = called->GetEntryPointFromPortableCompiledCode();
// TODO: remove this after we solve the link issue.
- { // for lazy link.
- if (code == NULL) {
- code = linker->GetOatCodeFor(called);
- }
+ if (code == nullptr) {
+ bool have_portable_code;
+ code = linker->GetPortableOatCodeFor(called, &have_portable_code);
}
} else if (called_class->IsInitializing()) {
if (invoke_type == kStatic) {
// Class is still initializing, go to oat and grab code (trampoline must be left in place
// until class is initialized to stop races between threads).
- code = linker->GetOatCodeFor(called);
+ bool have_portable_code;
+ code = linker->GetPortableOatCodeFor(called, &have_portable_code);
} else {
// No trampoline for non-static methods.
- code = called->GetEntryPointFromCompiledCode();
+ code = called->GetEntryPointFromPortableCompiledCode();
// TODO: remove this after we solve the link issue.
- { // for lazy link.
- if (code == NULL) {
- code = linker->GetOatCodeFor(called);
- }
+ if (code == nullptr) {
+ bool have_portable_code;
+ code = linker->GetPortableOatCodeFor(called, &have_portable_code);
}
}
} else {
DCHECK(called_class->IsErroneous());
}
}
- if (LIKELY(code != NULL)) {
+ if (LIKELY(code != nullptr)) {
// Expect class to at least be initializing.
DCHECK(called->GetDeclaringClass()->IsInitializing());
// Don't want infinite recursion.
- DCHECK(code != GetResolutionTrampoline(linker));
+ DCHECK(code != GetPortableResolutionTrampoline(linker));
// Set up entry into main method
*called_addr = called;
}
diff --git a/runtime/entrypoints/quick/quick_cast_entrypoints.cc b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
index ae53d6c..a6ab69b 100644
--- a/runtime/entrypoints/quick/quick_cast_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
@@ -20,8 +20,7 @@
namespace art {
// Assignable test for code, won't throw. Null and equality tests already performed
-extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
- const mirror::Class* ref_class)
+extern "C" uint32_t artIsAssignableFromCode(mirror::Class* klass, mirror::Class* ref_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(klass != NULL);
DCHECK(ref_class != NULL);
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 003047a..ab428a5 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -26,7 +26,7 @@
namespace art {
extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -38,7 +38,7 @@ extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx,
}
extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Called when method->dex_cache_resolved_types_[] misses.
@@ -47,7 +47,7 @@ extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx,
}
extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index 0a533bd..93ff7aa 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -26,7 +26,7 @@
namespace art {
extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
@@ -43,7 +43,7 @@ extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
}
extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
@@ -60,17 +60,17 @@ extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
}
extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(field->GetDeclaringClass());
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, self,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(field->GetDeclaringClass());
}
@@ -78,7 +78,7 @@ extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
}
extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
@@ -101,7 +101,7 @@ extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object*
}
extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
@@ -124,18 +124,18 @@ extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object*
}
extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL && obj != NULL)) {
return field->GetObj(obj);
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, self,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
@@ -148,7 +148,7 @@ extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror:
}
extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
@@ -166,7 +166,7 @@ extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
return -1; // failure
}
-extern "C" int artSet64StaticFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer,
+extern "C" int artSet64StaticFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
uint64_t new_value, Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
@@ -185,11 +185,11 @@ extern "C" int artSet64StaticFromCode(uint32_t field_idx, const mirror::ArtMetho
}
extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_value,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
field->SetObj(field->GetDeclaringClass(), new_value);
@@ -198,7 +198,7 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_v
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, self,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(field->GetDeclaringClass(), new_value);
return 0; // success
@@ -207,7 +207,7 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_v
}
extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint32_t new_value,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
@@ -261,18 +261,18 @@ extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
mirror::Object* new_value,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL && obj != NULL)) {
field->SetObj(obj, new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, self,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index ca0c92e..8dac750 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -56,7 +56,7 @@ extern "C" int artHandleFillArrayDataFromCode(mirror::Array* array,
return -1; // Error
}
uint32_t size_in_bytes = payload->element_count * payload->element_width;
- memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+ memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
return 0; // Success
}
diff --git a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
index 5a1b3e8..c081768 100644
--- a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
@@ -124,21 +124,23 @@ extern "C" uint64_t artInvokeInterfaceTrampoline(mirror::ArtMethod* interface_me
return 0; // Failure.
}
}
- const void* code = method->GetEntryPointFromCompiledCode();
+ const void* code = method->GetEntryPointFromQuickCompiledCode();
-#ifndef NDEBUG
// When we return, the caller will branch to this address, so it had better not be 0!
- if (UNLIKELY(code == NULL)) {
+ if (kIsDebugBuild && UNLIKELY(code == nullptr)) {
MethodHelper mh(method);
LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
<< " location: " << mh.GetDexFile().GetLocation();
}
-#endif
-
+#ifdef __LP64__
+ UNIMPLEMENTED(FATAL);
+ return 0;
+#else
uint32_t method_uint = reinterpret_cast<uint32_t>(method);
uint64_t code_uint = reinterpret_cast<uint32_t>(code);
uint64_t result = ((code_uint << 32) | method_uint);
return result;
+#endif
}
template<InvokeType type, bool access_check>
@@ -156,21 +158,23 @@ uint64_t artInvokeCommon(uint32_t method_idx, mirror::Object* this_object,
}
}
DCHECK(!self->IsExceptionPending());
- const void* code = method->GetEntryPointFromCompiledCode();
+ const void* code = method->GetEntryPointFromQuickCompiledCode();
-#ifndef NDEBUG
// When we return, the caller will branch to this address, so it had better not be 0!
- if (UNLIKELY(code == NULL)) {
+ if (kIsDebugBuild && UNLIKELY(code == NULL)) {
MethodHelper mh(method);
LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
<< " location: " << mh.GetDexFile().GetLocation();
}
-#endif
-
+#ifdef __LP64__
+ UNIMPLEMENTED(FATAL);
+ return 0;
+#else
uint32_t method_uint = reinterpret_cast<uint32_t>(method);
uint64_t code_uint = reinterpret_cast<uint32_t>(code);
uint64_t result = ((code_uint << 32) | method_uint);
return result;
+#endif
}
// Explicit template declarations of artInvokeCommon for all invoke types.
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index b589384..9f30190 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -97,6 +97,12 @@ class QuickArgumentVisitor {
#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 28
#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
#define QUICK_STACK_ARG_SKIP 16
+#elif defined(__x86_64__)
+// TODO: implement and check these.
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 56
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
+#define QUICK_STACK_ARG_SKIP 32
#else
#error "Unsupported architecture"
#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
@@ -567,15 +573,15 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
SirtRef<mirror::Class> called_class(soa.Self(), called->GetDeclaringClass());
linker->EnsureInitialized(called_class, true, true);
if (LIKELY(called_class->IsInitialized())) {
- code = called->GetEntryPointFromCompiledCode();
+ code = called->GetEntryPointFromQuickCompiledCode();
} else if (called_class->IsInitializing()) {
if (invoke_type == kStatic) {
// Class is still initializing, go to oat and grab code (trampoline must be left in place
// until class is initialized to stop races between threads).
- code = linker->GetOatCodeFor(called);
+ code = linker->GetQuickOatCodeFor(called);
} else {
// No trampoline for non-static methods.
- code = called->GetEntryPointFromCompiledCode();
+ code = called->GetEntryPointFromQuickCompiledCode();
}
} else {
DCHECK(called_class->IsErroneous());
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index 978faeb..f7b621f 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -76,7 +76,7 @@ class ExceptionTest : public CommonTest {
method_f_ = my_klass_->FindVirtualMethod("f", "()I");
ASSERT_TRUE(method_f_ != NULL);
method_f_->SetFrameSizeInBytes(kStackAlignment);
- method_f_->SetEntryPointFromCompiledCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
+ method_f_->SetEntryPointFromQuickCompiledCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
method_f_->SetMappingTable(&fake_mapping_data_.GetData()[0]);
method_f_->SetVmapTable(&fake_vmap_table_data_.GetData()[0]);
method_f_->SetNativeGcMap(&fake_gc_map_[0]);
@@ -84,7 +84,7 @@ class ExceptionTest : public CommonTest {
method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
ASSERT_TRUE(method_g_ != NULL);
method_g_->SetFrameSizeInBytes(kStackAlignment);
- method_g_->SetEntryPointFromCompiledCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
+ method_g_->SetEntryPointFromQuickCompiledCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
method_g_->SetMappingTable(&fake_mapping_data_.GetData()[0]);
method_g_->SetVmapTable(&fake_vmap_table_data_.GetData()[0]);
method_g_->SetNativeGcMap(&fake_gc_map_[0]);
@@ -105,6 +105,7 @@ class ExceptionTest : public CommonTest {
};
TEST_F(ExceptionTest, FindCatchHandler) {
+ ScopedObjectAccess soa(Thread::Current());
const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
ASSERT_TRUE(code_item != NULL);
@@ -151,51 +152,51 @@ TEST_F(ExceptionTest, StackTraceElement) {
ASSERT_EQ(kStackAlignment, 16U);
ASSERT_EQ(sizeof(uintptr_t), sizeof(uint32_t));
-#if !defined(ART_USE_PORTABLE_COMPILER)
- // Create two fake stack frames with mapping data created in SetUp. We map offset 3 in the code
- // to dex pc 3.
- const uint32_t dex_pc = 3;
-
- // Create/push fake 16byte stack frame for method g
- fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(method_f_->ToNativePc(dex_pc)); // return pc
-
- // Create/push fake 16byte stack frame for method f
- fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(0xEBAD6070); // return pc
-
- // Pull Method* of NULL to terminate the trace
- fake_stack.push_back(0);
-
- // Push null values which will become null incoming arguments.
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(0);
-
- // Set up thread to appear as if we called out of method_g_ at pc dex 3
- thread->SetTopOfStack(&fake_stack[0], method_g_->ToNativePc(dex_pc)); // return pc
-#else
- // Create/push fake 20-byte shadow frame for method g
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
- fake_stack.push_back(3);
- fake_stack.push_back(0);
-
- // Create/push fake 20-byte shadow frame for method f
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
- fake_stack.push_back(3);
- fake_stack.push_back(0);
-
- thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[5]));
- thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[0]));
-#endif
+ if (!kUsePortableCompiler) {
+ // Create two fake stack frames with mapping data created in SetUp. We map offset 3 in the code
+ // to dex pc 3.
+ const uint32_t dex_pc = 3;
+
+ // Create/push fake 16byte stack frame for method g
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(method_f_->ToNativePc(dex_pc)); // return pc
+
+ // Create/push fake 16byte stack frame for method f
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(0xEBAD6070); // return pc
+
+ // Pull Method* of NULL to terminate the trace
+ fake_stack.push_back(0);
+
+ // Push null values which will become null incoming arguments.
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+
+ // Set up thread to appear as if we called out of method_g_ at pc dex 3
+ thread->SetTopOfStack(&fake_stack[0], method_g_->ToNativePc(dex_pc)); // return pc
+ } else {
+ // Create/push fake 20-byte shadow frame for method g
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
+ fake_stack.push_back(3);
+ fake_stack.push_back(0);
+
+ // Create/push fake 20-byte shadow frame for method f
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
+ fake_stack.push_back(3);
+ fake_stack.push_back(0);
+
+ thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[5]));
+ thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[0]));
+ }
jobject internal = thread->CreateInternalStackTrace(soa);
ASSERT_TRUE(internal != NULL);
diff --git a/runtime/gc/accounting/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index 02e01b8..ea8f89c 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -19,7 +19,7 @@
#include <string>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/logging.h"
#include "base/macros.h"
#include "UniquePtr.h"
@@ -165,7 +165,7 @@ class AtomicStack {
void Init() {
std::string error_msg;
mem_map_.reset(MemMap::MapAnonymous(name_.c_str(), NULL, capacity_ * sizeof(T),
- PROT_READ | PROT_WRITE, &error_msg));
+ PROT_READ | PROT_WRITE, false, &error_msg));
CHECK(mem_map_.get() != NULL) << "couldn't allocate mark stack.\n" << error_msg;
byte* addr = mem_map_->Begin();
CHECK(addr != NULL);
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index e099137..714e6f7 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -57,7 +57,7 @@ CardTable* CardTable::Create(const byte* heap_begin, size_t heap_capacity) {
std::string error_msg;
UniquePtr<MemMap> mem_map(MemMap::MapAnonymous("card table", NULL,
capacity + 256, PROT_READ | PROT_WRITE,
- &error_msg));
+ false, &error_msg));
CHECK(mem_map.get() != NULL) << "couldn't allocate card table: " << error_msg;
// All zeros is the correct initial value; all clean. Anonymous mmaps are initialized to zero, we
// don't clear the card table to avoid unnecessary pages being allocated
@@ -72,11 +72,11 @@ CardTable* CardTable::Create(const byte* heap_begin, size_t heap_capacity) {
byte* biased_begin = reinterpret_cast<byte*>(reinterpret_cast<uintptr_t>(cardtable_begin) -
(reinterpret_cast<uintptr_t>(heap_begin) >> kCardShift));
if (((uintptr_t)biased_begin & 0xff) != kCardDirty) {
- int delta = kCardDirty - (reinterpret_cast<int>(biased_begin) & 0xff);
+ int delta = kCardDirty - (reinterpret_cast<uintptr_t>(biased_begin) & 0xff);
offset = delta + (delta < 0 ? 0x100 : 0);
biased_begin += offset;
}
- CHECK_EQ(reinterpret_cast<int>(biased_begin) & 0xff, kCardDirty);
+ CHECK_EQ(reinterpret_cast<uintptr_t>(biased_begin) & 0xff, kCardDirty);
return new CardTable(mem_map.release(), biased_begin, offset);
}
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index 6d9dde7..0225f29 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -82,9 +82,9 @@ class ModUnionUpdateObjectReferencesVisitor {
if (ref != nullptr) {
Object* new_ref = visitor_(ref, arg_);
if (new_ref != ref) {
- // Use SetFieldPtr to avoid card mark as an optimization which reduces dirtied pages and
- // improves performance.
- obj->SetFieldPtr(offset, new_ref, true);
+ // Use SetFieldObjectWithoutWriteBarrier to avoid card mark as an optimization which
+ // reduces dirtied pages and improves performance.
+ obj->SetFieldObjectWithoutWriteBarrier(offset, new_ref, true);
}
}
}
@@ -122,9 +122,8 @@ void ModUnionTableReferenceCache::ClearCards() {
class AddToReferenceArrayVisitor {
public:
explicit AddToReferenceArrayVisitor(ModUnionTableReferenceCache* mod_union_table,
- std::vector<Object**>* references)
- : mod_union_table_(mod_union_table),
- references_(references) {
+ std::vector<mirror::HeapReference<Object>*>* references)
+ : mod_union_table_(mod_union_table), references_(references) {
}
// Extra parameters are required since we use this same visitor signature for checking objects.
@@ -133,19 +132,19 @@ class AddToReferenceArrayVisitor {
// Only add the reference if it is non null and fits our criteria.
if (ref != nullptr && mod_union_table_->AddReference(obj, ref)) {
// Push the adddress of the reference.
- references_->push_back(obj->GetFieldObjectAddr(offset));
+ references_->push_back(obj->GetFieldObjectReferenceAddr(offset));
}
}
private:
ModUnionTableReferenceCache* const mod_union_table_;
- std::vector<Object**>* const references_;
+ std::vector<mirror::HeapReference<Object>*>* const references_;
};
class ModUnionReferenceVisitor {
public:
explicit ModUnionReferenceVisitor(ModUnionTableReferenceCache* const mod_union_table,
- std::vector<Object**>* references)
+ std::vector<mirror::HeapReference<Object>*>* references)
: mod_union_table_(mod_union_table),
references_(references) {
}
@@ -160,7 +159,7 @@ class ModUnionReferenceVisitor {
}
private:
ModUnionTableReferenceCache* const mod_union_table_;
- std::vector<Object**>* const references_;
+ std::vector<mirror::HeapReference<Object>*>* const references_;
};
class CheckReferenceVisitor {
@@ -173,7 +172,7 @@ class CheckReferenceVisitor {
// Extra parameters are required since we use this same visitor signature for checking objects.
// TODO: Fixme when anotatalysis works with visitors.
- void operator()(const Object* obj, const Object* ref,
+ void operator()(Object* obj, Object* ref,
const MemberOffset& /* offset */, bool /* is_static */) const
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
Heap* heap = mod_union_table_->GetHeap();
@@ -219,8 +218,8 @@ class ModUnionCheckReferences {
void ModUnionTableReferenceCache::Verify() {
// Start by checking that everything in the mod union table is marked.
for (const auto& ref_pair : references_) {
- for (Object** ref : ref_pair.second) {
- CHECK(heap_->IsLiveObjectLocked(*ref));
+ for (mirror::HeapReference<Object>* ref : ref_pair.second) {
+ CHECK(heap_->IsLiveObjectLocked(ref->AsMirrorPtr()));
}
}
@@ -231,8 +230,8 @@ void ModUnionTableReferenceCache::Verify() {
const byte* card = ref_pair.first;
if (*card == CardTable::kCardClean) {
std::set<const Object*> reference_set;
- for (Object** obj_ptr : ref_pair.second) {
- reference_set.insert(*obj_ptr);
+ for (mirror::HeapReference<Object>* obj_ptr : ref_pair.second) {
+ reference_set.insert(obj_ptr->AsMirrorPtr());
}
ModUnionCheckReferences visitor(this, reference_set);
uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
@@ -255,8 +254,8 @@ void ModUnionTableReferenceCache::Dump(std::ostream& os) {
uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card_addr));
uintptr_t end = start + CardTable::kCardSize;
os << reinterpret_cast<void*>(start) << "-" << reinterpret_cast<void*>(end) << "->{";
- for (Object** ref : ref_pair.second) {
- os << reinterpret_cast<const void*>(*ref) << ",";
+ for (mirror::HeapReference<Object>* ref : ref_pair.second) {
+ os << reinterpret_cast<const void*>(ref->AsMirrorPtr()) << ",";
}
os << "},";
}
@@ -266,7 +265,7 @@ void ModUnionTableReferenceCache::UpdateAndMarkReferences(RootVisitor visitor, v
Heap* heap = GetHeap();
CardTable* card_table = heap->GetCardTable();
- std::vector<Object**> cards_references;
+ std::vector<mirror::HeapReference<Object>*> cards_references;
ModUnionReferenceVisitor add_visitor(this, &cards_references);
for (const auto& card : cleared_cards_) {
@@ -294,13 +293,13 @@ void ModUnionTableReferenceCache::UpdateAndMarkReferences(RootVisitor visitor, v
cleared_cards_.clear();
size_t count = 0;
for (const auto& ref : references_) {
- for (const auto& obj_ptr : ref.second) {
- Object* obj = *obj_ptr;
+ for (mirror::HeapReference<Object>* obj_ptr : ref.second) {
+ Object* obj = obj_ptr->AsMirrorPtr();
if (obj != nullptr) {
Object* new_obj = visitor(obj, arg);
// Avoid dirtying pages in the image unless necessary.
if (new_obj != obj) {
- *obj_ptr = new_obj;
+ obj_ptr->Assign(new_obj);
}
}
}
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index 5a99f1b..a89dbd1 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -112,20 +112,23 @@ class ModUnionTableReferenceCache : public ModUnionTable {
// Exclusive lock is required since verify uses SpaceBitmap::VisitMarkedRange and
// VisitMarkedRange can't know if the callback will modify the bitmap or not.
- void Verify() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+ void Verify()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
// Function that tells whether or not to add a reference to the table.
virtual bool AddReference(const mirror::Object* obj, const mirror::Object* ref) = 0;
- void Dump(std::ostream& os);
+ void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
protected:
// Cleared card array, used to update the mod-union table.
ModUnionTable::CardSet cleared_cards_;
// Maps from dirty cards to their corresponding alloc space references.
- SafeMap<const byte*, std::vector<mirror::Object**>, std::less<const byte*>,
- GcAllocator<std::pair<const byte*, std::vector<mirror::Object**> > > > references_;
+ SafeMap<const byte*, std::vector<mirror::HeapReference<mirror::Object>*>, std::less<const byte*>,
+ GcAllocator<std::pair<const byte*, std::vector<mirror::HeapReference<mirror::Object>*> > > >
+ references_;
};
// Card caching implementation. Keeps track of which cards we cleared and only this information.
diff --git a/runtime/gc/accounting/space_bitmap-inl.h b/runtime/gc/accounting/space_bitmap-inl.h
index 01c70fa..d6d1b3e 100644
--- a/runtime/gc/accounting/space_bitmap-inl.h
+++ b/runtime/gc/accounting/space_bitmap-inl.h
@@ -37,9 +37,11 @@ inline bool SpaceBitmap::AtomicTestAndSet(const mirror::Object* obj) {
old_word = *address;
// Fast path: The bit is already set.
if ((old_word & mask) != 0) {
+ DCHECK(Test(obj));
return true;
}
} while (!__sync_bool_compare_and_swap(address, old_word, old_word | mask));
+ DCHECK(Test(obj));
return false;
}
@@ -56,6 +58,15 @@ template <typename Visitor>
void SpaceBitmap::VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end,
const Visitor& visitor) const {
DCHECK_LT(visit_begin, visit_end);
+#ifdef __LP64__
+ // TODO: make the optimized code below work in the 64bit case.
+ for (uintptr_t i = visit_begin; i < visit_end; i += kAlignment) {
+ mirror::Object* obj = reinterpret_cast<mirror::Object*>(i);
+ if (Test(obj)) {
+ visitor(obj);
+ }
+ }
+#else
const size_t bit_index_start = (visit_begin - heap_begin_) / kAlignment;
const size_t bit_index_end = (visit_end - heap_begin_ - 1) / kAlignment;
@@ -114,6 +125,7 @@ void SpaceBitmap::VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end,
visitor(obj);
edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift;
}
+#endif
}
inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) {
@@ -130,6 +142,7 @@ inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) {
} else {
*address = old_word & ~mask;
}
+ DCHECK_EQ(Test(obj), do_set);
return (old_word & mask) != 0;
}
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index b831843..a080bee 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -64,7 +64,7 @@ SpaceBitmap* SpaceBitmap::Create(const std::string& name, byte* heap_begin, size
size_t bitmap_size = OffsetToIndex(RoundUp(heap_capacity, kAlignment * kBitsPerWord)) * kWordSize;
std::string error_msg;
UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), NULL, bitmap_size,
- PROT_READ | PROT_WRITE, &error_msg));
+ PROT_READ | PROT_WRITE, false, &error_msg));
if (UNLIKELY(mem_map.get() == nullptr)) {
LOG(ERROR) << "Failed to allocate bitmap " << name << ": " << error_msg;
return NULL;
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 2d6cde5..aa074eb 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -72,8 +72,8 @@ class SpaceBitmap {
}
// Pack the bits in backwards so they come out in address order when using CLZ.
- static word OffsetToMask(uintptr_t offset_) {
- return static_cast<uintptr_t>(kWordHighBitMask) >> ((offset_ / kAlignment) % kBitsPerWord);
+ static word OffsetToMask(uintptr_t offset) {
+ return static_cast<uintptr_t>(kWordHighBitMask) >> ((offset / kAlignment) % kBitsPerWord);
}
inline bool Set(const mirror::Object* obj) {
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index 9c1c5dc..d148ae5 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -118,7 +118,7 @@ inline void MarkSweep::VisitFieldsReferences(mirror::Object* obj, uint32_t ref_o
while (ref_offsets != 0) {
size_t right_shift = CLZ(ref_offsets);
MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
- mirror::Object* ref = obj->GetFieldObject<mirror::Object*>(field_offset, false);
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(field_offset, false);
visitor(obj, ref, field_offset, is_static);
ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
}
@@ -127,17 +127,17 @@ inline void MarkSweep::VisitFieldsReferences(mirror::Object* obj, uint32_t ref_o
// walk up the class inheritance hierarchy and find reference
// offsets the hard way. In the static case, just consider this
// class.
- for (const mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
- klass != NULL;
- klass = is_static ? NULL : klass->GetSuperClass()) {
+ for (mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
+ klass != nullptr;
+ klass = is_static ? nullptr : klass->GetSuperClass()) {
size_t num_reference_fields = (is_static
? klass->NumReferenceStaticFields()
: klass->NumReferenceInstanceFields());
for (size_t i = 0; i < num_reference_fields; ++i) {
mirror::ArtField* field = (is_static ? klass->GetStaticField(i)
- : klass->GetInstanceField(i));
+ : klass->GetInstanceField(i));
MemberOffset field_offset = field->GetOffset();
- mirror::Object* ref = obj->GetFieldObject<mirror::Object*>(field_offset, false);
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(field_offset, false);
visitor(obj, ref, field_offset, is_static);
}
}
@@ -150,7 +150,7 @@ inline void MarkSweep::VisitObjectArrayReferences(mirror::ObjectArray<mirror::Ob
const size_t length = static_cast<size_t>(array->GetLength());
for (size_t i = 0; i < length; ++i) {
mirror::Object* element = array->GetWithoutChecks(static_cast<int32_t>(i));
- const size_t width = sizeof(mirror::Object*);
+ const size_t width = sizeof(mirror::HeapReference<mirror::Object>);
MemberOffset offset(i * width + mirror::Array::DataOffset(width).Int32Value());
visitor(array, element, offset, false);
}
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 0c27a3b..bfedac7 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_H_
#define ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_H_
-#include "atomic_integer.h"
+#include "atomic.h"
#include "barrier.h"
#include "base/macros.h"
#include "base/mutex.h"
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 3fb78b0..03307f5 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -600,9 +600,9 @@ void SemiSpace::ScanObject(Object* obj) {
if (new_address != ref) {
DCHECK(new_address != nullptr);
// Don't need to mark the card since we updating the object address and not changing the
- // actual objects its pointing to. Using SetFieldPtr is better in this case since it does not
- // dirty cards and use additional memory.
- obj->SetFieldPtr(offset, new_address, false);
+ // actual objects its pointing to. Using SetFieldObjectWithoutWriteBarrier is better in this
+ // case since it does not dirty cards and use additional memory.
+ obj->SetFieldObjectWithoutWriteBarrier(offset, new_address, false);
}
}, kMovingClasses);
mirror::Class* klass = obj->GetClass();
diff --git a/runtime/gc/collector/semi_space.h b/runtime/gc/collector/semi_space.h
index f81a7c2..685b33c 100644
--- a/runtime/gc/collector/semi_space.h
+++ b/runtime/gc/collector/semi_space.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_GC_COLLECTOR_SEMI_SPACE_H_
#define ART_RUNTIME_GC_COLLECTOR_SEMI_SPACE_H_
-#include "atomic_integer.h"
+#include "atomic.h"
#include "barrier.h"
#include "base/macros.h"
#include "base/mutex.h"
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 309adb7..b1bbfc6 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -231,7 +231,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max
std::string error_str;
post_zygote_non_moving_space_mem_map_.reset(
MemMap::MapAnonymous("post zygote non-moving space", nullptr, 64 * MB,
- PROT_READ | PROT_WRITE, &error_str));
+ PROT_READ | PROT_WRITE, true, &error_str));
CHECK(post_zygote_non_moving_space_mem_map_.get() != nullptr) << error_str;
heap_begin = std::min(post_zygote_non_moving_space_mem_map_->Begin(), heap_begin);
heap_end = std::max(post_zygote_non_moving_space_mem_map_->End(), heap_end);
@@ -653,15 +653,15 @@ void Heap::ProcessReferences(TimingLogger& timings, bool clear_soft,
bool Heap::IsEnqueued(mirror::Object* ref) const {
// Since the references are stored as cyclic lists it means that once enqueued, the pending next
// will always be non-null.
- return ref->GetFieldObject<mirror::Object*>(GetReferencePendingNextOffset(), false) != nullptr;
+ return ref->GetFieldObject<mirror::Object>(GetReferencePendingNextOffset(), false) != nullptr;
}
-bool Heap::IsEnqueuable(const mirror::Object* ref) const {
+bool Heap::IsEnqueuable(mirror::Object* ref) const {
DCHECK(ref != nullptr);
const mirror::Object* queue =
- ref->GetFieldObject<mirror::Object*>(GetReferenceQueueOffset(), false);
+ ref->GetFieldObject<mirror::Object>(GetReferenceQueueOffset(), false);
const mirror::Object* queue_next =
- ref->GetFieldObject<mirror::Object*>(GetReferenceQueueNextOffset(), false);
+ ref->GetFieldObject<mirror::Object>(GetReferenceQueueNextOffset(), false);
return queue != nullptr && queue_next == nullptr;
}
@@ -720,7 +720,7 @@ static void MSpaceChunkCallback(void* start, void* end, size_t used_bytes, void*
void Heap::ThrowOutOfMemoryError(Thread* self, size_t byte_count, bool large_object_allocation) {
std::ostringstream oss;
- int64_t total_bytes_free = GetFreeMemory();
+ size_t total_bytes_free = GetFreeMemory();
oss << "Failed to allocate a " << byte_count << " byte allocation with " << total_bytes_free
<< " free bytes";
// If the allocation failed due to fragmentation, print out the largest continuous allocation.
@@ -805,7 +805,7 @@ bool Heap::IsHeapAddress(const mirror::Object* obj) const {
return FindSpaceFromObject(obj, true) != nullptr;
}
-bool Heap::IsLiveObjectLocked(const mirror::Object* obj, bool search_allocation_stack,
+bool Heap::IsLiveObjectLocked(mirror::Object* obj, bool search_allocation_stack,
bool search_live_stack, bool sorted) {
if (UNLIKELY(!IsAligned<kObjectAlignment>(obj))) {
return false;
@@ -874,7 +874,7 @@ bool Heap::IsLiveObjectLocked(const mirror::Object* obj, bool search_allocation_
return false;
}
-void Heap::VerifyObjectImpl(const mirror::Object* obj) {
+void Heap::VerifyObjectImpl(mirror::Object* obj) {
if (Thread::Current() == NULL ||
Runtime::Current()->GetThreadList()->GetLockOwner() == Thread::Current()->GetTid()) {
return;
@@ -887,9 +887,9 @@ bool Heap::VerifyClassClass(const mirror::Class* c) const {
// to run
const byte* raw_addr =
reinterpret_cast<const byte*>(c) + mirror::Object::ClassOffset().Int32Value();
- const mirror::Class* c_c = *reinterpret_cast<mirror::Class* const *>(raw_addr);
+ mirror::Class* c_c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
raw_addr = reinterpret_cast<const byte*>(c_c) + mirror::Object::ClassOffset().Int32Value();
- const mirror::Class* c_c_c = *reinterpret_cast<mirror::Class* const *>(raw_addr);
+ mirror::Class* c_c_c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
return c_c == c_c_c;
}
@@ -910,7 +910,7 @@ void Heap::DumpSpaces(std::ostream& stream) {
}
}
-void Heap::VerifyObjectBody(const mirror::Object* obj) {
+void Heap::VerifyObjectBody(mirror::Object* obj) {
CHECK(IsAligned<kObjectAlignment>(obj)) << "Object isn't aligned: " << obj;
// Ignore early dawn of the universe verifications.
if (UNLIKELY(static_cast<size_t>(num_bytes_allocated_.Load()) < 10 * KB)) {
@@ -918,7 +918,7 @@ void Heap::VerifyObjectBody(const mirror::Object* obj) {
}
const byte* raw_addr = reinterpret_cast<const byte*>(obj) +
mirror::Object::ClassOffset().Int32Value();
- const mirror::Class* c = *reinterpret_cast<mirror::Class* const *>(raw_addr);
+ mirror::Class* c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
if (UNLIKELY(c == NULL)) {
LOG(FATAL) << "Null class in object: " << obj;
} else if (UNLIKELY(!IsAligned<kObjectAlignment>(c))) {
@@ -949,7 +949,7 @@ void Heap::VerifyHeap() {
GetLiveBitmap()->Walk(Heap::VerificationCallback, this);
}
-void Heap::RecordFree(int64_t freed_objects, int64_t freed_bytes) {
+void Heap::RecordFree(size_t freed_objects, size_t freed_bytes) {
DCHECK_LE(freed_bytes, num_bytes_allocated_.Load());
num_bytes_allocated_.FetchAndSub(freed_bytes);
if (Runtime::Current()->HasStatsEnabled()) {
@@ -1059,9 +1059,9 @@ class InstanceCounter {
: classes_(classes), use_is_assignable_from_(use_is_assignable_from), counts_(counts) {
}
- void operator()(const mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ void operator()(mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
for (size_t i = 0; i < classes_.size(); ++i) {
- const mirror::Class* instance_class = o->GetClass();
+ mirror::Class* instance_class = o->GetClass();
if (use_is_assignable_from_) {
if (instance_class != NULL && classes_[i]->IsAssignableFrom(instance_class)) {
++counts_[i];
@@ -1103,11 +1103,11 @@ class InstanceCollector {
: class_(c), max_count_(max_count), instances_(instances) {
}
- void operator()(const mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const mirror::Class* instance_class = o->GetClass();
+ void operator()(mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::Class* instance_class = o->GetClass();
if (instance_class == class_) {
if (max_count_ == 0 || instances_.size() < max_count_) {
- instances_.push_back(const_cast<mirror::Object*>(o));
+ instances_.push_back(o);
}
}
}
@@ -1190,8 +1190,8 @@ void Heap::TransitionCollector(CollectorType collector_type) {
return;
}
uint64_t start_time = NanoTime();
- int32_t before_size = GetTotalMemory();
- int32_t before_allocated = num_bytes_allocated_.Load();
+ uint32_t before_size = GetTotalMemory();
+ uint32_t before_allocated = num_bytes_allocated_.Load();
ThreadList* tl = Runtime::Current()->GetThreadList();
Thread* self = Thread::Current();
ScopedThreadStateChange tsc(self, kWaitingPerformingGc);
@@ -1718,7 +1718,7 @@ class VerifyReferenceVisitor {
// TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for smarter
// analysis on visitors.
- void operator()(const mirror::Object* obj, const mirror::Object* ref,
+ void operator()(mirror::Object* obj, mirror::Object* ref,
const MemberOffset& offset, bool /* is_static */) const
NO_THREAD_SAFETY_ANALYSIS {
if (ref == nullptr || IsLive(ref)) {
@@ -1813,7 +1813,7 @@ class VerifyReferenceVisitor {
}
}
- bool IsLive(const mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
+ bool IsLive(mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
return heap_->IsLiveObjectLocked(obj, true, false, true);
}
@@ -1898,7 +1898,7 @@ class VerifyReferenceCardVisitor {
// TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for
// annotalysis on visitors.
- void operator()(const mirror::Object* obj, const mirror::Object* ref, const MemberOffset& offset,
+ void operator()(mirror::Object* obj, mirror::Object* ref, const MemberOffset& offset,
bool is_static) const NO_THREAD_SAFETY_ANALYSIS {
// Filter out class references since changing an object's class does not mark the card as dirty.
// Also handles large objects, since the only reference they hold is a class reference.
@@ -1926,13 +1926,13 @@ class VerifyReferenceCardVisitor {
// Print which field of the object is dead.
if (!obj->IsObjectArray()) {
- const mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
+ mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
CHECK(klass != NULL);
- const mirror::ObjectArray<mirror::ArtField>* fields = is_static ? klass->GetSFields()
- : klass->GetIFields();
+ mirror::ObjectArray<mirror::ArtField>* fields = is_static ? klass->GetSFields()
+ : klass->GetIFields();
CHECK(fields != NULL);
for (int32_t i = 0; i < fields->GetLength(); ++i) {
- const mirror::ArtField* cur = fields->Get(i);
+ mirror::ArtField* cur = fields->Get(i);
if (cur->GetOffset().Int32Value() == offset.Int32Value()) {
LOG(ERROR) << (is_static ? "Static " : "") << "field in the live stack is "
<< PrettyField(cur);
@@ -1940,7 +1940,7 @@ class VerifyReferenceCardVisitor {
}
}
} else {
- const mirror::ObjectArray<mirror::Object>* object_array =
+ mirror::ObjectArray<mirror::Object>* object_array =
obj->AsObjectArray<mirror::Object>();
for (int32_t i = 0; i < object_array->GetLength(); ++i) {
if (object_array->Get(i) == ref) {
@@ -2278,14 +2278,14 @@ void Heap::SetReferenceReferent(mirror::Object* reference, mirror::Object* refer
mirror::Object* Heap::GetReferenceReferent(mirror::Object* reference) {
DCHECK(reference != NULL);
DCHECK_NE(reference_referent_offset_.Uint32Value(), 0U);
- return reference->GetFieldObject<mirror::Object*>(reference_referent_offset_, true);
+ return reference->GetFieldObject<mirror::Object>(reference_referent_offset_, true);
}
void Heap::AddFinalizerReference(Thread* self, mirror::Object* object) {
ScopedObjectAccess soa(self);
JValue result;
ArgArray arg_array(NULL, 0);
- arg_array.Append(reinterpret_cast<uint32_t>(object));
+ arg_array.Append(object);
soa.DecodeMethod(WellKnownClasses::java_lang_ref_FinalizerReference_add)->Invoke(self,
arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
}
@@ -2299,7 +2299,7 @@ void Heap::EnqueueClearedReferences() {
ScopedObjectAccess soa(self);
JValue result;
ArgArray arg_array(NULL, 0);
- arg_array.Append(reinterpret_cast<uint32_t>(cleared_references_.GetList()));
+ arg_array.Append(cleared_references_.GetList());
soa.DecodeMethod(WellKnownClasses::java_lang_ref_ReferenceQueue_add)->Invoke(soa.Self(),
arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
}
@@ -2477,8 +2477,8 @@ void Heap::RegisterNativeFree(JNIEnv* env, int bytes) {
} while (!native_bytes_allocated_.CompareAndSwap(expected_size, new_size));
}
-int64_t Heap::GetTotalMemory() const {
- int64_t ret = 0;
+size_t Heap::GetTotalMemory() const {
+ size_t ret = 0;
for (const auto& space : continuous_spaces_) {
// Currently don't include the image space.
if (!space->IsImageSpace()) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 26d67a1..499d27c 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -21,7 +21,7 @@
#include <string>
#include <vector>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/timing_logger.h"
#include "gc/accounting/atomic_stack.h"
#include "gc/accounting/card_table.h"
@@ -204,14 +204,14 @@ class Heap {
void ChangeCollector(CollectorType collector_type);
// The given reference is believed to be to an object in the Java heap, check the soundness of it.
- void VerifyObjectImpl(const mirror::Object* o);
- void VerifyObject(const mirror::Object* o) {
+ void VerifyObjectImpl(mirror::Object* o);
+ void VerifyObject(mirror::Object* o) {
if (o != nullptr && this != nullptr && verify_object_mode_ > kNoHeapVerification) {
VerifyObjectImpl(o);
}
}
// Check that c.getClass() == c.getClass().getClass().
- bool VerifyClassClass(const mirror::Class* c) const;
+ bool VerifyClassClass(const mirror::Class* c) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Check sanity of all live references.
void VerifyHeap() LOCKS_EXCLUDED(Locks::heap_bitmap_lock_);
@@ -232,9 +232,9 @@ class Heap {
// Returns true if 'obj' is a live heap object, false otherwise (including for invalid addresses).
// Requires the heap lock to be held.
- bool IsLiveObjectLocked(const mirror::Object* obj, bool search_allocation_stack = true,
+ bool IsLiveObjectLocked(mirror::Object* obj, bool search_allocation_stack = true,
bool search_live_stack = true, bool sorted = false)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
// Returns true if there is any chance that the object (obj) will move.
bool IsMovableObject(const mirror::Object* obj) const;
@@ -358,7 +358,7 @@ class Heap {
// Freed bytes can be negative in cases where we copy objects from a compacted space to a
// free-list backed space.
- void RecordFree(int64_t freed_objects, int64_t freed_bytes);
+ void RecordFree(size_t freed_objects, size_t freed_bytes);
// Must be called if a field of an Object in the heap changes, and before any GC safe-point.
// The call is not needed if NULL is stored in the field.
@@ -411,16 +411,16 @@ class Heap {
// consume. For a regular VM this would relate to the -Xmx option and would return -1 if no Xmx
// were specified. Android apps start with a growth limit (small heap size) which is
// cleared/extended for large apps.
- int64_t GetMaxMemory() const {
+ size_t GetMaxMemory() const {
return growth_limit_;
}
// Implements java.lang.Runtime.totalMemory, returning the amount of memory consumed by an
// application.
- int64_t GetTotalMemory() const;
+ size_t GetTotalMemory() const;
// Implements java.lang.Runtime.freeMemory.
- int64_t GetFreeMemory() const {
+ size_t GetFreeMemory() const {
return GetTotalMemory() - num_bytes_allocated_;
}
@@ -550,7 +550,8 @@ class Heap {
static bool IsCompactingGC(CollectorType collector_type) {
return collector_type == kCollectorTypeSS || collector_type == kCollectorTypeGSS;
}
- bool ShouldAllocLargeObject(mirror::Class* c, size_t byte_count) const;
+ bool ShouldAllocLargeObject(mirror::Class* c, size_t byte_count) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ALWAYS_INLINE void CheckConcurrentGC(Thread* self, size_t new_num_bytes_allocated,
mirror::Object* obj);
@@ -596,8 +597,8 @@ class Heap {
}
void EnqueueClearedReferences();
// Returns true if the reference object has not yet been enqueued.
- bool IsEnqueuable(const mirror::Object* ref) const;
- bool IsEnqueued(mirror::Object* ref) const;
+ bool IsEnqueuable(mirror::Object* ref) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsEnqueued(mirror::Object* ref) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DelayReferenceReferent(mirror::Class* klass, mirror::Object* obj, RootVisitor mark_visitor,
void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -644,7 +645,7 @@ class Heap {
// No thread saftey analysis since we call this everywhere and it is impossible to find a proper
// lock ordering for it.
- void VerifyObjectBody(const mirror::Object *obj) NO_THREAD_SAFETY_ANALYSIS;
+ void VerifyObjectBody(mirror::Object *obj) NO_THREAD_SAFETY_ANALYSIS;
static void VerificationCallback(mirror::Object* obj, void* arg)
SHARED_LOCKS_REQUIRED(GlobalSychronization::heap_bitmap_lock_);
@@ -781,13 +782,13 @@ class Heap {
size_t total_objects_freed_ever_;
// Number of bytes allocated. Adjusted after each allocation and free.
- AtomicInteger num_bytes_allocated_;
+ Atomic<size_t> num_bytes_allocated_;
// Bytes which are allocated and managed by native code but still need to be accounted for.
- AtomicInteger native_bytes_allocated_;
+ Atomic<size_t> native_bytes_allocated_;
// Data structure GC overhead.
- AtomicInteger gc_memory_overhead_;
+ Atomic<size_t> gc_memory_overhead_;
// Heap verification flags.
const bool verify_missing_card_marks_;
diff --git a/runtime/gc/reference_queue.cc b/runtime/gc/reference_queue.cc
index d006349..2d73a71 100644
--- a/runtime/gc/reference_queue.cc
+++ b/runtime/gc/reference_queue.cc
@@ -52,8 +52,7 @@ void ReferenceQueue::EnqueuePendingReference(mirror::Object* ref) {
ref->SetFieldObject(pending_next_offset, ref, false);
list_ = ref;
} else {
- mirror::Object* head =
- list_->GetFieldObject<mirror::Object*>(pending_next_offset, false);
+ mirror::Object* head = list_->GetFieldObject<mirror::Object>(pending_next_offset, false);
ref->SetFieldObject(pending_next_offset, head, false);
list_->SetFieldObject(pending_next_offset, ref, false);
}
@@ -62,7 +61,7 @@ void ReferenceQueue::EnqueuePendingReference(mirror::Object* ref) {
mirror::Object* ReferenceQueue::DequeuePendingReference() {
DCHECK(!IsEmpty());
MemberOffset pending_next_offset = heap_->GetReferencePendingNextOffset();
- mirror::Object* head = list_->GetFieldObject<mirror::Object*>(pending_next_offset, false);
+ mirror::Object* head = list_->GetFieldObject<mirror::Object>(pending_next_offset, false);
DCHECK(head != nullptr);
mirror::Object* ref;
// Note: the following code is thread-safe because it is only called from ProcessReferences which
@@ -71,7 +70,7 @@ mirror::Object* ReferenceQueue::DequeuePendingReference() {
ref = list_;
list_ = nullptr;
} else {
- mirror::Object* next = head->GetFieldObject<mirror::Object*>(pending_next_offset, false);
+ mirror::Object* next = head->GetFieldObject<mirror::Object>(pending_next_offset, false);
list_->SetFieldObject(pending_next_offset, next, false);
ref = head;
}
@@ -84,11 +83,11 @@ void ReferenceQueue::Dump(std::ostream& os) const {
os << "Reference starting at list_=" << list_ << "\n";
while (cur != nullptr) {
mirror::Object* pending_next =
- cur->GetFieldObject<mirror::Object*>(heap_->GetReferencePendingNextOffset(), false);
+ cur->GetFieldObject<mirror::Object>(heap_->GetReferencePendingNextOffset(), false);
os << "PendingNext=" << pending_next;
if (cur->GetClass()->IsFinalizerReferenceClass()) {
os << " Zombie=" <<
- cur->GetFieldObject<mirror::Object*>(heap_->GetFinalizerReferenceZombieOffset(), false);
+ cur->GetFieldObject<mirror::Object>(heap_->GetFinalizerReferenceZombieOffset(), false);
}
os << "\n";
cur = pending_next;
diff --git a/runtime/gc/reference_queue.h b/runtime/gc/reference_queue.h
index 89589c3..3f3069e 100644
--- a/runtime/gc/reference_queue.h
+++ b/runtime/gc/reference_queue.h
@@ -21,7 +21,7 @@
#include <string>
#include <vector>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/timing_logger.h"
#include "globals.h"
#include "gtest/gtest.h"
@@ -83,7 +83,7 @@ class ReferenceQueue {
private:
// Lock, used for parallel GC reference enqueuing. It allows for multiple threads simultaneously
// calling AtomicEnqueueIfNotEnqueued.
- Mutex lock_;
+ Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
// The heap contains the reference offsets.
Heap* const heap_;
// The actual reference list. Not a root since it will be nullptr when the GC is not running.
diff --git a/runtime/gc/space/bump_pointer_space.cc b/runtime/gc/space/bump_pointer_space.cc
index 4dc17df..a314d74 100644
--- a/runtime/gc/space/bump_pointer_space.cc
+++ b/runtime/gc/space/bump_pointer_space.cc
@@ -29,7 +29,7 @@ BumpPointerSpace* BumpPointerSpace::Create(const std::string& name, size_t capac
capacity = RoundUp(capacity, kPageSize);
std::string error_msg;
UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), requested_begin, capacity,
- PROT_READ | PROT_WRITE, &error_msg));
+ PROT_READ | PROT_WRITE, true, &error_msg));
if (mem_map.get() == nullptr) {
LOG(ERROR) << "Failed to allocate pages for alloc space (" << name << ") of size "
<< PrettySize(capacity) << " with message " << error_msg;
@@ -69,7 +69,7 @@ mirror::Object* BumpPointerSpace::Alloc(Thread*, size_t num_bytes, size_t* bytes
return ret;
}
-size_t BumpPointerSpace::AllocationSize(const mirror::Object* obj) {
+size_t BumpPointerSpace::AllocationSize(mirror::Object* obj) {
return AllocationSizeNonvirtual(obj);
}
diff --git a/runtime/gc/space/bump_pointer_space.h b/runtime/gc/space/bump_pointer_space.h
index 3e25b6b..d73fe3b 100644
--- a/runtime/gc/space/bump_pointer_space.h
+++ b/runtime/gc/space/bump_pointer_space.h
@@ -49,8 +49,7 @@ class BumpPointerSpace : public ContinuousMemMapAllocSpace {
mirror::Object* AllocNonvirtualWithoutAccounting(size_t num_bytes);
// Return the storage space required by obj.
- virtual size_t AllocationSize(const mirror::Object* obj)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ virtual size_t AllocationSize(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// NOPS unless we support free lists.
virtual size_t Free(Thread*, mirror::Object*) {
@@ -60,7 +59,7 @@ class BumpPointerSpace : public ContinuousMemMapAllocSpace {
return 0;
}
- size_t AllocationSizeNonvirtual(const mirror::Object* obj)
+ size_t AllocationSizeNonvirtual(mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return obj->SizeOf();
}
@@ -135,7 +134,6 @@ class BumpPointerSpace : public ContinuousMemMapAllocSpace {
byte* AllocBlock(size_t bytes) EXCLUSIVE_LOCKS_REQUIRED(block_lock_);
void RevokeThreadLocalBuffersLocked(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(block_lock_);
- size_t InternalAllocationSize(const mirror::Object* obj);
mirror::Object* AllocWithoutGrowthLocked(size_t num_bytes, size_t* bytes_allocated)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index 9ae6a33..931ed21 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -228,7 +228,7 @@ extern "C" void* art_heap_morecore(void* mspace, intptr_t increment) {
return dlmalloc_space->MoreCore(increment);
}
-size_t DlMallocSpace::AllocationSize(const mirror::Object* obj) {
+size_t DlMallocSpace::AllocationSize(mirror::Object* obj) {
return AllocationSizeNonvirtual(obj);
}
diff --git a/runtime/gc/space/dlmalloc_space.h b/runtime/gc/space/dlmalloc_space.h
index 24308f7..4507c36 100644
--- a/runtime/gc/space/dlmalloc_space.h
+++ b/runtime/gc/space/dlmalloc_space.h
@@ -48,13 +48,15 @@ class DlMallocSpace : public MallocSpace {
virtual mirror::Object* AllocWithGrowth(Thread* self, size_t num_bytes,
size_t* bytes_allocated) LOCKS_EXCLUDED(lock_);
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated);
- virtual size_t AllocationSize(const mirror::Object* obj);
- virtual size_t Free(Thread* self, mirror::Object* ptr);
- virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs);
+ virtual size_t AllocationSize(mirror::Object* obj);
+ virtual size_t Free(Thread* self, mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Object* AllocNonvirtual(Thread* self, size_t num_bytes, size_t* bytes_allocated);
- size_t AllocationSizeNonvirtual(const mirror::Object* obj) {
+ size_t AllocationSizeNonvirtual(mirror::Object* obj) {
void* obj_ptr = const_cast<void*>(reinterpret_cast<const void*>(obj));
return mspace_usable_size(obj_ptr) + kChunkOverhead;
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 4777cc6..ebad8dd 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -35,7 +35,7 @@ namespace art {
namespace gc {
namespace space {
-AtomicInteger ImageSpace::bitmap_index_(0);
+Atomic<uint32_t> ImageSpace::bitmap_index_(0);
ImageSpace::ImageSpace(const std::string& name, MemMap* mem_map,
accounting::SpaceBitmap* live_bitmap)
@@ -171,7 +171,7 @@ void ImageSpace::VerifyImageAllocations() {
byte* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
while (current < End()) {
DCHECK_ALIGNED(current, kObjectAlignment);
- const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(current);
+ mirror::Object* obj = reinterpret_cast<mirror::Object*>(current);
CHECK(live_bitmap_->Test(obj));
CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class";
current += RoundUp(obj->SizeOf(), kObjectAlignment);
@@ -227,7 +227,7 @@ ImageSpace* ImageSpace::Init(const char* image_file_name, bool validate_oat_file
*error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str());
return nullptr;
}
- size_t bitmap_index = bitmap_index_.FetchAndAdd(1);
+ uint32_t bitmap_index = bitmap_index_.FetchAndAdd(1);
std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", image_file_name,
bitmap_index));
UniquePtr<accounting::SpaceBitmap> bitmap(
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index c3f0ae6..9e19774 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -94,7 +94,7 @@ class ImageSpace : public MemMapSpace {
friend class Space;
- static AtomicInteger bitmap_index_;
+ static Atomic<uint32_t> bitmap_index_;
UniquePtr<accounting::SpaceBitmap> live_bitmap_;
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index 7fcfed4..987a655 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -60,7 +60,7 @@ mirror::Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes,
size_t* bytes_allocated) {
std::string error_msg;
MemMap* mem_map = MemMap::MapAnonymous("large object space allocation", NULL, num_bytes,
- PROT_READ | PROT_WRITE, &error_msg);
+ PROT_READ | PROT_WRITE, true, &error_msg);
if (UNLIKELY(mem_map == NULL)) {
LOG(WARNING) << "Large object allocation failed: " << error_msg;
return NULL;
@@ -92,9 +92,9 @@ size_t LargeObjectMapSpace::Free(Thread* self, mirror::Object* ptr) {
return allocation_size;
}
-size_t LargeObjectMapSpace::AllocationSize(const mirror::Object* obj) {
+size_t LargeObjectMapSpace::AllocationSize(mirror::Object* obj) {
MutexLock mu(Thread::Current(), lock_);
- MemMaps::iterator found = mem_maps_.find(const_cast<mirror::Object*>(obj));
+ MemMaps::iterator found = mem_maps_.find(obj);
CHECK(found != mem_maps_.end()) << "Attempted to get size of a large object which is not live";
return found->second->Size();
}
@@ -134,7 +134,7 @@ FreeListSpace* FreeListSpace::Create(const std::string& name, byte* requested_be
CHECK_EQ(size % kAlignment, 0U);
std::string error_msg;
MemMap* mem_map = MemMap::MapAnonymous(name.c_str(), requested_begin, size,
- PROT_READ | PROT_WRITE, &error_msg);
+ PROT_READ | PROT_WRITE, true, &error_msg);
CHECK(mem_map != NULL) << "Failed to allocate large object space mem map: " << error_msg;
return new FreeListSpace(name, mem_map, mem_map->Begin(), mem_map->End());
}
@@ -244,7 +244,7 @@ bool FreeListSpace::Contains(const mirror::Object* obj) const {
return mem_map_->HasAddress(obj);
}
-size_t FreeListSpace::AllocationSize(const mirror::Object* obj) {
+size_t FreeListSpace::AllocationSize(mirror::Object* obj) {
AllocationHeader* header = GetAllocationHeader(obj);
DCHECK(Contains(obj));
DCHECK(!header->IsFree());
diff --git a/runtime/gc/space/large_object_space.h b/runtime/gc/space/large_object_space.h
index cd7c383..5274c8d 100644
--- a/runtime/gc/space/large_object_space.h
+++ b/runtime/gc/space/large_object_space.h
@@ -92,7 +92,7 @@ class LargeObjectMapSpace : public LargeObjectSpace {
static LargeObjectMapSpace* Create(const std::string& name);
// Return the storage space required by obj.
- size_t AllocationSize(const mirror::Object* obj);
+ size_t AllocationSize(mirror::Object* obj);
mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated);
size_t Free(Thread* self, mirror::Object* ptr);
void Walk(DlMallocSpace::WalkCallback, void* arg) LOCKS_EXCLUDED(lock_);
@@ -118,8 +118,7 @@ class FreeListSpace : public LargeObjectSpace {
virtual ~FreeListSpace();
static FreeListSpace* Create(const std::string& name, byte* requested_begin, size_t capacity);
- size_t AllocationSize(const mirror::Object* obj)
- EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ size_t AllocationSize(mirror::Object* obj) EXCLUSIVE_LOCKS_REQUIRED(lock_);
mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated);
size_t Free(Thread* self, mirror::Object* obj);
bool Contains(const mirror::Object* obj) const;
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index 6c6cb97..f90e6c7 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -87,7 +87,7 @@ MemMap* MallocSpace::CreateMemMap(const std::string& name, size_t starting_size,
std::string error_msg;
MemMap* mem_map = MemMap::MapAnonymous(name.c_str(), requested_begin, *capacity,
- PROT_READ | PROT_WRITE, &error_msg);
+ PROT_READ | PROT_WRITE, true, &error_msg);
if (mem_map == nullptr) {
LOG(ERROR) << "Failed to allocate pages for alloc space (" << name << ") of size "
<< PrettySize(*capacity) << ": " << error_msg;
diff --git a/runtime/gc/space/malloc_space.h b/runtime/gc/space/malloc_space.h
index 9a42e2c..f17bcd2 100644
--- a/runtime/gc/space/malloc_space.h
+++ b/runtime/gc/space/malloc_space.h
@@ -58,9 +58,11 @@ class MallocSpace : public ContinuousMemMapAllocSpace {
// Allocate num_bytes allowing the underlying space to grow.
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated) = 0;
// Return the storage space required by obj.
- virtual size_t AllocationSize(const mirror::Object* obj) = 0;
- virtual size_t Free(Thread* self, mirror::Object* ptr) = 0;
- virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) = 0;
+ virtual size_t AllocationSize(mirror::Object* obj) = 0;
+ virtual size_t Free(Thread* self, mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
+ virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
#ifndef NDEBUG
virtual void CheckMoreCoreForPrecondition() {} // to be overridden in the debug build.
@@ -136,7 +138,9 @@ class MallocSpace : public ContinuousMemMapAllocSpace {
virtual void* CreateAllocator(void* base, size_t morecore_start, size_t initial_size,
bool low_memory_mode) = 0;
- void RegisterRecentFree(mirror::Object* ptr) EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ void RegisterRecentFree(mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(lock_);
virtual accounting::SpaceBitmap::SweepCallback* GetSweepCallback() {
return &SweepCallback;
@@ -163,7 +167,8 @@ class MallocSpace : public ContinuousMemMapAllocSpace {
size_t growth_limit_;
private:
- static void SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg);
+ static void SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
DISALLOW_COPY_AND_ASSIGN(MallocSpace);
};
@@ -204,13 +209,14 @@ class ValgrindMallocSpace : public BaseMallocSpaceType {
return result;
}
- virtual size_t AllocationSize(const mirror::Object* obj) {
- size_t result = BaseMallocSpaceType::AllocationSize(reinterpret_cast<const mirror::Object*>(
- reinterpret_cast<const byte*>(obj) - kValgrindRedZoneBytes));
+ virtual size_t AllocationSize(mirror::Object* obj) {
+ size_t result = BaseMallocSpaceType::AllocationSize(reinterpret_cast<mirror::Object*>(
+ reinterpret_cast<byte*>(obj) - kValgrindRedZoneBytes));
return result - 2 * kValgrindRedZoneBytes;
}
- virtual size_t Free(Thread* self, mirror::Object* ptr) {
+ virtual size_t Free(Thread* self, mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
void* obj_after_rdz = reinterpret_cast<void*>(ptr);
void* obj_with_rdz = reinterpret_cast<byte*>(obj_after_rdz) - kValgrindRedZoneBytes;
// Make redzones undefined.
@@ -221,7 +227,8 @@ class ValgrindMallocSpace : public BaseMallocSpaceType {
return freed - 2 * kValgrindRedZoneBytes;
}
- virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) {
+ virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
size_t freed = 0;
for (size_t i = 0; i < num_ptrs; i++) {
freed += Free(self, ptrs[i]);
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 177e38e..86e441e 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -220,7 +220,7 @@ extern "C" void* art_heap_rosalloc_morecore(allocator::RosAlloc* rosalloc, intpt
return rosalloc_space->MoreCore(increment);
}
-size_t RosAllocSpace::AllocationSize(const mirror::Object* obj) {
+size_t RosAllocSpace::AllocationSize(mirror::Object* obj) {
return AllocationSizeNonvirtual(obj);
}
diff --git a/runtime/gc/space/rosalloc_space.h b/runtime/gc/space/rosalloc_space.h
index 555eb3c..4cd5a6d 100644
--- a/runtime/gc/space/rosalloc_space.h
+++ b/runtime/gc/space/rosalloc_space.h
@@ -47,13 +47,15 @@ class RosAllocSpace : public MallocSpace {
virtual mirror::Object* AllocWithGrowth(Thread* self, size_t num_bytes,
size_t* bytes_allocated) LOCKS_EXCLUDED(lock_);
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated);
- virtual size_t AllocationSize(const mirror::Object* obj);
- virtual size_t Free(Thread* self, mirror::Object* ptr);
- virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs);
+ virtual size_t AllocationSize(mirror::Object* obj);
+ virtual size_t Free(Thread* self, mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Object* AllocNonvirtual(Thread* self, size_t num_bytes, size_t* bytes_allocated);
- size_t AllocationSizeNonvirtual(const mirror::Object* obj)
+ size_t AllocationSizeNonvirtual(mirror::Object* obj)
NO_THREAD_SAFETY_ANALYSIS {
// TODO: NO_THREAD_SAFETY_ANALYSIS because SizeOf() requires that mutator_lock is held.
void* obj_ptr = const_cast<void*>(reinterpret_cast<const void*>(obj));
diff --git a/runtime/gc/space/space.h b/runtime/gc/space/space.h
index 95a79ec..98e6f65 100644
--- a/runtime/gc/space/space.h
+++ b/runtime/gc/space/space.h
@@ -223,7 +223,7 @@ class AllocSpace {
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated) = 0;
// Return the storage space required by obj.
- virtual size_t AllocationSize(const mirror::Object* obj) = 0;
+ virtual size_t AllocationSize(mirror::Object* obj) = 0;
// Returns how many bytes were freed.
virtual size_t Free(Thread* self, mirror::Object* ptr) = 0;
diff --git a/runtime/gc/space/space_test.cc b/runtime/gc/space/space_test.cc
index 427d547..9989ffe 100644
--- a/runtime/gc/space/space_test.cc
+++ b/runtime/gc/space/space_test.cc
@@ -163,6 +163,7 @@ void SpaceTest::ZygoteSpaceTestBody(CreateSpaceFn create_space) {
EXPECT_TRUE(ptr5 == NULL);
// Release some memory.
+ ScopedObjectAccess soa(self);
size_t free3 = space->AllocationSize(ptr3);
EXPECT_EQ(free3, ptr3_bytes_allocated);
EXPECT_EQ(free3, space->Free(self, ptr3));
@@ -257,6 +258,7 @@ void SpaceTest::AllocAndFreeTestBody(CreateSpaceFn create_space) {
EXPECT_TRUE(ptr5 == NULL);
// Release some memory.
+ ScopedObjectAccess soa(self);
size_t free3 = space->AllocationSize(ptr3);
EXPECT_EQ(free3, ptr3_bytes_allocated);
space->Free(self, ptr3);
@@ -354,30 +356,36 @@ void SpaceTest::AllocAndFreeListTestBody(CreateSpaceFn create_space) {
for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
size_t allocation_size = 0;
lots_of_objects[i] = space->Alloc(self, 16, &allocation_size);
- EXPECT_TRUE(lots_of_objects[i] != NULL);
+ EXPECT_TRUE(lots_of_objects[i] != nullptr);
InstallClass(lots_of_objects[i], 16);
EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i]));
}
- // Release memory and check pointers are NULL
- space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
- for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
- EXPECT_TRUE(lots_of_objects[i] == NULL);
+ // Release memory and check pointers are NULL.
+ {
+ ScopedObjectAccess soa(self);
+ space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
+ for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
+ EXPECT_TRUE(lots_of_objects[i] == nullptr);
+ }
}
// Succeeds, fits by adjusting the max allowed footprint.
for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
size_t allocation_size = 0;
lots_of_objects[i] = space->AllocWithGrowth(self, 1024, &allocation_size);
- EXPECT_TRUE(lots_of_objects[i] != NULL);
+ EXPECT_TRUE(lots_of_objects[i] != nullptr);
InstallClass(lots_of_objects[i], 1024);
EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i]));
}
// Release memory and check pointers are NULL
- space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
- for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
- EXPECT_TRUE(lots_of_objects[i] == NULL);
+ {
+ ScopedObjectAccess soa(self);
+ space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
+ for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
+ EXPECT_TRUE(lots_of_objects[i] == nullptr);
+ }
}
}
@@ -491,28 +499,30 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(MallocSpace* space, intptr_t
break;
}
- // Free some objects
- for (size_t i = 0; i < last_object; i += free_increment) {
- mirror::Object* object = lots_of_objects.get()[i];
- if (object == NULL) {
- continue;
- }
- size_t allocation_size = space->AllocationSize(object);
- if (object_size > 0) {
- EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
- } else {
- EXPECT_GE(allocation_size, 8u);
+ {
+ // Free some objects
+ ScopedObjectAccess soa(self);
+ for (size_t i = 0; i < last_object; i += free_increment) {
+ mirror::Object* object = lots_of_objects.get()[i];
+ if (object == NULL) {
+ continue;
+ }
+ size_t allocation_size = space->AllocationSize(object);
+ if (object_size > 0) {
+ EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
+ } else {
+ EXPECT_GE(allocation_size, 8u);
+ }
+ space->Free(self, object);
+ lots_of_objects.get()[i] = NULL;
+ amount_allocated -= allocation_size;
+ footprint = space->GetFootprint();
+ EXPECT_GE(space->Size(), footprint); // invariant
}
- space->Free(self, object);
- lots_of_objects.get()[i] = NULL;
- amount_allocated -= allocation_size;
- footprint = space->GetFootprint();
- EXPECT_GE(space->Size(), footprint); // invariant
- }
- free_increment >>= 1;
+ free_increment >>= 1;
+ }
}
-
// The space has become empty here before allocating a large object
// below. For RosAlloc, revoke thread-local runs, which are kept
// even when empty for a performance reason, so that they won't
@@ -540,8 +550,10 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(MallocSpace* space, intptr_t
EXPECT_LE(space->Size(), growth_limit);
// Clean up
- space->Free(self, large_object);
-
+ {
+ ScopedObjectAccess soa(self);
+ space->Free(self, large_object);
+ }
// Sanity check footprint
footprint = space->GetFootprint();
EXPECT_LE(footprint, growth_limit);
diff --git a/runtime/gc/space/zygote_space.h b/runtime/gc/space/zygote_space.h
index 10a5492..e0035b3 100644
--- a/runtime/gc/space/zygote_space.h
+++ b/runtime/gc/space/zygote_space.h
@@ -54,7 +54,7 @@ class ZygoteSpace : public ContinuousMemMapAllocSpace {
LOG(FATAL) << "Unimplemented";
return nullptr;
}
- virtual size_t AllocationSize(const mirror::Object* obj) {
+ virtual size_t AllocationSize(mirror::Object* obj) {
LOG(FATAL) << "Unimplemented";
return 0;
}
diff --git a/runtime/globals.h b/runtime/globals.h
index b1ccbdc..8c3ae56 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -36,7 +36,7 @@ static constexpr size_t kPointerSize = sizeof(void*);
static constexpr size_t kBitsPerByte = 8;
static constexpr size_t kBitsPerByteLog2 = 3;
static constexpr int kBitsPerWord = kWordSize * kBitsPerByte;
-static constexpr size_t kWordHighBitMask = 1 << (kBitsPerWord - 1);
+static constexpr size_t kWordHighBitMask = static_cast<size_t>(1) << (kBitsPerWord - 1);
// Required stack alignment
static constexpr size_t kStackAlignment = 16;
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 9f899e8..24d403d 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -167,14 +167,8 @@ enum HprofBasicType {
hprof_basic_long = 11,
};
-typedef uint32_t HprofId;
-typedef HprofId HprofStringId;
-typedef HprofId HprofObjectId;
-typedef HprofId HprofClassObjectId;
-typedef std::set<mirror::Class*> ClassSet;
-typedef std::set<mirror::Class*>::iterator ClassSetIterator;
-typedef SafeMap<std::string, size_t> StringMap;
-typedef SafeMap<std::string, size_t>::iterator StringMapIterator;
+typedef uint32_t HprofStringId;
+typedef uint32_t HprofClassObjectId;
// Represents a top-level hprof record, whose serialized format is:
// U1 TAG: denoting the type of the record
@@ -183,11 +177,8 @@ typedef SafeMap<std::string, size_t>::iterator StringMapIterator;
// U1* BODY: as many bytes as specified in the above uint32_t field
class HprofRecord {
public:
- HprofRecord() {
- dirty_ = false;
- alloc_length_ = 128;
+ HprofRecord() : alloc_length_(128), fp_(nullptr), tag_(0), time_(0), length_(0), dirty_(false) {
body_ = reinterpret_cast<unsigned char*>(malloc(alloc_length_));
- fp_ = NULL;
}
~HprofRecord() {
@@ -233,7 +224,7 @@ class HprofRecord {
int AddU1(uint8_t value) {
int err = GuaranteeRecordAppend(1);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -253,13 +244,30 @@ class HprofRecord {
return AddU8List(&value, 1);
}
- int AddId(HprofObjectId value) {
- return AddU4((uint32_t) value);
+ int AddObjectId(const mirror::Object* value) {
+ return AddU4(PointerToLowMemUInt32(value));
+ }
+
+ // The ID for the synthetic object generated to account for class static overhead.
+ int AddClassStaticsId(const mirror::Class* value) {
+ return AddU4(1 | PointerToLowMemUInt32(value));
+ }
+
+ int AddJniGlobalRefId(jobject value) {
+ return AddU4(PointerToLowMemUInt32(value));
+ }
+
+ int AddClassId(HprofClassObjectId value) {
+ return AddU4(value);
+ }
+
+ int AddStringId(HprofStringId value) {
+ return AddU4(value);
}
int AddU1List(const uint8_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -270,7 +278,7 @@ class HprofRecord {
int AddU2List(const uint16_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues * 2);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -285,7 +293,7 @@ class HprofRecord {
int AddU4List(const uint32_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues * 4);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -317,8 +325,16 @@ class HprofRecord {
return 0;
}
- int AddIdList(const HprofObjectId* values, size_t numValues) {
- return AddU4List((const uint32_t*) values, numValues);
+ int AddIdList(mirror::ObjectArray<mirror::Object>* values)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ int32_t length = values->GetLength();
+ for (int32_t i = 0; i < length; ++i) {
+ int err = AddObjectId(values->GetWithoutChecks(i));
+ if (UNLIKELY(err != 0)) {
+ return err;
+ }
+ }
+ return 0;
}
int AddUtf8String(const char* str) {
@@ -510,12 +526,11 @@ class Hprof {
HprofRecord* rec = &current_record_;
uint32_t nextSerialNumber = 1;
- for (ClassSetIterator it = classes_.begin(); it != classes_.end(); ++it) {
- const mirror::Class* c = *it;
- CHECK(c != NULL);
+ for (mirror::Class* c : classes_) {
+ CHECK(c != nullptr);
int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -525,9 +540,9 @@ class Hprof {
// U4: stack trace serial number
// ID: class name string ID
rec->AddU4(nextSerialNumber++);
- rec->AddId((HprofClassObjectId) c);
+ rec->AddObjectId(c);
rec->AddU4(HPROF_NULL_STACK_TRACE);
- rec->AddId(LookupClassNameId(c));
+ rec->AddStringId(LookupClassNameId(c));
}
return 0;
@@ -536,9 +551,9 @@ class Hprof {
int WriteStringTable() {
HprofRecord* rec = &current_record_;
- for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
- const std::string& string = (*it).first;
- size_t id = (*it).second;
+ for (std::pair<std::string, HprofStringId> p : strings_) {
+ const std::string& string = p.first;
+ size_t id = p.second;
int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_STRING, HPROF_TIME);
if (err != 0) {
@@ -573,24 +588,26 @@ class Hprof {
int MarkRootObject(const mirror::Object* obj, jobject jniObj);
- HprofClassObjectId LookupClassId(mirror::Class* c)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (c == NULL) {
- // c is the superclass of java.lang.Object or a primitive
- return (HprofClassObjectId)0;
+ HprofClassObjectId LookupClassId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (c == nullptr) {
+ // c is the superclass of java.lang.Object or a primitive.
+ return 0;
}
- std::pair<ClassSetIterator, bool> result = classes_.insert(c);
- const mirror::Class* present = *result.first;
+ {
+ auto result = classes_.insert(c);
+ const mirror::Class* present = *result.first;
+ CHECK_EQ(present, c);
+ }
// Make sure that we've assigned a string ID for this class' name
LookupClassNameId(c);
- CHECK_EQ(present, c);
- return (HprofStringId) present;
+ HprofClassObjectId result = PointerToLowMemUInt32(c);
+ return result;
}
- HprofStringId LookupStringId(mirror::String* string) {
+ HprofStringId LookupStringId(mirror::String* string) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return LookupStringId(string->ToModifiedUtf8());
}
@@ -599,7 +616,7 @@ class Hprof {
}
HprofStringId LookupStringId(const std::string& string) {
- StringMapIterator it = strings_.find(string);
+ auto it = strings_.find(string);
if (it != strings_.end()) {
return it->second;
}
@@ -608,8 +625,7 @@ class Hprof {
return id;
}
- HprofStringId LookupClassNameId(const mirror::Class* c)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ HprofStringId LookupClassNameId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return LookupStringId(PrettyDescriptor(c));
}
@@ -675,9 +691,9 @@ class Hprof {
char* body_data_ptr_;
size_t body_data_size_;
- ClassSet classes_;
- size_t next_string_id_;
- StringMap strings_;
+ std::set<mirror::Class*> classes_;
+ HprofStringId next_string_id_;
+ SafeMap<std::string, HprofStringId> strings_;
DISALLOW_COPY_AND_ASSIGN(Hprof);
};
@@ -685,11 +701,8 @@ class Hprof {
#define OBJECTS_PER_SEGMENT ((size_t)128)
#define BYTES_PER_SEGMENT ((size_t)4096)
-// The static field-name for the synthetic object generated to account
-// for class static overhead.
+// The static field-name for the synthetic object generated to account for class static overhead.
#define STATIC_OVERHEAD_NAME "$staticOverhead"
-// The ID for the synthetic object generated to account for class static overhead.
-#define CLASS_STATICS_ID(c) ((HprofObjectId)(((uint32_t)(c)) | 1))
static HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* sizeOut) {
char c = sig[0];
@@ -765,15 +778,15 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_DEBUGGER:
case HPROF_ROOT_VM_INTERNAL:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
break;
// ID: object ID
// ID: JNI global ref ID
case HPROF_ROOT_JNI_GLOBAL:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
- rec->AddId((HprofId)jniObj);
+ rec->AddObjectId(obj);
+ rec->AddJniGlobalRefId(jniObj);
break;
// ID: object ID
@@ -783,7 +796,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_JNI_MONITOR:
case HPROF_ROOT_JAVA_FRAME:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
rec->AddU4((uint32_t)-1);
break;
@@ -793,7 +806,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_NATIVE_STACK:
case HPROF_ROOT_THREAD_BLOCK:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
break;
@@ -802,7 +815,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
// U4: stack trace serial number
case HPROF_ROOT_THREAD_OBJECT:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
rec->AddU4((uint32_t)-1); // xxx
break;
@@ -859,7 +872,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
nameId = LookupStringId("<ILLEGAL>");
break;
}
- rec->AddId(nameId);
+ rec->AddStringId(nameId);
current_heap_ = desiredHeap;
}
@@ -875,11 +888,11 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// obj is a ClassObject.
size_t sFieldCount = thisClass->NumStaticFields();
if (sFieldCount != 0) {
- int byteLength = sFieldCount*sizeof(JValue); // TODO bogus; fields are packed
+ int byteLength = sFieldCount * sizeof(JValue); // TODO bogus; fields are packed
// Create a byte array to reflect the allocation of the
// StaticField array at the end of this class.
rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
- rec->AddId(CLASS_STATICS_ID(obj));
+ rec->AddClassStaticsId(thisClass);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(byteLength);
rec->AddU1(hprof_basic_byte);
@@ -889,14 +902,14 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
}
rec->AddU1(HPROF_CLASS_DUMP);
- rec->AddId(LookupClassId(thisClass));
+ rec->AddClassId(LookupClassId(thisClass));
rec->AddU4(StackTraceSerialNumber(thisClass));
- rec->AddId(LookupClassId(thisClass->GetSuperClass()));
- rec->AddId((HprofObjectId)thisClass->GetClassLoader());
- rec->AddId((HprofObjectId)0); // no signer
- rec->AddId((HprofObjectId)0); // no prot domain
- rec->AddId((HprofId)0); // reserved
- rec->AddId((HprofId)0); // reserved
+ rec->AddClassId(LookupClassId(thisClass->GetSuperClass()));
+ rec->AddObjectId(thisClass->GetClassLoader());
+ rec->AddObjectId(nullptr); // no signer
+ rec->AddObjectId(nullptr); // no prot domain
+ rec->AddObjectId(nullptr); // reserved
+ rec->AddObjectId(nullptr); // reserved
if (thisClass->IsClassClass()) {
// ClassObjects have their static fields appended, so aren't all the same size.
// But they're at least this size.
@@ -916,9 +929,9 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
rec->AddU2((uint16_t)0);
} else {
rec->AddU2((uint16_t)(sFieldCount+1));
- rec->AddId(LookupStringId(STATIC_OVERHEAD_NAME));
+ rec->AddStringId(LookupStringId(STATIC_OVERHEAD_NAME));
rec->AddU1(hprof_basic_object);
- rec->AddId(CLASS_STATICS_ID(obj));
+ rec->AddClassStaticsId(thisClass);
for (size_t i = 0; i < sFieldCount; ++i) {
mirror::ArtField* f = thisClass->GetStaticField(i);
@@ -926,7 +939,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
size_t size;
HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), &size);
- rec->AddId(LookupStringId(fh.GetName()));
+ rec->AddStringId(LookupStringId(fh.GetName()));
rec->AddU1(t);
if (size == 1) {
rec->AddU1(static_cast<uint8_t>(f->Get32(thisClass)));
@@ -949,24 +962,24 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
mirror::ArtField* f = thisClass->GetInstanceField(i);
fh.ChangeField(f);
HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), NULL);
- rec->AddId(LookupStringId(fh.GetName()));
+ rec->AddStringId(LookupStringId(fh.GetName()));
rec->AddU1(t);
}
} else if (c->IsArrayClass()) {
- const mirror::Array* aobj = obj->AsArray();
+ mirror::Array* aobj = obj->AsArray();
uint32_t length = aobj->GetLength();
if (obj->IsObjectArray()) {
// obj is an object array.
rec->AddU1(HPROF_OBJECT_ARRAY_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(length);
- rec->AddId(LookupClassId(c));
+ rec->AddClassId(LookupClassId(c));
// Dump the elements, which are always objects or NULL.
- rec->AddIdList((const HprofObjectId*)aobj->GetRawData(sizeof(mirror::Object*)), length);
+ rec->AddIdList(aobj->AsObjectArray<mirror::Object>());
} else {
size_t size;
HprofBasicType t = PrimitiveToBasicTypeAndSize(c->GetComponentType()->GetPrimitiveType(), &size);
@@ -974,28 +987,28 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// obj is a primitive array.
rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(length);
rec->AddU1(t);
// Dump the raw, packed element values.
if (size == 1) {
- rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t)), length);
+ rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t), 0), length);
} else if (size == 2) {
- rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t)), length);
+ rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t), 0), length);
} else if (size == 4) {
- rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t)), length);
+ rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t), 0), length);
} else if (size == 8) {
- rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t)), length);
+ rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t), 0), length);
}
}
} else {
// obj is an instance object.
rec->AddU1(HPROF_INSTANCE_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
- rec->AddId(LookupClassId(c));
+ rec->AddClassId(LookupClassId(c));
// Reserve some space for the length of the instance data, which we won't
// know until we're done writing it.
@@ -1004,7 +1017,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// Write the instance data; fields for this class, followed by super class fields,
// and so on. Don't write the klass or monitor fields of Object.class.
- const mirror::Class* sclass = c;
+ mirror::Class* sclass = c;
FieldHelper fh;
while (!sclass->IsObjectClass()) {
int ifieldCount = sclass->NumInstanceFields();
@@ -1019,10 +1032,9 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
rec->AddU2(f->Get32(obj));
} else if (size == 4) {
rec->AddU4(f->Get32(obj));
- } else if (size == 8) {
- rec->AddU8(f->Get64(obj));
} else {
- CHECK(false);
+ CHECK_EQ(size, 8U);
+ rec->AddU8(f->Get64(obj));
}
}
diff --git a/runtime/instruction_set.h b/runtime/instruction_set.h
index aee7447..ac83601 100644
--- a/runtime/instruction_set.h
+++ b/runtime/instruction_set.h
@@ -29,6 +29,7 @@ enum InstructionSet {
kArm,
kThumb2,
kX86,
+ kX86_64,
kMips
};
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 0b11543..59ffdc1 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -18,7 +18,7 @@
#include <sys/uio.h>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "debugger.h"
@@ -68,10 +68,21 @@ bool Instrumentation::InstallStubsForClass(mirror::Class* klass) {
return true;
}
-static void UpdateEntrypoints(mirror::ArtMethod* method, const void* code) {
- method->SetEntryPointFromCompiledCode(code);
+static void UpdateEntrypoints(mirror::ArtMethod* method, const void* quick_code,
+ const void* portable_code, bool have_portable_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ method->SetEntryPointFromPortableCompiledCode(portable_code);
+ method->SetEntryPointFromQuickCompiledCode(quick_code);
+ bool portable_enabled = method->IsPortableCompiled();
+ if (have_portable_code && !portable_enabled) {
+ method->SetIsPortableCompiled();
+ } else if (portable_enabled) {
+ method->ClearIsPortableCompiled();
+ }
if (!method->IsResolutionMethod()) {
- if (code == GetCompiledCodeToInterpreterBridge()) {
+ if (quick_code == GetQuickToInterpreterBridge()) {
+ DCHECK(portable_code == GetPortableToInterpreterBridge());
+ DCHECK(!method->IsNative()) << PrettyMethod(method);
method->SetEntryPointFromInterpreter(art::interpreter::artInterpreterToInterpreterBridge);
} else {
method->SetEntryPointFromInterpreter(art::artInterpreterToCompiledCodeBridge);
@@ -84,37 +95,47 @@ void Instrumentation::InstallStubsForMethod(mirror::ArtMethod* method) {
// Do not change stubs for these methods.
return;
}
- const void* new_code;
+ const void* new_portable_code;
+ const void* new_quick_code;
bool uninstall = !entry_exit_stubs_installed_ && !interpreter_stubs_installed_;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
bool is_class_initialized = method->GetDeclaringClass()->IsInitialized();
+ bool have_portable_code = false;
if (uninstall) {
if ((forced_interpret_only_ || IsDeoptimized(method)) && !method->IsNative()) {
- new_code = GetCompiledCodeToInterpreterBridge();
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_quick_code = GetQuickToInterpreterBridge();
} else if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) {
- new_code = class_linker->GetOatCodeFor(method);
+ new_portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
+ new_quick_code = class_linker->GetQuickOatCodeFor(method);
} else {
- new_code = GetResolutionTrampoline(class_linker);
+ new_portable_code = GetPortableResolutionTrampoline(class_linker);
+ new_quick_code = GetQuickResolutionTrampoline(class_linker);
}
} else { // !uninstall
if ((interpreter_stubs_installed_ || IsDeoptimized(method)) && !method->IsNative()) {
- new_code = GetCompiledCodeToInterpreterBridge();
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_quick_code = GetQuickToInterpreterBridge();
} else {
// Do not overwrite resolution trampoline. When the trampoline initializes the method's
// class, all its static methods code will be set to the instrumentation entry point.
// For more details, see ClassLinker::FixupStaticTrampolines.
if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) {
// Do not overwrite interpreter to prevent from posting method entry/exit events twice.
- new_code = class_linker->GetOatCodeFor(method);
- if (entry_exit_stubs_installed_ && new_code != GetCompiledCodeToInterpreterBridge()) {
- new_code = GetQuickInstrumentationEntryPoint();
+ new_portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
+ new_quick_code = class_linker->GetQuickOatCodeFor(method);
+ if (entry_exit_stubs_installed_ && new_quick_code != GetQuickToInterpreterBridge()) {
+ DCHECK(new_portable_code != GetPortableToInterpreterBridge());
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_quick_code = GetQuickInstrumentationEntryPoint();
}
} else {
- new_code = GetResolutionTrampoline(class_linker);
+ new_portable_code = GetPortableResolutionTrampoline(class_linker);
+ new_quick_code = GetQuickResolutionTrampoline(class_linker);
}
}
}
- UpdateEntrypoints(method, new_code);
+ UpdateEntrypoints(method, new_quick_code, new_portable_code, have_portable_code);
}
// Places the instrumentation exit pc as the return PC for every quick frame. This also allows
@@ -470,23 +491,38 @@ void Instrumentation::ResetQuickAllocEntryPoints() {
}
}
-void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const {
- const void* new_code;
+void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code,
+ const void* portable_code, bool have_portable_code) const {
+ const void* new_portable_code;
+ const void* new_quick_code;
+ bool new_have_portable_code;
if (LIKELY(!instrumentation_stubs_installed_)) {
- new_code = code;
+ new_portable_code = portable_code;
+ new_quick_code = quick_code;
+ new_have_portable_code = have_portable_code;
} else {
if ((interpreter_stubs_installed_ || IsDeoptimized(method)) && !method->IsNative()) {
- new_code = GetCompiledCodeToInterpreterBridge();
- } else if (code == GetResolutionTrampoline(Runtime::Current()->GetClassLinker()) ||
- code == GetCompiledCodeToInterpreterBridge()) {
- new_code = code;
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_quick_code = GetQuickToInterpreterBridge();
+ new_have_portable_code = false;
+ } else if (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker()) ||
+ quick_code == GetQuickToInterpreterBridge()) {
+ DCHECK((portable_code == GetPortableResolutionTrampoline(Runtime::Current()->GetClassLinker())) ||
+ (portable_code == GetPortableToInterpreterBridge()));
+ new_portable_code = portable_code;
+ new_quick_code = quick_code;
+ new_have_portable_code = have_portable_code;
} else if (entry_exit_stubs_installed_) {
- new_code = GetQuickInstrumentationEntryPoint();
+ new_quick_code = GetQuickInstrumentationEntryPoint();
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_have_portable_code = false;
} else {
- new_code = code;
+ new_portable_code = portable_code;
+ new_quick_code = quick_code;
+ new_have_portable_code = have_portable_code;
}
}
- UpdateEntrypoints(method, new_code);
+ UpdateEntrypoints(method, new_quick_code, new_portable_code, new_have_portable_code);
}
void Instrumentation::Deoptimize(mirror::ArtMethod* method) {
@@ -499,7 +535,8 @@ void Instrumentation::Deoptimize(mirror::ArtMethod* method) {
CHECK(!already_deoptimized) << "Method " << PrettyMethod(method) << " is already deoptimized";
if (!interpreter_stubs_installed_) {
- UpdateEntrypoints(method, GetCompiledCodeToInterpreterBridge());
+ UpdateEntrypoints(method, GetQuickToInterpreterBridge(), GetPortableToInterpreterBridge(),
+ false);
// Install instrumentation exit stub and instrumentation frames. We may already have installed
// these previously so it will only cover the newly created frames.
@@ -522,10 +559,15 @@ void Instrumentation::Undeoptimize(mirror::ArtMethod* method) {
if (!interpreter_stubs_installed_) {
// Restore its code or resolution trampoline.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (method->IsStatic() && !method->IsConstructor() && !method->GetDeclaringClass()->IsInitialized()) {
- UpdateEntrypoints(method, GetResolutionTrampoline(class_linker));
+ if (method->IsStatic() && !method->IsConstructor() &&
+ !method->GetDeclaringClass()->IsInitialized()) {
+ UpdateEntrypoints(method, GetQuickResolutionTrampoline(class_linker),
+ GetPortableResolutionTrampoline(class_linker), false);
} else {
- UpdateEntrypoints(method, class_linker->GetOatCodeFor(method));
+ bool have_portable_code = false;
+ const void* quick_code = class_linker->GetQuickOatCodeFor(method);
+ const void* portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
+ UpdateEntrypoints(method, quick_code, portable_code, have_portable_code);
}
// If there is no deoptimized method left, we can restore the stack of each thread.
@@ -582,21 +624,21 @@ void Instrumentation::DisableMethodTracing() {
ConfigureStubs(false, false);
}
-const void* Instrumentation::GetQuickCodeFor(const mirror::ArtMethod* method) const {
+const void* Instrumentation::GetQuickCodeFor(mirror::ArtMethod* method) const {
Runtime* runtime = Runtime::Current();
if (LIKELY(!instrumentation_stubs_installed_)) {
- const void* code = method->GetEntryPointFromCompiledCode();
+ const void* code = method->GetEntryPointFromQuickCompiledCode();
DCHECK(code != NULL);
if (LIKELY(code != GetQuickResolutionTrampoline(runtime->GetClassLinker()) &&
code != GetQuickToInterpreterBridge())) {
return code;
}
}
- return runtime->GetClassLinker()->GetOatCodeFor(method);
+ return runtime->GetClassLinker()->GetQuickOatCodeFor(method);
}
void Instrumentation::MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc) const {
auto it = method_entry_listeners_.begin();
bool is_end = (it == method_entry_listeners_.end());
@@ -610,7 +652,7 @@ void Instrumentation::MethodEnterEventImpl(Thread* thread, mirror::Object* this_
}
void Instrumentation::MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc, const JValue& return_value) const {
auto it = method_exit_listeners_.begin();
bool is_end = (it == method_exit_listeners_.end());
@@ -624,7 +666,7 @@ void Instrumentation::MethodExitEventImpl(Thread* thread, mirror::Object* this_o
}
void Instrumentation::MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc) const {
if (have_method_unwind_listeners_) {
for (InstrumentationListener* listener : method_unwind_listeners_) {
@@ -634,7 +676,7 @@ void Instrumentation::MethodUnwindEvent(Thread* thread, mirror::Object* this_obj
}
void Instrumentation::DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc) const {
// TODO: STL copy-on-write collection? The copy below is due to the debug listener having an
// action where it can remove itself as a listener and break the iterator. The copy only works
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 41b545d..f01add1 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_INSTRUMENTATION_H_
#define ART_RUNTIME_INSTRUMENTATION_H_
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/macros.h"
#include "locks.h"
@@ -55,26 +55,26 @@ struct InstrumentationListener {
// Call-back for when a method is entered.
virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back for when a method is exited.
// TODO: its likely passing the return value would be useful, however, we may need to get and
// parse the shorty to determine what kind of register holds the result.
virtual void MethodExited(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc,
+ mirror::ArtMethod* method, uint32_t dex_pc,
const JValue& return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back for when a method is popped due to an exception throw. A method will either cause a
// MethodExited call-back or a MethodUnwind call-back when its activation is removed.
virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back for when the dex pc moves in a method.
virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc)
+ mirror::ArtMethod* method, uint32_t new_dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back when an exception is caught.
@@ -171,13 +171,14 @@ class Instrumentation {
void ResetQuickAllocEntryPoints();
// Update the code of a method respecting any installed stubs.
- void UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const
+ void UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code,
+ const void* portable_code, bool have_portable_code) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get the quick code for the given method. More efficient than asking the class linker as it
// will short-cut to GetCode if instrumentation and static method resolution stubs aren't
// installed.
- const void* GetQuickCodeFor(const mirror::ArtMethod* method) const
+ const void* GetQuickCodeFor(mirror::ArtMethod* method) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void ForceInterpretOnly() {
@@ -218,7 +219,7 @@ class Instrumentation {
// Inform listeners that a method has been entered. A dex PC is provided as we may install
// listeners into executing code and get method enter events for methods already on the stack.
void MethodEnterEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(HasMethodEntryListeners())) {
MethodEnterEventImpl(thread, this_object, method, dex_pc);
@@ -227,7 +228,7 @@ class Instrumentation {
// Inform listeners that a method has been exited.
void MethodExitEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc,
+ mirror::ArtMethod* method, uint32_t dex_pc,
const JValue& return_value) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(HasMethodExitListeners())) {
@@ -237,12 +238,12 @@ class Instrumentation {
// Inform listeners that a method has been exited due to an exception.
void MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Inform listeners that the dex pc has moved (only supported by the interpreter).
void DexPcMovedEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(HasDexPcListeners())) {
DexPcMovedEventImpl(thread, this_object, method, dex_pc);
@@ -289,14 +290,14 @@ class Instrumentation {
}
void MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc, const JValue& return_value) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Have we hijacked ArtMethod::code_ so that it calls instrumentation/interpreter code?
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index f574a0f..02a9aa6 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -356,7 +356,7 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive
DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
switch (shorty[shorty_pos + 1]) {
case 'L': {
- Object* o = reinterpret_cast<Object*>(args[arg_pos]);
+ Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr();
shadow_frame->SetVRegReference(cur_reg, o);
break;
}
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 0f94ccd..0b959fb 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -25,15 +25,16 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Assign register 'src_reg' from shadow_frame to register 'dest_reg' into new_shadow_frame.
-static inline void AssignRegister(ShadowFrame& new_shadow_frame, const ShadowFrame& shadow_frame,
- size_t dest_reg, size_t src_reg) {
+static inline void AssignRegister(ShadowFrame* new_shadow_frame, const ShadowFrame& shadow_frame,
+ size_t dest_reg, size_t src_reg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// If both register locations contains the same value, the register probably holds a reference.
int32_t src_value = shadow_frame.GetVReg(src_reg);
mirror::Object* o = shadow_frame.GetVRegReference<false>(src_reg);
- if (src_value == reinterpret_cast<int32_t>(o)) {
- new_shadow_frame.SetVRegReference(dest_reg, o);
+ if (src_value == reinterpret_cast<intptr_t>(o)) {
+ new_shadow_frame->SetVRegReference(dest_reg, o);
} else {
- new_shadow_frame.SetVReg(dest_reg, src_value);
+ new_shadow_frame->SetVReg(dest_reg, src_value);
}
}
@@ -84,7 +85,7 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
++dest_reg;
++arg_offset;
}
- for (size_t shorty_pos = 0; dest_reg < num_regs; ++shorty_pos, ++dest_reg, ++arg_offset) {
+ for (uint32_t shorty_pos = 0; dest_reg < num_regs; ++shorty_pos, ++dest_reg, ++arg_offset) {
DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
const size_t src_reg = (is_range) ? vregC + arg_offset : arg[arg_offset];
switch (shorty[shorty_pos + 1]) {
@@ -131,18 +132,18 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
const uint16_t first_src_reg = inst->VRegC_3rc();
for (size_t src_reg = first_src_reg, dest_reg = first_dest_reg; dest_reg < num_regs;
++dest_reg, ++src_reg) {
- AssignRegister(*new_shadow_frame, shadow_frame, dest_reg, src_reg);
+ AssignRegister(new_shadow_frame, shadow_frame, dest_reg, src_reg);
}
} else {
DCHECK_LE(num_ins, 5U);
uint16_t regList = inst->Fetch16(2);
uint16_t count = num_ins;
if (count == 5) {
- AssignRegister(*new_shadow_frame, shadow_frame, first_dest_reg + 4U, (inst_data >> 8) & 0x0f);
+ AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + 4U, (inst_data >> 8) & 0x0f);
--count;
}
for (size_t arg_index = 0; arg_index < count; ++arg_index, regList >>= 4) {
- AssignRegister(*new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
+ AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
}
}
}
@@ -289,7 +290,7 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
CHECK(field.get() != NULL);
ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>", "(Ljava/lang/reflect/ArtField;)V");
uint32_t args[1];
- args[0] = reinterpret_cast<uint32_t>(found);
+ args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue();
EnterInterpreterFromInvoke(self, c, field.get(), args, NULL);
result->SetL(field.get());
} else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" ||
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 4481210..768ca33 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -218,7 +218,7 @@ static inline bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* ins
shadow_frame.SetVRegLong(vregA, static_cast<int64_t>(obj->GetField64(field_offset, is_volatile)));
break;
case Primitive::kPrimNot:
- shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object*>(field_offset, is_volatile));
+ shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object>(field_offset, is_volatile));
break;
default:
LOG(FATAL) << "Unreachable: " << field_type;
@@ -529,10 +529,10 @@ static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruc
oss << PrettyMethod(shadow_frame.GetMethod())
<< StringPrintf("\n0x%x: ", dex_pc)
<< inst->DumpString(&mh.GetDexFile()) << "\n";
- for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
+ for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
uint32_t raw_value = shadow_frame.GetVReg(i);
Object* ref_value = shadow_frame.GetVRegReference(i);
- oss << StringPrintf(" vreg%d=0x%08X", i, raw_value);
+ oss << StringPrintf(" vreg%u=0x%08X", i, raw_value);
if (ref_value != NULL) {
if (ref_value->GetClass()->IsStringClass() &&
ref_value->AsString()->GetCharArray() != NULL) {
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index ca03885..e8504b7 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -568,7 +568,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
HANDLE_PENDING_EXCEPTION();
} else {
uint32_t size_in_bytes = payload->element_count * payload->element_width;
- memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+ memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
ADVANCE(3);
}
}
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 7631736..e5d15b1 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -483,7 +483,7 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem
break;
}
uint32_t size_in_bytes = payload->element_count * payload->element_width;
- memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+ memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
inst = inst->Next_3xx();
break;
}
diff --git a/runtime/invoke_arg_array_builder.h b/runtime/invoke_arg_array_builder.h
index f615e8e..6ecce40 100644
--- a/runtime/invoke_arg_array_builder.h
+++ b/runtime/invoke_arg_array_builder.h
@@ -78,6 +78,10 @@ class ArgArray {
num_bytes_ += 4;
}
+ void Append(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Append(StackReference<mirror::Object>::FromMirrorPtr(obj).AsVRegValue());
+ }
+
void AppendWide(uint64_t value) {
// For ARM and MIPS portable, align wide values to 8 bytes (ArgArray starts at offset of 4).
#if defined(ART_USE_PORTABLE_COMPILER) && (defined(__arm__) || defined(__mips__))
@@ -93,8 +97,8 @@ class ArgArray {
void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, va_list ap)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Set receiver if non-null (method is not static)
- if (receiver != NULL) {
- Append(reinterpret_cast<int32_t>(receiver));
+ if (receiver != nullptr) {
+ Append(receiver);
}
for (size_t i = 1; i < shorty_len_; ++i) {
switch (shorty_[i]) {
@@ -112,7 +116,7 @@ class ArgArray {
break;
}
case 'L':
- Append(reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(va_arg(ap, jobject))));
+ Append(soa.Decode<mirror::Object*>(va_arg(ap, jobject)));
break;
case 'D': {
JValue value;
@@ -131,8 +135,8 @@ class ArgArray {
void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, jvalue* args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Set receiver if non-null (method is not static)
- if (receiver != NULL) {
- Append(reinterpret_cast<int32_t>(receiver));
+ if (receiver != nullptr) {
+ Append(receiver);
}
for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
switch (shorty_[i]) {
@@ -153,7 +157,7 @@ class ArgArray {
Append(args[args_offset].i);
break;
case 'L':
- Append(reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(args[args_offset].l)));
+ Append(soa.Decode<mirror::Object*>(args[args_offset].l));
break;
case 'D':
case 'J':
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index ebc844e..334dca4 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_JDWP_JDWP_H_
#define ART_RUNTIME_JDWP_JDWP_H_
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/mutex.h"
#include "jdwp/jdwp_bits.h"
#include "jdwp/jdwp_constants.h"
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 5cd09c2..deea5f6 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -22,7 +22,7 @@
#include <utility>
#include <vector>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/logging.h"
#include "base/mutex.h"
#include "base/stl_util.h"
@@ -590,7 +590,7 @@ class Libraries {
}
// See section 11.3 "Linking Native Methods" of the JNI spec.
- void* FindNativeMethod(const ArtMethod* m, std::string& detail)
+ void* FindNativeMethod(ArtMethod* m, std::string& detail)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string jni_short_name(JniShortName(m));
std::string jni_long_name(JniLongName(m));
@@ -2215,7 +2215,7 @@ class JNI {
if (is_copy != nullptr) {
*is_copy = JNI_FALSE;
}
- return array->GetRawData(array->GetClass()->GetComponentSize());
+ return array->GetRawData(array->GetClass()->GetComponentSize(), 0);
}
static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* elements, jint mode) {
@@ -2518,10 +2518,10 @@ class JNI {
static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
if (capacity < 0) {
- JniAbortF("NewDirectByteBuffer", "negative buffer capacity: %lld", capacity);
+ JniAbortF("NewDirectByteBuffer", "negative buffer capacity: %" PRId64, capacity);
}
if (address == NULL && capacity != 0) {
- JniAbortF("NewDirectByteBuffer", "non-zero capacity for NULL pointer: %lld", capacity);
+ JniAbortF("NewDirectByteBuffer", "non-zero capacity for NULL pointer: %" PRId64, capacity);
}
// At the moment, the Java side is limited to 32 bits.
@@ -2644,7 +2644,7 @@ class JNI {
ScopedObjectAccess soa(env);
Array* array = soa.Decode<Array*>(java_array);
size_t component_size = array->GetClass()->GetComponentSize();
- void* array_data = array->GetRawData(component_size);
+ void* array_data = array->GetRawData(component_size, 0);
gc::Heap* heap = Runtime::Current()->GetHeap();
bool is_copy = array_data != reinterpret_cast<void*>(elements);
size_t bytes = array->GetLength() * component_size;
@@ -2944,10 +2944,6 @@ JNIEnvExt::JNIEnvExt(Thread* self, JavaVMExt* vm)
if (vm->check_jni) {
SetCheckJniEnabled(true);
}
- // The JniEnv local reference values must be at a consistent offset or else cross-compilation
- // errors will ensue.
- CHECK_EQ(JNIEnvExt::LocalRefCookieOffset().Int32Value(), 12);
- CHECK_EQ(JNIEnvExt::SegmentStateOffset().Int32Value(), 16);
}
JNIEnvExt::~JNIEnvExt() {
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 9b278f8..fed734e 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -131,7 +131,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
}
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
@@ -148,11 +148,11 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
+ arg_array.Append(0U);
result.SetB(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
EXPECT_EQ(0, result.GetB());
@@ -184,11 +184,11 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
+ arg_array.Append(0U);
result.SetI(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -221,7 +221,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -264,12 +264,12 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
- arg_array.Append(0);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
result.SetI(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -310,13 +310,13 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
result.SetI(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -361,14 +361,14 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
result.SetI(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -417,15 +417,15 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
result.SetI(-1.0);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -480,7 +480,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -547,7 +547,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -603,7 +603,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -668,7 +668,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -1492,8 +1492,8 @@ TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
} while (false)
-#if !defined(ART_USE_PORTABLE_COMPILER)
TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
+ TEST_DISABLED_FOR_PORTABLE();
Thread::Current()->TransitionFromSuspendedToRunnable();
LoadDex("AllFields");
bool started = runtime_->Start();
@@ -1524,6 +1524,7 @@ TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
}
TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
+ TEST_DISABLED_FOR_PORTABLE();
Thread::Current()->TransitionFromSuspendedToRunnable();
LoadDex("AllFields");
runtime_->Start();
@@ -1553,7 +1554,6 @@ TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
env_->SetObjectField(o, i_fid, s2);
ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
}
-#endif
TEST_F(JniInternalTest, NewLocalRef_NULL) {
EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
@@ -1756,7 +1756,7 @@ TEST_F(JniInternalTest, StaticMainMethod) {
ASSERT_TRUE(method != NULL);
ArgArray arg_array(NULL, 0);
- arg_array.Append(0);
+ arg_array.Append(0U);
JValue result;
// Start runtime.
diff --git a/runtime/lock_word-inl.h b/runtime/lock_word-inl.h
index 8b9a3cd..414b3bb 100644
--- a/runtime/lock_word-inl.h
+++ b/runtime/lock_word-inl.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_LOCK_WORD_INL_H_
#include "lock_word.h"
+#include "monitor_pool.h"
namespace art {
@@ -33,7 +34,8 @@ inline uint32_t LockWord::ThinLockCount() const {
inline Monitor* LockWord::FatLockMonitor() const {
DCHECK_EQ(GetState(), kFatLocked);
- return reinterpret_cast<Monitor*>(value_ << kStateSize);
+ MonitorId mon_id = static_cast<MonitorId>(value_ & ~(kStateMask << kStateShift));
+ return MonitorPool::MonitorFromMonitorId(mon_id);
}
inline size_t LockWord::ForwardingAddress() const {
@@ -46,8 +48,7 @@ inline LockWord::LockWord() : value_(0) {
}
inline LockWord::LockWord(Monitor* mon)
- : value_(((reinterpret_cast<uintptr_t>(mon) >> kStateSize) | (kStateFat << kStateShift)) &
- 0xFFFFFFFFU) {
+ : value_(mon->GetMonitorId() | (kStateFat << kStateShift)) {
DCHECK_EQ(FatLockMonitor(), mon);
}
diff --git a/runtime/lock_word.h b/runtime/lock_word.h
index d24a3bb..ab86eaa 100644
--- a/runtime/lock_word.h
+++ b/runtime/lock_word.h
@@ -42,7 +42,7 @@ class Monitor;
*
* |33|222222222211111111110000000000|
* |10|987654321098765432109876543210|
- * |01| Monitor* >> kStateSize |
+ * |01| MonitorId |
*
* When the lock word is in hash state and its bits are formatted as follows:
*
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 2795e1d..393ea68 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -79,7 +79,7 @@ static void CheckMapRequest(byte*, size_t) { }
#endif
MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t byte_count, int prot,
- std::string* error_msg) {
+ bool low_4gb, std::string* error_msg) {
if (byte_count == 0) {
return new MemMap(name, NULL, 0, NULL, 0, prot);
}
@@ -101,7 +101,11 @@ MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t byte_count, in
ScopedFd fd(-1);
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
#endif
-
+#ifdef __LP64__
+ if (low_4gb) {
+ flags |= MAP_32BIT;
+ }
+#endif
byte* actual = reinterpret_cast<byte*>(mmap(addr, page_aligned_byte_count, prot, flags, fd.get(), 0));
if (actual == MAP_FAILED) {
std::string maps;
diff --git a/runtime/mem_map.h b/runtime/mem_map.h
index d2059b5..e39c10e 100644
--- a/runtime/mem_map.h
+++ b/runtime/mem_map.h
@@ -39,7 +39,7 @@ class MemMap {
//
// On success, returns returns a MemMap instance. On failure, returns a NULL;
static MemMap* MapAnonymous(const char* ashmem_name, byte* addr, size_t byte_count, int prot,
- std::string* error_msg);
+ bool low_4gb, std::string* error_msg);
// Map part of a file, taking care of non-page aligned offsets. The
// "start" offset is absolute, not relative.
diff --git a/runtime/mem_map_test.cc b/runtime/mem_map_test.cc
index cf2c9d0..6cb59b4 100644
--- a/runtime/mem_map_test.cc
+++ b/runtime/mem_map_test.cc
@@ -23,76 +23,111 @@ namespace art {
class MemMapTest : public testing::Test {
public:
- byte* BaseBegin(MemMap* mem_map) {
+ static byte* BaseBegin(MemMap* mem_map) {
return reinterpret_cast<byte*>(mem_map->base_begin_);
}
- size_t BaseSize(MemMap* mem_map) {
+ static size_t BaseSize(MemMap* mem_map) {
return mem_map->base_size_;
}
+
+ static void RemapAtEndTest(bool low_4gb) {
+ std::string error_msg;
+ // Cast the page size to size_t.
+ const size_t page_size = static_cast<size_t>(kPageSize);
+ // Map a two-page memory region.
+ MemMap* m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0",
+ nullptr,
+ 2 * page_size,
+ PROT_READ | PROT_WRITE,
+ low_4gb,
+ &error_msg);
+ // Check its state and write to it.
+ byte* base0 = m0->Begin();
+ ASSERT_TRUE(base0 != nullptr) << error_msg;
+ size_t size0 = m0->Size();
+ EXPECT_EQ(m0->Size(), 2 * page_size);
+ EXPECT_EQ(BaseBegin(m0), base0);
+ EXPECT_EQ(BaseSize(m0), size0);
+ memset(base0, 42, 2 * page_size);
+ // Remap the latter half into a second MemMap.
+ MemMap* m1 = m0->RemapAtEnd(base0 + page_size,
+ "MemMapTest_RemapAtEndTest_map1",
+ PROT_READ | PROT_WRITE,
+ &error_msg);
+ // Check the states of the two maps.
+ EXPECT_EQ(m0->Begin(), base0) << error_msg;
+ EXPECT_EQ(m0->Size(), page_size);
+ EXPECT_EQ(BaseBegin(m0), base0);
+ EXPECT_EQ(BaseSize(m0), page_size);
+ byte* base1 = m1->Begin();
+ size_t size1 = m1->Size();
+ EXPECT_EQ(base1, base0 + page_size);
+ EXPECT_EQ(size1, page_size);
+ EXPECT_EQ(BaseBegin(m1), base1);
+ EXPECT_EQ(BaseSize(m1), size1);
+ // Write to the second region.
+ memset(base1, 43, page_size);
+ // Check the contents of the two regions.
+ for (size_t i = 0; i < page_size; ++i) {
+ EXPECT_EQ(base0[i], 42);
+ }
+ for (size_t i = 0; i < page_size; ++i) {
+ EXPECT_EQ(base1[i], 43);
+ }
+ // Unmap the first region.
+ delete m0;
+ // Make sure the second region is still accessible after the first
+ // region is unmapped.
+ for (size_t i = 0; i < page_size; ++i) {
+ EXPECT_EQ(base1[i], 43);
+ }
+ delete m1;
+ }
};
TEST_F(MemMapTest, MapAnonymousEmpty) {
std::string error_msg;
UniquePtr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
- NULL,
+ nullptr,
0,
PROT_READ,
+ false,
&error_msg));
- ASSERT_TRUE(map.get() != NULL) << error_msg;
+ ASSERT_TRUE(map.get() != nullptr) << error_msg;
+ ASSERT_TRUE(error_msg.empty());
+ map.reset(MemMap::MapAnonymous("MapAnonymousEmpty",
+ nullptr,
+ kPageSize,
+ PROT_READ | PROT_WRITE,
+ false,
+ &error_msg));
+ ASSERT_TRUE(map.get() != nullptr) << error_msg;
ASSERT_TRUE(error_msg.empty());
}
-TEST_F(MemMapTest, RemapAtEnd) {
+#ifdef __LP64__
+TEST_F(MemMapTest, MapAnonymousEmpty32bit) {
std::string error_msg;
- // Cast the page size to size_t.
- const size_t page_size = static_cast<size_t>(kPageSize);
- // Map a two-page memory region.
- MemMap* m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0",
- NULL,
- 2 * page_size,
- PROT_READ | PROT_WRITE,
- &error_msg);
- // Check its state and write to it.
- byte* base0 = m0->Begin();
- ASSERT_TRUE(base0 != NULL) << error_msg;
- size_t size0 = m0->Size();
- EXPECT_EQ(m0->Size(), 2 * page_size);
- EXPECT_EQ(BaseBegin(m0), base0);
- EXPECT_EQ(BaseSize(m0), size0);
- memset(base0, 42, 2 * page_size);
- // Remap the latter half into a second MemMap.
- MemMap* m1 = m0->RemapAtEnd(base0 + page_size,
- "MemMapTest_RemapAtEndTest_map1",
- PROT_READ | PROT_WRITE,
- &error_msg);
- // Check the states of the two maps.
- EXPECT_EQ(m0->Begin(), base0) << error_msg;
- EXPECT_EQ(m0->Size(), page_size);
- EXPECT_EQ(BaseBegin(m0), base0);
- EXPECT_EQ(BaseSize(m0), page_size);
- byte* base1 = m1->Begin();
- size_t size1 = m1->Size();
- EXPECT_EQ(base1, base0 + page_size);
- EXPECT_EQ(size1, page_size);
- EXPECT_EQ(BaseBegin(m1), base1);
- EXPECT_EQ(BaseSize(m1), size1);
- // Write to the second region.
- memset(base1, 43, page_size);
- // Check the contents of the two regions.
- for (size_t i = 0; i < page_size; ++i) {
- EXPECT_EQ(base0[i], 42);
- }
- for (size_t i = 0; i < page_size; ++i) {
- EXPECT_EQ(base1[i], 43);
- }
- // Unmap the first region.
- delete m0;
- // Make sure the second region is still accessible after the first
- // region is unmapped.
- for (size_t i = 0; i < page_size; ++i) {
- EXPECT_EQ(base1[i], 43);
- }
- delete m1;
+ UniquePtr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
+ nullptr,
+ kPageSize,
+ PROT_READ | PROT_WRITE,
+ true,
+ &error_msg));
+ ASSERT_TRUE(map.get() != nullptr) << error_msg;
+ ASSERT_TRUE(error_msg.empty());
+ ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32);
+}
+#endif
+
+TEST_F(MemMapTest, RemapAtEnd) {
+ RemapAtEndTest(false);
+}
+
+#ifdef __LP64__
+TEST_F(MemMapTest, RemapAtEnd32bit) {
+ RemapAtEndTest(true);
}
+#endif
} // namespace art
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index bd81bd5..b2725e5 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -27,7 +27,7 @@
namespace art {
namespace mirror {
-inline size_t Array::SizeOf() const {
+inline size_t Array::SizeOf() {
// This is safe from overflow because the array was already allocated, so we know it's sane.
size_t component_size = GetClass()->GetComponentSize();
int32_t component_count = GetLength();
@@ -64,9 +64,10 @@ class SetLengthVisitor {
explicit SetLengthVisitor(int32_t length) : length_(length) {
}
- void operator()(mirror::Object* obj) const {
- mirror::Array* array = obj->AsArray();
- DCHECK(array->IsArrayInstance());
+ void operator()(Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ // Avoid AsArray as object is not yet in live bitmap or allocation stack.
+ Array* array = down_cast<Array*>(obj);
+ // DCHECK(array->IsArrayInstance());
array->SetLength(length_);
}
@@ -116,6 +117,114 @@ inline void PrimitiveArray<T>::VisitRoots(RootVisitor* visitor, void* arg) {
}
}
+// Similar to memmove except elements are of aligned appropriately for T, count is in T sized units
+// copies are guaranteed not to tear when T is less-than 64bit.
+template<typename T>
+static inline void ArrayBackwardCopy(T* d, const T* s, int32_t count) {
+ d += count;
+ s += count;
+ for (int32_t i = 0; i < count; ++i) {
+ d--;
+ s--;
+ *d = *s;
+ }
+}
+
+template<class T>
+void PrimitiveArray<T>::Memmove(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos,
+ int32_t count) {
+ if (UNLIKELY(count == 0)) {
+ return;
+ }
+ DCHECK_GE(dst_pos, 0);
+ DCHECK_GE(src_pos, 0);
+ DCHECK_GT(count, 0);
+ DCHECK(src != nullptr);
+ DCHECK_LT(dst_pos, GetLength());
+ DCHECK_LE(dst_pos, GetLength() - count);
+ DCHECK_LT(src_pos, src->GetLength());
+ DCHECK_LE(src_pos, src->GetLength() - count);
+
+ // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
+ // in our implementation, because they may copy byte-by-byte.
+ if (LIKELY(src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count)) {
+ // Forward copy ok.
+ Memcpy(dst_pos, src, src_pos, count);
+ } else {
+ // Backward copy necessary.
+ void* dst_raw = GetRawData(sizeof(T), dst_pos);
+ const void* src_raw = src->GetRawData(sizeof(T), src_pos);
+ if (sizeof(T) == sizeof(uint8_t)) {
+ // TUNING: use memmove here?
+ uint8_t* d = reinterpret_cast<uint8_t*>(dst_raw);
+ const uint8_t* s = reinterpret_cast<const uint8_t*>(src_raw);
+ ArrayBackwardCopy<uint8_t>(d, s, count);
+ } else if (sizeof(T) == sizeof(uint16_t)) {
+ uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
+ const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
+ ArrayBackwardCopy<uint16_t>(d, s, count);
+ } else if (sizeof(T) == sizeof(uint32_t)) {
+ uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
+ const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
+ ArrayBackwardCopy<uint32_t>(d, s, count);
+ } else {
+ DCHECK_EQ(sizeof(T), sizeof(uint64_t));
+ uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
+ const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
+ ArrayBackwardCopy<uint64_t>(d, s, count);
+ }
+ }
+}
+
+// Similar to memcpy except elements are of aligned appropriately for T, count is in T sized units
+// copies are guaranteed not to tear when T is less-than 64bit.
+template<typename T>
+static inline void ArrayForwardCopy(T* d, const T* s, int32_t count) {
+ for (int32_t i = 0; i < count; ++i) {
+ *d = *s;
+ d++;
+ s++;
+ }
+}
+
+
+template<class T>
+void PrimitiveArray<T>::Memcpy(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos,
+ int32_t count) {
+ if (UNLIKELY(count == 0)) {
+ return;
+ }
+ DCHECK_GE(dst_pos, 0);
+ DCHECK_GE(src_pos, 0);
+ DCHECK_GT(count, 0);
+ DCHECK(src != nullptr);
+ DCHECK_LT(dst_pos, GetLength());
+ DCHECK_LE(dst_pos, GetLength() - count);
+ DCHECK_LT(src_pos, src->GetLength());
+ DCHECK_LE(src_pos, src->GetLength() - count);
+
+ // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
+ // in our implementation, because they may copy byte-by-byte.
+ void* dst_raw = GetRawData(sizeof(T), dst_pos);
+ const void* src_raw = src->GetRawData(sizeof(T), src_pos);
+ if (sizeof(T) == sizeof(uint8_t)) {
+ memcpy(dst_raw, src_raw, count);
+ } else if (sizeof(T) == sizeof(uint16_t)) {
+ uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
+ const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
+ ArrayForwardCopy<uint16_t>(d, s, count);
+ } else if (sizeof(T) == sizeof(uint32_t)) {
+ uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
+ const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
+ ArrayForwardCopy<uint32_t>(d, s, count);
+ } else {
+ DCHECK_EQ(sizeof(T), sizeof(uint64_t));
+ uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
+ const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
+ ArrayForwardCopy<uint64_t>(d, s, count);
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 00b88db..ca0d1f3 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -103,11 +103,11 @@ Array* Array::CreateMultiArray(Thread* self, Class* element_class, IntArray* dim
return new_array;
}
-void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
+void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) {
art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
}
-void Array::ThrowArrayStoreException(Object* object) const {
+void Array::ThrowArrayStoreException(Object* object) {
art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
}
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 207573f..6e366a0 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -50,15 +50,15 @@ class MANAGED Array : public Object {
static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t SizeOf() const;
+ size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetLength() const {
+ int32_t GetLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false);
}
- void SetLength(int32_t length) {
+ void SetLength(int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK_GE(length, 0);
- SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false, false);
}
static MemberOffset LengthOffset() {
@@ -74,20 +74,22 @@ class MANAGED Array : public Object {
}
}
- void* GetRawData(size_t component_size) {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value();
+ void* GetRawData(size_t component_size, int32_t index)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value() +
+ + (index * component_size);
return reinterpret_cast<void*>(data);
}
- const void* GetRawData(size_t component_size) const {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value();
- return reinterpret_cast<const void*>(data);
+ const void* GetRawData(size_t component_size, int32_t index) const {
+ intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value() +
+ + (index * component_size);
+ return reinterpret_cast<void*>(data);
}
// Returns true if the index is valid. If not, throws an ArrayIndexOutOfBoundsException and
// returns false.
- bool CheckIsValidIndex(int32_t index) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool CheckIsValidIndex(int32_t index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(static_cast<uint32_t>(index) >= static_cast<uint32_t>(GetLength()))) {
ThrowArrayIndexOutOfBoundsException(index);
return false;
@@ -96,11 +98,10 @@ class MANAGED Array : public Object {
}
protected:
- void ThrowArrayStoreException(Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void ThrowArrayStoreException(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
- void ThrowArrayIndexOutOfBoundsException(int32_t index) const
+ void ThrowArrayIndexOutOfBoundsException(int32_t index)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// The number of array elements.
@@ -119,17 +120,15 @@ class MANAGED PrimitiveArray : public Array {
static PrimitiveArray<T>* Alloc(Thread* self, size_t length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const T* GetData() const {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value();
- return reinterpret_cast<T*>(data);
+ const T* GetData() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return reinterpret_cast<const T*>(GetRawData(sizeof(T), 0));
}
- T* GetData() {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value();
- return reinterpret_cast<T*>(data);
+ T* GetData() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return reinterpret_cast<T*>(GetRawData(sizeof(T), 0));
}
- T Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ T Get(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(!CheckIsValidIndex(i))) {
DCHECK(Thread::Current()->IsExceptionPending());
return T(0);
@@ -137,7 +136,7 @@ class MANAGED PrimitiveArray : public Array {
return GetWithoutChecks(i);
}
- T GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ T GetWithoutChecks(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(CheckIsValidIndex(i));
return GetData()[i];
}
@@ -155,6 +154,22 @@ class MANAGED PrimitiveArray : public Array {
GetData()[i] = value;
}
+ /*
+ * Works like memmove(), except we guarantee not to allow tearing of array values (ie using
+ * smaller than element size copies). Arguments are assumed to be within the bounds of the array
+ * and the arrays non-null.
+ */
+ void Memmove(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos, int32_t count)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ /*
+ * Works like memcpy(), except we guarantee not to allow tearing of array values (ie using
+ * smaller than element size copies). Arguments are assumed to be within the bounds of the array
+ * and the arrays non-null.
+ */
+ void Memcpy(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos, int32_t count)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
static void SetArrayClass(Class* array_class) {
CHECK(array_class_ == NULL);
CHECK(array_class != NULL);
diff --git a/runtime/mirror/art_field-inl.h b/runtime/mirror/art_field-inl.h
index d8c278c..530226b 100644
--- a/runtime/mirror/art_field-inl.h
+++ b/runtime/mirror/art_field-inl.h
@@ -29,8 +29,8 @@
namespace art {
namespace mirror {
-inline Class* ArtField::GetDeclaringClass() const {
- Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_), false);
+inline Class* ArtField::GetDeclaringClass() {
+ Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_), false);
DCHECK(result != NULL);
DCHECK(result->IsLoaded() || result->IsErroneous());
return result;
@@ -40,106 +40,106 @@ inline void ArtField::SetDeclaringClass(Class *new_declaring_class) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_), new_declaring_class, false);
}
-inline uint32_t ArtField::GetAccessFlags() const {
+inline uint32_t ArtField::GetAccessFlags() {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_), false);
}
-inline MemberOffset ArtField::GetOffset() const {
+inline MemberOffset ArtField::GetOffset() {
DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_), false));
}
-inline MemberOffset ArtField::GetOffsetDuringLinking() const {
+inline MemberOffset ArtField::GetOffsetDuringLinking() {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_), false));
}
-inline uint32_t ArtField::Get32(const Object* object) const {
+inline uint32_t ArtField::Get32(Object* object) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
return object->GetField32(GetOffset(), IsVolatile());
}
-inline void ArtField::Set32(Object* object, uint32_t new_value) const {
+inline void ArtField::Set32(Object* object, uint32_t new_value) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
object->SetField32(GetOffset(), new_value, IsVolatile());
}
-inline uint64_t ArtField::Get64(const Object* object) const {
+inline uint64_t ArtField::Get64(Object* object) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
return object->GetField64(GetOffset(), IsVolatile());
}
-inline void ArtField::Set64(Object* object, uint64_t new_value) const {
+inline void ArtField::Set64(Object* object, uint64_t new_value) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
object->SetField64(GetOffset(), new_value, IsVolatile());
}
-inline Object* ArtField::GetObj(const Object* object) const {
+inline Object* ArtField::GetObj(Object* object) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
- return object->GetFieldObject<Object*>(GetOffset(), IsVolatile());
+ return object->GetFieldObject<Object>(GetOffset(), IsVolatile());
}
-inline void ArtField::SetObj(Object* object, const Object* new_value) const {
+inline void ArtField::SetObj(Object* object, Object* new_value) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
object->SetFieldObject(GetOffset(), new_value, IsVolatile());
}
-inline bool ArtField::GetBoolean(const Object* object) const {
+inline bool ArtField::GetBoolean(Object* object) {
DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return Get32(object);
}
-inline void ArtField::SetBoolean(Object* object, bool z) const {
+inline void ArtField::SetBoolean(Object* object, bool z) {
DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
Set32(object, z);
}
-inline int8_t ArtField::GetByte(const Object* object) const {
+inline int8_t ArtField::GetByte(Object* object) {
DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return Get32(object);
}
-inline void ArtField::SetByte(Object* object, int8_t b) const {
+inline void ArtField::SetByte(Object* object, int8_t b) {
DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
Set32(object, b);
}
-inline uint16_t ArtField::GetChar(const Object* object) const {
+inline uint16_t ArtField::GetChar(Object* object) {
DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return Get32(object);
}
-inline void ArtField::SetChar(Object* object, uint16_t c) const {
+inline void ArtField::SetChar(Object* object, uint16_t c) {
DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
Set32(object, c);
}
-inline int16_t ArtField::GetShort(const Object* object) const {
+inline int16_t ArtField::GetShort(Object* object) {
DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return Get32(object);
}
-inline void ArtField::SetShort(Object* object, int16_t s) const {
+inline void ArtField::SetShort(Object* object, int16_t s) {
DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
Set32(object, s);
}
-inline int32_t ArtField::GetInt(const Object* object) const {
+inline int32_t ArtField::GetInt(Object* object) {
#ifndef NDEBUG
Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType();
CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this);
@@ -147,7 +147,7 @@ inline int32_t ArtField::GetInt(const Object* object) const {
return Get32(object);
}
-inline void ArtField::SetInt(Object* object, int32_t i) const {
+inline void ArtField::SetInt(Object* object, int32_t i) {
#ifndef NDEBUG
Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType();
CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this);
@@ -155,7 +155,7 @@ inline void ArtField::SetInt(Object* object, int32_t i) const {
Set32(object, i);
}
-inline int64_t ArtField::GetLong(const Object* object) const {
+inline int64_t ArtField::GetLong(Object* object) {
#ifndef NDEBUG
Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType();
CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this);
@@ -163,7 +163,7 @@ inline int64_t ArtField::GetLong(const Object* object) const {
return Get64(object);
}
-inline void ArtField::SetLong(Object* object, int64_t j) const {
+inline void ArtField::SetLong(Object* object, int64_t j) {
#ifndef NDEBUG
Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType();
CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this);
@@ -171,7 +171,7 @@ inline void ArtField::SetLong(Object* object, int64_t j) const {
Set64(object, j);
}
-inline float ArtField::GetFloat(const Object* object) const {
+inline float ArtField::GetFloat(Object* object) {
DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
JValue bits;
@@ -179,7 +179,7 @@ inline float ArtField::GetFloat(const Object* object) const {
return bits.GetF();
}
-inline void ArtField::SetFloat(Object* object, float f) const {
+inline void ArtField::SetFloat(Object* object, float f) {
DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
JValue bits;
@@ -187,7 +187,7 @@ inline void ArtField::SetFloat(Object* object, float f) const {
Set32(object, bits.GetI());
}
-inline double ArtField::GetDouble(const Object* object) const {
+inline double ArtField::GetDouble(Object* object) {
DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
JValue bits;
@@ -195,7 +195,7 @@ inline double ArtField::GetDouble(const Object* object) const {
return bits.GetD();
}
-inline void ArtField::SetDouble(Object* object, double d) const {
+inline void ArtField::SetDouble(Object* object, double d) {
DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
JValue bits;
@@ -203,13 +203,13 @@ inline void ArtField::SetDouble(Object* object, double d) const {
Set64(object, bits.GetJ());
}
-inline Object* ArtField::GetObject(const Object* object) const {
+inline Object* ArtField::GetObject(Object* object) {
DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return GetObj(object);
}
-inline void ArtField::SetObject(Object* object, const Object* l) const {
+inline void ArtField::SetObject(Object* object, Object* l) {
DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
SetObj(object, l);
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index 62bcf06..b33fe4b 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -30,98 +30,74 @@ namespace mirror {
// C++ mirror of java.lang.reflect.ArtField
class MANAGED ArtField : public Object {
public:
- Class* GetDeclaringClass() const;
+ Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint32_t GetAccessFlags() const;
+ uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetAccessFlags(uint32_t new_access_flags) {
+ void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_), new_access_flags, false);
}
- bool IsPublic() const {
+ bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPublic) != 0;
}
- bool IsStatic() const {
+ bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccStatic) != 0;
}
- bool IsFinal() const {
+ bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccFinal) != 0;
}
- uint32_t GetDexFieldIndex() const {
+ uint32_t GetDexFieldIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, field_dex_idx_), false);
}
- void SetDexFieldIndex(uint32_t new_idx) {
+ void SetDexFieldIndex(uint32_t new_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, field_dex_idx_), new_idx, false);
}
- // Offset to field within an Object
- MemberOffset GetOffset() const;
+ // Offset to field within an Object.
+ MemberOffset GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static MemberOffset OffsetOffset() {
return MemberOffset(OFFSETOF_MEMBER(ArtField, offset_));
}
- MemberOffset GetOffsetDuringLinking() const;
+ MemberOffset GetOffsetDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetOffset(MemberOffset num_bytes);
+ void SetOffset(MemberOffset num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// field access, null object for static fields
- bool GetBoolean(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetBoolean(Object* object, bool z) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int8_t GetByte(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetByte(Object* object, int8_t b) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint16_t GetChar(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetChar(Object* object, uint16_t c) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int16_t GetShort(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetShort(Object* object, int16_t s) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetInt(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetInt(Object* object, int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int64_t GetLong(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetLong(Object* object, int64_t j) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- float GetFloat(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetFloat(Object* object, float f) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- double GetDouble(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetDouble(Object* object, double d) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Object* GetObject(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetObject(Object* object, const Object* l) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // raw field accesses
- uint32_t Get32(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Set32(Object* object, uint32_t new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint64_t Get64(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Set64(Object* object, uint64_t new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Object* GetObj(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetObj(Object* object, const Object* new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool GetBoolean(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetBoolean(Object* object, bool z) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int8_t GetByte(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetByte(Object* object, int8_t b) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint16_t GetChar(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetChar(Object* object, uint16_t c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int16_t GetShort(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetShort(Object* object, int16_t s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int32_t GetInt(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetInt(Object* object, int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int64_t GetLong(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetLong(Object* object, int64_t j) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ float GetFloat(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetFloat(Object* object, float f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ double GetDouble(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetDouble(Object* object, double d) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ Object* GetObject(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetObject(Object* object, Object* l) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Raw field accesses.
+ uint32_t Get32(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Set32(Object* object, uint32_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint64_t Get64(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Set64(Object* object, uint64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ Object* GetObj(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetObj(Object* object, Object* new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static Class* GetJavaLangReflectArtField() {
DCHECK(java_lang_reflect_ArtField_ != NULL);
@@ -133,14 +109,14 @@ class MANAGED ArtField : public Object {
static void VisitRoots(RootVisitor* visitor, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsVolatile() const {
+ bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccVolatile) != 0;
}
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// The class we are a part of
- Class* declaring_class_;
+ HeapReference<Class> declaring_class_;
uint32_t access_flags_;
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 088f616..8ef3be8 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -27,8 +27,9 @@
namespace art {
namespace mirror {
-inline Class* ArtMethod::GetDeclaringClass() const {
- Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_), false);
+inline Class* ArtMethod::GetDeclaringClass() {
+ Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_),
+ false);
DCHECK(result != NULL) << this;
DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this;
return result;
@@ -38,44 +39,44 @@ inline void ArtMethod::SetDeclaringClass(Class *new_declaring_class) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_), new_declaring_class, false);
}
-inline uint32_t ArtMethod::GetAccessFlags() const {
+inline uint32_t ArtMethod::GetAccessFlags() {
DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_), false);
}
-inline uint16_t ArtMethod::GetMethodIndex() const {
+inline uint16_t ArtMethod::GetMethodIndex() {
DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_), false);
}
-inline uint32_t ArtMethod::GetDexMethodIndex() const {
+inline uint32_t ArtMethod::GetDexMethodIndex() {
#ifdef ART_SEA_IR_MODE
// TODO: Re-add this check for (PORTABLE + SMALL + ) SEA IR when PORTABLE IS fixed!
// DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
#else
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
#endif
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_dex_index_), false);
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_), false);
}
-inline ObjectArray<String>* ArtMethod::GetDexCacheStrings() const {
- return GetFieldObject<ObjectArray<String>*>(
+inline ObjectArray<String>* ArtMethod::GetDexCacheStrings() {
+ return GetFieldObject<ObjectArray<String> >(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_strings_), false);
}
-inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() const {
- return GetFieldObject<ObjectArray<ArtMethod>*>(
+inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() {
+ return GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_), false);
}
-inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() const {
- return GetFieldObject<ObjectArray<Class>*>(
+inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() {
+ return GetFieldObject<ObjectArray<Class> >(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_), false);
}
-inline uint32_t ArtMethod::GetCodeSize() const {
+inline uint32_t ArtMethod::GetCodeSize() {
DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
- uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromCompiledCode());
+ uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode());
if (code == 0) {
return 0;
}
@@ -106,7 +107,7 @@ inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
}
}
-inline void ArtMethod::AssertPcIsWithinCode(uintptr_t pc) const {
+inline void ArtMethod::AssertPcIsWithinQuickCode(uintptr_t pc) {
if (!kIsDebugBuild) {
return;
}
@@ -116,34 +117,44 @@ inline void ArtMethod::AssertPcIsWithinCode(uintptr_t pc) const {
if (pc == GetQuickInstrumentationExitPc()) {
return;
}
- const void* code = GetEntryPointFromCompiledCode();
- if (code == GetCompiledCodeToInterpreterBridge() || code == GetQuickInstrumentationEntryPoint()) {
+ const void* code = GetEntryPointFromQuickCompiledCode();
+ if (code == GetQuickToInterpreterBridge() || code == GetQuickInstrumentationEntryPoint()) {
return;
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (code == GetResolutionTrampoline(class_linker)) {
+ if (code == GetQuickResolutionTrampoline(class_linker)) {
return;
}
- DCHECK(IsWithinCode(pc))
+ DCHECK(IsWithinQuickCode(pc))
<< PrettyMethod(this)
<< " pc=" << std::hex << pc
<< " code=" << code
<< " size=" << GetCodeSize();
}
-inline uint32_t ArtMethod::GetOatCodeOffset() const {
+inline uint32_t ArtMethod::GetQuickOatCodeOffset() {
DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetEntryPointFromCompiledCode());
+ return PointerToLowMemUInt32(GetEntryPointFromQuickCompiledCode());
}
-inline void ArtMethod::SetOatCodeOffset(uint32_t code_offset) {
+inline uint32_t ArtMethod::GetPortableOatCodeOffset() {
DCHECK(!Runtime::Current()->IsStarted());
- SetEntryPointFromCompiledCode(reinterpret_cast<void*>(code_offset));
+ return PointerToLowMemUInt32(GetEntryPointFromPortableCompiledCode());
}
-inline uint32_t ArtMethod::GetOatMappingTableOffset() const {
+inline void ArtMethod::SetQuickOatCodeOffset(uint32_t code_offset) {
DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetMappingTable());
+ SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(code_offset));
+}
+
+inline void ArtMethod::SetPortableOatCodeOffset(uint32_t code_offset) {
+ DCHECK(!Runtime::Current()->IsStarted());
+ SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(code_offset));
+}
+
+inline uint32_t ArtMethod::GetOatMappingTableOffset() {
+ DCHECK(!Runtime::Current()->IsStarted());
+ return PointerToLowMemUInt32(GetMappingTable());
}
inline void ArtMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) {
@@ -151,9 +162,9 @@ inline void ArtMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) {
SetMappingTable(reinterpret_cast<const uint8_t*>(mapping_table_offset));
}
-inline uint32_t ArtMethod::GetOatVmapTableOffset() const {
+inline uint32_t ArtMethod::GetOatVmapTableOffset() {
DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetVmapTable());
+ return PointerToLowMemUInt32(GetVmapTable());
}
inline void ArtMethod::SetOatVmapTableOffset(uint32_t vmap_table_offset) {
@@ -166,16 +177,16 @@ inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) {
SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset));
}
-inline uint32_t ArtMethod::GetOatNativeGcMapOffset() const {
+inline uint32_t ArtMethod::GetOatNativeGcMapOffset() {
DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetNativeGcMap());
+ return PointerToLowMemUInt32(GetNativeGcMap());
}
-inline bool ArtMethod::IsRuntimeMethod() const {
+inline bool ArtMethod::IsRuntimeMethod() {
return GetDexMethodIndex() == DexFile::kDexNoIndex;
}
-inline bool ArtMethod::IsCalleeSaveMethod() const {
+inline bool ArtMethod::IsCalleeSaveMethod() {
if (!IsRuntimeMethod()) {
return false;
}
@@ -190,14 +201,14 @@ inline bool ArtMethod::IsCalleeSaveMethod() const {
return result;
}
-inline bool ArtMethod::IsResolutionMethod() const {
+inline bool ArtMethod::IsResolutionMethod() {
bool result = this == Runtime::Current()->GetResolutionMethod();
// Check that if we do think it is phony it looks like the resolution method.
DCHECK(!result || IsRuntimeMethod());
return result;
}
-inline bool ArtMethod::IsImtConflictMethod() const {
+inline bool ArtMethod::IsImtConflictMethod() {
bool result = this == Runtime::Current()->GetImtConflictMethod();
// Check that if we do think it is phony it looks like the imt conflict method.
DCHECK(!result || IsRuntimeMethod());
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index f4a076c..575ea03 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -47,7 +47,7 @@ void ArtMethod::VisitRoots(RootVisitor* visitor, void* arg) {
}
}
-InvokeType ArtMethod::GetInvokeType() const {
+InvokeType ArtMethod::GetInvokeType() {
// TODO: kSuper?
if (GetDeclaringClass()->IsInterface()) {
return kInterface;
@@ -100,11 +100,11 @@ size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) {
return num_registers;
}
-bool ArtMethod::IsProxyMethod() const {
+bool ArtMethod::IsProxyMethod() {
return GetDeclaringClass()->IsProxyClass();
}
-ArtMethod* ArtMethod::FindOverriddenMethod() const {
+ArtMethod* ArtMethod::FindOverriddenMethod() {
if (IsStatic()) {
return NULL;
}
@@ -147,13 +147,16 @@ ArtMethod* ArtMethod::FindOverriddenMethod() const {
return result;
}
-uintptr_t ArtMethod::NativePcOffset(const uintptr_t pc) const {
+uintptr_t ArtMethod::NativePcOffset(const uintptr_t pc) {
const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this);
return pc - reinterpret_cast<uintptr_t>(code);
}
-uint32_t ArtMethod::ToDexPc(const uintptr_t pc) const {
-#if !defined(ART_USE_PORTABLE_COMPILER)
+uint32_t ArtMethod::ToDexPc(const uintptr_t pc) {
+ if (IsPortableCompiled()) {
+ // Portable doesn't use the machine pc, we just use dex pc instead.
+ return static_cast<uint32_t>(pc);
+ }
MappingTable table(GetMappingTable());
if (table.TotalSize() == 0) {
DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this);
@@ -176,16 +179,12 @@ uint32_t ArtMethod::ToDexPc(const uintptr_t pc) const {
}
}
LOG(FATAL) << "Failed to find Dex offset for PC offset " << reinterpret_cast<void*>(sought_offset)
- << "(PC " << reinterpret_cast<void*>(pc) << ", code=" << code
- << ") in " << PrettyMethod(this);
+ << "(PC " << reinterpret_cast<void*>(pc) << ", code=" << code
+ << ") in " << PrettyMethod(this);
return DexFile::kDexNoIndex;
-#else
- // Compiler LLVM doesn't use the machine pc, we just use dex pc instead.
- return static_cast<uint32_t>(pc);
-#endif
}
-uintptr_t ArtMethod::ToNativePc(const uint32_t dex_pc) const {
+uintptr_t ArtMethod::ToNativePc(const uint32_t dex_pc) {
MappingTable table(GetMappingTable());
if (table.TotalSize() == 0) {
DCHECK_EQ(dex_pc, 0U);
@@ -213,7 +212,7 @@ uintptr_t ArtMethod::ToNativePc(const uint32_t dex_pc) const {
}
uint32_t ArtMethod::FindCatchBlock(Class* exception_type, uint32_t dex_pc,
- bool* has_no_move_exception) const {
+ bool* has_no_move_exception) {
MethodHelper mh(this);
const DexFile::CodeItem* code_item = mh.GetCodeItem();
// Default to handler not found.
@@ -265,16 +264,21 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
}
} else {
const bool kLogInvocationStartAndReturn = false;
- if (GetEntryPointFromCompiledCode() != NULL) {
+ bool have_quick_code = GetEntryPointFromQuickCompiledCode() != nullptr;
+ bool have_portable_code = GetEntryPointFromPortableCompiledCode() != nullptr;
+ if (LIKELY(have_quick_code || have_portable_code)) {
if (kLogInvocationStartAndReturn) {
- LOG(INFO) << StringPrintf("Invoking '%s' code=%p", PrettyMethod(this).c_str(), GetEntryPointFromCompiledCode());
+ LOG(INFO) << StringPrintf("Invoking '%s' %s code=%p", PrettyMethod(this).c_str(),
+ have_quick_code ? "quick" : "portable",
+ have_quick_code ? GetEntryPointFromQuickCompiledCode()
+ : GetEntryPointFromPortableCompiledCode());
}
-#ifdef ART_USE_PORTABLE_COMPILER
- (*art_portable_invoke_stub)(this, args, args_size, self, result, result_type);
-#else
- (*art_quick_invoke_stub)(this, args, args_size, self, result, result_type);
-#endif
- if (UNLIKELY(reinterpret_cast<int32_t>(self->GetException(NULL)) == -1)) {
+ if (!IsPortableCompiled()) {
+ (*art_quick_invoke_stub)(this, args, args_size, self, result, result_type);
+ } else {
+ (*art_portable_invoke_stub)(this, args, args_size, self, result, result_type);
+ }
+ if (UNLIKELY(reinterpret_cast<intptr_t>(self->GetException(NULL)) == -1)) {
// Unusual case where we were running LLVM generated code and an
// exception was thrown to force the activations to be removed from the
// stack. Continue execution in the interpreter.
@@ -285,11 +289,13 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
interpreter::EnterInterpreterFromDeoptimize(self, shadow_frame, result);
}
if (kLogInvocationStartAndReturn) {
- LOG(INFO) << StringPrintf("Returned '%s' code=%p", PrettyMethod(this).c_str(), GetEntryPointFromCompiledCode());
+ LOG(INFO) << StringPrintf("Returned '%s' %s code=%p", PrettyMethod(this).c_str(),
+ have_quick_code ? "quick" : "portable",
+ have_quick_code ? GetEntryPointFromQuickCompiledCode()
+ : GetEntryPointFromPortableCompiledCode());
}
} else {
- LOG(INFO) << "Not invoking '" << PrettyMethod(this)
- << "' code=" << reinterpret_cast<const void*>(GetEntryPointFromCompiledCode());
+ LOG(INFO) << "Not invoking '" << PrettyMethod(this) << "' code=null";
if (result != NULL) {
result->SetJ(0);
}
@@ -300,9 +306,10 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
self->PopManagedStackFragment(fragment);
}
-bool ArtMethod::IsRegistered() const {
- void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, native_method_), false);
- CHECK(native_method != NULL);
+bool ArtMethod::IsRegistered() {
+ void* native_method =
+ GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_), false);
+ CHECK(native_method != nullptr);
void* jni_stub = GetJniDlsymLookupStub();
return native_method != jni_stub;
}
@@ -323,7 +330,7 @@ void ArtMethod::RegisterNative(Thread* self, const void* native_method, bool is_
// around JNI bugs, that include not giving Object** SIRT references to native methods. Direct
// the native method to runtime support and store the target somewhere runtime support will
// find it.
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
UNIMPLEMENTED(FATAL);
#else
SetNativeMethod(reinterpret_cast<void*>(art_work_around_app_jni_bugs));
@@ -340,7 +347,7 @@ void ArtMethod::UnregisterNative(Thread* self) {
}
void ArtMethod::SetNativeMethod(const void* native_method) {
- SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, native_method_),
+ SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_),
native_method, false);
}
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 95ca4c9..bfa7cbe 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -45,7 +45,7 @@ typedef void (EntryPointFromInterpreter)(Thread* self, MethodHelper& mh,
// C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor
class MANAGED ArtMethod : public Object {
public:
- Class* GetDeclaringClass() const;
+ Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -53,41 +53,37 @@ class MANAGED ArtMethod : public Object {
return MemberOffset(OFFSETOF_MEMBER(ArtMethod, declaring_class_));
}
- static MemberOffset EntryPointFromCompiledCodeOffset() {
- return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_compiled_code_));
- }
-
- uint32_t GetAccessFlags() const;
+ uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetAccessFlags(uint32_t new_access_flags) {
+ void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_), new_access_flags, false);
}
// Approximate what kind of method call would be used for this method.
- InvokeType GetInvokeType() const;
+ InvokeType GetInvokeType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns true if the method is declared public.
- bool IsPublic() const {
+ bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPublic) != 0;
}
// Returns true if the method is declared private.
- bool IsPrivate() const {
+ bool IsPrivate() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPrivate) != 0;
}
// Returns true if the method is declared static.
- bool IsStatic() const {
+ bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccStatic) != 0;
}
// Returns true if the method is a constructor.
- bool IsConstructor() const {
+ bool IsConstructor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccConstructor) != 0;
}
// Returns true if the method is static, private, or a constructor.
- bool IsDirect() const {
+ bool IsDirect() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return IsDirect(GetAccessFlags());
}
@@ -96,55 +92,70 @@ class MANAGED ArtMethod : public Object {
}
// Returns true if the method is declared synchronized.
- bool IsSynchronized() const {
+ bool IsSynchronized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
return (GetAccessFlags() & synchonized) != 0;
}
- bool IsFinal() const {
+ bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccFinal) != 0;
}
- bool IsMiranda() const {
+ bool IsMiranda() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccMiranda) != 0;
}
- bool IsNative() const {
+ bool IsNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccNative) != 0;
}
- bool IsFastNative() const {
+ bool IsFastNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t mask = kAccFastNative | kAccNative;
return (GetAccessFlags() & mask) == mask;
}
- bool IsAbstract() const {
+ bool IsAbstract() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccAbstract) != 0;
}
- bool IsSynthetic() const {
+ bool IsSynthetic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccSynthetic) != 0;
}
- bool IsProxyMethod() const;
+ bool IsProxyMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsPreverified() const {
+ bool IsPreverified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPreverified) != 0;
}
- void SetPreverified() {
+ void SetPreverified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(!IsPreverified());
SetAccessFlags(GetAccessFlags() | kAccPreverified);
}
+ bool IsPortableCompiled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return (GetAccessFlags() & kAccPortableCompiled) != 0;
+ }
+
+ void SetIsPortableCompiled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(!IsPortableCompiled());
+ SetAccessFlags(GetAccessFlags() | kAccPortableCompiled);
+ }
+
+ void ClearIsPortableCompiled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(IsPortableCompiled());
+ SetAccessFlags(GetAccessFlags() & ~kAccPortableCompiled);
+ }
+
bool CheckIncompatibleClassChange(InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint16_t GetMethodIndex() const;
+ uint16_t GetMethodIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t GetVtableIndex() const {
+ size_t GetVtableIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetMethodIndex();
}
- void SetMethodIndex(uint16_t new_method_index) {
+ void SetMethodIndex(uint16_t new_method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_), new_method_index, false);
}
@@ -152,24 +163,24 @@ class MANAGED ArtMethod : public Object {
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
}
- uint32_t GetCodeItemOffset() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, code_item_offset_), false);
+ uint32_t GetCodeItemOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_code_item_offset_), false);
}
void SetCodeItemOffset(uint32_t new_code_off) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, code_item_offset_), new_code_off, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_code_item_offset_), new_code_off, false);
}
// Number of 32bit registers that would be required to hold all the arguments
static size_t NumArgRegisters(const StringPiece& shorty);
- uint32_t GetDexMethodIndex() const;
+ uint32_t GetDexMethodIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexMethodIndex(uint32_t new_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_dex_index_), new_idx, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_), new_idx, false);
}
- ObjectArray<String>* GetDexCacheStrings() const;
+ ObjectArray<String>* GetDexCacheStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -185,41 +196,62 @@ class MANAGED ArtMethod : public Object {
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_);
}
- ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() const;
+ ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheResolvedMethods(ObjectArray<ArtMethod>* new_dex_cache_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<Class>* GetDexCacheResolvedTypes() const;
+ ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find the method that this method overrides
- ArtMethod* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, char result_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- EntryPointFromInterpreter* GetEntryPointFromInterpreter() const {
- return GetFieldPtr<EntryPointFromInterpreter*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_), false);
+ EntryPointFromInterpreter* GetEntryPointFromInterpreter() {
+ return GetFieldPtr<EntryPointFromInterpreter*>(
+ OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_), false);
}
void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) {
- SetFieldPtr<EntryPointFromInterpreter*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_), entry_point_from_interpreter, false);
+ SetFieldPtr<EntryPointFromInterpreter*>(
+ OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_),
+ entry_point_from_interpreter, false);
}
- const void* GetEntryPointFromCompiledCode() const {
- return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_compiled_code_), false);
+ static MemberOffset EntryPointFromPortableCompiledCodeOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_portable_compiled_code_));
}
- void SetEntryPointFromCompiledCode(const void* entry_point_from_compiled_code) {
- SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_compiled_code_), entry_point_from_compiled_code, false);
+ const void* GetEntryPointFromPortableCompiledCode() {
+ return GetFieldPtr<const void*>(EntryPointFromPortableCompiledCodeOffset(), false);
}
- uint32_t GetCodeSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetEntryPointFromPortableCompiledCode(const void* entry_point_from_portable_compiled_code) {
+ SetFieldPtr<const void*>(EntryPointFromPortableCompiledCodeOffset(),
+ entry_point_from_portable_compiled_code, false);
+ }
+
+ static MemberOffset EntryPointFromQuickCompiledCodeOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_quick_compiled_code_));
+ }
- bool IsWithinCode(uintptr_t pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromCompiledCode());
+ const void* GetEntryPointFromQuickCompiledCode() {
+ return GetFieldPtr<const void*>(EntryPointFromQuickCompiledCodeOffset(), false);
+ }
+
+ void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) {
+ SetFieldPtr<const void*>(EntryPointFromQuickCompiledCodeOffset(),
+ entry_point_from_quick_compiled_code, false);
+ }
+
+
+ uint32_t GetCodeSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ bool IsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode());
if (code == 0) {
return pc == 0;
}
@@ -231,45 +263,44 @@ class MANAGED ArtMethod : public Object {
return (code <= pc && pc <= code + GetCodeSize());
}
- void AssertPcIsWithinCode(uintptr_t pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- uint32_t GetOatCodeOffset() const;
+ void AssertPcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetOatCodeOffset(uint32_t code_offset);
-
- static MemberOffset GetEntryPointFromCompiledCodeOffset() {
- return OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_compiled_code_);
- }
+ uint32_t GetQuickOatCodeOffset();
+ uint32_t GetPortableOatCodeOffset();
+ void SetQuickOatCodeOffset(uint32_t code_offset);
+ void SetPortableOatCodeOffset(uint32_t code_offset);
// Callers should wrap the uint8_t* in a MappingTable instance for convenient access.
- const uint8_t* GetMappingTable() const {
- return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, mapping_table_), false);
+ const uint8_t* GetMappingTable() {
+ return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_),
+ false);
}
void SetMappingTable(const uint8_t* mapping_table) {
- SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, mapping_table_),
- mapping_table, false);
+ SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_),
+ mapping_table, false);
}
- uint32_t GetOatMappingTableOffset() const;
+ uint32_t GetOatMappingTableOffset();
void SetOatMappingTableOffset(uint32_t mapping_table_offset);
// Callers should wrap the uint8_t* in a VmapTable instance for convenient access.
- const uint8_t* GetVmapTable() const {
- return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, vmap_table_), false);
+ const uint8_t* GetVmapTable() {
+ return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_),
+ false);
}
void SetVmapTable(const uint8_t* vmap_table) {
- SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, vmap_table_), vmap_table, false);
+ SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table,
+ false);
}
- uint32_t GetOatVmapTableOffset() const;
+ uint32_t GetOatVmapTableOffset();
void SetOatVmapTableOffset(uint32_t vmap_table_offset);
- const uint8_t* GetNativeGcMap() const {
+ const uint8_t* GetNativeGcMap() {
return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), false);
}
void SetNativeGcMap(const uint8_t* data) {
@@ -278,31 +309,30 @@ class MANAGED ArtMethod : public Object {
// When building the oat need a convenient place to stuff the offset of the native GC map.
void SetOatNativeGcMapOffset(uint32_t gc_map_offset);
- uint32_t GetOatNativeGcMapOffset() const;
+ uint32_t GetOatNativeGcMapOffset();
- size_t GetFrameSizeInBytes() const {
+ size_t GetFrameSizeInBytes() {
DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
- size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, frame_size_in_bytes_), false);
+ size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_frame_size_in_bytes_), false);
DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
return result;
}
void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) {
- DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, frame_size_in_bytes_),
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_frame_size_in_bytes_),
new_frame_size_in_bytes, false);
}
- size_t GetReturnPcOffsetInBytes() const {
+ size_t GetReturnPcOffsetInBytes() {
return GetFrameSizeInBytes() - kPointerSize;
}
- size_t GetSirtOffsetInBytes() const {
+ size_t GetSirtOffsetInBytes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK(IsNative());
return kPointerSize;
}
- bool IsRegistered() const;
+ bool IsRegistered();
void RegisterNative(Thread* self, const void* native_method, bool is_fast)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -310,10 +340,10 @@ class MANAGED ArtMethod : public Object {
void UnregisterNative(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static MemberOffset NativeMethodOffset() {
- return OFFSET_OF_OBJECT_MEMBER(ArtMethod, native_method_);
+ return OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_);
}
- const void* GetNativeMethod() const {
+ const void* GetNativeMethod() {
return reinterpret_cast<const void*>(GetField32(NativeMethodOffset(), false));
}
@@ -323,47 +353,47 @@ class MANAGED ArtMethod : public Object {
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
}
- uint32_t GetCoreSpillMask() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, core_spill_mask_), false);
+ uint32_t GetCoreSpillMask() {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_core_spill_mask_), false);
}
void SetCoreSpillMask(uint32_t core_spill_mask) {
// Computed during compilation
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, core_spill_mask_), core_spill_mask, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_core_spill_mask_), core_spill_mask, false);
}
- uint32_t GetFpSpillMask() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, fp_spill_mask_), false);
+ uint32_t GetFpSpillMask() {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_fp_spill_mask_), false);
}
void SetFpSpillMask(uint32_t fp_spill_mask) {
// Computed during compilation
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, fp_spill_mask_), fp_spill_mask, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_fp_spill_mask_), fp_spill_mask, false);
}
// Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
// conventions for a method of managed code. Returns false for Proxy methods.
- bool IsRuntimeMethod() const;
+ bool IsRuntimeMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Is this a hand crafted method used for something like describing callee saves?
- bool IsCalleeSaveMethod() const;
+ bool IsCalleeSaveMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsResolutionMethod() const;
+ bool IsResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsImtConflictMethod() const;
+ bool IsImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uintptr_t NativePcOffset(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uintptr_t NativePcOffset(const uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Converts a native PC to a dex PC.
- uint32_t ToDexPc(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t ToDexPc(const uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Converts a dex PC to a native PC.
- uintptr_t ToNativePc(const uint32_t dex_pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uintptr_t ToNativePc(const uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find the catch block for the given exception type and dex_pc. When a catch block is found,
// indicates whether the found catch block is responsible for clearing the exception or whether
// a move-exception instruction is present.
- uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc, bool* has_no_move_exception) const
+ uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc, bool* has_no_move_exception)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void SetClass(Class* java_lang_reflect_ArtMethod);
@@ -379,65 +409,83 @@ class MANAGED ArtMethod : public Object {
protected:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- // The class we are a part of
- Class* declaring_class_;
+ // The class we are a part of.
+ HeapReference<Class> declaring_class_;
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<ArtMethod>* dex_cache_resolved_methods_;
+ // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
+ HeapReference<ObjectArray<ArtMethod> > dex_cache_resolved_methods_;
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<Class>* dex_cache_resolved_types_;
+ // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
+ HeapReference<ObjectArray<Class> > dex_cache_resolved_types_;
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<String>* dex_cache_strings_;
+ // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
+ HeapReference<ObjectArray<String> > dex_cache_strings_;
- // Access flags; low 16 bits are defined by spec.
- uint32_t access_flags_;
+ // Method dispatch from the interpreter invokes this pointer which may cause a bridge into
+ // compiled code.
+ uint64_t entry_point_from_interpreter_;
- // Offset to the CodeItem.
- uint32_t code_item_offset_;
+ // Pointer to JNI function registered to this method, or a function to resolve the JNI function.
+ uint64_t entry_point_from_jni_;
+
+ // Method dispatch from portable compiled code invokes this pointer which may cause bridging into
+ // quick compiled code or the interpreter.
+ uint64_t entry_point_from_portable_compiled_code_;
- // Architecture-dependent register spill mask
- uint32_t core_spill_mask_;
+ // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
+ // portable compiled code or the interpreter.
+ uint64_t entry_point_from_quick_compiled_code_;
- // Compiled code associated with this method for callers from managed code.
- // May be compiled managed code or a bridge for invoking a native method.
- // TODO: Break apart this into portable and quick.
- const void* entry_point_from_compiled_code_;
+ // Pointer to a data structure created by the compiler and used by the garbage collector to
+ // determine which registers hold live references to objects within the heap. Keyed by native PC
+ // offsets for the quick compiler and dex PCs for the portable.
+ uint64_t gc_map_;
+
+ // --- Quick compiler meta-data. ---
+ // TODO: merge and place in native heap, such as done with the code size.
+
+ // Pointer to a data structure created by the quick compiler to map between dex PCs and native
+ // PCs, and vice-versa.
+ uint64_t quick_mapping_table_;
+
+ // When a register is promoted into a register, the spill mask holds which registers hold dex
+ // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth
+ // is vmap_table_[N]. vmap_table_[0] holds the length of the table.
+ uint64_t quick_vmap_table_;
- // Called by the interpreter to execute this method.
- EntryPointFromInterpreter* entry_point_from_interpreter_;
+ // --- End of quick compiler meta-data. ---
- // Architecture-dependent register spill mask
- uint32_t fp_spill_mask_;
+ // Access flags; low 16 bits are defined by spec.
+ uint32_t access_flags_;
- // Total size in bytes of the frame
- size_t frame_size_in_bytes_;
+ /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
- // Garbage collection map of native PC offsets (quick) or dex PCs (portable) to reference bitmaps.
- const uint8_t* gc_map_;
+ // Offset to the CodeItem.
+ uint32_t dex_code_item_offset_;
- // Mapping from native pc to dex pc
- const uint32_t* mapping_table_;
+ // Index into method_ids of the dex file associated with this method.
+ uint32_t dex_method_index_;
- // Index into method_ids of the dex file associated with this method
- uint32_t method_dex_index_;
+ /* End of dex file fields. */
- // For concrete virtual methods, this is the offset of the method in Class::vtable_.
- //
- // For abstract methods in an interface class, this is the offset of the method in
- // "iftable_->Get(n)->GetMethodArray()".
- //
- // For static and direct methods this is the index in the direct methods table.
+ // Entry within a dispatch table for this method. For static/direct methods the index is into
+ // the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
+ // ifTable.
uint32_t method_index_;
- // The target native method registered with this method
- const void* native_method_;
+ // --- Quick compiler meta-data. ---
+ // TODO: merge and place in native heap, such as done with the code size.
- // When a register is promoted into a register, the spill mask holds which registers hold dex
- // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth
- // is vmap_table_[N]. vmap_table_[0] holds the length of the table.
- const uint16_t* vmap_table_;
+ // Bit map of spilled machine registers.
+ uint32_t quick_core_spill_mask_;
+
+ // Bit map of spilled floating point machine registers.
+ uint32_t quick_fp_spill_mask_;
+
+ // Fixed frame size for this method when executed.
+ uint32_t quick_frame_size_in_bytes_;
+
+ // --- End of quick compiler meta-data. ---
static Class* java_lang_reflect_ArtMethod_;
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 8ddaeb2..a5f743b 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -33,63 +33,61 @@
namespace art {
namespace mirror {
-inline size_t Class::GetObjectSize() const {
+inline uint32_t Class::GetObjectSize() {
DCHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this);
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), false);
}
-inline Class* Class::GetSuperClass() const {
+inline Class* Class::GetSuperClass() {
// Can only get super class for loaded classes (hack for when runtime is
// initializing)
DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded();
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
}
-inline ClassLoader* Class::GetClassLoader() const {
- return GetFieldObject<ClassLoader*>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
+inline ClassLoader* Class::GetClassLoader() {
+ return GetFieldObject<ClassLoader>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
}
-inline DexCache* Class::GetDexCache() const {
- return GetFieldObject<DexCache*>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
+inline DexCache* Class::GetDexCache() {
+ return GetFieldObject<DexCache>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
}
-inline ObjectArray<ArtMethod>* Class::GetDirectMethods() const {
+inline ObjectArray<ArtMethod>* Class::GetDirectMethods() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtMethod>*>(
+ return GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
}
inline void Class::SetDirectMethods(ObjectArray<ArtMethod>* new_direct_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<ArtMethod>*>(
+ DCHECK(NULL == GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false));
DCHECK_NE(0, new_direct_methods->GetLength());
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
new_direct_methods, false);
}
-inline ArtMethod* Class::GetDirectMethod(int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::GetDirectMethod(int32_t i) {
return GetDirectMethods()->Get(i);
}
inline void Class::SetDirectMethod(uint32_t i, ArtMethod* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ObjectArray<ArtMethod>* direct_methods =
- GetFieldObject<ObjectArray<ArtMethod>*>(
+ GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
direct_methods->Set(i, f);
}
// Returns the number of static, private, and constructor methods.
-inline size_t Class::NumDirectMethods() const {
+inline uint32_t Class::NumDirectMethods() {
return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
}
-inline ObjectArray<ArtMethod>* Class::GetVirtualMethods() const {
+inline ObjectArray<ArtMethod>* Class::GetVirtualMethods() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtMethod>*>(
+ return GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
}
@@ -101,18 +99,16 @@ inline void Class::SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods
new_virtual_methods, false);
}
-inline size_t Class::NumVirtualMethods() const {
+inline uint32_t Class::NumVirtualMethods() {
return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
}
-inline ArtMethod* Class::GetVirtualMethod(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::GetVirtualMethod(uint32_t i) {
DCHECK(IsResolved() || IsErroneous());
return GetVirtualMethods()->Get(i);
}
-inline ArtMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) {
DCHECK(IsLoaded() || IsErroneous());
return GetVirtualMethods()->Get(i);
}
@@ -120,35 +116,34 @@ inline ArtMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) const
inline void Class::SetVirtualMethod(uint32_t i, ArtMethod* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ObjectArray<ArtMethod>* virtual_methods =
- GetFieldObject<ObjectArray<ArtMethod>*>(
+ GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
virtual_methods->Set(i, f);
}
-inline ObjectArray<ArtMethod>* Class::GetVTable() const {
+inline ObjectArray<ArtMethod>* Class::GetVTable() {
DCHECK(IsResolved() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+ return GetFieldObject<ObjectArray<ArtMethod> >(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
}
-inline ObjectArray<ArtMethod>* Class::GetVTableDuringLinking() const {
+inline ObjectArray<ArtMethod>* Class::GetVTableDuringLinking() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+ return GetFieldObject<ObjectArray<ArtMethod> >(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
}
-inline void Class::SetVTable(ObjectArray<ArtMethod>* new_vtable)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline void Class::SetVTable(ObjectArray<ArtMethod>* new_vtable) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false);
}
-inline ObjectArray<ArtMethod>* Class::GetImTable() const {
- return GetFieldObject<ObjectArray<ArtMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, imtable_), false);
+inline ObjectArray<ArtMethod>* Class::GetImTable() {
+ return GetFieldObject<ObjectArray<ArtMethod> >(OFFSET_OF_OBJECT_MEMBER(Class, imtable_), false);
}
inline void Class::SetImTable(ObjectArray<ArtMethod>* new_imtable) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, imtable_), new_imtable, false);
}
-inline bool Class::Implements(const Class* klass) const {
+inline bool Class::Implements(Class* klass) {
DCHECK(klass != NULL);
DCHECK(klass->IsInterface()) << PrettyClass(this);
// All interfaces implemented directly and by our superclass, and
@@ -183,13 +178,13 @@ inline bool Class::Implements(const Class* klass) const {
// Don't forget about primitive types.
// Object[] = int[] --> false
//
-inline bool Class::IsArrayAssignableFromArray(const Class* src) const {
+inline bool Class::IsArrayAssignableFromArray(Class* src) {
DCHECK(IsArrayClass()) << PrettyClass(this);
DCHECK(src->IsArrayClass()) << PrettyClass(src);
return GetComponentType()->IsAssignableFrom(src->GetComponentType());
}
-inline bool Class::IsAssignableFromArray(const Class* src) const {
+inline bool Class::IsAssignableFromArray(Class* src) {
DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom
DCHECK(src->IsArrayClass()) << PrettyClass(src);
if (!IsArrayClass()) {
@@ -205,13 +200,13 @@ inline bool Class::IsAssignableFromArray(const Class* src) const {
template <bool throw_on_failure, bool use_referrers_cache>
inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field,
- uint32_t field_idx, const DexCache* dex_cache) {
+ uint32_t field_idx, DexCache* dex_cache) {
DCHECK_EQ(use_referrers_cache, dex_cache == nullptr);
if (UNLIKELY(!this->CanAccess(access_to))) {
// The referrer class can't access the field's declaring class but may still be able
// to access the field if the FieldId specifies an accessible subclass of the declaring
// class rather than the declaring class itself.
- const DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
+ DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_;
// The referenced class has already been resolved with the field, get it from the dex cache.
Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx);
@@ -236,14 +231,14 @@ inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field,
template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type>
inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method,
- uint32_t method_idx, const DexCache* dex_cache) {
+ uint32_t method_idx, DexCache* dex_cache) {
COMPILE_ASSERT(throw_on_failure || throw_invoke_type == kStatic, non_default_throw_invoke_type);
DCHECK_EQ(use_referrers_cache, dex_cache == nullptr);
if (UNLIKELY(!this->CanAccess(access_to))) {
// The referrer class can't access the method's declaring class but may still be able
// to access the method if the MethodId specifies an accessible subclass of the declaring
// class rather than the declaring class itself.
- const DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
+ DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_;
// The referenced class has already been resolved with the method, get it from the dex cache.
Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx);
@@ -268,8 +263,8 @@ inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method,
}
inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field,
- const DexCache& dex_cache, uint32_t field_idx) {
- return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, &dex_cache);
+ DexCache* dex_cache, uint32_t field_idx) {
+ return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, dex_cache);
}
inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field,
@@ -278,8 +273,8 @@ inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field,
}
inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method,
- const DexCache& dex_cache, uint32_t method_idx) {
- return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, &dex_cache);
+ DexCache* dex_cache, uint32_t method_idx) {
+ return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, dex_cache);
}
template <InvokeType throw_invoke_type>
@@ -289,10 +284,10 @@ inline bool Class::CheckResolvedMethodAccess(Class* access_to, ArtMethod* method
nullptr);
}
-inline bool Class::IsSubClass(const Class* klass) const {
+inline bool Class::IsSubClass(Class* klass) {
DCHECK(!IsInterface()) << PrettyClass(this);
DCHECK(!IsArrayClass()) << PrettyClass(this);
- const Class* current = this;
+ Class* current = this;
do {
if (current == klass) {
return true;
@@ -302,7 +297,7 @@ inline bool Class::IsSubClass(const Class* klass) const {
return false;
}
-inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method) const {
+inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method) {
Class* declaring_class = method->GetDeclaringClass();
DCHECK(declaring_class != NULL) << PrettyClass(this);
DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
@@ -317,21 +312,19 @@ inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method) const
return NULL;
}
-inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method) {
DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsMiranda());
// The argument method may from a super class.
// Use the index to a potentially overridden one for this instance's class.
return GetVTable()->Get(method->GetMethodIndex());
}
-inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method) {
DCHECK(!method->GetDeclaringClass()->IsInterface());
return GetSuperClass()->GetVTable()->Get(method->GetMethodIndex());
}
-inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method) const {
+inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method) {
if (method->IsDirect()) {
return method;
}
@@ -341,11 +334,11 @@ inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* metho
return FindVirtualMethodForVirtual(method);
}
-inline IfTable* Class::GetIfTable() const {
- return GetFieldObject<IfTable*>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
+inline IfTable* Class::GetIfTable() {
+ return GetFieldObject<IfTable>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
}
-inline int32_t Class::GetIfTableCount() const {
+inline int32_t Class::GetIfTableCount() {
IfTable* iftable = GetIfTable();
if (iftable == NULL) {
return 0;
@@ -357,59 +350,58 @@ inline void Class::SetIfTable(IfTable* new_iftable) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable, false);
}
-inline ObjectArray<ArtField>* Class::GetIFields() const {
+inline ObjectArray<ArtField>* Class::GetIFields() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
+ return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
}
inline void Class::SetIFields(ObjectArray<ArtField>* new_ifields)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<ArtField>*>(
+ DCHECK(NULL == GetFieldObject<ObjectArray<ArtField> >(
OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false));
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields, false);
}
-inline ObjectArray<ArtField>* Class::GetSFields() const {
+inline ObjectArray<ArtField>* Class::GetSFields() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
+ return GetFieldObject<ObjectArray<ArtField> >(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
}
inline void Class::SetSFields(ObjectArray<ArtField>* new_sfields)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<ArtField>*>(
+ DCHECK(NULL == GetFieldObject<ObjectArray<ArtField> >(
OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false));
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields, false);
}
-inline size_t Class::NumStaticFields() const {
+inline uint32_t Class::NumStaticFields() {
return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0;
}
-inline ArtField* Class::GetStaticField(uint32_t i) const // TODO: uint16_t
+inline ArtField* Class::GetStaticField(uint32_t i) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetSFields()->Get(i);
}
inline void Class::SetStaticField(uint32_t i, ArtField* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ObjectArray<ArtField>* sfields= GetFieldObject<ObjectArray<ArtField>*>(
+ ObjectArray<ArtField>* sfields= GetFieldObject<ObjectArray<ArtField> >(
OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
sfields->Set(i, f);
}
-inline size_t Class::NumInstanceFields() const {
+inline uint32_t Class::NumInstanceFields() {
return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0;
}
-inline ArtField* Class::GetInstanceField(uint32_t i) const // TODO: uint16_t
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtField* Class::GetInstanceField(uint32_t i) { // TODO: uint16_t
DCHECK_NE(NumInstanceFields(), 0U);
return GetIFields()->Get(i);
}
inline void Class::SetInstanceField(uint32_t i, ArtField* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ObjectArray<ArtField>* ifields= GetFieldObject<ObjectArray<ArtField>*>(
+ ObjectArray<ArtField>* ifields= GetFieldObject<ObjectArray<ArtField> >(
OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
ifields->Set(i, f);
}
@@ -419,7 +411,7 @@ inline void Class::SetVerifyErrorClass(Class* klass) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false);
}
-inline uint32_t Class::GetAccessFlags() const {
+inline uint32_t Class::GetAccessFlags() {
// Check class is loaded or this is java.lang.String that has a
// circularity issue during loading the names of its members
DCHECK(IsLoaded() || IsErroneous() ||
@@ -429,8 +421,8 @@ inline uint32_t Class::GetAccessFlags() const {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
}
-inline String* Class::GetName() const {
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
+inline String* Class::GetName() {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
}
inline void Class::SetName(String* name) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false);
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index bd965fa..8051c9b 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -125,7 +125,7 @@ void Class::SetDexCache(DexCache* new_dex_cache) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache, false);
}
-void Class::SetClassSize(size_t new_class_size) {
+void Class::SetClassSize(uint32_t new_class_size) {
if (kIsDebugBuild && (new_class_size < GetClassSize())) {
DumpClass(LOG(ERROR), kDumpClassFullDetail);
CHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this);
@@ -177,7 +177,7 @@ String* Class::ComputeName() {
return name;
}
-void Class::DumpClass(std::ostream& os, int flags) const {
+void Class::DumpClass(std::ostream& os, int flags) {
if ((flags & kDumpClassFullDetail) == 0) {
os << PrettyClass(this);
if ((flags & kDumpClassClassLoader) != 0) {
@@ -281,9 +281,9 @@ bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& d
}
}
-bool Class::IsInSamePackage(const Class* that) const {
- const Class* klass1 = this;
- const Class* klass2 = that;
+bool Class::IsInSamePackage(Class* that) {
+ Class* klass1 = this;
+ Class* klass2 = that;
if (klass1 == klass2) {
return true;
}
@@ -307,7 +307,7 @@ bool Class::IsInSamePackage(const Class* that) const {
ClassHelper(klass2).GetDescriptor());
}
-bool Class::IsClassClass() const {
+bool Class::IsClassClass() {
Class* java_lang_Class = GetClass()->GetClass();
return this == java_lang_Class;
}
@@ -316,17 +316,17 @@ bool Class::IsStringClass() const {
return this == String::GetJavaLangString();
}
-bool Class::IsThrowableClass() const {
+bool Class::IsThrowableClass() {
return WellKnownClasses::ToClass(WellKnownClasses::java_lang_Throwable)->IsAssignableFrom(this);
}
-bool Class::IsArtFieldClass() const {
+bool Class::IsArtFieldClass() {
Class* java_lang_Class = GetClass();
Class* java_lang_reflect_ArtField = java_lang_Class->GetInstanceField(0)->GetClass();
return this == java_lang_reflect_ArtField;
}
-bool Class::IsArtMethodClass() const {
+bool Class::IsArtMethodClass() {
return this == ArtMethod::GetJavaLangReflectArtMethod();
}
@@ -334,7 +334,7 @@ void Class::SetClassLoader(ClassLoader* new_class_loader) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false);
}
-ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature& signature) const {
+ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature& signature) {
// Check the current class before checking the interfaces.
ArtMethod* method = FindDeclaredVirtualMethod(name, signature);
if (method != NULL) {
@@ -352,7 +352,7 @@ ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature&
return NULL;
}
-ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
// Check the current class before checking the interfaces.
ArtMethod* method = FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
if (method != NULL) {
@@ -370,7 +370,7 @@ ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_me
return NULL;
}
-ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const {
+ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
@@ -382,7 +382,7 @@ ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const String
return NULL;
}
-ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) const {
+ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
@@ -394,7 +394,7 @@ ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signat
return NULL;
}
-ArtMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+ArtMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
if (GetDexCache() == dex_cache) {
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
@@ -406,8 +406,8 @@ ArtMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t d
return NULL;
}
-ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature);
if (method != NULL) {
return method;
@@ -416,8 +416,8 @@ ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& s
return NULL;
}
-ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& signature) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature);
if (method != NULL) {
return method;
@@ -426,8 +426,8 @@ ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& sig
return NULL;
}
-ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx);
if (method != NULL) {
return method;
@@ -436,7 +436,7 @@ ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_metho
return NULL;
}
-ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const {
+ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
ArtMethod* method = GetVirtualMethod(i);
@@ -449,7 +449,7 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const Strin
}
ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name,
- const Signature& signature) const {
+ const Signature& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
ArtMethod* method = GetVirtualMethod(i);
@@ -461,7 +461,7 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name,
return NULL;
}
-ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
if (GetDexCache() == dex_cache) {
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
ArtMethod* method = GetVirtualMethod(i);
@@ -473,8 +473,8 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t
return NULL;
}
-ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature);
if (method != NULL) {
return method;
@@ -483,8 +483,8 @@ ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece&
return NULL;
}
-ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const Signature& signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const Signature& signature) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature);
if (method != NULL) {
return method;
@@ -493,8 +493,8 @@ ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const Signature& si
return NULL;
}
-ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
if (method != NULL) {
return method;
@@ -503,7 +503,7 @@ ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_meth
return NULL;
}
-ArtMethod* Class::FindClassInitializer() const {
+ArtMethod* Class::FindClassInitializer() {
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
if (method->IsConstructor() && method->IsStatic()) {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index a692381..cbec476 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -120,7 +120,7 @@ class MANAGED Class : public Object {
kStatusMax = 10,
};
- Status GetStatus() const {
+ Status GetStatus() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(sizeof(Status), sizeof(uint32_t));
return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), true));
}
@@ -132,107 +132,107 @@ class MANAGED Class : public Object {
}
// Returns true if the class has failed to link.
- bool IsErroneous() const {
+ bool IsErroneous() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() == kStatusError;
}
// Returns true if the class has been loaded.
- bool IsIdxLoaded() const {
+ bool IsIdxLoaded() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusIdx;
}
// Returns true if the class has been loaded.
- bool IsLoaded() const {
+ bool IsLoaded() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusLoaded;
}
// Returns true if the class has been linked.
- bool IsResolved() const {
+ bool IsResolved() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusResolved;
}
// Returns true if the class was compile-time verified.
- bool IsCompileTimeVerified() const {
+ bool IsCompileTimeVerified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusRetryVerificationAtRuntime;
}
// Returns true if the class has been verified.
- bool IsVerified() const {
+ bool IsVerified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusVerified;
}
// Returns true if the class is initializing.
- bool IsInitializing() const {
+ bool IsInitializing() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusInitializing;
}
// Returns true if the class is initialized.
- bool IsInitialized() const {
+ bool IsInitialized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() == kStatusInitialized;
}
- uint32_t GetAccessFlags() const;
+ uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetAccessFlags(uint32_t new_access_flags) {
+ void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags, false);
}
// Returns true if the class is an interface.
- bool IsInterface() const {
+ bool IsInterface() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccInterface) != 0;
}
// Returns true if the class is declared public.
- bool IsPublic() const {
+ bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPublic) != 0;
}
// Returns true if the class is declared final.
- bool IsFinal() const {
+ bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccFinal) != 0;
}
- bool IsFinalizable() const {
+ bool IsFinalizable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsFinalizable) != 0;
}
- void SetFinalizable() {
+ void SetFinalizable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
SetAccessFlags(flags | kAccClassIsFinalizable);
}
// Returns true if the class is abstract.
- bool IsAbstract() const {
+ bool IsAbstract() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccAbstract) != 0;
}
// Returns true if the class is an annotation.
- bool IsAnnotation() const {
+ bool IsAnnotation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccAnnotation) != 0;
}
// Returns true if the class is synthetic.
- bool IsSynthetic() const {
+ bool IsSynthetic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccSynthetic) != 0;
}
- bool IsReferenceClass() const {
+ bool IsReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsReference) != 0;
}
- bool IsWeakReferenceClass() const {
+ bool IsWeakReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsWeakReference) != 0;
}
- bool IsSoftReferenceClass() const {
+ bool IsSoftReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccReferenceFlagsMask) == kAccClassIsReference;
}
- bool IsFinalizerReferenceClass() const {
+ bool IsFinalizerReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsFinalizerReference) != 0;
}
- bool IsPhantomReferenceClass() const {
+ bool IsPhantomReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
}
@@ -241,7 +241,7 @@ class MANAGED Class : public Object {
// For array classes, where all the classes are final due to there being no sub-classes, an
// Object[] may be assigned to by a String[] but a String[] may not be assigned to by other
// types as the component is final.
- bool CannotBeAssignedFromOtherTypes() const {
+ bool CannotBeAssignedFromOtherTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (!IsArrayClass()) {
return IsFinal();
} else {
@@ -254,12 +254,12 @@ class MANAGED Class : public Object {
}
}
- String* GetName() const; // Returns the cached name.
+ String* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns the cached name.
void SetName(String* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Sets the cached name.
// Computes the name, then sets the cached value.
String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsProxyClass() const {
+ bool IsProxyClass() {
// Read access flags without using getter as whether something is a proxy can be check in
// any loaded state
// TODO: switch to a check if the super class is java.lang.reflect.Proxy?
@@ -267,91 +267,91 @@ class MANAGED Class : public Object {
return (access_flags & kAccClassIsProxy) != 0;
}
- Primitive::Type GetPrimitiveType() const {
+ Primitive::Type GetPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
return static_cast<Primitive::Type>(
GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
}
- void SetPrimitiveType(Primitive::Type new_type) {
+ void SetPrimitiveType(Primitive::Type new_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), new_type, false);
}
// Returns true if the class is a primitive type.
- bool IsPrimitive() const {
+ bool IsPrimitive() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() != Primitive::kPrimNot;
}
- bool IsPrimitiveBoolean() const {
+ bool IsPrimitiveBoolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimBoolean;
}
- bool IsPrimitiveByte() const {
+ bool IsPrimitiveByte() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimByte;
}
- bool IsPrimitiveChar() const {
+ bool IsPrimitiveChar() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimChar;
}
- bool IsPrimitiveShort() const {
+ bool IsPrimitiveShort() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimShort;
}
- bool IsPrimitiveInt() const {
+ bool IsPrimitiveInt() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimInt;
}
- bool IsPrimitiveLong() const {
+ bool IsPrimitiveLong() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimLong;
}
- bool IsPrimitiveFloat() const {
+ bool IsPrimitiveFloat() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimFloat;
}
- bool IsPrimitiveDouble() const {
+ bool IsPrimitiveDouble() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimDouble;
}
- bool IsPrimitiveVoid() const {
+ bool IsPrimitiveVoid() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimVoid;
}
- bool IsPrimitiveArray() const {
+ bool IsPrimitiveArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return IsArrayClass() && GetComponentType()->IsPrimitive();
}
// Depth of class from java.lang.Object
- size_t Depth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- size_t depth = 0;
+ uint32_t Depth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uint32_t depth = 0;
for (Class* klass = this; klass->GetSuperClass() != NULL; klass = klass->GetSuperClass()) {
depth++;
}
return depth;
}
- bool IsArrayClass() const {
+ bool IsArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetComponentType() != NULL;
}
- bool IsClassClass() const;
+ bool IsClassClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsStringClass() const;
- bool IsThrowableClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsThrowableClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArtFieldClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsArtFieldClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArtMethodClass() const;
+ bool IsArtMethodClass();
static MemberOffset ComponentTypeOffset() {
return OFFSET_OF_OBJECT_MEMBER(Class, component_type_);
}
- Class* GetComponentType() const {
- return GetFieldObject<Class*>(ComponentTypeOffset(), false);
+ Class* GetComponentType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<Class>(ComponentTypeOffset(), false);
}
void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -360,18 +360,18 @@ class MANAGED Class : public Object {
SetFieldObject(ComponentTypeOffset(), new_component_type, false);
}
- size_t GetComponentSize() const {
+ size_t GetComponentSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType());
}
- bool IsObjectClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool IsObjectClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return !IsPrimitive() && GetSuperClass() == NULL;
}
- bool IsInstantiable() const {
+ bool IsInstantiable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (!IsPrimitive() && !IsInterface() && !IsAbstract()) || ((IsAbstract()) && IsArrayClass());
}
- bool IsObjectArrayClass() const {
+ bool IsObjectArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetComponentType() != NULL && !GetComponentType()->IsPrimitive();
}
@@ -385,48 +385,44 @@ class MANAGED Class : public Object {
Object* AllocNonMovableObject(Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsVariableSize() const {
+ bool IsVariableSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Classes and arrays vary in size, and so the object_size_ field cannot
// be used to get their instance size
return IsClassClass() || IsArrayClass();
}
- size_t SizeOf() const {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
+ uint32_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
- size_t GetClassSize() const {
- DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
+ uint32_t GetClassSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
- void SetClassSize(size_t new_class_size)
+ void SetClassSize(uint32_t new_class_size)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t GetObjectSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t GetObjectSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetObjectSize(size_t new_object_size) {
+ void SetObjectSize(uint32_t new_object_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(!IsVariableSize());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size, false);
}
// Returns true if this class is in the same packages as that class.
- bool IsInSamePackage(const Class* that) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsInSamePackage(Class* that) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static bool IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2);
// Returns true if this class can access that class.
- bool CanAccess(Class* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool CanAccess(Class* that) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return that->IsPublic() || this->IsInSamePackage(that);
}
// Can this class access a member in the provided class with the provided member access flags?
// Note that access to the class isn't checked in case the declaring class is protected and the
// method has been exposed by a public sub-class
- bool CanAccessMember(Class* access_to, uint32_t member_flags) const
+ bool CanAccessMember(Class* access_to, uint32_t member_flags)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Classes can access all of their own members
if (this == access_to) {
@@ -454,7 +450,7 @@ class MANAGED Class : public Object {
// Note that access to field's class is checked and this may require looking up the class
// referenced by the FieldId in the DexFile in case the declaring class is inaccessible.
bool CanAccessResolvedField(Class* access_to, ArtField* field,
- const DexCache& dex_cache, uint32_t field_idx)
+ DexCache* dex_cache, uint32_t field_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool CheckResolvedFieldAccess(Class* access_to, ArtField* field,
uint32_t field_idx)
@@ -464,22 +460,21 @@ class MANAGED Class : public Object {
// Note that access to methods's class is checked and this may require looking up the class
// referenced by the MethodId in the DexFile in case the declaring class is inaccessible.
bool CanAccessResolvedMethod(Class* access_to, ArtMethod* resolved_method,
- const DexCache& dex_cache, uint32_t method_idx)
+ DexCache* dex_cache, uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template <InvokeType throw_invoke_type>
bool CheckResolvedMethodAccess(Class* access_to, ArtMethod* resolved_method,
uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSubClass(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsSubClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Can src be assigned to this class? For example, String can be assigned to Object (by an
// upcast), however, an Object cannot be assigned to a String as a potentially exception throwing
// downcast would be necessary. Similarly for interfaces, a class that implements (or an interface
// that extends) another can be assigned to its parent, but not vice-versa. All Classes may assign
// to themselves. Classes for primitive types may not assign to each other.
- inline bool IsAssignableFrom(const Class* src) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ inline bool IsAssignableFrom(Class* src) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(src != NULL);
if (this == src) {
// Can always assign to things of the same type.
@@ -496,18 +491,18 @@ class MANAGED Class : public Object {
}
}
- Class* GetSuperClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ Class* GetSuperClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetSuperClass(Class *new_super_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // super class is assigned once, except during class linker initialization
- Class* old_super_class = GetFieldObject<Class*>(
- OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
- DCHECK(old_super_class == NULL || old_super_class == new_super_class);
- DCHECK(new_super_class != NULL);
+ // Super class is assigned once, except during class linker initialization.
+ Class* old_super_class = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_),
+ false);
+ DCHECK(old_super_class == nullptr || old_super_class == new_super_class);
+ DCHECK(new_super_class != nullptr);
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), new_super_class, false);
}
- bool HasSuperClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool HasSuperClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetSuperClass() != NULL;
}
@@ -515,7 +510,7 @@ class MANAGED Class : public Object {
return MemberOffset(OFFSETOF_MEMBER(Class, super_class_));
}
- ClassLoader* GetClassLoader() const;
+ ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetClassLoader(ClassLoader* new_cl) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -529,46 +524,43 @@ class MANAGED Class : public Object {
kDumpClassInitialized = (1 << 2),
};
- void DumpClass(std::ostream& os, int flags) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void DumpClass(std::ostream& os, int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- DexCache* GetDexCache() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCache(DexCache* new_dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetDirectMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ObjectArray<ArtMethod>* GetDirectMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDirectMethods(ObjectArray<ArtMethod>* new_direct_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* GetDirectMethod(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetDirectMethod(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDirectMethod(uint32_t i, ArtMethod* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns the number of static, private, and constructor methods.
- size_t NumDirectMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t NumDirectMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetVirtualMethods() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ObjectArray<ArtMethod>* GetVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns the number of non-inherited virtual methods.
- size_t NumVirtualMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t NumVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* GetVirtualMethod(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetVirtualMethod(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* GetVirtualMethodDuringLinking(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetVirtualMethodDuringLinking(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetVirtualMethod(uint32_t i, ArtMethod* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetVTable() const;
+ ObjectArray<ArtMethod>* GetVTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetVTableDuringLinking() const;
+ ObjectArray<ArtMethod>* GetVTableDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetVTable(ObjectArray<ArtMethod>* new_vtable)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -577,7 +569,7 @@ class MANAGED Class : public Object {
return OFFSET_OF_OBJECT_MEMBER(Class, vtable_);
}
- ObjectArray<ArtMethod>* GetImTable() const;
+ ObjectArray<ArtMethod>* GetImTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetImTable(ObjectArray<ArtMethod>* new_imtable)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -588,105 +580,102 @@ class MANAGED Class : public Object {
// Given a method implemented by this class but potentially from a super class, return the
// specific implementation method for this class.
- ArtMethod* FindVirtualMethodForVirtual(ArtMethod* method) const
+ ArtMethod* FindVirtualMethodForVirtual(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Given a method implemented by this class' super class, return the specific implementation
// method for this class.
- ArtMethod* FindVirtualMethodForSuper(ArtMethod* method) const
+ ArtMethod* FindVirtualMethodForSuper(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Given a method implemented by this class, but potentially from a
// super class or interface, return the specific implementation
// method for this class.
- ArtMethod* FindVirtualMethodForInterface(ArtMethod* method) const
+ ArtMethod* FindVirtualMethodForInterface(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE;
- ArtMethod* FindVirtualMethodForVirtualOrInterface(ArtMethod* method) const
+ ArtMethod* FindVirtualMethodForVirtualOrInterface(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindInterfaceMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindInterfaceMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const
+ ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const
+ ArtMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDirectMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindDirectMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const
+ ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const
+ ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindVirtualMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindVirtualMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindClassInitializer() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* FindClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetIfTableCount() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int32_t GetIfTableCount() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- IfTable* GetIfTable() const;
+ IfTable* GetIfTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetIfTable(IfTable* new_iftable) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get instance fields of the class (See also GetSFields).
- ObjectArray<ArtField>* GetIFields() const;
+ ObjectArray<ArtField>* GetIFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetIFields(ObjectArray<ArtField>* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t NumInstanceFields() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t NumInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtField* GetInstanceField(uint32_t i) const // TODO: uint16_t
+ ArtField* GetInstanceField(uint32_t i) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetInstanceField(uint32_t i, ArtField* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns the number of instance fields containing reference types.
- size_t NumReferenceInstanceFields() const {
+ uint32_t NumReferenceInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsResolved() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
}
- size_t NumReferenceInstanceFieldsDuringLinking() const {
+ uint32_t NumReferenceInstanceFieldsDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsLoaded() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
}
- void SetNumReferenceInstanceFields(size_t new_num) {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
+ void SetNumReferenceInstanceFields(uint32_t new_num) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), new_num, false);
}
- uint32_t GetReferenceInstanceOffsets() const {
+ uint32_t GetReferenceInstanceOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsResolved() || IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false);
}
@@ -700,39 +689,39 @@ class MANAGED Class : public Object {
}
// Returns the number of static fields containing reference types.
- size_t NumReferenceStaticFields() const {
+ uint32_t NumReferenceStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsResolved() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
}
- size_t NumReferenceStaticFieldsDuringLinking() const {
+ uint32_t NumReferenceStaticFieldsDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsLoaded() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
}
- void SetNumReferenceStaticFields(size_t new_num) {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
+ void SetNumReferenceStaticFields(uint32_t new_num) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), new_num, false);
}
// Gets the static fields of the class.
- ObjectArray<ArtField>* GetSFields() const;
+ ObjectArray<ArtField>* GetSFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetSFields(ObjectArray<ArtField>* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t NumStaticFields() const;
+ uint32_t NumStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtField* GetStaticField(uint32_t i) const; // TODO: uint16_t
+ // TODO: uint16_t
+ ArtField* GetStaticField(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetStaticField(uint32_t i, ArtField* f); // TODO: uint16_t
+ // TODO: uint16_t
+ void SetStaticField(uint32_t i, ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint32_t GetReferenceStaticOffsets() const {
+ uint32_t GetReferenceStaticOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), false);
}
- void SetReferenceStaticOffsets(uint32_t new_reference_offsets);
+ void SetReferenceStaticOffsets(uint32_t new_reference_offsets)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find a static or instance field using the JLS resolution order
ArtField* FindField(const StringPiece& name, const StringPiece& type)
@@ -768,33 +757,33 @@ class MANAGED Class : public Object {
ArtField* FindDeclaredStaticField(const DexCache* dex_cache, uint32_t dex_field_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- pid_t GetClinitThreadId() const {
+ pid_t GetClinitThreadId() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsIdxLoaded() || IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), false);
}
- void SetClinitThreadId(pid_t new_clinit_thread_id) {
+ void SetClinitThreadId(pid_t new_clinit_thread_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id, false);
}
- Class* GetVerifyErrorClass() const {
+ Class* GetVerifyErrorClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// DCHECK(IsErroneous());
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), false);
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), false);
}
- uint16_t GetDexClassDefIndex() const {
+ uint16_t GetDexClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_class_def_idx_), false);
}
- void SetDexClassDefIndex(uint16_t class_def_idx) {
+ void SetDexClassDefIndex(uint16_t class_def_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_class_def_idx_), class_def_idx, false);
}
- uint16_t GetDexTypeIndex() const {
+ uint16_t GetDexTypeIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), false);
}
- void SetDexTypeIndex(uint16_t type_idx) {
+ void SetDexTypeIndex(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx, false);
}
@@ -817,35 +806,32 @@ class MANAGED Class : public Object {
template <bool throw_on_failure, bool use_referrers_cache>
bool ResolvedFieldAccessTest(Class* access_to, ArtField* field,
- uint32_t field_idx, const DexCache* dex_cache)
+ uint32_t field_idx, DexCache* dex_cache)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type>
bool ResolvedMethodAccessTest(Class* access_to, ArtMethod* resolved_method,
- uint32_t method_idx, const DexCache* dex_cache)
+ uint32_t method_idx, DexCache* dex_cache)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Implements(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArrayAssignableFromArray(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsAssignableFromArray(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool Implements(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsArrayAssignableFromArray(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsAssignableFromArray(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CheckObjectAlloc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// defining class loader, or NULL for the "bootstrap" system loader
- ClassLoader* class_loader_;
+ HeapReference<ClassLoader> class_loader_;
// For array classes, the component class object for instanceof/checkcast
// (for String[][][], this will be String[][]). NULL for non-array classes.
- Class* component_type_;
+ HeapReference<Class> component_type_;
// DexCache of resolved constant pool entries (will be NULL for classes generated by the
// runtime such as arrays and primitive classes).
- DexCache* dex_cache_;
+ HeapReference<DexCache> dex_cache_;
// static, private, and <init> methods
- ObjectArray<ArtMethod>* direct_methods_;
+ HeapReference<ObjectArray<ArtMethod> > direct_methods_;
// instance fields
//
@@ -857,7 +843,7 @@ class MANAGED Class : public Object {
// All instance fields that refer to objects are guaranteed to be at
// the beginning of the field list. num_reference_instance_fields_
// specifies the number of reference fields.
- ObjectArray<ArtField>* ifields_;
+ HeapReference<ObjectArray<ArtField> > ifields_;
// The interface table (iftable_) contains pairs of a interface class and an array of the
// interface methods. There is one pair per interface supported by this class. That means one
@@ -870,38 +856,38 @@ class MANAGED Class : public Object {
//
// For every interface a concrete class implements, we create an array of the concrete vtable_
// methods for the methods in the interface.
- IfTable* iftable_;
+ HeapReference<IfTable> iftable_;
// Interface method table (imt), for quick "invoke-interface".
- ObjectArray<ArtMethod>* imtable_;
+ HeapReference<ObjectArray<ArtMethod> > imtable_;
- // descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
- String* name_;
+ // Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
+ HeapReference<String> name_;
// Static fields
- ObjectArray<ArtField>* sfields_;
+ HeapReference<ObjectArray<ArtField>> sfields_;
// The superclass, or NULL if this is java.lang.Object, an interface or primitive type.
- Class* super_class_;
+ HeapReference<Class> super_class_;
// If class verify fails, we must return same error on subsequent tries.
- Class* verify_error_class_;
+ HeapReference<Class> verify_error_class_;
// Virtual methods defined in this class; invoked through vtable.
- ObjectArray<ArtMethod>* virtual_methods_;
+ HeapReference<ObjectArray<ArtMethod> > virtual_methods_;
// Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass is
// copied in, and virtual methods from our class either replace those from the super or are
// appended. For abstract classes, methods may be created in the vtable that aren't in
// virtual_ methods_ for miranda methods.
- ObjectArray<ArtMethod>* vtable_;
+ HeapReference<ObjectArray<ArtMethod> > vtable_;
// Access flags; low 16 bits are defined by VM spec.
uint32_t access_flags_;
// Total size of the Class instance; used when allocating storage on gc heap.
// See also object_size_.
- size_t class_size_;
+ uint32_t class_size_;
// Tid used to check for recursive <clinit> invocation.
pid_t clinit_thread_id_;
@@ -915,15 +901,15 @@ class MANAGED Class : public Object {
int32_t dex_type_idx_;
// Number of instance fields that are object refs.
- size_t num_reference_instance_fields_;
+ uint32_t num_reference_instance_fields_;
// Number of static fields that are object refs,
- size_t num_reference_static_fields_;
+ uint32_t num_reference_static_fields_;
// Total object size; used when allocating storage on gc heap.
// (For interfaces and abstract classes this will be zero.)
// See also class_size_.
- size_t object_size_;
+ uint32_t object_size_;
// Primitive type value, or Primitive::kPrimNot (0); set for generated primitive classes.
Primitive::Type primitive_type_;
diff --git a/runtime/mirror/class_loader.h b/runtime/mirror/class_loader.h
index 415cb67..69accf5 100644
--- a/runtime/mirror/class_loader.h
+++ b/runtime/mirror/class_loader.h
@@ -32,9 +32,9 @@ namespace mirror {
class MANAGED ClassLoader : public Object {
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- Object* packages_;
- ClassLoader* parent_;
- Object* proxyCache_;
+ HeapReference<Object> packages_;
+ HeapReference<ClassLoader> parent_;
+ HeapReference<Object> proxyCache_;
friend struct art::ClassLoaderOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(ClassLoader);
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index da26be5..f59c3a2 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -22,7 +22,7 @@
namespace art {
namespace mirror {
-inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx) const
+inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ArtMethod* method = GetResolvedMethods()->Get(method_idx);
// Hide resolution trampoline methods from the caller
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index a5fe598..99529f0 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -52,8 +52,8 @@ class MANAGED DexCache : public Object {
void Fixup(ArtMethod* trampoline) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- String* GetLocation() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), false);
+ String* GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), false);
}
static MemberOffset StringsOffset() {
@@ -68,24 +68,23 @@ class MANAGED DexCache : public Object {
return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_);
}
- size_t NumStrings() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t NumStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStrings()->GetLength();
}
- size_t NumResolvedTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t NumResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedTypes()->GetLength();
}
- size_t NumResolvedMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t NumResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedMethods()->GetLength();
}
- size_t NumResolvedFields() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t NumResolvedFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedFields()->GetLength();
}
- String* GetResolvedString(uint32_t string_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ String* GetResolvedString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStrings()->Get(string_idx);
}
@@ -94,8 +93,7 @@ class MANAGED DexCache : public Object {
GetStrings()->Set(string_idx, resolved);
}
- Class* GetResolvedType(uint32_t type_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Class* GetResolvedType(uint32_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedTypes()->Get(type_idx);
}
@@ -104,16 +102,14 @@ class MANAGED DexCache : public Object {
GetResolvedTypes()->Set(type_idx, resolved);
}
- ArtMethod* GetResolvedMethod(uint32_t method_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetResolvedMethod(uint32_t method_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetResolvedMethod(uint32_t method_idx, ArtMethod* resolved)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
GetResolvedMethods()->Set(method_idx, resolved);
}
- ArtField* GetResolvedField(uint32_t field_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ArtField* GetResolvedField(uint32_t field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedFields()->Get(field_idx);
}
@@ -122,28 +118,24 @@ class MANAGED DexCache : public Object {
GetResolvedFields()->Set(field_idx, resolved);
}
- ObjectArray<String>* GetStrings() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject< ObjectArray<String>* >(StringsOffset(), false);
+ ObjectArray<String>* GetStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject< ObjectArray<String> >(StringsOffset(), false);
}
- ObjectArray<Class>* GetResolvedTypes() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject< ObjectArray<Class>* >(
+ ObjectArray<Class>* GetResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<Class> >(
OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), false);
}
- ObjectArray<ArtMethod>* GetResolvedMethods() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject< ObjectArray<ArtMethod>* >(ResolvedMethodsOffset(), false);
+ ObjectArray<ArtMethod>* GetResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject< ObjectArray<ArtMethod> >(ResolvedMethodsOffset(), false);
}
- ObjectArray<ArtField>* GetResolvedFields() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject< ObjectArray<ArtField>* >(ResolvedFieldsOffset(), false);
+ ObjectArray<ArtField>* GetResolvedFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<ArtField> >(ResolvedFieldsOffset(), false);
}
- const DexFile* GetDexFile() const {
+ const DexFile* GetDexFile() {
return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), false);
}
@@ -152,13 +144,13 @@ class MANAGED DexCache : public Object {
}
private:
- Object* dex_;
- String* location_;
- ObjectArray<ArtField>* resolved_fields_;
- ObjectArray<ArtMethod>* resolved_methods_;
- ObjectArray<Class>* resolved_types_;
- ObjectArray<String>* strings_;
- uint32_t dex_file_;
+ HeapReference<Object> dex_;
+ HeapReference<String> location_;
+ HeapReference<ObjectArray<ArtField> > resolved_fields_;
+ HeapReference<ObjectArray<ArtMethod> > resolved_methods_;
+ HeapReference<ObjectArray<Class> > resolved_types_;
+ HeapReference<ObjectArray<String> > strings_;
+ uint64_t dex_file_;
friend struct art::DexCacheOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache);
diff --git a/runtime/mirror/iftable.h b/runtime/mirror/iftable.h
index 421893d..be83d03 100644
--- a/runtime/mirror/iftable.h
+++ b/runtime/mirror/iftable.h
@@ -24,7 +24,7 @@ namespace mirror {
class MANAGED IfTable : public ObjectArray<Object> {
public:
- Class* GetInterface(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Class* GetInterface(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Class* interface = Get((i * kMax) + kInterface)->AsClass();
DCHECK(interface != NULL);
return interface;
@@ -32,15 +32,14 @@ class MANAGED IfTable : public ObjectArray<Object> {
void SetInterface(int32_t i, Class* interface) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetMethodArray(int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ObjectArray<ArtMethod>* GetMethodArray(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ObjectArray<ArtMethod>* method_array =
down_cast<ObjectArray<ArtMethod>*>(Get((i * kMax) + kMethodArray));
DCHECK(method_array != NULL);
return method_array;
}
- size_t GetMethodArrayCount(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t GetMethodArrayCount(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ObjectArray<ArtMethod>* method_array =
down_cast<ObjectArray<ArtMethod>*>(Get((i * kMax) + kMethodArray));
if (method_array == NULL) {
@@ -56,7 +55,7 @@ class MANAGED IfTable : public ObjectArray<Object> {
Set((i * kMax) + kMethodArray, new_ma);
}
- size_t Count() const {
+ size_t Count() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetLength() / kMax;
}
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 9161bc5..afa4112 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -32,19 +32,18 @@
namespace art {
namespace mirror {
-inline Class* Object::GetClass() const {
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
+inline Class* Object::GetClass() {
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
}
inline void Object::SetClass(Class* new_klass) {
- // new_klass may be NULL prior to class linker initialization
- // We don't mark the card since the class is guaranteed to be referenced from another location.
- // Proxy classes are held live by the class loader, and other classes are roots of the class
- // linker.
- SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false);
+ // new_klass may be NULL prior to class linker initialization.
+ // We don't mark the card as this occurs as part of object allocation. Not all objects have
+ // backing cards, such as large objects.
+ SetFieldObjectWithoutWriteBarrier(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false);
}
-inline LockWord Object::GetLockWord() const {
+inline LockWord Object::GetLockWord() {
return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), true));
}
@@ -85,19 +84,19 @@ inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
}
-inline bool Object::VerifierInstanceOf(const Class* klass) const {
+inline bool Object::VerifierInstanceOf(Class* klass) {
DCHECK(klass != NULL);
DCHECK(GetClass() != NULL);
return klass->IsInterface() || InstanceOf(klass);
}
-inline bool Object::InstanceOf(const Class* klass) const {
+inline bool Object::InstanceOf(Class* klass) {
DCHECK(klass != NULL);
DCHECK(GetClass() != NULL);
return klass->IsAssignableFrom(GetClass());
}
-inline bool Object::IsClass() const {
+inline bool Object::IsClass() {
Class* java_lang_Class = GetClass()->GetClass();
return GetClass() == java_lang_Class;
}
@@ -107,12 +106,7 @@ inline Class* Object::AsClass() {
return down_cast<Class*>(this);
}
-inline const Class* Object::AsClass() const {
- DCHECK(IsClass());
- return down_cast<const Class*>(this);
-}
-
-inline bool Object::IsObjectArray() const {
+inline bool Object::IsObjectArray() {
return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive();
}
@@ -122,17 +116,11 @@ inline ObjectArray<T>* Object::AsObjectArray() {
return down_cast<ObjectArray<T>*>(this);
}
-template<class T>
-inline const ObjectArray<T>* Object::AsObjectArray() const {
- DCHECK(IsObjectArray());
- return down_cast<const ObjectArray<T>*>(this);
-}
-
-inline bool Object::IsArrayInstance() const {
+inline bool Object::IsArrayInstance() {
return GetClass()->IsArrayClass();
}
-inline bool Object::IsArtField() const {
+inline bool Object::IsArtField() {
return GetClass()->IsArtFieldClass();
}
@@ -141,12 +129,7 @@ inline ArtField* Object::AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_
return down_cast<ArtField*>(this);
}
-inline const ArtField* Object::AsArtField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsArtField());
- return down_cast<const ArtField*>(this);
-}
-
-inline bool Object::IsArtMethod() const {
+inline bool Object::IsArtMethod() {
return GetClass()->IsArtMethodClass();
}
@@ -155,12 +138,7 @@ inline ArtMethod* Object::AsArtMethod() {
return down_cast<ArtMethod*>(this);
}
-inline const ArtMethod* Object::AsArtMethod() const {
- DCHECK(IsArtMethod());
- return down_cast<const ArtMethod*>(this);
-}
-
-inline bool Object::IsReferenceInstance() const {
+inline bool Object::IsReferenceInstance() {
return GetClass()->IsReferenceClass();
}
@@ -169,11 +147,6 @@ inline Array* Object::AsArray() {
return down_cast<Array*>(this);
}
-inline const Array* Object::AsArray() const {
- DCHECK(IsArrayInstance());
- return down_cast<const Array*>(this);
-}
-
inline BooleanArray* Object::AsBooleanArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean());
@@ -186,6 +159,13 @@ inline ByteArray* Object::AsByteArray() {
return down_cast<ByteArray*>(this);
}
+inline ByteArray* Object::AsByteSizedArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte() ||
+ GetClass()->GetComponentType()->IsPrimitiveBoolean());
+ return down_cast<ByteArray*>(this);
+}
+
inline CharArray* Object::AsCharArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar());
@@ -198,6 +178,13 @@ inline ShortArray* Object::AsShortArray() {
return down_cast<ShortArray*>(this);
}
+inline ShortArray* Object::AsShortSizedArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort() ||
+ GetClass()->GetComponentType()->IsPrimitiveChar());
+ return down_cast<ShortArray*>(this);
+}
+
inline IntArray* Object::AsIntArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() ||
@@ -222,23 +209,23 @@ inline Throwable* Object::AsThrowable() {
return down_cast<Throwable*>(this);
}
-inline bool Object::IsWeakReferenceInstance() const {
+inline bool Object::IsWeakReferenceInstance() {
return GetClass()->IsWeakReferenceClass();
}
-inline bool Object::IsSoftReferenceInstance() const {
+inline bool Object::IsSoftReferenceInstance() {
return GetClass()->IsSoftReferenceClass();
}
-inline bool Object::IsFinalizerReferenceInstance() const {
+inline bool Object::IsFinalizerReferenceInstance() {
return GetClass()->IsFinalizerReferenceClass();
}
-inline bool Object::IsPhantomReferenceInstance() const {
+inline bool Object::IsPhantomReferenceInstance() {
return GetClass()->IsPhantomReferenceClass();
}
-inline size_t Object::SizeOf() const {
+inline size_t Object::SizeOf() {
size_t result;
if (IsArrayInstance()) {
result = AsArray()->SizeOf();
@@ -253,13 +240,13 @@ inline size_t Object::SizeOf() const {
return result;
}
-inline uint32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) const {
+inline uint32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) {
VerifyObject(this);
const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr)));
- QuasiAtomic::MembarLoadLoad();
+ QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order.
return result;
} else {
return *word_addr;
@@ -276,7 +263,7 @@ inline void Object::SetField32(MemberOffset field_offset, uint32_t new_value, bo
if (UNLIKELY(is_volatile)) {
QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
*word_addr = new_value;
- QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads.
} else {
*word_addr = new_value;
}
@@ -289,28 +276,31 @@ inline bool Object::CasField32(MemberOffset field_offset, uint32_t old_value, ui
return __sync_bool_compare_and_swap(addr, old_value, new_value);
}
-inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) const {
+inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) {
VerifyObject(this);
const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
uint64_t result = QuasiAtomic::Read64(addr);
- QuasiAtomic::MembarLoadLoad();
+ QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order.
return result;
} else {
return *addr;
}
}
-inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile) {
- VerifyObject(this);
+inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile,
+ bool this_is_valid) {
+ if (this_is_valid) {
+ VerifyObject(this);
+ }
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
QuasiAtomic::Write64(addr, new_value);
if (!QuasiAtomic::LongAtomicsUseMutexes()) {
- QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads.
} else {
// Fence from from mutex is enough.
}
@@ -319,12 +309,69 @@ inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bo
}
}
-inline void Object::WriteBarrierField(const Object* dst, MemberOffset field_offset,
- const Object* new_value) {
- Runtime::Current()->GetHeap()->WriteBarrierField(dst, field_offset, new_value);
+inline bool Object::CasField64(MemberOffset field_offset, uint64_t old_value, uint64_t new_value) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ volatile uint64_t* addr = reinterpret_cast<volatile uint64_t*>(raw_addr);
+ return __sync_bool_compare_and_swap(addr, old_value, new_value);
+}
+
+template<class T>
+inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
+ HeapReference<T> objref = *objref_addr;
+
+ if (UNLIKELY(is_volatile)) {
+ QuasiAtomic::MembarLoadLoad(); // Ensure loads don't re-order.
+ }
+ T* result = objref.AsMirrorPtr();
+ VerifyObject(result);
+ return result;
+}
+
+inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
+ bool is_volatile, bool this_is_valid) {
+ if (this_is_valid) {
+ VerifyObject(this);
+ }
+ VerifyObject(new_value);
+ HeapReference<Object> objref(HeapReference<Object>::FromMirrorPtr(new_value));
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
+ if (UNLIKELY(is_volatile)) {
+ QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
+ objref_addr->Assign(new_value);
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ } else {
+ objref_addr->Assign(new_value);
+ }
+}
+
+inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
+ bool this_is_valid) {
+ SetFieldObjectWithoutWriteBarrier(field_offset, new_value, is_volatile, this_is_valid);
+ if (new_value != nullptr) {
+ CheckFieldAssignment(field_offset, new_value);
+ Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
+ }
+}
+
+inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ volatile uint32_t* addr = reinterpret_cast<volatile uint32_t*>(raw_addr);
+ HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
+ HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
+ bool success = __sync_bool_compare_and_swap(addr, old_ref.reference_, new_ref.reference_);
+ if (success) {
+ Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
+ }
+ return success;
}
-inline void Object::VerifyObject(const Object* obj) {
+inline void Object::VerifyObject(Object* obj) {
if (kIsDebugBuild) {
Runtime::Current()->GetHeap()->VerifyObject(obj);
}
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index bdb3250..1251852 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -52,7 +52,7 @@ static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* sr
Class* c = src->GetClass();
if (c->IsArrayClass()) {
if (!c->GetComponentType()->IsPrimitive()) {
- const ObjectArray<Object>* array = dest->AsObjectArray<Object>();
+ ObjectArray<Object>* array = dest->AsObjectArray<Object>();
heap->WriteBarrierArray(dest, 0, array->GetLength());
}
} else {
@@ -139,14 +139,15 @@ int32_t Object::IdentityHashCode() const {
return 0;
}
-void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, const Object* new_value) {
- const Class* c = GetClass();
+void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value) {
+ Class* c = GetClass();
if (Runtime::Current()->GetClassLinker() == NULL ||
+ !Runtime::Current()->IsStarted() ||
!Runtime::Current()->GetHeap()->IsObjectValidationEnabled() ||
!c->IsResolved()) {
return;
}
- for (const Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
+ for (Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
ObjectArray<ArtField>* fields = cur->GetIFields();
if (fields != NULL) {
size_t num_ref_ifields = cur->NumReferenceInstanceFields();
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 058aee7..6fe8b73 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "cutils/atomic-inline.h"
+#include "object_reference.h"
#include "offsets.h"
namespace art {
@@ -51,17 +52,13 @@ typedef PrimitiveArray<int16_t> ShortArray;
class String;
class Throwable;
-// Classes shared with the managed side of the world need to be packed so that they don't have
-// extra platform specific padding.
-#define MANAGED PACKED(4)
-
// Fields within mirror objects aren't accessed directly so that the appropriate amount of
// handshaking is done with GC (for example, read and write barriers). This macro is used to
// compute an offset for the Set/Get methods defined in Object that can safely access fields.
#define OFFSET_OF_OBJECT_MEMBER(type, field) \
MemberOffset(OFFSETOF_MEMBER(type, field))
-const bool kCheckFieldAssignments = false;
+constexpr bool kCheckFieldAssignments = false;
// C++ mirror of java.lang.Object
class MANAGED Object {
@@ -70,19 +67,17 @@ class MANAGED Object {
return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
}
- Class* GetClass() const;
+ Class* GetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetClass(Class* new_klass);
+ void SetClass(Class* new_klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// The verifier treats all interfaces as java.lang.Object and relies on runtime checks in
// invoke-interface to detect incompatible interface types.
- bool VerifierInstanceOf(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool VerifierInstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool InstanceOf(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t SizeOf() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -92,9 +87,9 @@ class MANAGED Object {
return OFFSET_OF_OBJECT_MEMBER(Object, monitor_);
}
- LockWord GetLockWord() const;
+ LockWord GetLockWord();
void SetLockWord(LockWord new_val);
- bool CasLockWord(LockWord old_val, LockWord new_val);
+ bool CasLockWord(LockWord old_val, LockWord new_val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
uint32_t GetLockOwnerThreadId();
void MonitorEnter(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
@@ -111,111 +106,113 @@ class MANAGED Object {
void Wait(Thread* self, int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsClass() const;
-
- Class* AsClass();
+ bool IsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const Class* AsClass() const;
+ Class* AsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsObjectArray() const;
+ bool IsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template<class T>
- ObjectArray<T>* AsObjectArray();
+ ObjectArray<T>* AsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- template<class T>
- const ObjectArray<T>* AsObjectArray() const;
+ bool IsArrayInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArrayInstance() const;
+ Array* AsArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Array* AsArray();
+ BooleanArray* AsBooleanArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ByteArray* AsByteArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ByteArray* AsByteSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const Array* AsArray() const;
+ CharArray* AsCharArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ShortArray* AsShortArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ShortArray* AsShortSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- BooleanArray* AsBooleanArray();
- ByteArray* AsByteArray();
- CharArray* AsCharArray();
- ShortArray* AsShortArray();
- IntArray* AsIntArray();
- LongArray* AsLongArray();
+ IntArray* AsIntArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ LongArray* AsLongArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- String* AsString();
+ String* AsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArtMethod() const;
-
- ArtMethod* AsArtMethod();
+ bool IsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const ArtMethod* AsArtMethod() const;
+ ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArtField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ArtField* AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const ArtField* AsArtField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool IsReferenceInstance() const;
+ bool IsReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsWeakReferenceInstance() const;
+ bool IsWeakReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSoftReferenceInstance() const;
+ bool IsSoftReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsFinalizerReferenceInstance() const;
+ bool IsFinalizerReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsPhantomReferenceInstance() const;
+ bool IsPhantomReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Accessors for Java type fields
- template<class T>
- T GetFieldObject(MemberOffset field_offset, bool is_volatile) const {
- T result = reinterpret_cast<T>(GetField32(field_offset, is_volatile));
- VerifyObject(result);
- return result;
- }
-
- void SetFieldObject(MemberOffset field_offset, const Object* new_value, bool is_volatile,
- bool this_is_valid = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- VerifyObject(new_value);
- SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
- if (new_value != NULL) {
- CheckFieldAssignment(field_offset, new_value);
- WriteBarrierField(this, field_offset, new_value);
- }
- }
+ // Accessor for Java type fields.
+ template<class T> T* GetFieldObject(MemberOffset field_offset, bool is_volatile)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
+ bool is_volatile, bool this_is_valid = true)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
+ bool this_is_valid = true)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Object** GetFieldObjectAddr(MemberOffset field_offset) ALWAYS_INLINE {
+ HeapReference<Object>* GetFieldObjectReferenceAddr(MemberOffset field_offset) ALWAYS_INLINE {
VerifyObject(this);
- return reinterpret_cast<Object**>(reinterpret_cast<byte*>(this) + field_offset.Int32Value());
+ return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) +
+ field_offset.Int32Value());
}
- uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const;
+ uint32_t GetField32(MemberOffset field_offset, bool is_volatile);
void SetField32(MemberOffset field_offset, uint32_t new_value, bool is_volatile,
bool this_is_valid = true);
- bool CasField32(MemberOffset field_offset, uint32_t old_value, uint32_t new_value);
+ bool CasField32(MemberOffset field_offset, uint32_t old_value, uint32_t new_value)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint64_t GetField64(MemberOffset field_offset, bool is_volatile) const;
+ uint64_t GetField64(MemberOffset field_offset, bool is_volatile);
- void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile);
+ void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile,
+ bool this_is_valid = true);
+
+ bool CasField64(MemberOffset field_offset, uint64_t old_value, uint64_t new_value)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template<typename T>
- void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) {
+ void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile,
+ bool this_is_valid = true) {
+#ifndef __LP64__
SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
+#else
+ SetField64(field_offset, reinterpret_cast<uint64_t>(new_value), is_volatile, this_is_valid);
+#endif
}
protected:
// Accessors for non-Java type fields
template<class T>
- T GetFieldPtr(MemberOffset field_offset, bool is_volatile) const {
+ T GetFieldPtr(MemberOffset field_offset, bool is_volatile) {
+#ifndef __LP64__
return reinterpret_cast<T>(GetField32(field_offset, is_volatile));
+#else
+ return reinterpret_cast<T>(GetField64(field_offset, is_volatile));
+#endif
}
private:
- static void VerifyObject(const Object* obj) ALWAYS_INLINE;
+ static void VerifyObject(Object* obj) ALWAYS_INLINE;
// Verify the type correctness of stores to fields.
- void CheckFieldAssignmentImpl(MemberOffset field_offset, const Object* new_value)
+ void CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckFieldAssignment(MemberOffset field_offset, const Object* new_value)
+ void CheckFieldAssignment(MemberOffset field_offset, Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (kCheckFieldAssignments) {
CheckFieldAssignmentImpl(field_offset, new_value);
@@ -225,11 +222,9 @@ class MANAGED Object {
// Generate an identity hash code.
static int32_t GenerateIdentityHashCode();
- // Write barrier called post update to a reference bearing field.
- static void WriteBarrierField(const Object* dst, MemberOffset offset, const Object* new_value);
-
- Class* klass_;
-
+ // The Class representing the type of the object.
+ HeapReference<Class> klass_;
+ // Monitor and hash code information.
uint32_t monitor_;
friend class art::ImageWriter;
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 6a50dfe..c342479 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -25,6 +25,7 @@
#include "runtime.h"
#include "sirt_ref.h"
#include "thread.h"
+#include <string>
namespace art {
namespace mirror {
@@ -32,8 +33,8 @@ namespace mirror {
template<class T>
inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class,
int32_t length, gc::AllocatorType allocator_type) {
- Array* array = Array::Alloc<true>(self, object_array_class, length, sizeof(Object*),
- allocator_type);
+ Array* array = Array::Alloc<true>(self, object_array_class, length,
+ sizeof(HeapReference<Object>), allocator_type);
if (UNLIKELY(array == nullptr)) {
return nullptr;
} else {
@@ -49,12 +50,12 @@ inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_c
}
template<class T>
-inline T* ObjectArray<T>::Get(int32_t i) const {
+inline T* ObjectArray<T>::Get(int32_t i) {
if (UNLIKELY(!CheckIsValidIndex(i))) {
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
- return GetWithoutChecks(i);
+ return GetFieldObject<T>(OffsetOfElement(i), false);
}
template<class T>
@@ -72,7 +73,7 @@ inline bool ObjectArray<T>::CheckAssignable(T* object) {
template<class T>
inline void ObjectArray<T>::Set(int32_t i, T* object) {
if (LIKELY(CheckIsValidIndex(i) && CheckAssignable(object))) {
- SetWithoutChecks(i, object);
+ SetFieldObject(OffsetOfElement(i), object, false);
} else {
DCHECK(Thread::Current()->IsExceptionPending());
}
@@ -82,72 +83,123 @@ template<class T>
inline void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) {
DCHECK(CheckIsValidIndex(i));
DCHECK(CheckAssignable(object));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- SetFieldObject(data_offset, object, false);
+ SetFieldObject(OffsetOfElement(i), object, false);
}
template<class T>
-inline void ObjectArray<T>::SetPtrWithoutChecks(int32_t i, T* object) {
+inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, T* object) {
DCHECK(CheckIsValidIndex(i));
- // TODO enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
+ // TODO: enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
// DCHECK(CheckAssignable(object));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- SetFieldPtr(data_offset, object, false);
+ SetFieldObjectWithoutWriteBarrier(OffsetOfElement(i), object, false);
}
template<class T>
-inline T* ObjectArray<T>::GetWithoutChecks(int32_t i) const {
+inline T* ObjectArray<T>::GetWithoutChecks(int32_t i) {
DCHECK(CheckIsValidIndex(i));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- return GetFieldObject<T*>(data_offset, false);
+ return GetFieldObject<T>(OffsetOfElement(i), false);
}
template<class T>
-inline void ObjectArray<T>::Copy(const ObjectArray<T>* src, int src_pos,
- ObjectArray<T>* dst, int dst_pos,
- size_t length) {
- if (src->CheckIsValidIndex(src_pos) &&
- src->CheckIsValidIndex(src_pos + length - 1) &&
- dst->CheckIsValidIndex(dst_pos) &&
- dst->CheckIsValidIndex(dst_pos + length - 1)) {
- MemberOffset src_offset(DataOffset(sizeof(Object*)).Int32Value() + src_pos * sizeof(Object*));
- MemberOffset dst_offset(DataOffset(sizeof(Object*)).Int32Value() + dst_pos * sizeof(Object*));
- Class* array_class = dst->GetClass();
- gc::Heap* heap = Runtime::Current()->GetHeap();
- if (array_class == src->GetClass()) {
- // No need for array store checks if arrays are of the same type
- for (size_t i = 0; i < length; i++) {
- Object* object = src->GetFieldObject<Object*>(src_offset, false);
- heap->VerifyObject(object);
- // directly set field, we do a bulk write barrier at the end
- dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true);
- src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
- dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
- }
+inline void ObjectArray<T>::AssignableMemmove(int32_t dst_pos, ObjectArray<T>* src,
+ int32_t src_pos, int32_t count) {
+ if (kIsDebugBuild) {
+ for (int i = 0; i < count; ++i) {
+ // The Get will perform the VerifyObject.
+ src->GetWithoutChecks(src_pos + i);
+ }
+ }
+ // Perform the memmove using int memmove then perform the write barrier.
+ CHECK_EQ(sizeof(HeapReference<T>), sizeof(uint32_t));
+ IntArray* dstAsIntArray = reinterpret_cast<IntArray*>(this);
+ IntArray* srcAsIntArray = reinterpret_cast<IntArray*>(src);
+ dstAsIntArray->Memmove(dst_pos, srcAsIntArray, src_pos, count);
+ Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
+ if (kIsDebugBuild) {
+ for (int i = 0; i < count; ++i) {
+ // The Get will perform the VerifyObject.
+ GetWithoutChecks(dst_pos + i);
+ }
+ }
+}
+
+template<class T>
+inline void ObjectArray<T>::AssignableMemcpy(int32_t dst_pos, ObjectArray<T>* src,
+ int32_t src_pos, int32_t count) {
+ if (kIsDebugBuild) {
+ for (int i = 0; i < count; ++i) {
+ // The Get will perform the VerifyObject.
+ src->GetWithoutChecks(src_pos + i);
+ }
+ }
+ // Perform the memmove using int memcpy then perform the write barrier.
+ CHECK_EQ(sizeof(HeapReference<T>), sizeof(uint32_t));
+ IntArray* dstAsIntArray = reinterpret_cast<IntArray*>(this);
+ IntArray* srcAsIntArray = reinterpret_cast<IntArray*>(src);
+ dstAsIntArray->Memcpy(dst_pos, srcAsIntArray, src_pos, count);
+ Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
+ if (kIsDebugBuild) {
+ for (int i = 0; i < count; ++i) {
+ // The Get will perform the VerifyObject.
+ GetWithoutChecks(dst_pos + i);
+ }
+ }
+}
+
+template<class T>
+inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos, ObjectArray<T>* src,
+ int32_t src_pos, int32_t count,
+ bool throw_exception) {
+ DCHECK_NE(this, src)
+ << "This case should be handled with memmove that handles overlaps correctly";
+ // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
+ // we know is assignable to the destination array's component type.
+ Class* dst_class = GetClass()->GetComponentType();
+ Class* lastAssignableElementClass = dst_class;
+
+ Object* o = nullptr;
+ int i = 0;
+ for (; i < count; ++i) {
+ // The follow get operations force the objects to be verified.
+ o = src->GetWithoutChecks(src_pos + i);
+ if (o == nullptr) {
+ // Null is always assignable.
+ SetWithoutChecks(dst_pos + i, nullptr);
} else {
- Class* element_class = array_class->GetComponentType();
- CHECK(!element_class->IsPrimitive());
- for (size_t i = 0; i < length; i++) {
- Object* object = src->GetFieldObject<Object*>(src_offset, false);
- if (object != NULL && !object->InstanceOf(element_class)) {
- dst->ThrowArrayStoreException(object);
- return;
- }
- heap->VerifyObject(object);
- // directly set field, we do a bulk write barrier at the end
- dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true);
- src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
- dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
+ // TODO: use the underlying class reference to avoid uncompression when not necessary.
+ Class* o_class = o->GetClass();
+ if (LIKELY(lastAssignableElementClass == o_class)) {
+ SetWithoutChecks(dst_pos + i, o);
+ } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
+ lastAssignableElementClass = o_class;
+ SetWithoutChecks(dst_pos + i, o);
+ } else {
+ // Can't put this element into the array, break to perform write-barrier and throw
+ // exception.
+ break;
}
}
- heap->WriteBarrierArray(dst, dst_pos, length);
- } else {
- DCHECK(Thread::Current()->IsExceptionPending());
+ }
+ Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
+ if (UNLIKELY(i != count)) {
+ std::string actualSrcType(PrettyTypeOf(o));
+ std::string dstType(PrettyTypeOf(this));
+ Thread* self = Thread::Current();
+ ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+ if (throw_exception) {
+ self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
+ "source[%d] of type %s cannot be stored in destination array of type %s",
+ src_pos + i, actualSrcType.c_str(), dstType.c_str());
+ } else {
+ LOG(FATAL) << StringPrintf("source[%d] of type %s cannot be stored in destination array of type %s",
+ src_pos + i, actualSrcType.c_str(), dstType.c_str());
+ }
}
}
template<class T>
inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
+ DCHECK_GE(new_length, 0);
// We may get copied by a compacting GC.
SirtRef<ObjectArray<T> > sirt_this(self, this);
gc::Heap* heap = Runtime::Current()->GetHeap();
@@ -155,11 +207,17 @@ inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length)
heap->GetCurrentNonMovingAllocator();
ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length, allocator_type);
if (LIKELY(new_array != nullptr)) {
- Copy(sirt_this.get(), 0, new_array, 0, std::min(sirt_this->GetLength(), new_length));
+ new_array->AssignableMemcpy(0, sirt_this.get(), 0, std::min(sirt_this->GetLength(), new_length));
}
return new_array;
}
+template<class T>
+inline MemberOffset ObjectArray<T>::OffsetOfElement(int32_t i) {
+ return MemberOffset(DataOffset(sizeof(HeapReference<Object>)).Int32Value() +
+ (i * sizeof(HeapReference<Object>)));
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 5da8845..347494e 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -33,7 +33,7 @@ class MANAGED ObjectArray : public Array {
static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- T* Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ T* Get(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns true if the object can be stored into the array. If not, throws
// an ArrayStoreException and returns false.
@@ -44,22 +44,30 @@ class MANAGED ObjectArray : public Array {
// Set element without bound and element type checks, to be used in limited
// circumstances, such as during boot image writing
void SetWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetWithoutChecksAndWriteBarrier(int32_t i, T* object)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ T* GetWithoutChecks(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Set element without bound and element type checks, to be used in limited circumstances, such
- // as during boot image writing. Does not do write barrier.
- void SetPtrWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Copy src into this array (dealing with overlaps as memmove does) without assignability checks.
+ void AssignableMemmove(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
+ int32_t count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- T* GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Copy src into this array assuming no overlap and without assignability checks.
+ void AssignableMemcpy(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
+ int32_t count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void Copy(const ObjectArray<T>* src, int src_pos,
- ObjectArray<T>* dst, int dst_pos,
- size_t length)
+ // Copy src into this array with assignability checks.
+ void AssignableCheckingMemcpy(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
+ int32_t count, bool throw_exception)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
+ static MemberOffset OffsetOfElement(int32_t i);
+
DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectArray);
};
diff --git a/runtime/mirror/object_reference.h b/runtime/mirror/object_reference.h
new file mode 100644
index 0000000..b30890f
--- /dev/null
+++ b/runtime/mirror/object_reference.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
+#define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
+
+#include "locks.h"
+
+namespace art {
+namespace mirror {
+
+class Object;
+
+// Classes shared with the managed side of the world need to be packed so that they don't have
+// extra platform specific padding.
+#define MANAGED PACKED(4)
+
+// Value type representing a reference to a mirror::Object of type MirrorType.
+template<bool kPoisonReferences, class MirrorType>
+class MANAGED ObjectReference {
+ public:
+ MirrorType* AsMirrorPtr() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return UnCompress();
+ }
+
+ void Assign(MirrorType* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ reference_ = Compress(other);
+ }
+
+ void Clear() {
+ reference_ = 0;
+ }
+
+ uint32_t AsVRegValue() const {
+ return reference_;
+ }
+
+ protected:
+ ObjectReference<kPoisonReferences, MirrorType>(MirrorType* mirror_ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : reference_(Compress(mirror_ptr)) {
+ }
+
+ // Compress reference to its bit representation.
+ static uint32_t Compress(MirrorType* mirror_ptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uintptr_t as_bits = reinterpret_cast<uintptr_t>(mirror_ptr);
+ return static_cast<uint32_t>(kPoisonReferences ? -as_bits : as_bits);
+ }
+
+ // Uncompress an encoded reference from its bit representation.
+ MirrorType* UnCompress() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uintptr_t as_bits = kPoisonReferences ? -reference_ : reference_;
+ return reinterpret_cast<MirrorType*>(as_bits);
+ }
+
+ friend class Object;
+
+ // The encoded reference to a mirror::Object.
+ uint32_t reference_;
+};
+
+// References between objects within the managed heap.
+template<class MirrorType>
+class MANAGED HeapReference : public ObjectReference<false, MirrorType> {
+ public:
+ static HeapReference<MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return HeapReference<MirrorType>(mirror_ptr);
+ }
+ private:
+ HeapReference<MirrorType>(MirrorType* mirror_ptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : ObjectReference<false, MirrorType>(mirror_ptr) {}
+};
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 3637181..2af32da 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -77,7 +77,7 @@ TEST_F(ObjectTest, AsmConstants) {
EXPECT_EQ(CLASS_COMPONENT_TYPE_OFFSET, Class::ComponentTypeOffset().Int32Value());
EXPECT_EQ(ARRAY_LENGTH_OFFSET, Array::LengthOffset().Int32Value());
- EXPECT_EQ(OBJECT_ARRAY_DATA_OFFSET, Array::DataOffset(sizeof(Object*)).Int32Value());
+ EXPECT_EQ(OBJECT_ARRAY_DATA_OFFSET, Array::DataOffset(sizeof(HeapReference<Object>)).Int32Value());
EXPECT_EQ(STRING_VALUE_OFFSET, String::ValueOffset().Int32Value());
EXPECT_EQ(STRING_COUNT_OFFSET, String::CountOffset().Int32Value());
@@ -85,7 +85,8 @@ TEST_F(ObjectTest, AsmConstants) {
EXPECT_EQ(STRING_DATA_OFFSET, Array::DataOffset(sizeof(uint16_t)).Int32Value());
EXPECT_EQ(METHOD_DEX_CACHE_METHODS_OFFSET, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
- EXPECT_EQ(METHOD_CODE_OFFSET, ArtMethod::EntryPointFromCompiledCodeOffset().Int32Value());
+ EXPECT_EQ(METHOD_PORTABLE_CODE_OFFSET, ArtMethod::EntryPointFromPortableCompiledCodeOffset().Int32Value());
+ EXPECT_EQ(METHOD_QUICK_CODE_OFFSET, ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value());
}
TEST_F(ObjectTest, IsInSamePackage) {
@@ -295,7 +296,7 @@ TEST_F(ObjectTest, StaticFieldFromCode) {
uint32_t field_idx = dex_file->GetIndexForFieldId(*field_id);
ArtField* field = FindFieldFromCode<StaticObjectRead, true>(field_idx, clinit, Thread::Current(),
- sizeof(Object*));
+ sizeof(HeapReference<Object>));
Object* s0 = field->GetObj(klass);
EXPECT_TRUE(s0 != NULL);
diff --git a/runtime/mirror/proxy.h b/runtime/mirror/proxy.h
index 18a84dc..ff019c6 100644
--- a/runtime/mirror/proxy.h
+++ b/runtime/mirror/proxy.h
@@ -29,24 +29,28 @@ namespace mirror {
// has the static fields used to implement reflection on proxy objects.
class MANAGED SynthesizedProxyClass : public Class {
public:
- ObjectArray<Class>* GetInterfaces() {
- return interfaces_;
+ ObjectArray<Class>* GetInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<Class> >(OFFSET_OF_OBJECT_MEMBER(SynthesizedProxyClass,
+ interfaces_),
+ false);
}
- ObjectArray<ObjectArray<Class> >* GetThrows() {
- return throws_;
+ ObjectArray<ObjectArray<Class> >* GetThrows() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<ObjectArray<Class> > >(OFFSET_OF_OBJECT_MEMBER(SynthesizedProxyClass,
+ throws_),
+ false);
}
private:
- ObjectArray<Class>* interfaces_;
- ObjectArray<ObjectArray<Class> >* throws_;
+ HeapReference<ObjectArray<Class> > interfaces_;
+ HeapReference<ObjectArray<ObjectArray<Class> > > throws_;
DISALLOW_IMPLICIT_CONSTRUCTORS(SynthesizedProxyClass);
};
// C++ mirror of java.lang.reflect.Proxy.
class MANAGED Proxy : public Object {
private:
- Object* h_;
+ HeapReference<Object> h_;
friend struct art::ProxyOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy);
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index d1be4dc..73d2673 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -29,24 +29,23 @@ namespace mirror {
// C++ mirror of java.lang.StackTraceElement
class MANAGED StackTraceElement : public Object {
public:
- const String* GetDeclaringClass() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), false);
+ String* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
+ false);
}
- const String* GetMethodName() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), false);
+ String* GetMethodName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
+ false);
}
- const String* GetFileName() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_), false);
+ String* GetFileName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
+ false);
}
- int32_t GetLineNumber() const {
- return GetField32(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false);
+ int32_t GetLineNumber() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false);
}
static StackTraceElement* Alloc(Thread* self,
@@ -63,9 +62,9 @@ class MANAGED StackTraceElement : public Object {
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- String* declaring_class_;
- String* file_name_;
- String* method_name_;
+ HeapReference<String> declaring_class_;
+ HeapReference<String> file_name_;
+ HeapReference<String> method_name_;
int32_t line_number_;
static Class* GetStackTraceElement() {
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index 1f756a1..10ae066 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -29,23 +29,19 @@
namespace art {
namespace mirror {
-const CharArray* String::GetCharArray() const {
- return GetFieldObject<const CharArray*>(ValueOffset(), false);
-}
-
CharArray* String::GetCharArray() {
- return GetFieldObject<CharArray*>(ValueOffset(), false);
+ return GetFieldObject<CharArray>(ValueOffset(), false);
}
void String::ComputeHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetHashCode(ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()));
}
-int32_t String::GetUtfLength() const {
+int32_t String::GetUtfLength() {
return CountUtf8Bytes(GetCharArray()->GetData() + GetOffset(), GetLength());
}
-int32_t String::FastIndexOf(int32_t ch, int32_t start) const {
+int32_t String::FastIndexOf(int32_t ch, int32_t start) {
int32_t count = GetLength();
if (start < 0) {
start = 0;
@@ -97,13 +93,13 @@ int32_t String::GetHashCode() {
return result;
}
-int32_t String::GetLength() const {
+int32_t String::GetLength() {
int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false);
DCHECK(result >= 0 && result <= GetCharArray()->GetLength());
return result;
}
-uint16_t String::CharAt(int32_t index) const {
+uint16_t String::CharAt(int32_t index) {
// TODO: do we need this? Equals is the only caller, and could
// bounds check itself.
DCHECK_GE(count_, 0); // ensures the unsigned comparison is safe.
@@ -179,7 +175,7 @@ String* String::Alloc(Thread* self, const SirtRef<CharArray>& array) {
return string;
}
-bool String::Equals(const String* that) const {
+bool String::Equals(String* that) {
if (this == that) {
// Quick reference equality test
return true;
@@ -201,7 +197,7 @@ bool String::Equals(const String* that) const {
}
}
-bool String::Equals(const uint16_t* that_chars, int32_t that_offset, int32_t that_length) const {
+bool String::Equals(const uint16_t* that_chars, int32_t that_offset, int32_t that_length) {
if (this->GetLength() != that_length) {
return false;
} else {
@@ -214,7 +210,7 @@ bool String::Equals(const uint16_t* that_chars, int32_t that_offset, int32_t tha
}
}
-bool String::Equals(const char* modified_utf8) const {
+bool String::Equals(const char* modified_utf8) {
for (int32_t i = 0; i < GetLength(); ++i) {
uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
if (ch == '\0' || ch != CharAt(i)) {
@@ -224,7 +220,7 @@ bool String::Equals(const char* modified_utf8) const {
return *modified_utf8 == '\0';
}
-bool String::Equals(const StringPiece& modified_utf8) const {
+bool String::Equals(const StringPiece& modified_utf8) {
const char* p = modified_utf8.data();
for (int32_t i = 0; i < GetLength(); ++i) {
uint16_t ch = GetUtf16FromUtf8(&p);
@@ -236,7 +232,7 @@ bool String::Equals(const StringPiece& modified_utf8) const {
}
// Create a modified UTF-8 encoded std::string from a java/lang/String object.
-std::string String::ToModifiedUtf8() const {
+std::string String::ToModifiedUtf8() {
const uint16_t* chars = GetCharArray()->GetData() + GetOffset();
size_t byte_count = GetUtfLength();
std::string result(byte_count, static_cast<char>(0));
@@ -259,9 +255,9 @@ static uint32_t MemCmp16(const uint16_t* s0, const uint16_t* s1, size_t count) {
}
#endif
-int32_t String::CompareTo(String* rhs) const {
+int32_t String::CompareTo(String* rhs) {
// Quick test for comparison of a string with itself.
- const String* lhs = this;
+ String* lhs = this;
if (lhs == rhs) {
return 0;
}
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 4bbcb9c..a82b26c 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -44,24 +44,23 @@ class MANAGED String : public Object {
return OFFSET_OF_OBJECT_MEMBER(String, offset_);
}
- const CharArray* GetCharArray() const;
- CharArray* GetCharArray();
+ CharArray* GetCharArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetOffset() const {
+ int32_t GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
int32_t result = GetField32(OffsetOffset(), false);
DCHECK_LE(0, result);
return result;
}
- int32_t GetLength() const;
+ int32_t GetLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
int32_t GetHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void ComputeHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetUtfLength() const;
+ int32_t GetUtfLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint16_t CharAt(int32_t index) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint16_t CharAt(int32_t index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
String* Intern() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -78,29 +77,28 @@ class MANAGED String : public Object {
const char* utf8_data_in)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Equals(const char* modified_utf8) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool Equals(const char* modified_utf8) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// TODO: do we need this overload? give it a more intention-revealing name.
- bool Equals(const StringPiece& modified_utf8) const
+ bool Equals(const StringPiece& modified_utf8)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Equals(const String* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool Equals(String* that) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Compare UTF-16 code point values not in a locale-sensitive manner
int Compare(int32_t utf16_length, const char* utf8_data_in);
// TODO: do we need this overload? give it a more intention-revealing name.
bool Equals(const uint16_t* that_chars, int32_t that_offset,
- int32_t that_length) const
+ int32_t that_length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Create a modified UTF-8 encoded std::string from a java/lang/String object.
- std::string ToModifiedUtf8() const;
+ std::string ToModifiedUtf8() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t FastIndexOf(int32_t ch, int32_t start) const;
+ int32_t FastIndexOf(int32_t ch, int32_t start) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t CompareTo(String* other) const;
+ int32_t CompareTo(String* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static Class* GetJavaLangString() {
DCHECK(java_lang_String_ != NULL);
@@ -123,7 +121,7 @@ class MANAGED String : public Object {
SetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), new_count, false);
}
- void SetOffset(int32_t new_offset) {
+ void SetOffset(int32_t new_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LE(0, new_offset);
DCHECK_GE(GetLength(), new_offset);
SetField32(OFFSET_OF_OBJECT_MEMBER(String, offset_), new_offset, false);
@@ -138,7 +136,7 @@ class MANAGED String : public Object {
void SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- CharArray* array_;
+ HeapReference<CharArray> array_;
int32_t count_;
@@ -155,8 +153,8 @@ class MANAGED String : public Object {
class MANAGED StringClass : public Class {
private:
- CharArray* ASCII_;
- Object* CASE_INSENSITIVE_ORDER_;
+ HeapReference<CharArray> ASCII_;
+ HeapReference<Object> CASE_INSENSITIVE_ORDER_;
uint32_t REPLACEMENT_CHAR_;
int64_t serialVersionUID_;
friend struct art::StringClassOffsets; // for verifying offset information
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index b55db72..2318b74 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -33,22 +33,22 @@ namespace mirror {
Class* Throwable::java_lang_Throwable_ = NULL;
void Throwable::SetCause(Throwable* cause) {
- CHECK(cause != NULL);
+ CHECK(cause != nullptr);
CHECK(cause != this);
- Throwable* current_cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_),
- false);
+ Throwable* current_cause = GetFieldObject<Throwable>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_),
+ false);
CHECK(current_cause == NULL || current_cause == this);
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), cause, false);
}
-bool Throwable::IsCheckedException() const {
+bool Throwable::IsCheckedException() {
if (InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_Error))) {
return false;
}
return !InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_RuntimeException));
}
-std::string Throwable::Dump() const {
+std::string Throwable::Dump() {
std::string result(PrettyTypeOf(this));
result += ": ";
String* msg = GetDetailMessage();
@@ -74,7 +74,7 @@ std::string Throwable::Dump() const {
source_file, line_number);
}
}
- Throwable* cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false);
+ Throwable* cause = GetFieldObject<Throwable>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false);
if (cause != NULL && cause != this) { // Constructor makes cause == this by default.
result += "Caused by: ";
result += cause->Dump();
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index 5a90599..bc9848a 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -33,16 +33,16 @@ class MANAGED Throwable : public Object {
void SetDetailMessage(String* new_detail_message) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), new_detail_message, false);
}
- String* GetDetailMessage() const {
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false);
+ String* GetDetailMessage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false);
}
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string Dump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// This is a runtime version of initCause, you shouldn't use it if initCause may have been
// overridden. Also it asserts rather than throwing exceptions. Currently this is only used
// in cases like the verifier where the checks cannot fail and initCause isn't overridden.
void SetCause(Throwable* cause) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsCheckedException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsCheckedException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static Class* GetJavaLangThrowable() {
DCHECK(java_lang_Throwable_ != NULL);
@@ -55,16 +55,16 @@ class MANAGED Throwable : public Object {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
- Object* GetStackState() const {
- return GetFieldObject<Object*>(OFFSET_OF_OBJECT_MEMBER(Throwable, stack_state_), true);
+ Object* GetStackState() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<Object>(OFFSET_OF_OBJECT_MEMBER(Throwable, stack_state_), true);
}
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- Throwable* cause_;
- String* detail_message_;
- Object* stack_state_; // Note this is Java volatile:
- Object* stack_trace_;
- Object* suppressed_exceptions_;
+ HeapReference<Throwable> cause_;
+ HeapReference<String> detail_message_;
+ HeapReference<Object> stack_state_; // Note this is Java volatile:
+ HeapReference<Object> stack_trace_;
+ HeapReference<Object> suppressed_exceptions_;
static Class* java_lang_Throwable_;
diff --git a/runtime/modifiers.h b/runtime/modifiers.h
index 4e365be..0addd51 100644
--- a/runtime/modifiers.h
+++ b/runtime/modifiers.h
@@ -47,6 +47,7 @@ static const uint32_t kAccDeclaredSynchronized = 0x00020000; // method (dex onl
static const uint32_t kAccClassIsProxy = 0x00040000; // class (dex only)
static const uint32_t kAccPreverified = 0x00080000; // method (dex only)
static const uint32_t kAccFastNative = 0x0080000; // method (dex only)
+static const uint32_t kAccPortableCompiled = 0x0100000; // method (dex only)
// Special runtime-only flags.
// Note: if only kAccClassIsReference is set, we have a soft reference.
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 4186693..72220e0 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -79,7 +79,7 @@ void Monitor::Init(uint32_t lock_profiling_threshold, bool (*is_sensitive_thread
is_sensitive_thread_hook_ = is_sensitive_thread_hook;
}
-Monitor::Monitor(Thread* owner, mirror::Object* obj, int32_t hash_code)
+Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code)
: monitor_lock_("a monitor lock", kMonitorLock),
monitor_contenders_("monitor contenders", monitor_lock_),
num_waiters_(0),
@@ -89,10 +89,11 @@ Monitor::Monitor(Thread* owner, mirror::Object* obj, int32_t hash_code)
wait_set_(NULL),
hash_code_(hash_code),
locking_method_(NULL),
- locking_dex_pc_(0) {
+ locking_dex_pc_(0),
+ monitor_id_(MonitorPool::CreateMonitorId(self, this)) {
// We should only inflate a lock if the owner is ourselves or suspended. This avoids a race
// with the owner unlocking the thin-lock.
- CHECK(owner == nullptr || owner == Thread::Current() || owner->IsSuspended());
+ CHECK(owner == nullptr || owner == self || owner->IsSuspended());
// The identity hash code is set for the life time of the monitor.
}
@@ -145,6 +146,7 @@ bool Monitor::Install(Thread* self) {
}
Monitor::~Monitor() {
+ MonitorPool::ReleaseMonitorId(monitor_id_);
// Deflated monitors have a null object.
}
@@ -219,7 +221,7 @@ void Monitor::Lock(Thread* self) {
// Contended.
const bool log_contention = (lock_profiling_threshold_ != 0);
uint64_t wait_start_ms = log_contention ? 0 : MilliTime();
- const mirror::ArtMethod* owners_method = locking_method_;
+ mirror::ArtMethod* owners_method = locking_method_;
uint32_t owners_dex_pc = locking_dex_pc_;
monitor_lock_.Unlock(self); // Let go of locks in order.
{
@@ -411,7 +413,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns,
if (ms < 0 || ns < 0 || ns > 999999) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
self->ThrowNewExceptionF(throw_location, "Ljava/lang/IllegalArgumentException;",
- "timeout arguments out of range: ms=%lld ns=%d", ms, ns);
+ "timeout arguments out of range: ms=%" PRId64 " ns=%d", ms, ns);
monitor_lock_.Unlock(self);
return;
}
@@ -430,7 +432,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns,
int prev_lock_count = lock_count_;
lock_count_ = 0;
owner_ = NULL;
- const mirror::ArtMethod* saved_method = locking_method_;
+ mirror::ArtMethod* saved_method = locking_method_;
locking_method_ = NULL;
uintptr_t saved_dex_pc = locking_dex_pc_;
locking_dex_pc_ = 0;
@@ -611,7 +613,7 @@ void Monitor::Inflate(Thread* self, Thread* owner, mirror::Object* obj, int32_t
DCHECK(self != NULL);
DCHECK(obj != NULL);
// Allocate and acquire a new monitor.
- UniquePtr<Monitor> m(new Monitor(owner, obj, hash_code));
+ UniquePtr<Monitor> m(new Monitor(self, owner, obj, hash_code));
if (m->Install(self)) {
VLOG(monitor) << "monitor: thread " << owner->GetThreadId()
<< " created monitor " << m.get() << " for object " << obj;
@@ -1008,7 +1010,7 @@ bool Monitor::IsLocked() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return owner_ != nullptr;
}
-void Monitor::TranslateLocation(const mirror::ArtMethod* method, uint32_t dex_pc,
+void Monitor::TranslateLocation(mirror::ArtMethod* method, uint32_t dex_pc,
const char** source_file, uint32_t* line_number) const {
// If method is null, location is unknown
if (method == NULL) {
diff --git a/runtime/monitor.h b/runtime/monitor.h
index 16e9410..85a8c48 100644
--- a/runtime/monitor.h
+++ b/runtime/monitor.h
@@ -24,7 +24,7 @@
#include <list>
#include <vector>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/mutex.h"
#include "root_visitor.h"
#include "sirt_ref.h"
@@ -40,6 +40,8 @@ class LockWord;
class Thread;
class StackVisitor;
+typedef uint32_t MonitorId;
+
class Monitor {
public:
// The default number of spins that are done before thread suspension is used to forcibly inflate
@@ -108,6 +110,10 @@ class Monitor {
return hash_code_.Load() != 0;
}
+ MonitorId GetMonitorId() const {
+ return monitor_id_;
+ }
+
static void InflateThinLocked(Thread* self, SirtRef<mirror::Object>& obj, LockWord lock_word,
uint32_t hash_code) NO_THREAD_SAFETY_ANALYSIS;
@@ -115,7 +121,7 @@ class Monitor {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
- explicit Monitor(Thread* owner, mirror::Object* obj, int32_t hash_code)
+ explicit Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Install the monitor into its object, may fail if another thread installs a different monitor
@@ -162,7 +168,7 @@ class Monitor {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Translates the provided method and pc into its declaring class' source file and line number.
- void TranslateLocation(const mirror::ArtMethod* method, uint32_t pc,
+ void TranslateLocation(mirror::ArtMethod* method, uint32_t pc,
const char** source_file, uint32_t* line_number) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -195,9 +201,12 @@ class Monitor {
// Method and dex pc where the lock owner acquired the lock, used when lock
// sampling is enabled. locking_method_ may be null if the lock is currently
// unlocked, or if the lock is acquired by the system when the stack is empty.
- const mirror::ArtMethod* locking_method_ GUARDED_BY(monitor_lock_);
+ mirror::ArtMethod* locking_method_ GUARDED_BY(monitor_lock_);
uint32_t locking_dex_pc_ GUARDED_BY(monitor_lock_);
+ // The denser encoded version of this monitor as stored in the lock word.
+ MonitorId monitor_id_;
+
friend class MonitorInfo;
friend class MonitorList;
friend class mirror::Object;
diff --git a/runtime/monitor_pool.cc b/runtime/monitor_pool.cc
new file mode 100644
index 0000000..eadd7a6
--- /dev/null
+++ b/runtime/monitor_pool.cc
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#include "monitor_pool.h"
+
+#include "base/logging.h"
+#include "base/mutex-inl.h"
+#include "monitor.h"
+
+namespace art {
+
+MonitorPool::MonitorPool() : allocated_ids_lock_("allocated monitor ids lock") {
+}
+
+Monitor* MonitorPool::LookupMonitorFromTable(MonitorId mon_id) {
+ ReaderMutexLock mu(Thread::Current(), allocated_ids_lock_);
+ return table_.Get(mon_id);
+}
+
+MonitorId MonitorPool::AllocMonitorIdFromTable(Thread* self, Monitor* mon) {
+ WriterMutexLock mu(self, allocated_ids_lock_);
+ for (size_t i = 0; i < allocated_ids_.size(); ++i) {
+ if (!allocated_ids_[i]) {
+ allocated_ids_.set(i);
+ MonitorId mon_id = i + 1; // Zero is reserved to mean "invalid".
+ table_.Put(mon_id, mon);
+ return mon_id;
+ }
+ }
+ LOG(FATAL) << "Out of internal monitor ids";
+ return 0;
+}
+
+void MonitorPool::ReleaseMonitorIdFromTable(MonitorId mon_id) {
+ WriterMutexLock mu(Thread::Current(), allocated_ids_lock_);
+ DCHECK(table_.Get(mon_id) != nullptr);
+ table_.erase(mon_id);
+ --mon_id; // Zero is reserved to mean "invalid".
+ DCHECK(allocated_ids_[mon_id]) << mon_id;
+ allocated_ids_.reset(mon_id);
+}
+
+} // namespace art
diff --git a/runtime/monitor_pool.h b/runtime/monitor_pool.h
new file mode 100644
index 0000000..32f3f4e
--- /dev/null
+++ b/runtime/monitor_pool.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_MONITOR_POOL_H_
+#define ART_RUNTIME_MONITOR_POOL_H_
+
+#include "monitor.h"
+
+#include "safe_map.h"
+
+#include <stdint.h>
+
+namespace art {
+
+// Abstraction to keep monitors small enough to fit in a lock word (32bits). On 32bit systems the
+// monitor id loses the alignment bits of the Monitor*.
+class MonitorPool {
+ public:
+ static MonitorPool* Create() {
+#ifndef __LP64__
+ return nullptr;
+#else
+ return new MonitorPool();
+#endif
+ }
+
+ static Monitor* MonitorFromMonitorId(MonitorId mon_id) {
+#ifndef __LP64__
+ return reinterpret_cast<Monitor*>(mon_id << 3);
+#else
+ return Runtime::Current()->GetMonitorPool()->LookupMonitorFromTable(mon_id);
+#endif
+ }
+
+ static MonitorId MonitorIdFromMonitor(Monitor* mon) {
+#ifndef __LP64__
+ return reinterpret_cast<MonitorId>(mon) >> 3;
+#else
+ return mon->GetMonitorId();
+#endif
+ }
+
+ static MonitorId CreateMonitorId(Thread* self, Monitor* mon) {
+#ifndef __LP64__
+ UNUSED(self);
+ return MonitorIdFromMonitor(mon);
+#else
+ return Runtime::Current()->GetMonitorPool()->AllocMonitorIdFromTable(self, mon);
+#endif
+ }
+
+ static void ReleaseMonitorId(MonitorId mon_id) {
+#ifndef __LP64__
+ UNUSED(mon_id);
+#else
+ Runtime::Current()->GetMonitorPool()->ReleaseMonitorIdFromTable(mon_id);
+#endif
+ }
+
+ private:
+#ifdef __LP64__
+ MonitorPool();
+
+ Monitor* LookupMonitorFromTable(MonitorId mon_id);
+
+ MonitorId LookupMonitorIdFromTable(Monitor* mon);
+
+ MonitorId AllocMonitorIdFromTable(Thread* self, Monitor* mon);
+
+ void ReleaseMonitorIdFromTable(MonitorId mon_id);
+
+ ReaderWriterMutex allocated_ids_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ static constexpr uint32_t kMaxMonitorId = 0xFFFF;
+ std::bitset<kMaxMonitorId> allocated_ids_ GUARDED_BY(allocated_ids_lock_);
+ SafeMap<MonitorId, Monitor*> table_ GUARDED_BY(allocated_ids_lock_);
+#endif
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_MONITOR_POOL_H_
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 2c75ecc..1a3ceb8 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -290,7 +290,7 @@ static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename
return JNI_TRUE;
}
if (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin()
- != reinterpret_cast<uint32_t>(image_header.GetOatDataBegin())) {
+ != reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin())) {
if (kDebugLogging) {
ScopedObjectAccess soa(env);
LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index c9e255c..e1b5f97 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -90,7 +90,7 @@ static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) {
ThrowRuntimeException("Trying to get address of movable array object");
return 0;
}
- return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize()));
+ return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize(), 0));
}
static void VMRuntime_clearGrowthLimit(JNIEnv*, jobject) {
@@ -181,7 +181,8 @@ static void VMRuntime_concurrentGC(JNIEnv* env, jobject) {
typedef std::map<std::string, mirror::String*> StringTable;
-static mirror::Object* PreloadDexCachesStringsVisitor(mirror::Object* root, void* arg) {
+static mirror::Object* PreloadDexCachesStringsVisitor(mirror::Object* root, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
StringTable& table = *reinterpret_cast<StringTable*>(arg);
mirror::String* string = const_cast<mirror::Object*>(root)->AsString();
// LOG(INFO) << "VMRuntime.preloadDexCaches interned=" << string->ToModifiedUtf8();
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index f915365..7e02e29 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -79,7 +79,7 @@ static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject ja
ClosestUserClassLoaderVisitor(Thread* thread, mirror::Object* bootstrap, mirror::Object* system)
: StackVisitor(thread, NULL), bootstrap(bootstrap), system(system), class_loader(NULL) {}
- bool VisitFrame() {
+ bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(class_loader == NULL);
mirror::Class* c = GetMethod()->GetDeclaringClass();
mirror::Object* cl = c->GetClassLoader();
diff --git a/runtime/native/dalvik_system_Zygote.cc b/runtime/native/dalvik_system_Zygote.cc
index 7fa9457..22c5430 100644
--- a/runtime/native/dalvik_system_Zygote.cc
+++ b/runtime/native/dalvik_system_Zygote.cc
@@ -47,8 +47,10 @@
#if defined(__linux__)
#include <sys/personality.h>
#include <sys/utsname.h>
+#if defined(HAVE_ANDROID_OS)
#include <sys/capability.h>
#endif
+#endif
namespace art {
diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc
index ea78e04..6bbe642 100644
--- a/runtime/native/java_lang_System.cc
+++ b/runtime/native/java_lang_System.cc
@@ -24,150 +24,14 @@
#include "mirror/object_array-inl.h"
#include "scoped_fast_native_object_access.h"
-/*
- * We make guarantees about the atomicity of accesses to primitive
- * variables. These guarantees also apply to elements of arrays.
- * In particular, 8-bit, 16-bit, and 32-bit accesses must be atomic and
- * must not cause "word tearing". Accesses to 64-bit array elements must
- * either be atomic or treated as two 32-bit operations. References are
- * always read and written atomically, regardless of the number of bits
- * used to represent them.
- *
- * We can't rely on standard libc functions like memcpy(3) and memmove(3)
- * in our implementation of System.arraycopy, because they may copy
- * byte-by-byte (either for the full run or for "unaligned" parts at the
- * start or end). We need to use functions that guarantee 16-bit or 32-bit
- * atomicity as appropriate.
- *
- * System.arraycopy() is heavily used, so having an efficient implementation
- * is important. The bionic libc provides a platform-optimized memory move
- * function that should be used when possible. If it's not available,
- * the trivial "reference implementation" versions below can be used until
- * a proper version can be written.
- *
- * For these functions, The caller must guarantee that dst/src are aligned
- * appropriately for the element type, and that n is a multiple of the
- * element size.
- */
+namespace art {
/*
- * Works like memmove(), except:
- * - if all arguments are at least 32-bit aligned, we guarantee that we
- * will use operations that preserve atomicity of 32-bit values
- * - if not, we guarantee atomicity of 16-bit values
- *
- * If all three arguments are not at least 16-bit aligned, the behavior
- * of this function is undefined. (We could remove this restriction by
- * testing for unaligned values and punting to memmove(), but that's
- * not currently useful.)
- *
- * TODO: add loop for 64-bit alignment
- * TODO: use __builtin_prefetch
- * TODO: write ARM/MIPS/x86 optimized versions
+ * We make guarantees about the atomicity of accesses to primitive variables. These guarantees
+ * also apply to elements of arrays. In particular, 8-bit, 16-bit, and 32-bit accesses must not
+ * cause "word tearing". Accesses to 64-bit array elements may be two 32-bit operations.
+ * References are never torn regardless of the number of bits used to represent them.
*/
-void MemmoveWords(void* dst, const void* src, size_t n) {
- DCHECK_EQ((((uintptr_t) dst | (uintptr_t) src | n) & 0x01), 0U);
-
- char* d = reinterpret_cast<char*>(dst);
- const char* s = reinterpret_cast<const char*>(src);
- size_t copyCount;
-
- // If the source and destination pointers are the same, this is
- // an expensive no-op. Testing for an empty move now allows us
- // to skip a check later.
- if (n == 0 || d == s) {
- return;
- }
-
- // Determine if the source and destination buffers will overlap if
- // we copy data forward (i.e. *dst++ = *src++).
- //
- // It's okay if the destination buffer starts before the source and
- // there is some overlap, because the reader is always ahead of the
- // writer.
- if (LIKELY((d < s) || ((size_t)(d - s) >= n))) {
- // Copy forward. We prefer 32-bit loads and stores even for 16-bit
- // data, so sort that out.
- if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
- // Not 32-bit aligned. Two possibilities:
- // (1) Congruent, we can align to 32-bit by copying one 16-bit val
- // (2) Non-congruent, we can do one of:
- // a. copy whole buffer as a series of 16-bit values
- // b. load/store 32 bits, using shifts to ensure alignment
- // c. just copy the as 32-bit values and assume the CPU
- // will do a reasonable job
- //
- // We're currently using (a), which is suboptimal.
- if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
- copyCount = n;
- } else {
- copyCount = 2;
- }
- n -= copyCount;
- copyCount /= sizeof(uint16_t);
-
- while (copyCount--) {
- *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
- d += sizeof(uint16_t);
- s += sizeof(uint16_t);
- }
- }
-
- // Copy 32-bit aligned words.
- copyCount = n / sizeof(uint32_t);
- while (copyCount--) {
- *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
- d += sizeof(uint32_t);
- s += sizeof(uint32_t);
- }
-
- // Check for leftovers. Either we finished exactly, or we have one remaining 16-bit chunk.
- if ((n & 0x02) != 0) {
- *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
- }
- } else {
- // Copy backward, starting at the end.
- d += n;
- s += n;
-
- if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
- // try for 32-bit alignment.
- if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
- copyCount = n;
- } else {
- copyCount = 2;
- }
- n -= copyCount;
- copyCount /= sizeof(uint16_t);
-
- while (copyCount--) {
- d -= sizeof(uint16_t);
- s -= sizeof(uint16_t);
- *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
- }
- }
-
- // Copy 32-bit aligned words.
- copyCount = n / sizeof(uint32_t);
- while (copyCount--) {
- d -= sizeof(uint32_t);
- s -= sizeof(uint32_t);
- *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
- }
-
- // Copy leftovers.
- if ((n & 0x02) != 0) {
- d -= sizeof(uint16_t);
- s -= sizeof(uint16_t);
- *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
- }
- }
-}
-
-#define move16 MemmoveWords
-#define move32 MemmoveWords
-
-namespace art {
static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -178,168 +42,132 @@ static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::
"%s of type %s is not an array", identifier, actualType.c_str());
}
-static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
+static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst,
+ jint dstPos, jint length) {
+ // The API is defined in terms of length, but length is somewhat overloaded so we use count.
+ const jint count = length;
ScopedFastNativeObjectAccess soa(env);
// Null pointer checks.
- if (UNLIKELY(javaSrc == NULL)) {
- ThrowNullPointerException(NULL, "src == null");
+ if (UNLIKELY(javaSrc == nullptr)) {
+ ThrowNullPointerException(nullptr, "src == null");
return;
}
- if (UNLIKELY(javaDst == NULL)) {
- ThrowNullPointerException(NULL, "dst == null");
+ if (UNLIKELY(javaDst == nullptr)) {
+ ThrowNullPointerException(nullptr, "dst == null");
return;
}
// Make sure source and destination are both arrays.
mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
- mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
if (UNLIKELY(!srcObject->IsArrayInstance())) {
ThrowArrayStoreException_NotAnArray("source", srcObject);
return;
}
+ mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
if (UNLIKELY(!dstObject->IsArrayInstance())) {
ThrowArrayStoreException_NotAnArray("destination", dstObject);
return;
}
mirror::Array* srcArray = srcObject->AsArray();
mirror::Array* dstArray = dstObject->AsArray();
- mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
- mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
// Bounds checking.
- if (UNLIKELY(srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length)) {
+ if (UNLIKELY(srcPos < 0) || UNLIKELY(dstPos < 0) || UNLIKELY(count < 0) ||
+ UNLIKELY(srcPos > srcArray->GetLength() - count) ||
+ UNLIKELY(dstPos > dstArray->GetLength() - count)) {
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
"src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
- srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
+ srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos,
+ count);
return;
}
- // Handle primitive arrays.
- if (srcComponentType->IsPrimitive() || dstComponentType->IsPrimitive()) {
- // If one of the arrays holds a primitive type the other array must hold the exact same type.
- if (UNLIKELY(srcComponentType != dstComponentType)) {
- std::string srcType(PrettyTypeOf(srcArray));
- std::string dstType(PrettyTypeOf(dstArray));
- ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
- soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
- "Incompatible types: src=%s, dst=%s",
- srcType.c_str(), dstType.c_str());
- return;
- }
-
- size_t width = srcArray->GetClass()->GetComponentSize();
- uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
- const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
-
- switch (width) {
- case 1:
- memmove(dstBytes + dstPos, srcBytes + srcPos, length);
- break;
- case 2:
- move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
- break;
- case 4:
- move32(dstBytes + dstPos * 4, srcBytes + srcPos * 4, length * 4);
- break;
- case 8:
- // We don't need to guarantee atomicity of the entire 64-bit word.
- move32(dstBytes + dstPos * 8, srcBytes + srcPos * 8, length * 8);
- break;
- default:
- LOG(FATAL) << "Unknown primitive array type: " << PrettyTypeOf(srcArray);
- }
-
- return;
- }
-
- // Neither class is primitive. Are the types trivially compatible?
- const size_t width = sizeof(mirror::Object*);
- uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
- const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
- if (dstArray == srcArray || dstComponentType->IsAssignableFrom(srcComponentType)) {
- // Yes. Bulk copy.
- COMPILE_ASSERT(sizeof(width) == sizeof(uint32_t), move32_assumes_Object_references_are_32_bit);
- move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
- Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
- return;
- }
-
- // The arrays are not trivially compatible. However, we may still be able to copy some or all of
- // the elements if the source objects are compatible (for example, copying an Object[] to
- // String[], the Objects being copied might actually be Strings).
- // We can't do a bulk move because that would introduce a check-use race condition, so we copy
- // elements one by one.
-
- // We already dealt with overlapping copies, so we don't need to cope with that case below.
- CHECK_NE(dstArray, srcArray);
-
- mirror::Object* const * srcObjects =
- reinterpret_cast<mirror::Object* const *>(srcBytes + srcPos * width);
- mirror::Object** dstObjects = reinterpret_cast<mirror::Object**>(dstBytes + dstPos * width);
- mirror::Class* dstClass = dstArray->GetClass()->GetComponentType();
-
- // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
- // we know is assignable to the destination array's component type.
- mirror::Class* lastAssignableElementClass = dstClass;
-
- mirror::Object* o = NULL;
- int i = 0;
- for (; i < length; ++i) {
- o = srcObjects[i];
- if (o != NULL) {
- mirror::Class* oClass = o->GetClass();
- if (lastAssignableElementClass == oClass) {
- dstObjects[i] = o;
- } else if (dstClass->IsAssignableFrom(oClass)) {
- lastAssignableElementClass = oClass;
- dstObjects[i] = o;
- } else {
- // Can't put this element into the array.
- break;
+ mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
+ mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
+ Primitive::Type dstComponentPrimitiveType = dstComponentType->GetPrimitiveType();
+
+ if (LIKELY(srcComponentType == dstComponentType)) {
+ // Trivial assignability.
+ switch (dstComponentPrimitiveType) {
+ case Primitive::kPrimVoid:
+ LOG(FATAL) << "Unreachable, cannot have arrays of type void";
+ return;
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 1U);
+ dstArray->AsByteSizedArray()->Memmove(dstPos, srcArray->AsByteSizedArray(), srcPos, count);
+ return;
+ case Primitive::kPrimChar:
+ case Primitive::kPrimShort:
+ DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 2U);
+ dstArray->AsShortSizedArray()->Memmove(dstPos, srcArray->AsShortSizedArray(), srcPos, count);
+ return;
+ case Primitive::kPrimInt:
+ case Primitive::kPrimFloat:
+ DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 4U);
+ dstArray->AsIntArray()->Memmove(dstPos, srcArray->AsIntArray(), srcPos, count);
+ return;
+ case Primitive::kPrimLong:
+ case Primitive::kPrimDouble:
+ DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 8U);
+ dstArray->AsLongArray()->Memmove(dstPos, srcArray->AsLongArray(), srcPos, count);
+ return;
+ case Primitive::kPrimNot: {
+ mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
+ mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
+ dstObjArray->AssignableMemmove(dstPos, srcObjArray, srcPos, count);
+ return;
}
- } else {
- dstObjects[i] = NULL;
+ default:
+ LOG(FATAL) << "Unknown array type: " << PrettyTypeOf(srcArray);
+ return;
}
}
-
- Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
- if (UNLIKELY(i != length)) {
- std::string actualSrcType(PrettyTypeOf(o));
+ // If one of the arrays holds a primitive type the other array must hold the exact same type.
+ if (UNLIKELY((dstComponentPrimitiveType != Primitive::kPrimNot) ||
+ srcComponentType->IsPrimitive())) {
+ std::string srcType(PrettyTypeOf(srcArray));
std::string dstType(PrettyTypeOf(dstArray));
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
- "source[%d] of type %s cannot be stored in destination array of type %s",
- srcPos + i, actualSrcType.c_str(), dstType.c_str());
+ "Incompatible types: src=%s, dst=%s",
+ srcType.c_str(), dstType.c_str());
+ return;
+ }
+ // Arrays hold distinct types and so therefore can't alias - use memcpy instead of memmove.
+ mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
+ mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
+ // If we're assigning into say Object[] then we don't need per element checks.
+ if (dstComponentType->IsAssignableFrom(srcComponentType)) {
+ dstObjArray->AssignableMemcpy(dstPos, srcObjArray, srcPos, count);
return;
}
+ dstObjArray->AssignableCheckingMemcpy(dstPos, srcObjArray, srcPos, count, true);
}
-static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
+static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
+ jobject javaDst, jint dstPos, jint count) {
ScopedFastNativeObjectAccess soa(env);
- DCHECK(javaSrc != NULL);
- DCHECK(javaDst != NULL);
mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
- DCHECK(srcObject->IsArrayInstance());
- DCHECK(dstObject->IsArrayInstance());
+ DCHECK(srcObject != nullptr);
+ DCHECK(dstObject != nullptr);
mirror::Array* srcArray = srcObject->AsArray();
mirror::Array* dstArray = dstObject->AsArray();
- DCHECK(srcPos >= 0 && dstPos >= 0 && length >= 0 &&
- srcPos + length <= srcArray->GetLength() && dstPos + length <= dstArray->GetLength());
- DCHECK_EQ(srcArray->GetClass()->GetComponentType(), dstArray->GetClass()->GetComponentType());
- DCHECK(srcArray->GetClass()->GetComponentType()->IsPrimitive());
- DCHECK(dstArray->GetClass()->GetComponentType()->IsPrimitive());
- DCHECK_EQ(srcArray->GetClass()->GetComponentSize(), static_cast<size_t>(2));
- DCHECK_EQ(dstArray->GetClass()->GetComponentSize(), static_cast<size_t>(2));
- uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(2));
- const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(2));
- move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
+ DCHECK_GE(srcPos, 0);
+ DCHECK_GE(dstPos, 0);
+ DCHECK_GE(count, 0);
+ DCHECK_LE(srcPos + count, srcArray->GetLength());
+ DCHECK_LE(dstPos + count, dstArray->GetLength());
+ DCHECK_EQ(srcArray->GetClass(), dstArray->GetClass());
+ DCHECK_EQ(srcArray->GetClass()->GetComponentType()->GetPrimitiveType(), Primitive::kPrimChar);
+ dstArray->AsCharArray()->Memmove(dstPos, srcArray->AsCharArray(), srcPos, count);
}
static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
- if (javaObject == nullptr) {
+ if (UNLIKELY(javaObject == nullptr)) {
return 0;
}
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index b5fc7e7..6c22003 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include "atomic.h"
#include "gc/accounting/card_table-inl.h"
#include "jni_internal.h"
#include "mirror/object.h"
@@ -23,40 +22,30 @@
namespace art {
-static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) {
+static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jint expectedValue, jint newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
- volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
- // Note: android_atomic_release_cas() returns 0 on success, not failure.
- int result = android_atomic_release_cas(expectedValue, newValue, address);
- return (result == 0) ? JNI_TRUE : JNI_FALSE;
+ bool success = obj->CasField32(MemberOffset(offset), expectedValue, newValue);
+ return success ? JNI_TRUE : JNI_FALSE;
}
-static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) {
+static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jlong expectedValue, jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
- volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr);
- // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
- bool success = QuasiAtomic::Cas64(expectedValue, newValue, address);
+ bool success = obj->CasField64(MemberOffset(offset), expectedValue, newValue);
return success ? JNI_TRUE : JNI_FALSE;
}
-static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) {
+static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jobject javaExpectedValue, jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue);
mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
- byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
- int32_t* address = reinterpret_cast<int32_t*>(raw_addr);
- // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
- int result = android_atomic_release_cas(reinterpret_cast<int32_t>(expectedValue),
- reinterpret_cast<int32_t>(newValue), address);
- if (result == 0) {
- Runtime::Current()->GetHeap()->WriteBarrierField(obj, MemberOffset(offset), newValue);
- }
- return (result == 0) ? JNI_TRUE : JNI_FALSE;
+ bool success = obj->CasFieldObject(MemberOffset(offset), expectedValue, newValue);
+ return success ? JNI_TRUE : JNI_FALSE;
}
static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
@@ -77,13 +66,15 @@ static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, j
obj->SetField32(MemberOffset(offset), newValue, false);
}
-static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
+static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jint newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
obj->SetField32(MemberOffset(offset), newValue, true);
}
-static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
+static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jint newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
QuasiAtomic::MembarStoreStore();
@@ -108,13 +99,15 @@ static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
obj->SetField64(MemberOffset(offset), newValue, false);
}
-static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
+static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
obj->SetField64(MemberOffset(offset), newValue, true);
}
-static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
+static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
QuasiAtomic::MembarStoreStore();
@@ -124,32 +117,35 @@ static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong o
static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), true);
+ mirror::Object* value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset), true);
return soa.AddLocalReference<jobject>(value);
}
static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), false);
+ mirror::Object* value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset), false);
return soa.AddLocalReference<jobject>(value);
}
-static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
+static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
obj->SetFieldObject(MemberOffset(offset), newValue, false);
}
-static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
+static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
obj->SetFieldObject(MemberOffset(offset), newValue, true);
}
-static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
+static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index be88204..0f380ad 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -66,16 +66,16 @@ OatFile* OatFile::Open(const std::string& filename,
std::string* error_msg) {
CHECK(!filename.empty()) << location;
CheckLocation(filename);
-#ifdef ART_USE_PORTABLE_COMPILER
- // If we are using PORTABLE, use dlopen to deal with relocations.
- //
- // We use our own ELF loader for Quick to deal with legacy apps that
- // open a generated dex file by name, remove the file, then open
- // another generated dex file with the same name. http://b/10614658
- if (executable) {
- return OpenDlopen(filename, location, requested_base, error_msg);
+ if (kUsePortableCompiler) {
+ // If we are using PORTABLE, use dlopen to deal with relocations.
+ //
+ // We use our own ELF loader for Quick to deal with legacy apps that
+ // open a generated dex file by name, remove the file, then open
+ // another generated dex file with the same name. http://b/10614658
+ if (executable) {
+ return OpenDlopen(filename, location, requested_base, error_msg);
+ }
}
-#endif
// If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
//
// On target, dlopen may fail when compiling due to selinux restrictions on installd.
@@ -503,51 +503,40 @@ OatFile::OatMethod::OatMethod(const byte* base,
mapping_table_offset_(mapping_table_offset),
vmap_table_offset_(vmap_table_offset),
native_gc_map_offset_(gc_map_offset) {
-#ifndef NDEBUG
- if (mapping_table_offset_ != 0) { // implies non-native, non-stub code
- if (vmap_table_offset_ == 0) {
- DCHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
- __builtin_popcount(fp_spill_mask_)));
+ if (kIsDebugBuild) {
+ if (mapping_table_offset_ != 0) { // implies non-native, non-stub code
+ if (vmap_table_offset_ == 0) {
+ CHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
+ __builtin_popcount(fp_spill_mask_)));
+ } else {
+ VmapTable vmap_table(reinterpret_cast<const uint8_t*>(begin_ + vmap_table_offset_));
+
+ CHECK_EQ(vmap_table.Size(), static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
+ __builtin_popcount(fp_spill_mask_)));
+ }
} else {
- VmapTable vmap_table(reinterpret_cast<const uint8_t*>(begin_ + vmap_table_offset_));
-
- DCHECK_EQ(vmap_table.Size(), static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
- __builtin_popcount(fp_spill_mask_)));
+ CHECK_EQ(vmap_table_offset_, 0U);
}
- } else {
- DCHECK_EQ(vmap_table_offset_, 0U);
}
-#endif
}
OatFile::OatMethod::~OatMethod() {}
-const void* OatFile::OatMethod::GetCode() const {
- return GetOatPointer<const void*>(code_offset_);
-}
-
-uint32_t OatFile::OatMethod::GetCodeSize() const {
-#if defined(ART_USE_PORTABLE_COMPILER)
- // TODO: With Quick, we store the size before the code. With
- // Portable, the code is in a .o file we don't manage ourselves. ELF
- // symbols do have a concept of size, so we could capture that and
- // store it somewhere, such as the OatMethod.
- return 0;
-#else
- uintptr_t code = reinterpret_cast<uint32_t>(GetCode());
+uint32_t OatFile::OatMethod::GetQuickCodeSize() const {
+ uintptr_t code = reinterpret_cast<uintptr_t>(GetQuickCode());
if (code == 0) {
return 0;
}
// TODO: make this Thumb2 specific
code &= ~0x1;
return reinterpret_cast<uint32_t*>(code)[-1];
-#endif
}
void OatFile::OatMethod::LinkMethod(mirror::ArtMethod* method) const {
CHECK(method != NULL);
- method->SetEntryPointFromCompiledCode(GetCode());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableCode());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
method->SetFrameSizeInBytes(frame_size_in_bytes_);
method->SetCoreSpillMask(core_spill_mask_);
method->SetFpSpillMask(fp_spill_mask_);
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 887a9d1..d6e8dc0 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -97,8 +97,30 @@ class OatFile {
return native_gc_map_offset_;
}
- const void* GetCode() const;
- uint32_t GetCodeSize() const;
+ const void* GetPortableCode() const {
+ // TODO: encode whether code is portable/quick in flags within OatMethod.
+ if (kUsePortableCompiler) {
+ return GetOatPointer<const void*>(code_offset_);
+ } else {
+ return nullptr;
+ }
+ }
+
+ const void* GetQuickCode() const {
+ if (kUsePortableCompiler) {
+ return nullptr;
+ } else {
+ return GetOatPointer<const void*>(code_offset_);
+ }
+ }
+
+ uint32_t GetPortableCodeSize() const {
+ // TODO: With Quick, we store the size before the code. With Portable, the code is in a .o
+ // file we don't manage ourselves. ELF symbols do have a concept of size, so we could capture
+ // that and store it somewhere, such as the OatMethod.
+ return 0;
+ }
+ uint32_t GetQuickCodeSize() const;
const uint8_t* GetMappingTable() const {
return GetOatPointer<const uint8_t*>(mapping_table_offset_);
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 407aa65..0451f5d 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -69,30 +69,29 @@ class ObjectLock {
class ClassHelper {
public:
- explicit ClassHelper(const mirror::Class* c )
+ explicit ClassHelper(mirror::Class* c )
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : interface_type_list_(NULL),
- klass_(NULL) {
- if (c != NULL) {
+ : interface_type_list_(nullptr), klass_(nullptr) {
+ if (c != nullptr) {
ChangeClass(c);
}
}
- void ChangeClass(const mirror::Class* new_c)
+ void ChangeClass(mirror::Class* new_c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(new_c != NULL) << "klass_=" << klass_; // Log what we were changing from if any
+ CHECK(new_c != nullptr) << "klass_=" << klass_; // Log what we were changing from if any
if (!new_c->IsClass()) {
LOG(FATAL) << "new_c=" << new_c << " cc " << new_c->GetClass() << " ccc "
- << ((new_c->GetClass() != nullptr) ? new_c->GetClass()->GetClass() : NULL);
+ << ((new_c->GetClass() != nullptr) ? new_c->GetClass()->GetClass() : nullptr);
}
klass_ = new_c;
- interface_type_list_ = NULL;
+ interface_type_list_ = nullptr;
}
// The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
// If you need it longer, copy it into a std::string.
const char* GetDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(klass_ != NULL);
+ CHECK(klass_ != nullptr);
if (UNLIKELY(klass_->IsArrayClass())) {
return GetArrayDescriptor();
} else if (UNLIKELY(klass_->IsPrimitive())) {
@@ -109,8 +108,8 @@ class ClassHelper {
const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string result("[");
- const mirror::Class* saved_klass = klass_;
- CHECK(saved_klass != NULL);
+ mirror::Class* saved_klass = klass_;
+ CHECK(saved_klass != nullptr);
ChangeClass(klass_->GetComponentType());
result += GetDescriptor();
ChangeClass(saved_klass);
@@ -128,7 +127,7 @@ class ClassHelper {
}
uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != NULL);
+ DCHECK(klass_ != nullptr);
if (klass_->IsPrimitive()) {
return 0;
} else if (klass_->IsArrayClass()) {
@@ -137,7 +136,7 @@ class ClassHelper {
return klass_->GetIfTable()->GetLength();
} else {
const DexFile::TypeList* interfaces = GetInterfaceTypeList();
- if (interfaces == NULL) {
+ if (interfaces == nullptr) {
return 0;
} else {
return interfaces->Size();
@@ -147,7 +146,7 @@ class ClassHelper {
uint16_t GetDirectInterfaceTypeIdx(uint32_t idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != NULL);
+ DCHECK(klass_ != nullptr);
DCHECK(!klass_->IsPrimitive());
DCHECK(!klass_->IsArrayClass());
return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
@@ -155,7 +154,7 @@ class ClassHelper {
mirror::Class* GetDirectInterface(uint32_t idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != NULL);
+ DCHECK(klass_ != nullptr);
DCHECK(!klass_->IsPrimitive());
if (klass_->IsArrayClass()) {
if (idx == 0) {
@@ -169,9 +168,9 @@ class ClassHelper {
} else {
uint16_t type_idx = GetDirectInterfaceTypeIdx(idx);
mirror::Class* interface = GetDexCache()->GetResolvedType(type_idx);
- if (interface == NULL) {
+ if (interface == nullptr) {
interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
- CHECK(interface != NULL || Thread::Current()->IsExceptionPending());
+ CHECK(interface != nullptr || Thread::Current()->IsExceptionPending());
}
return interface;
}
@@ -181,13 +180,13 @@ class ClassHelper {
std::string descriptor(GetDescriptor());
const DexFile& dex_file = GetDexFile();
const DexFile::ClassDef* dex_class_def = GetClassDef();
- CHECK(dex_class_def != NULL);
+ CHECK(dex_class_def != nullptr);
return dex_file.GetSourceFile(*dex_class_def);
}
std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::DexCache* dex_cache = GetDexCache();
- if (dex_cache != NULL && !klass_->IsProxyClass()) {
+ if (dex_cache != nullptr && !klass_->IsProxyClass()) {
return dex_cache->GetLocation()->ToModifiedUtf8();
} else {
// Arrays and proxies are generated and have no corresponding dex file location.
@@ -207,9 +206,9 @@ class ClassHelper {
const DexFile::TypeList* GetInterfaceTypeList()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const DexFile::TypeList* result = interface_type_list_;
- if (result == NULL) {
+ if (result == nullptr) {
const DexFile::ClassDef* class_def = GetClassDef();
- if (class_def != NULL) {
+ if (class_def != nullptr) {
result = GetDexFile().GetInterfacesList(*class_def);
interface_type_list_ = result;
}
@@ -222,7 +221,7 @@ class ClassHelper {
}
const DexFile::TypeList* interface_type_list_;
- const mirror::Class* klass_;
+ mirror::Class* klass_;
std::string descriptor_;
DISALLOW_COPY_AND_ASSIGN(ClassHelper);
@@ -230,11 +229,11 @@ class ClassHelper {
class FieldHelper {
public:
- FieldHelper() : field_(NULL) {}
- explicit FieldHelper(const mirror::ArtField* f) : field_(f) {}
+ FieldHelper() : field_(nullptr) {}
+ explicit FieldHelper(mirror::ArtField* f) : field_(f) {}
- void ChangeField(const mirror::ArtField* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(new_f != NULL);
+ void ChangeField(mirror::ArtField* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(new_f != nullptr);
field_ = new_f;
}
@@ -257,9 +256,9 @@ class FieldHelper {
const DexFile& dex_file = GetDexFile();
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
- if (resolve && (type == NULL)) {
+ if (resolve && (type == nullptr)) {
type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
- CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+ CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
}
return type;
}
@@ -320,7 +319,7 @@ class FieldHelper {
const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *GetDexCache()->GetDexFile();
}
- const mirror::ArtField* field_;
+ mirror::ArtField* field_;
std::string declaring_class_descriptor_;
DISALLOW_COPY_AND_ASSIGN(FieldHelper);
@@ -328,20 +327,18 @@ class FieldHelper {
class MethodHelper {
public:
- MethodHelper()
- : method_(NULL), shorty_(NULL),
- shorty_len_(0) {}
+ MethodHelper() : method_(nullptr), shorty_(nullptr), shorty_len_(0) {}
- explicit MethodHelper(const mirror::ArtMethod* m)
+ explicit MethodHelper(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : method_(NULL), shorty_(NULL), shorty_len_(0) {
+ : method_(nullptr), shorty_(nullptr), shorty_len_(0) {
SetMethod(m);
}
void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(new_m != NULL);
+ DCHECK(new_m != nullptr);
SetMethod(new_m);
- shorty_ = NULL;
+ shorty_ = nullptr;
}
const mirror::ArtMethod* GetMethod() const {
@@ -381,7 +378,7 @@ class MethodHelper {
const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const char* result = shorty_;
- if (result == NULL) {
+ if (result == nullptr) {
const DexFile& dex_file = GetDexFile();
result = dex_file.GetMethodShorty(dex_file.GetMethodId(method_->GetDexMethodIndex()),
&shorty_len_);
@@ -391,7 +388,7 @@ class MethodHelper {
}
uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (shorty_ == NULL) {
+ if (shorty_ == nullptr) {
GetShorty();
}
return shorty_len_;
@@ -529,15 +526,15 @@ class MethodHelper {
bool IsResolvedTypeIdx(uint16_t type_idx) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return method_->GetDexCacheResolvedTypes()->Get(type_idx) != NULL;
+ return method_->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr;
}
mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx);
- if (type == NULL && resolve) {
+ if (type == nullptr && resolve) {
type = GetClassLinker()->ResolveType(type_idx, method_);
- CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+ CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
}
return type;
}
@@ -563,7 +560,7 @@ class MethodHelper {
mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::String* s = method_->GetDexCacheStrings()->Get(string_idx);
- if (UNLIKELY(s == NULL)) {
+ if (UNLIKELY(s == nullptr)) {
SirtRef<mirror::DexCache> dex_cache(Thread::Current(), GetDexCache());
s = GetClassLinker()->ResolveString(GetDexFile(), string_idx, dex_cache);
}
@@ -613,13 +610,13 @@ class MethodHelper {
private:
// Set the method_ field, for proxy methods looking up the interface method via the resolved
// methods table.
- void SetMethod(const mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (method != NULL) {
+ void SetMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (method != nullptr) {
mirror::Class* klass = method->GetDeclaringClass();
if (UNLIKELY(klass->IsProxyClass())) {
mirror::ArtMethod* interface_method =
method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
- DCHECK(interface_method != NULL);
+ DCHECK(interface_method != nullptr);
DCHECK(interface_method == GetClassLinker()->FindMethodForProxy(klass, method));
method = interface_method;
}
@@ -631,7 +628,7 @@ class MethodHelper {
return Runtime::Current()->GetClassLinker();
}
- const mirror::ArtMethod* method_;
+ mirror::ArtMethod* method_;
const char* shorty_;
uint32_t shorty_len_;
diff --git a/runtime/offsets.h b/runtime/offsets.h
index 94ae805..e2dba9d 100644
--- a/runtime/offsets.h
+++ b/runtime/offsets.h
@@ -22,7 +22,7 @@
namespace art {
-// Allow the meaning of offsets to be strongly typed
+// Allow the meaning of offsets to be strongly typed.
class Offset {
public:
explicit Offset(size_t val) : val_(val) {}
@@ -37,7 +37,7 @@ class Offset {
};
std::ostream& operator<<(std::ostream& os, const Offset& offs);
-// Offsets relative to the current frame
+// Offsets relative to the current frame.
class FrameOffset : public Offset {
public:
explicit FrameOffset(size_t val) : Offset(val) {}
@@ -45,13 +45,13 @@ class FrameOffset : public Offset {
bool operator<(FrameOffset other) const { return val_ < other.val_; }
};
-// Offsets relative to the current running thread
+// Offsets relative to the current running thread.
class ThreadOffset : public Offset {
public:
explicit ThreadOffset(size_t val) : Offset(val) {}
};
-// Offsets relative to an object
+// Offsets relative to an object.
class MemberOffset : public Offset {
public:
explicit MemberOffset(size_t val) : Offset(val) {}
diff --git a/runtime/primitive.h b/runtime/primitive.h
index 5e07311..b436bd2 100644
--- a/runtime/primitive.h
+++ b/runtime/primitive.h
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "mirror/object_reference.h"
namespace art {
namespace mirror {
@@ -78,7 +79,7 @@ class Primitive {
case kPrimFloat: return 4;
case kPrimLong:
case kPrimDouble: return 8;
- case kPrimNot: return sizeof(mirror::Object*);
+ case kPrimNot: return sizeof(mirror::HeapReference<mirror::Object>);
default:
LOG(FATAL) << "Invalid type " << static_cast<int>(type);
return 0;
diff --git a/runtime/profiler.cc b/runtime/profiler.cc
index 365c9c3..20e08b8 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -455,9 +455,7 @@ void ProfileSampleResults::Clear() {
}
uint32_t ProfileSampleResults::Hash(mirror::ArtMethod* method) {
- uint32_t value = reinterpret_cast<uint32_t>(method);
- value >>= 2;
- return value % kHashSize;
+ return (PointerToLowMemUInt32(method) >> 3) % kHashSize;
}
} // namespace art
diff --git a/runtime/reference_table.cc b/runtime/reference_table.cc
index 6f65bff..b5ef735 100644
--- a/runtime/reference_table.cc
+++ b/runtime/reference_table.cc
@@ -59,7 +59,7 @@ void ReferenceTable::Remove(mirror::Object* obj) {
// If "obj" is an array, return the number of elements in the array.
// Otherwise, return zero.
-static size_t GetElementCount(const mirror::Object* obj) {
+static size_t GetElementCount(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (obj == NULL || obj == kClearedJniWeakGlobal || !obj->IsArrayInstance()) {
return 0;
}
@@ -67,7 +67,7 @@ static size_t GetElementCount(const mirror::Object* obj) {
}
struct ObjectComparator {
- bool operator()(const mirror::Object* obj1, const mirror::Object* obj2)
+ bool operator()(mirror::Object* obj1, mirror::Object* obj2)
// TODO: enable analysis when analysis can work with the STL.
NO_THREAD_SAFETY_ANALYSIS {
Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
@@ -105,7 +105,7 @@ struct ObjectComparator {
// Pass in the number of elements in the array (or 0 if this is not an
// array object), and the number of additional objects that are identical
// or equivalent to the original.
-static void DumpSummaryLine(std::ostream& os, const mirror::Object* obj, size_t element_count,
+static void DumpSummaryLine(std::ostream& os, mirror::Object* obj, size_t element_count,
int identical, int equiv)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (obj == NULL) {
@@ -159,7 +159,7 @@ void ReferenceTable::Dump(std::ostream& os, const Table& entries) {
}
os << " Last " << (count - first) << " entries (of " << count << "):\n";
for (int idx = count - 1; idx >= first; --idx) {
- const mirror::Object* ref = entries[idx];
+ mirror::Object* ref = entries[idx];
if (ref == NULL) {
continue;
}
@@ -212,8 +212,8 @@ void ReferenceTable::Dump(std::ostream& os, const Table& entries) {
size_t equiv = 0;
size_t identical = 0;
for (size_t idx = 1; idx < count; idx++) {
- const mirror::Object* prev = sorted_entries[idx-1];
- const mirror::Object* current = sorted_entries[idx];
+ mirror::Object* prev = sorted_entries[idx-1];
+ mirror::Object* current = sorted_entries[idx];
size_t element_count = GetElementCount(prev);
if (current == prev) {
// Same reference, added more than once.
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index bcd3d31..4e90478 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -31,6 +31,7 @@
#include "arch/arm/registers_arm.h"
#include "arch/mips/registers_mips.h"
#include "arch/x86/registers_x86.h"
+#include "arch/x86_64/registers_x86_64.h"
#include "atomic.h"
#include "class_linker.h"
#include "debugger.h"
@@ -75,19 +76,27 @@ Runtime::Runtime()
is_zygote_(false),
is_concurrent_gc_enabled_(true),
is_explicit_gc_disabled_(false),
+ compiler_filter_(kSpeed),
+ huge_method_threshold_(0),
+ large_method_threshold_(0),
+ small_method_threshold_(0),
+ tiny_method_threshold_(0),
+ num_dex_methods_threshold_(0),
+ sea_ir_mode_(false),
default_stack_size_(0),
- heap_(NULL),
+ heap_(nullptr),
max_spins_before_thin_lock_inflation_(Monitor::kDefaultMaxSpinsBeforeThinLockInflation),
- monitor_list_(NULL),
- thread_list_(NULL),
- intern_table_(NULL),
- class_linker_(NULL),
- signal_catcher_(NULL),
- java_vm_(NULL),
- pre_allocated_OutOfMemoryError_(NULL),
- resolution_method_(NULL),
- imt_conflict_method_(NULL),
- default_imt_(NULL),
+ monitor_list_(nullptr),
+ monitor_pool_(nullptr),
+ thread_list_(nullptr),
+ intern_table_(nullptr),
+ class_linker_(nullptr),
+ signal_catcher_(nullptr),
+ java_vm_(nullptr),
+ pre_allocated_OutOfMemoryError_(nullptr),
+ resolution_method_(nullptr),
+ imt_conflict_method_(nullptr),
+ default_imt_(nullptr),
method_verifiers_lock_("Method verifiers lock"),
threads_being_born_(0),
shutdown_cond_(new ConditionVariable("Runtime shutdown", *Locks::runtime_shutdown_lock_)),
@@ -95,19 +104,25 @@ Runtime::Runtime()
shutting_down_started_(false),
started_(false),
finished_starting_(false),
- vfprintf_(NULL),
- exit_(NULL),
- abort_(NULL),
+ vfprintf_(nullptr),
+ exit_(nullptr),
+ abort_(nullptr),
stats_enabled_(false),
- method_trace_(0),
+ profile_(false),
+ profile_period_s_(0),
+ profile_duration_s_(0),
+ profile_interval_us_(0),
+ profile_backoff_coefficient_(0),
+ method_trace_(false),
method_trace_file_size_(0),
instrumentation_(),
use_compile_time_class_path_(false),
- main_thread_group_(NULL),
- system_thread_group_(NULL),
- system_class_loader_(NULL) {
+ main_thread_group_(nullptr),
+ system_thread_group_(nullptr),
+ system_class_loader_(nullptr),
+ dump_gc_performance_on_shutdown_(false) {
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
- callee_save_methods_[i] = NULL;
+ callee_save_methods_[i] = nullptr;
}
}
@@ -141,6 +156,7 @@ Runtime::~Runtime() {
// Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
delete thread_list_;
delete monitor_list_;
+ delete monitor_pool_;
delete class_linker_;
delete heap_;
delete intern_table_;
@@ -149,8 +165,8 @@ Runtime::~Runtime() {
QuasiAtomic::Shutdown();
verifier::MethodVerifier::Shutdown();
// TODO: acquire a static mutex on Runtime to avoid racing.
- CHECK(instance_ == NULL || instance_ == this);
- instance_ = NULL;
+ CHECK(instance_ == nullptr || instance_ == this);
+ instance_ = nullptr;
}
struct AbortState {
@@ -976,6 +992,7 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
max_spins_before_thin_lock_inflation_ = options->max_spins_before_thin_lock_inflation_;
monitor_list_ = new MonitorList;
+ monitor_pool_ = MonitorPool::Create();
thread_list_ = new ThreadList;
intern_table_ = new InternTable;
@@ -1345,40 +1362,53 @@ mirror::ObjectArray<mirror::ArtMethod>* Runtime::CreateDefaultImt(ClassLinker* c
mirror::ArtMethod* Runtime::CreateImtConflictMethod() {
Thread* self = Thread::Current();
- Runtime* r = Runtime::Current();
- ClassLinker* cl = r->GetClassLinker();
- SirtRef<mirror::ArtMethod> method(self, cl->AllocArtMethod(self));
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ SirtRef<mirror::ArtMethod> method(self, class_linker->AllocArtMethod(self));
method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
- // TODO: use a special method for imt conflict method saves
+ // TODO: use a special method for imt conflict method saves.
method->SetDexMethodIndex(DexFile::kDexNoIndex);
// When compiling, the code pointer will get set later when the image is loaded.
- method->SetEntryPointFromCompiledCode(r->IsCompiler() ? NULL : GetImtConflictTrampoline(cl));
+ if (runtime->IsCompiler()) {
+ method->SetEntryPointFromPortableCompiledCode(nullptr);
+ method->SetEntryPointFromQuickCompiledCode(nullptr);
+ } else {
+ method->SetEntryPointFromPortableCompiledCode(GetPortableImtConflictTrampoline(class_linker));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickImtConflictTrampoline(class_linker));
+ }
return method.get();
}
mirror::ArtMethod* Runtime::CreateResolutionMethod() {
Thread* self = Thread::Current();
- Runtime* r = Runtime::Current();
- ClassLinker* cl = r->GetClassLinker();
- SirtRef<mirror::ArtMethod> method(self, cl->AllocArtMethod(self));
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ SirtRef<mirror::ArtMethod> method(self, class_linker->AllocArtMethod(self));
method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
// TODO: use a special method for resolution method saves
method->SetDexMethodIndex(DexFile::kDexNoIndex);
// When compiling, the code pointer will get set later when the image is loaded.
- method->SetEntryPointFromCompiledCode(r->IsCompiler() ? NULL : GetResolutionTrampoline(cl));
+ if (runtime->IsCompiler()) {
+ method->SetEntryPointFromPortableCompiledCode(nullptr);
+ method->SetEntryPointFromQuickCompiledCode(nullptr);
+ } else {
+ method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline(class_linker));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline(class_linker));
+ }
return method.get();
}
mirror::ArtMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set,
CalleeSaveType type) {
Thread* self = Thread::Current();
- Runtime* r = Runtime::Current();
- ClassLinker* cl = r->GetClassLinker();
- SirtRef<mirror::ArtMethod> method(self, cl->AllocArtMethod(self));
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ SirtRef<mirror::ArtMethod> method(self, class_linker->AllocArtMethod(self));
method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
// TODO: use a special method for callee saves
method->SetDexMethodIndex(DexFile::kDexNoIndex);
- method->SetEntryPointFromCompiledCode(NULL);
+ method->SetEntryPointFromPortableCompiledCode(nullptr);
+ method->SetEntryPointFromQuickCompiledCode(nullptr);
if ((instruction_set == kThumb2) || (instruction_set == kArm)) {
uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6) | (1 << art::arm::R7) |
(1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
@@ -1428,8 +1458,23 @@ mirror::ArtMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_se
method->SetFrameSizeInBytes(frame_size);
method->SetCoreSpillMask(core_spills);
method->SetFpSpillMask(0);
+ } else if (instruction_set == kX86_64) {
+ uint32_t ref_spills =
+ (1 << art::x86_64::RBP) | (1 << art::x86_64::RSI) | (1 << art::x86_64::RDI) |
+ (1 << art::x86_64::R8) | (1 << art::x86_64::R9) | (1 << art::x86_64::R10) |
+ (1 << art::x86_64::R11) | (1 << art::x86_64::R12) | (1 << art::x86_64::R13) |
+ (1 << art::x86_64::R14) | (1 << art::x86_64::R15);
+ uint32_t arg_spills =
+ (1 << art::x86_64::RCX) | (1 << art::x86_64::RDX) | (1 << art::x86_64::RBX);
+ uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
+ (1 << art::x86::kNumberOfCpuRegisters); // fake return address callee save
+ size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
+ 1 /* Method* */) * kPointerSize, kStackAlignment);
+ method->SetFrameSizeInBytes(frame_size);
+ method->SetCoreSpillMask(core_spills);
+ method->SetFpSpillMask(0);
} else {
- UNIMPLEMENTED(FATAL);
+ UNIMPLEMENTED(FATAL) << instruction_set;
}
return method.get();
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 9d48631..557ba2c 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -61,6 +61,7 @@ class DexFile;
class InternTable;
struct JavaVMExt;
class MonitorList;
+class MonitorPool;
class SignalCatcher;
class ThreadList;
class Trace;
@@ -314,6 +315,10 @@ class Runtime {
return monitor_list_;
}
+ MonitorPool* GetMonitorPool() const {
+ return monitor_pool_;
+ }
+
mirror::Throwable* GetPreAllocatedOutOfMemoryError() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -524,6 +529,7 @@ class Runtime {
// The number of spins that are done before thread suspension is used to forcibly inflate.
size_t max_spins_before_thin_lock_inflation_;
MonitorList* monitor_list_;
+ MonitorPool* monitor_pool_;
ThreadList* thread_list_;
diff --git a/runtime/runtime_linux.cc b/runtime/runtime_linux.cc
index 47b72e9..d8f408a 100644
--- a/runtime/runtime_linux.cc
+++ b/runtime/runtime_linux.cc
@@ -133,7 +133,7 @@ struct UContext {
void Dump(std::ostream& os) {
// TODO: support non-x86 hosts (not urgent because this code doesn't run on targets).
-#if defined(__APPLE__)
+#if defined(__APPLE__) && defined(__i386__)
DumpRegister32(os, "eax", context->__ss.__eax);
DumpRegister32(os, "ebx", context->__ss.__ebx);
DumpRegister32(os, "ecx", context->__ss.__ecx);
@@ -159,7 +159,7 @@ struct UContext {
os << '\n';
DumpRegister32(os, "gs", context->__ss.__gs);
DumpRegister32(os, "ss", context->__ss.__ss);
-#else
+#elif defined(__linux__) && defined(__i386__)
DumpRegister32(os, "eax", context.gregs[REG_EAX]);
DumpRegister32(os, "ebx", context.gregs[REG_EBX]);
DumpRegister32(os, "ecx", context.gregs[REG_ECX]);
@@ -185,6 +185,8 @@ struct UContext {
os << '\n';
DumpRegister32(os, "gs", context.gregs[REG_GS]);
DumpRegister32(os, "ss", context.gregs[REG_SS]);
+#else
+ os << "Unknown architecture/word size/OS in ucontext dump";
#endif
}
diff --git a/runtime/sirt_ref.h b/runtime/sirt_ref.h
index 56d81ec..3c5e4f8 100644
--- a/runtime/sirt_ref.h
+++ b/runtime/sirt_ref.h
@@ -35,13 +35,17 @@ class SirtRef {
DCHECK_EQ(top_sirt, &sirt_);
}
- T& operator*() const { return *get(); }
- T* operator->() const { return get(); }
- T* get() const {
+ T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return *get();
+ }
+ T* operator->() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return get();
+ }
+ T* get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return down_cast<T*>(sirt_.GetReference(0));
}
- void reset(T* object = NULL) {
+ void reset(T* object = nullptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
sirt_.SetReference(0, object);
}
diff --git a/runtime/stack.cc b/runtime/stack.cc
index e583ced..fd7d981 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -75,7 +75,7 @@ size_t ManagedStack::NumJniShadowFrameReferences() const {
return count;
}
-bool ManagedStack::ShadowFramesContain(mirror::Object** shadow_frame_entry) const {
+bool ManagedStack::ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const {
for (const ManagedStack* current_fragment = this; current_fragment != NULL;
current_fragment = current_fragment->GetLink()) {
for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != NULL;
@@ -251,7 +251,7 @@ std::string StackVisitor::DescribeLocation() const {
return "upcall";
}
result += PrettyMethod(m);
- result += StringPrintf("' at dex PC 0x%04zx", GetDexPc());
+ result += StringPrintf("' at dex PC 0x%04x", GetDexPc());
if (!IsShadowFrame()) {
result += StringPrintf(" (native PC %p)", reinterpret_cast<void*>(GetCurrentQuickFramePc()));
}
@@ -264,23 +264,23 @@ instrumentation::InstrumentationStackFrame& StackVisitor::GetInstrumentationStac
}
void StackVisitor::SanityCheckFrame() const {
-#ifndef NDEBUG
- mirror::ArtMethod* method = GetMethod();
- CHECK(method->GetClass() == mirror::ArtMethod::GetJavaLangReflectArtMethod());
- if (cur_quick_frame_ != NULL) {
- method->AssertPcIsWithinCode(cur_quick_frame_pc_);
- // Frame sanity.
- size_t frame_size = method->GetFrameSizeInBytes();
- CHECK_NE(frame_size, 0u);
- // A rough guess at an upper size we expect to see for a frame. The 256 is
- // a dex register limit. The 16 incorporates callee save spills and
- // outgoing argument set up.
- const size_t kMaxExpectedFrameSize = 256 * sizeof(word) + 16;
- CHECK_LE(frame_size, kMaxExpectedFrameSize);
- size_t return_pc_offset = method->GetReturnPcOffsetInBytes();
- CHECK_LT(return_pc_offset, frame_size);
+ if (kIsDebugBuild) {
+ mirror::ArtMethod* method = GetMethod();
+ CHECK(method->GetClass() == mirror::ArtMethod::GetJavaLangReflectArtMethod());
+ if (cur_quick_frame_ != nullptr) {
+ method->AssertPcIsWithinQuickCode(cur_quick_frame_pc_);
+ // Frame sanity.
+ size_t frame_size = method->GetFrameSizeInBytes();
+ CHECK_NE(frame_size, 0u);
+ // A rough guess at an upper size we expect to see for a frame. The 256 is
+ // a dex register limit. The 16 incorporates callee save spills and
+ // outgoing argument set up.
+ const size_t kMaxExpectedFrameSize = 256 * sizeof(word) + 16;
+ CHECK_LE(frame_size, kMaxExpectedFrameSize);
+ size_t return_pc_offset = method->GetReturnPcOffsetInBytes();
+ CHECK_LT(return_pc_offset, frame_size);
+ }
}
-#endif
}
void StackVisitor::WalkStack(bool include_transitions) {
diff --git a/runtime/stack.h b/runtime/stack.h
index 0692390..8466069 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -19,8 +19,10 @@
#include "dex_file.h"
#include "instrumentation.h"
+#include "base/casts.h"
#include "base/macros.h"
#include "arch/context.h"
+#include "mirror/object_reference.h"
#include <stdint.h>
#include <string>
@@ -96,16 +98,33 @@ enum VRegBaseRegNum : int {
kVRegNonSpecialTempBaseReg = -3,
};
+// A reference from the shadow stack to a MirrorType object within the Java heap.
+template<class MirrorType>
+class MANAGED StackReference : public mirror::ObjectReference<false, MirrorType> {
+ public:
+ StackReference<MirrorType>() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : mirror::ObjectReference<false, MirrorType>(nullptr) {}
+
+ static StackReference<MirrorType> FromMirrorPtr(MirrorType* p)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return StackReference<MirrorType>(p);
+ }
+
+ private:
+ StackReference<MirrorType>(MirrorType* p) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : mirror::ObjectReference<false, MirrorType>(p) {}
+};
+
// ShadowFrame has 3 possible layouts:
// - portable - a unified array of VRegs and references. Precise references need GC maps.
// - interpreter - separate VRegs and reference arrays. References are in the reference array.
// - JNI - just VRegs, but where every VReg holds a reference.
class ShadowFrame {
public:
- // Compute size of ShadowFrame in bytes.
+ // Compute size of ShadowFrame in bytes assuming it has a reference array.
static size_t ComputeSize(uint32_t num_vregs) {
return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) +
- (sizeof(mirror::Object*) * num_vregs);
+ (sizeof(StackReference<mirror::Object>) * num_vregs);
}
// Create ShadowFrame in heap for deoptimization.
@@ -195,22 +214,19 @@ class ShadowFrame {
}
template <bool kChecked = false>
- mirror::Object* GetVRegReference(size_t i) const {
+ mirror::Object* GetVRegReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, NumberOfVRegs());
if (HasReferenceArray()) {
- mirror::Object* ref = References()[i];
+ mirror::Object* ref = References()[i].AsMirrorPtr();
if (kChecked) {
CHECK(VerifyReference(ref)) << "VReg " << i << "(" << ref
<< ") is in protected space, reference array " << true;
}
- // If the vreg reference is not equal to the vreg then the vreg reference is stale.
- if (UNLIKELY(reinterpret_cast<uint32_t>(ref) != vregs_[i])) {
- return nullptr;
- }
return ref;
} else {
- const uint32_t* vreg = &vregs_[i];
- mirror::Object* ref = *reinterpret_cast<mirror::Object* const*>(vreg);
+ const uint32_t* vreg_ptr = &vregs_[i];
+ mirror::Object* ref =
+ reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr();
if (kChecked) {
CHECK(VerifyReference(ref)) << "VReg " << i
<< "(" << ref << ") is in protected space, reference array " << false;
@@ -231,7 +247,7 @@ class ShadowFrame {
// This is needed for moving collectors since these can update the vreg references if they
// happen to agree with references in the reference array.
if (kMovingCollector && HasReferenceArray()) {
- References()[i] = nullptr;
+ References()[i].Clear();
}
}
@@ -242,7 +258,7 @@ class ShadowFrame {
// This is needed for moving collectors since these can update the vreg references if they
// happen to agree with references in the reference array.
if (kMovingCollector && HasReferenceArray()) {
- References()[i] = nullptr;
+ References()[i].Clear();
}
}
@@ -255,8 +271,8 @@ class ShadowFrame {
// This is needed for moving collectors since these can update the vreg references if they
// happen to agree with references in the reference array.
if (kMovingCollector && HasReferenceArray()) {
- References()[i] = nullptr;
- References()[i + 1] = nullptr;
+ References()[i].Clear();
+ References()[i + 1].Clear();
}
}
@@ -269,24 +285,24 @@ class ShadowFrame {
// This is needed for moving collectors since these can update the vreg references if they
// happen to agree with references in the reference array.
if (kMovingCollector && HasReferenceArray()) {
- References()[i] = nullptr;
- References()[i + 1] = nullptr;
+ References()[i].Clear();
+ References()[i + 1].Clear();
}
}
- void SetVRegReference(size_t i, mirror::Object* val) {
+ void SetVRegReference(size_t i, mirror::Object* val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, NumberOfVRegs());
DCHECK(!kMovingCollector || VerifyReference(val))
<< "VReg " << i << "(" << val << ") is in protected space";
uint32_t* vreg = &vregs_[i];
- *reinterpret_cast<mirror::Object**>(vreg) = val;
+ reinterpret_cast<StackReference<mirror::Object>*>(vreg)->Assign(val);
if (HasReferenceArray()) {
- References()[i] = val;
+ References()[i].Assign(val);
}
}
- mirror::ArtMethod* GetMethod() const {
- DCHECK_NE(method_, static_cast<void*>(NULL));
+ mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(method_ != nullptr);
return method_;
}
@@ -298,7 +314,7 @@ class ShadowFrame {
void SetMethod(mirror::ArtMethod* method) {
#if defined(ART_USE_PORTABLE_COMPILER)
- DCHECK_NE(method, static_cast<void*>(NULL));
+ DCHECK(method != nullptr);
method_ = method;
#else
UNUSED(method);
@@ -306,7 +322,7 @@ class ShadowFrame {
#endif
}
- bool Contains(mirror::Object** shadow_frame_entry_obj) const {
+ bool Contains(StackReference<mirror::Object>* shadow_frame_entry_obj) const {
if (HasReferenceArray()) {
return ((&References()[0] <= shadow_frame_entry_obj) &&
(shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1])));
@@ -346,22 +362,22 @@ class ShadowFrame {
CHECK_LT(num_vregs, static_cast<uint32_t>(kHasReferenceArray));
number_of_vregs_ |= kHasReferenceArray;
#endif
- memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(mirror::Object*)));
+ memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(StackReference<mirror::Object>)));
} else {
memset(vregs_, 0, num_vregs * sizeof(uint32_t));
}
}
- mirror::Object* const* References() const {
+ const StackReference<mirror::Object>* References() const {
DCHECK(HasReferenceArray());
const uint32_t* vreg_end = &vregs_[NumberOfVRegs()];
- return reinterpret_cast<mirror::Object* const*>(vreg_end);
+ return reinterpret_cast<const StackReference<mirror::Object>*>(vreg_end);
}
bool VerifyReference(const mirror::Object* val) const;
- mirror::Object** References() {
- return const_cast<mirror::Object**>(const_cast<const ShadowFrame*>(this)->References());
+ StackReference<mirror::Object>* References() {
+ return const_cast<StackReference<mirror::Object>*>(const_cast<const ShadowFrame*>(this)->References());
}
#if defined(ART_USE_PORTABLE_COMPILER)
@@ -470,9 +486,9 @@ class PACKED(4) ManagedStack {
return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_);
}
- size_t NumJniShadowFrameReferences() const;
+ size_t NumJniShadowFrameReferences() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool ShadowFramesContain(mirror::Object** shadow_frame_entry) const;
+ bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const;
private:
ManagedStack* link_;
@@ -494,18 +510,18 @@ class StackVisitor {
void WalkStack(bool include_transitions = false)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtMethod* GetMethod() const {
- if (cur_shadow_frame_ != NULL) {
+ mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (cur_shadow_frame_ != nullptr) {
return cur_shadow_frame_->GetMethod();
- } else if (cur_quick_frame_ != NULL) {
+ } else if (cur_quick_frame_ != nullptr) {
return *cur_quick_frame_;
} else {
- return NULL;
+ return nullptr;
}
}
bool IsShadowFrame() const {
- return cur_shadow_frame_ != NULL;
+ return cur_shadow_frame_ != nullptr;
}
uint32_t GetDexPc() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -514,9 +530,10 @@ class StackVisitor {
size_t GetNativePcOffset() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uintptr_t* CalleeSaveAddress(int num, size_t frame_size) const {
+ uintptr_t* CalleeSaveAddress(int num, size_t frame_size) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Callee saves are held at the top of the frame
- DCHECK(GetMethod() != NULL);
+ DCHECK(GetMethod() != nullptr);
byte* save_addr =
reinterpret_cast<byte*>(cur_quick_frame_) + frame_size - ((num + 1) * kPointerSize);
#if defined(__i386__)
@@ -553,17 +570,17 @@ class StackVisitor {
// This is a fast-path for getting/setting values in a quick frame.
uint32_t* GetVRegAddr(mirror::ArtMethod** cur_quick_frame, const DexFile::CodeItem* code_item,
- uint32_t core_spills, uint32_t fp_spills, size_t frame_size,
- uint16_t vreg) const {
+ uint32_t core_spills, uint32_t fp_spills, size_t frame_size,
+ uint16_t vreg) const {
int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
DCHECK_EQ(cur_quick_frame, GetCurrentQuickFrame());
byte* vreg_addr = reinterpret_cast<byte*>(cur_quick_frame) + offset;
return reinterpret_cast<uint32_t*>(vreg_addr);
}
- uintptr_t GetReturnPc() const;
+ uintptr_t GetReturnPc() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetReturnPc(uintptr_t new_ret_pc);
+ void SetReturnPc(uintptr_t new_ret_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*
* Return sp-relative offset for a Dalvik virtual register, compiler
diff --git a/runtime/stack_indirect_reference_table.h b/runtime/stack_indirect_reference_table.h
index 4c9b038..d22650b 100644
--- a/runtime/stack_indirect_reference_table.h
+++ b/runtime/stack_indirect_reference_table.h
@@ -19,6 +19,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "stack.h"
namespace art {
namespace mirror {
@@ -33,7 +34,7 @@ class StackIndirectReferenceTable {
public:
explicit StackIndirectReferenceTable(mirror::Object* object) :
number_of_references_(1), link_(NULL) {
- references_[0] = object;
+ references_[0].Assign(object);
}
~StackIndirectReferenceTable() {}
@@ -53,17 +54,17 @@ class StackIndirectReferenceTable {
link_ = sirt;
}
- mirror::Object* GetReference(size_t i) const {
+ mirror::Object* GetReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, number_of_references_);
- return references_[i];
+ return references_[i].AsMirrorPtr();
}
- void SetReference(size_t i, mirror::Object* object) {
+ void SetReference(size_t i, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, number_of_references_);
- references_[i] = object;
+ references_[i].Assign(object);
}
- bool Contains(mirror::Object** sirt_entry) const {
+ bool Contains(StackReference<mirror::Object>* sirt_entry) const {
// A SIRT should always contain something. One created by the
// jni_compiler should have a jobject/jclass as a native method is
// passed in a this pointer or a class
@@ -89,7 +90,7 @@ class StackIndirectReferenceTable {
StackIndirectReferenceTable* link_;
// number_of_references_ are available if this is allocated and filled in by jni_compiler.
- mirror::Object* references_[1];
+ StackReference<mirror::Object> references_[1];
DISALLOW_COPY_AND_ASSIGN(StackIndirectReferenceTable);
};
diff --git a/runtime/thread.cc b/runtime/thread.cc
index c3ef228..c649765 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -178,7 +178,7 @@ void* Thread::CreateCallback(void* arg) {
receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
JValue result;
ArgArray arg_array(nullptr, 0);
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
m->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
}
// Detach and delete self.
@@ -190,7 +190,7 @@ void* Thread::CreateCallback(void* arg) {
Thread* Thread::FromManagedThread(const ScopedObjectAccessUnchecked& soa,
mirror::Object* thread_peer) {
mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer);
- Thread* result = reinterpret_cast<Thread*>(static_cast<uintptr_t>(f->GetInt(thread_peer)));
+ Thread* result = reinterpret_cast<Thread*>(static_cast<uintptr_t>(f->GetLong(thread_peer)));
// Sanity check that if we have a result it is either suspended or we hold the thread_list_lock_
// to stop it from going away.
if (kIsDebugBuild) {
@@ -260,8 +260,8 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz
// Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing to
// assign it.
- env->SetIntField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
- reinterpret_cast<jint>(child_thread));
+ env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
+ reinterpret_cast<jlong>(child_thread));
pthread_t new_pthread;
pthread_attr_t attr;
@@ -283,7 +283,7 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz
delete child_thread;
child_thread = nullptr;
// TODO: remove from thread group?
- env->SetIntField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
+ env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
{
std::string msg(StringPrintf("pthread_create (%s stack) failed: %s",
PrettySize(stack_size).c_str(), strerror(pthread_create_result)));
@@ -388,8 +388,8 @@ void Thread::CreatePeer(const char* name, bool as_daemon, jobject thread_group)
Thread* self = this;
DCHECK_EQ(self, Thread::Current());
- jni_env_->SetIntField(peer.get(), WellKnownClasses::java_lang_Thread_nativePeer,
- reinterpret_cast<jint>(self));
+ jni_env_->SetLongField(peer.get(), WellKnownClasses::java_lang_Thread_nativePeer,
+ reinterpret_cast<jlong>(self));
ScopedObjectAccess soa(self);
SirtRef<mirror::String> peer_thread_name(soa.Self(), GetThreadName(soa));
@@ -767,7 +767,7 @@ struct StackDumpVisitor : public StackVisitor {
}
const int kMaxRepetition = 3;
mirror::Class* c = m->GetDeclaringClass();
- const mirror::DexCache* dex_cache = c->GetDexCache();
+ mirror::DexCache* dex_cache = c->GetDexCache();
int line_number = -1;
if (dex_cache != nullptr) { // be tolerant of bad input
const DexFile& dex_file = *dex_cache->GetDexFile();
@@ -1017,7 +1017,7 @@ void Thread::Destroy() {
RemoveFromThreadGroup(soa);
// this.nativePeer = 0;
- soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer)->SetInt(opeer_, 0);
+ soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer)->SetLong(opeer_, 0);
Dbg::PostThreadDeath(self);
// Thread.join() is implemented as an Object.wait() on the Thread.lock object. Signal anyone
@@ -1133,7 +1133,8 @@ size_t Thread::NumSirtReferences() {
}
bool Thread::SirtContains(jobject obj) const {
- mirror::Object** sirt_entry = reinterpret_cast<mirror::Object**>(obj);
+ StackReference<mirror::Object>* sirt_entry =
+ reinterpret_cast<StackReference<mirror::Object>*>(obj);
for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) {
if (cur->Contains(sirt_entry)) {
return true;
@@ -1172,10 +1173,11 @@ mirror::Object* Thread::DecodeJObject(jobject obj) const {
IndirectReferenceTable& locals = jni_env_->locals;
result = const_cast<mirror::Object*>(locals.Get(ref));
} else if (kind == kSirtOrInvalid) {
- // TODO: make stack indirect reference table lookup more efficient
- // Check if this is a local reference in the SIRT
+ // TODO: make stack indirect reference table lookup more efficient.
+ // Check if this is a local reference in the SIRT.
if (LIKELY(SirtContains(obj))) {
- result = *reinterpret_cast<mirror::Object**>(obj); // Read from SIRT
+ // Read from SIRT.
+ result = reinterpret_cast<StackReference<mirror::Object>*>(obj)->AsMirrorPtr();
} else if (Runtime::Current()->GetJavaVM()->work_around_app_jni_bugs) {
// Assume an invalid local reference is actually a direct pointer.
result = reinterpret_cast<mirror::Object*>(obj);
@@ -1569,12 +1571,12 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
SetException(gc_safe_throw_location, exception.get());
} else {
ArgArray args("VLL", 3);
- args.Append(reinterpret_cast<uint32_t>(exception.get()));
+ args.Append(exception.get());
if (msg != nullptr) {
- args.Append(reinterpret_cast<uint32_t>(msg_string.get()));
+ args.Append(msg_string.get());
}
if (cause.get() != nullptr) {
- args.Append(reinterpret_cast<uint32_t>(cause.get()));
+ args.Append(cause.get());
}
JValue result;
exception_init_method->Invoke(this, args.GetArray(), args.GetNumBytes(), &result, 'V');
@@ -1920,13 +1922,13 @@ class ReferenceMapVisitor : public StackVisitor {
}
}
} else {
- uint32_t* reg_addr =
- GetVRegAddr(cur_quick_frame, code_item, core_spills, fp_spills, frame_size, reg);
+ uintptr_t* reg_addr = reinterpret_cast<uintptr_t*>(
+ GetVRegAddr(cur_quick_frame, code_item, core_spills, fp_spills, frame_size, reg));
mirror::Object* ref = reinterpret_cast<mirror::Object*>(*reg_addr);
if (ref != nullptr) {
mirror::Object* new_ref = visitor_(ref, reg, this);
if (ref != new_ref) {
- *reg_addr = reinterpret_cast<uint32_t>(new_ref);
+ *reg_addr = reinterpret_cast<uintptr_t>(new_ref);
}
}
}
diff --git a/runtime/thread.h b/runtime/thread.h
index 4a37ca0..b7f8bb0 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -487,23 +487,23 @@ class PACKED(4) Thread {
ManagedStack::TopShadowFrameOffset());
}
- // Number of references allocated in JNI ShadowFrames on this thread
- size_t NumJniShadowFrameReferences() const {
+ // Number of references allocated in JNI ShadowFrames on this thread.
+ size_t NumJniShadowFrameReferences() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return managed_stack_.NumJniShadowFrameReferences();
}
- // Number of references in SIRTs on this thread
+ // Number of references in SIRTs on this thread.
size_t NumSirtReferences();
- // Number of references allocated in SIRTs & JNI shadow frames on this thread
- size_t NumStackReferences() {
+ // Number of references allocated in SIRTs & JNI shadow frames on this thread.
+ size_t NumStackReferences() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return NumSirtReferences() + NumJniShadowFrameReferences();
};
// Is the given obj in this thread's stack indirect reference table?
bool SirtContains(jobject obj) const;
- void SirtVisitRoots(RootVisitor* visitor, void* arg);
+ void SirtVisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void PushSirt(StackIndirectReferenceTable* sirt) {
sirt->SetLink(top_sirt_);
@@ -788,7 +788,7 @@ class PACKED(4) Thread {
// A positive value implies we're in a region where thread suspension isn't expected.
uint32_t no_thread_suspension_;
- // Cause for last suspension.
+ // If no_thread_suspension_ is > 0, what is causing that assertion.
const char* last_no_thread_suspension_cause_;
// Maximum number of checkpoint functions.
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index aca0561..e8c9ff8 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -31,7 +31,7 @@ ThreadPoolWorker::ThreadPoolWorker(ThreadPool* thread_pool, const std::string& n
name_(name) {
std::string error_msg;
stack_.reset(MemMap::MapAnonymous(name.c_str(), nullptr, stack_size, PROT_READ | PROT_WRITE,
- &error_msg));
+ false, &error_msg));
CHECK(stack_.get() != nullptr) << error_msg;
const char* reason = "new thread pool worker thread";
pthread_attr_t attr;
diff --git a/runtime/thread_pool_test.cc b/runtime/thread_pool_test.cc
index 2029d4b..c6f0e92 100644
--- a/runtime/thread_pool_test.cc
+++ b/runtime/thread_pool_test.cc
@@ -17,7 +17,7 @@
#include <string>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "common_test.h"
#include "thread_pool.h"
diff --git a/runtime/trace.cc b/runtime/trace.cc
index b0f6e37..18185d4 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -89,7 +89,7 @@ class BuildStackTraceVisitor : public StackVisitor {
explicit BuildStackTraceVisitor(Thread* thread) : StackVisitor(thread, NULL),
method_trace_(Trace::AllocStackTrace()) {}
- bool VisitFrame() {
+ bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* m = GetMethod();
// Ignore runtime frames (in particular callee save).
if (!m->IsRuntimeMethod()) {
@@ -133,9 +133,9 @@ static TraceAction DecodeTraceAction(uint32_t tmid) {
return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
}
-static uint32_t EncodeTraceMethodAndAction(const mirror::ArtMethod* method,
+static uint32_t EncodeTraceMethodAndAction(mirror::ArtMethod* method,
TraceAction action) {
- uint32_t tmid = reinterpret_cast<uint32_t>(method) | action;
+ uint32_t tmid = PointerToLowMemUInt32(method) | action;
DCHECK_EQ(method, DecodeTraceMethodId(tmid));
return tmid;
}
@@ -298,7 +298,7 @@ void Trace::CompareAndUpdateStackTrace(Thread* thread,
void* Trace::RunSamplingThread(void* arg) {
Runtime* runtime = Runtime::Current();
- int interval_us = reinterpret_cast<int>(arg);
+ intptr_t interval_us = reinterpret_cast<intptr_t>(arg);
CHECK_GE(interval_us, 0);
CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
!runtime->IsCompiler()));
@@ -508,7 +508,7 @@ void Trace::FinishTracing() {
} else {
os << StringPrintf("clock=wall\n");
}
- os << StringPrintf("elapsed-time-usec=%llu\n", elapsed);
+ os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed);
size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_);
os << StringPrintf("num-method-calls=%zd\n", num_records);
os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns);
@@ -548,13 +548,13 @@ void Trace::FinishTracing() {
}
void Trace::DexPcMoved(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc) {
+ mirror::ArtMethod* method, uint32_t new_dex_pc) {
// We're not recorded to listen to this kind of event, so complain.
LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc;
};
void Trace::MethodEntered(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) {
+ mirror::ArtMethod* method, uint32_t dex_pc) {
uint32_t thread_clock_diff = 0;
uint32_t wall_clock_diff = 0;
ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
@@ -563,7 +563,7 @@ void Trace::MethodEntered(Thread* thread, mirror::Object* this_object,
}
void Trace::MethodExited(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc,
+ mirror::ArtMethod* method, uint32_t dex_pc,
const JValue& return_value) {
UNUSED(return_value);
uint32_t thread_clock_diff = 0;
@@ -574,7 +574,7 @@ void Trace::MethodExited(Thread* thread, mirror::Object* this_object,
}
void Trace::MethodUnwind(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) {
+ mirror::ArtMethod* method, uint32_t dex_pc) {
uint32_t thread_clock_diff = 0;
uint32_t wall_clock_diff = 0;
ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
@@ -605,7 +605,7 @@ void Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wa
}
}
-void Trace::LogMethodTraceEvent(Thread* thread, const mirror::ArtMethod* method,
+void Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
instrumentation::Instrumentation::InstrumentationEvent event,
uint32_t thread_clock_diff, uint32_t wall_clock_diff) {
// Advance cur_offset_ atomically.
diff --git a/runtime/trace.h b/runtime/trace.h
index 9be015a..d810df0 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -73,17 +73,17 @@ class Trace : public instrumentation::InstrumentationListener {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void MethodExited(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc,
+ mirror::ArtMethod* method, uint32_t dex_pc,
const JValue& return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc)
+ mirror::ArtMethod* method, uint32_t new_dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
@@ -105,7 +105,7 @@ class Trace : public instrumentation::InstrumentationListener {
void ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff);
- void LogMethodTraceEvent(Thread* thread, const mirror::ArtMethod* method,
+ void LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
instrumentation::Instrumentation::InstrumentationEvent event,
uint32_t thread_clock_diff, uint32_t wall_clock_diff);
diff --git a/runtime/utf.cc b/runtime/utf.cc
index 5ec2ea1..e48d6d2 100644
--- a/runtime/utf.cc
+++ b/runtime/utf.cc
@@ -68,7 +68,7 @@ void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t
}
}
-int32_t ComputeUtf16Hash(const mirror::CharArray* chars, int32_t offset,
+int32_t ComputeUtf16Hash(mirror::CharArray* chars, int32_t offset,
size_t char_count) {
int32_t hash = 0;
for (size_t i = 0; i < char_count; i++) {
diff --git a/runtime/utf.h b/runtime/utf.h
index cc5e6d4..5b2289e 100644
--- a/runtime/utf.h
+++ b/runtime/utf.h
@@ -73,7 +73,7 @@ void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t
/*
* The java.lang.String hashCode() algorithm.
*/
-int32_t ComputeUtf16Hash(const mirror::CharArray* chars, int32_t offset, size_t char_count)
+int32_t ComputeUtf16Hash(mirror::CharArray* chars, int32_t offset, size_t char_count)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
int32_t ComputeUtf16Hash(const uint16_t* chars, size_t char_count);
diff --git a/runtime/utils.cc b/runtime/utils.cc
index a293043..aad21bc 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -215,14 +215,14 @@ void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts
}
}
-std::string PrettyDescriptor(const mirror::String* java_descriptor) {
+std::string PrettyDescriptor(mirror::String* java_descriptor) {
if (java_descriptor == NULL) {
return "null";
}
return PrettyDescriptor(java_descriptor->ToModifiedUtf8());
}
-std::string PrettyDescriptor(const mirror::Class* klass) {
+std::string PrettyDescriptor(mirror::Class* klass) {
if (klass == NULL) {
return "null";
}
@@ -283,7 +283,7 @@ std::string PrettyDescriptor(Primitive::Type type) {
return PrettyDescriptor(descriptor_string);
}
-std::string PrettyField(const mirror::ArtField* f, bool with_type) {
+std::string PrettyField(mirror::ArtField* f, bool with_type) {
if (f == NULL) {
return "null";
}
@@ -358,7 +358,7 @@ std::string PrettyReturnType(const char* signature) {
return PrettyDescriptor(return_type);
}
-std::string PrettyMethod(const mirror::ArtMethod* m, bool with_signature) {
+std::string PrettyMethod(mirror::ArtMethod* m, bool with_signature) {
if (m == nullptr) {
return "null";
}
@@ -401,7 +401,7 @@ std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with
return result;
}
-std::string PrettyTypeOf(const mirror::Object* obj) {
+std::string PrettyTypeOf(mirror::Object* obj) {
if (obj == NULL) {
return "null";
}
@@ -417,7 +417,7 @@ std::string PrettyTypeOf(const mirror::Object* obj) {
return result;
}
-std::string PrettyClass(const mirror::Class* c) {
+std::string PrettyClass(mirror::Class* c) {
if (c == NULL) {
return "null";
}
@@ -428,7 +428,7 @@ std::string PrettyClass(const mirror::Class* c) {
return result;
}
-std::string PrettyClassAndClassLoader(const mirror::Class* c) {
+std::string PrettyClassAndClassLoader(mirror::Class* c) {
if (c == NULL) {
return "null";
}
@@ -445,7 +445,7 @@ std::string PrettyClassAndClassLoader(const mirror::Class* c) {
std::string PrettySize(int64_t byte_count) {
// The byte thresholds at which we display amounts. A byte count is displayed
// in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
- static const size_t kUnitThresholds[] = {
+ static const int64_t kUnitThresholds[] = {
0, // B up to...
3*1024, // KB up to...
2*1024*1024, // MB up to...
@@ -464,7 +464,7 @@ std::string PrettySize(int64_t byte_count) {
break;
}
}
- return StringPrintf("%s%lld%s", negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
+ return StringPrintf("%s%" PRId64 "%s", negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
}
std::string PrettyDuration(uint64_t nano_duration) {
@@ -534,18 +534,18 @@ std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit) {
uint64_t whole_part = nano_duration / divisor;
uint64_t fractional_part = nano_duration % divisor;
if (fractional_part == 0) {
- return StringPrintf("%llu%s", whole_part, unit);
+ return StringPrintf("%" PRIu64 "%s", whole_part, unit);
} else {
while ((fractional_part % 1000) == 0) {
zero_fill -= 3;
fractional_part /= 1000;
}
if (zero_fill == 3) {
- return StringPrintf("%llu.%03llu%s", whole_part, fractional_part, unit);
+ return StringPrintf("%" PRIu64 ".%03" PRIu64 "%s", whole_part, fractional_part, unit);
} else if (zero_fill == 6) {
- return StringPrintf("%llu.%06llu%s", whole_part, fractional_part, unit);
+ return StringPrintf("%" PRIu64 ".%06" PRIu64 "%s", whole_part, fractional_part, unit);
} else {
- return StringPrintf("%llu.%09llu%s", whole_part, fractional_part, unit);
+ return StringPrintf("%" PRIu64 ".%09" PRIu64 "%s", whole_part, fractional_part, unit);
}
}
}
@@ -627,7 +627,7 @@ std::string DescriptorToName(const char* descriptor) {
return descriptor;
}
-std::string JniShortName(const mirror::ArtMethod* m) {
+std::string JniShortName(mirror::ArtMethod* m) {
MethodHelper mh(m);
std::string class_name(mh.GetDeclaringClassDescriptor());
// Remove the leading 'L' and trailing ';'...
@@ -646,7 +646,7 @@ std::string JniShortName(const mirror::ArtMethod* m) {
return short_name;
}
-std::string JniLongName(const mirror::ArtMethod* m) {
+std::string JniLongName(mirror::ArtMethod* m) {
std::string long_name;
long_name += JniShortName(m);
long_name += "__";
diff --git a/runtime/utils.h b/runtime/utils.h
index f063c0a..e2d8966 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -166,8 +166,29 @@ static inline int CountOneBits(uint32_t x) {
return static_cast<int>(x & 0x0000003F);
}
-#define CLZ(x) __builtin_clz(x)
-#define CTZ(x) __builtin_ctz(x)
+template<typename T>
+static inline int CLZ(T x) {
+ if (sizeof(T) == sizeof(uint32_t)) {
+ return __builtin_clz(x);
+ } else {
+ return __builtin_clzll(x);
+ }
+}
+
+template<typename T>
+static inline int CTZ(T x) {
+ if (sizeof(T) == sizeof(uint32_t)) {
+ return __builtin_ctz(x);
+ } else {
+ return __builtin_ctzll(x);
+ }
+}
+
+static inline uint32_t PointerToLowMemUInt32(const void* p) {
+ uintptr_t intp = reinterpret_cast<uintptr_t>(p);
+ DCHECK_LE(intp, 0xFFFFFFFFU);
+ return intp & 0xFFFFFFFFU;
+}
static inline bool NeedsEscaping(uint16_t ch) {
return (ch < ' ' || ch > '~');
@@ -200,21 +221,22 @@ bool EndsWith(const std::string& s, const char* suffix);
// Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
// "[[I" would be "int[][]", "[Ljava/lang/String;" would be
// "java.lang.String[]", and so forth.
-std::string PrettyDescriptor(const mirror::String* descriptor);
+std::string PrettyDescriptor(mirror::String* descriptor)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string PrettyDescriptor(const std::string& descriptor);
std::string PrettyDescriptor(Primitive::Type type);
-std::string PrettyDescriptor(const mirror::Class* klass)
+std::string PrettyDescriptor(mirror::Class* klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a human-readable signature for 'f'. Something like "a.b.C.f" or
// "int a.b.C.f" (depending on the value of 'with_type').
-std::string PrettyField(const mirror::ArtField* f, bool with_type = true)
+std::string PrettyField(mirror::ArtField* f, bool with_type = true)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type = true);
// Returns a human-readable signature for 'm'. Something like "a.b.C.m" or
// "a.b.C.m(II)V" (depending on the value of 'with_signature').
-std::string PrettyMethod(const mirror::ArtMethod* m, bool with_signature = true)
+std::string PrettyMethod(mirror::ArtMethod* m, bool with_signature = true)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature = true);
@@ -222,7 +244,7 @@ std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with
// So given an instance of java.lang.String, the output would
// be "java.lang.String". Given an array of int, the output would be "int[]".
// Given String.class, the output would be "java.lang.Class<java.lang.String>".
-std::string PrettyTypeOf(const mirror::Object* obj)
+std::string PrettyTypeOf(mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a human-readable form of the type at an index in the specified dex file.
@@ -231,11 +253,11 @@ std::string PrettyType(uint32_t type_idx, const DexFile& dex_file);
// Returns a human-readable form of the name of the given class.
// Given String.class, the output would be "java.lang.Class<java.lang.String>".
-std::string PrettyClass(const mirror::Class* c)
+std::string PrettyClass(mirror::Class* c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a human-readable form of the name of the given class with its class loader.
-std::string PrettyClassAndClassLoader(const mirror::Class* c)
+std::string PrettyClassAndClassLoader(mirror::Class* c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a human-readable size string such as "1MB".
@@ -278,10 +300,10 @@ bool IsValidDescriptor(const char* s); // "Ljava/lang/String;"
bool IsValidMemberName(const char* s);
// Returns the JNI native function name for the non-overloaded method 'm'.
-std::string JniShortName(const mirror::ArtMethod* m)
+std::string JniShortName(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns the JNI native function name for the overloaded method 'm'.
-std::string JniLongName(const mirror::ArtMethod* m)
+std::string JniLongName(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool ReadFileToString(const std::string& file_name, std::string* result);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index d2681df..30be36c 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -85,7 +85,7 @@ PcToRegisterLineTable::~PcToRegisterLineTable() {
}
}
-MethodVerifier::FailureKind MethodVerifier::VerifyClass(const mirror::Class* klass,
+MethodVerifier::FailureKind MethodVerifier::VerifyClass(mirror::Class* klass,
bool allow_soft_failures,
std::string* error) {
if (klass->IsVerified()) {
@@ -837,7 +837,7 @@ bool MethodVerifier::CheckArrayData(uint32_t cur_offset) {
/* offset to array data table is a relative branch-style offset */
array_data = insns + array_data_offset;
/* make sure the table is 32-bit aligned */
- if ((((uint32_t) array_data) & 0x03) != 0) {
+ if ((reinterpret_cast<uintptr_t>(array_data) & 0x03) != 0) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unaligned array data table: at " << cur_offset
<< ", data offset " << array_data_offset;
return false;
@@ -941,7 +941,7 @@ bool MethodVerifier::CheckSwitchTargets(uint32_t cur_offset) {
/* offset to switch table is a relative branch-style offset */
const uint16_t* switch_insns = insns + switch_offset;
/* make sure the table is 32-bit aligned */
- if ((((uint32_t) switch_insns) & 0x03) != 0) {
+ if ((reinterpret_cast<uintptr_t>(switch_insns) & 0x03) != 0) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unaligned switch table: at " << cur_offset
<< ", switch offset " << switch_offset;
return false;
@@ -3616,10 +3616,9 @@ void MethodVerifier::VerifyISPut(const Instruction* inst, const RegType& insn_ty
// Look for an instance field with this offset.
// TODO: we may speed up the search if offsets are sorted by doing a quick search.
-static mirror::ArtField* FindInstanceFieldWithOffset(const mirror::Class* klass,
- uint32_t field_offset)
+static mirror::ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const mirror::ObjectArray<mirror::ArtField>* instance_fields = klass->GetIFields();
+ mirror::ObjectArray<mirror::ArtField>* instance_fields = klass->GetIFields();
if (instance_fields != NULL) {
for (int32_t i = 0, e = instance_fields->GetLength(); i < e; ++i) {
mirror::ArtField* field = instance_fields->Get(i);
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 053cee5..7c75c9c 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -140,8 +140,7 @@ class MethodVerifier {
};
/* Verify a class. Returns "kNoFailure" on success. */
- static FailureKind VerifyClass(const mirror::Class* klass, bool allow_soft_failures,
- std::string* error)
+ static FailureKind VerifyClass(mirror::Class* klass, bool allow_soft_failures, std::string* error)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static FailureKind VerifyClass(const DexFile* dex_file, SirtRef<mirror::DexCache>& dex_cache,
SirtRef<mirror::ClassLoader>& class_loader,
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 4be1d02..3818375 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -203,7 +203,7 @@ class RegType {
bool IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Primitive::Type GetPrimitiveType() const;
bool IsJavaLangObjectArray() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsInstantiableTypes() const;
+ bool IsInstantiableTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const std::string& GetDescriptor() const {
DCHECK(HasClass() || (IsUnresolvedTypes() && !IsUnresolvedMergedReference() &&
!IsUnresolvedSuperClass()));
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index e3946f7..546eb40 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -179,7 +179,7 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Thread_name = CacheField(env, java_lang_Thread, false, "name", "Ljava/lang/String;");
java_lang_Thread_priority = CacheField(env, java_lang_Thread, false, "priority", "I");
java_lang_Thread_uncaughtHandler = CacheField(env, java_lang_Thread, false, "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;");
- java_lang_Thread_nativePeer = CacheField(env, java_lang_Thread, false, "nativePeer", "I");
+ java_lang_Thread_nativePeer = CacheField(env, java_lang_Thread, false, "nativePeer", "J");
java_lang_ThreadGroup_mainThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "mainThreadGroup", "Ljava/lang/ThreadGroup;");
java_lang_ThreadGroup_name = CacheField(env, java_lang_ThreadGroup, false, "name", "Ljava/lang/String;");
java_lang_ThreadGroup_systemThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "systemThreadGroup", "Ljava/lang/ThreadGroup;");
diff --git a/runtime/zip_archive.cc b/runtime/zip_archive.cc
index 8cb1993..ba0b91e 100644
--- a/runtime/zip_archive.cc
+++ b/runtime/zip_archive.cc
@@ -55,7 +55,7 @@ MemMap* ZipEntry::ExtractToMemMap(const char* entry_filename, std::string* error
name += entry_filename;
UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(),
NULL, GetUncompressedLength(),
- PROT_READ | PROT_WRITE, error_msg));
+ PROT_READ | PROT_WRITE, false, error_msg));
if (map.get() == nullptr) {
DCHECK(!error_msg->empty());
return nullptr;