Object model changes to support 64bit.
Modify mirror objects so that references between them use an ObjectReference
value type rather than an Object* so that functionality to compress larger
references can be captured in the ObjectRefererence implementation.
ObjectReferences are 32bit and all other aspects of object layout remain as
they are currently.
Expand fields in objects holding pointers so they can hold 64bit pointers. Its
expected the size of these will come down by improving where we hold compiler
meta-data.
Stub out x86_64 architecture specific runtime implementation.
Modify OutputStream so that reads and writes are of unsigned quantities.
Make the use of portable or quick code more explicit.
Templatize AtomicInteger to support more than just int32_t as a type.
Add missing, and fix issues relating to, missing annotalysis information on the
mutator lock.
Refactor and share implementations for array copy between System and uses
elsewhere in the runtime.
Fix numerous 64bit build issues.
Change-Id: I1a5694c251a42c9eff71084dfdd4b51fff716822
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 @@
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 @@
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 @@
// 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 @@
}
}
-#if defined(ART_USE_PORTABLE_COMPILER)
const std::string& CompiledCode::GetSymbol() const {
CHECK_NE(0U, symbol_.size());
return symbol_;
@@ -114,18 +144,17 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
} 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 @@
}
}
-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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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::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 @@
// 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::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 @@
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 @@
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 @@
// 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 @@
? 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 @@
// 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 @@
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 @@
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::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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
} 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* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
+ if (compiled_method != NULL) {
+ 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 @@
}
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 @@
// 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 @@
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_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;
+ }
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;
- }
- 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 @@
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 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 @@
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 @@
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 @@
// 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 @@
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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
#elif defined(__mips__)
InstructionSet instruction_set = kMips;
#else
-#error "Unsupported architecture"
+ InstructionSet instruction_set = kNone;
#endif
@@ -777,6 +773,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
<< "': " << 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 @@
// 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 @@
}
}
{
+ 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 @@
}
}
+ 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));
}
- os << "\n";
+ } 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));
+ }
}
}
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 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
.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_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 @@
* [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 @@
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 @@
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::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 @@
: "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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
"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 @@
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 @@
*
* 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 @@
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 @@
}
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 @@
* 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 @@
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 @@
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 @@
*/
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 @@
*/
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 @@
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 @@
} 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 @@
} 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 @@
} 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 @@
}
} 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 @@
}
} 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 @@
}
} 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 @@
*/
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 @@
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 @@
* 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 @@
}
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 @@
*/
void CheckObject(jobject java_object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (java_object == NULL) {
+ if (java_object == nullptr) {
return;
}
@@ -752,7 +754,7 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
};
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 @@
};
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::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 @@
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::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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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).GetCode();
- if (result == NULL) {
- // No code? You must mean to go into the interpreter.
- result = GetCompiledCodeToInterpreterBridge();
+ 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();
+ }
}
return result;
}
-const void* ClassLinker::GetOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
- uint32_t method_idx) {
+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::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 @@
// 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 @@
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 @@
// 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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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::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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 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 @@
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 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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
*
* 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 @@
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 @@
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::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 @@
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::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 @@
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 @@
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 @@
// 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 @@
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 @@
*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 @@
<< 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 @@
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 @@
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 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 @@
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 @@
// 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 @@
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 @@
};
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 @@
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 @@
#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 @@
// 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 @@
// 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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
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 @@
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 @@
#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 @@
// 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* 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* 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" 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" 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" 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" 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" 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" 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 @@
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 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 @@
}
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 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 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 @@
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 @@
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 @@
}
}
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 @@
#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 @@
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 @@
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 @@
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 @@
};
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 @@
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;
+ 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 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
+ // 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);
+ // 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);
+ // 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);
+ // 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);
+ // 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
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
private:
ModUnionTableReferenceCache* const mod_union_table_;
- std::vector<Object**>* const references_;
+ std::vector<mirror::HeapReference<Object>*>* const references_;
};
class CheckReferenceVisitor {
@@ -173,7 +172,7 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
}
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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::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 @@
}
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 @@
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 @@
: 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_(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 @@
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 @@
// 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 @@
}
}
- 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 @@
// 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 @@
// 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 @@
}
}
} 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 @@
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 @@
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 @@
} 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
*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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
+ {
+ // 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
}
- 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
+
+ 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 @@
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 @@
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 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 @@
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 @@
// 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 @@
int AddU1(uint8_t value) {
int err = GuaranteeRecordAppend(1);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -253,13 +244,30 @@
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 @@
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 @@
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 @@
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 @@
HprofRecord* rec = ¤t_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 @@
// 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 @@
int WriteStringTable() {
HprofRecord* rec = ¤t_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 @@
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 @@
}
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
// 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 @@
nameId = LookupStringId("<ILLEGAL>");
break;
}
- rec->AddId(nameId);
+ rec->AddStringId(nameId);
current_heap_ = desiredHeap;
}
@@ -875,11 +888,11 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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::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 @@
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 @@
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 @@
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::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::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::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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
}
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 @@
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 @@
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 @@
++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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -264,12 +264,12 @@
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 @@
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 @@
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 @@
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 @@
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -547,7 +547,7 @@
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -603,7 +603,7 @@
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -668,7 +668,7 @@
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -1492,8 +1492,8 @@
} 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, GetObjectField_SetObjectField) {
+ TEST_DISABLED_FOR_PORTABLE();
Thread::Current()->TransitionFromSuspendedToRunnable();
LoadDex("AllFields");
runtime_->Start();
@@ -1553,7 +1554,6 @@
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 @@
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 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(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 @@
*
* |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 @@
#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 @@
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 @@
//
// 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 @@
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 @@
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 @@
}
}
+// 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 @@
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 @@
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 @@
}
}
- 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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_);
+ 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(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_);
+ // 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 @@
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 @@
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 void ArtMethod::AssertPcIsWithinCode(uintptr_t pc) const {
+inline void ArtMethod::AssertPcIsWithinQuickCode(uintptr_t pc) {
if (!kIsDebugBuild) {
return;
}
@@ -116,34 +117,44 @@
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 @@
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 @@
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 @@
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 @@
}
}
-InvokeType ArtMethod::GetInvokeType() const {
+InvokeType ArtMethod::GetInvokeType() {
// TODO: kSuper?
if (GetDeclaringClass()->IsInterface()) {
return kInterface;
@@ -100,11 +100,11 @@
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 @@
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 @@
}
}
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 @@
}
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 @@
}
} 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 @@
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 @@
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 @@
// 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::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 @@
// 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 @@
return MemberOffset(OFFSETOF_MEMBER(ArtMethod, declaring_class_));
}
- static MemberOffset EntryPointFromCompiledCodeOffset() {
- return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_compiled_code_));
- }
+ uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint32_t GetAccessFlags() const;
-
- 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 @@
}
// 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 @@
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 @@
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);
+ }
- bool IsWithinCode(uintptr_t pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromCompiledCode());
+ static MemberOffset EntryPointFromQuickCompiledCodeOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_quick_compiled_code_));
+ }
+
+ 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 @@
return (code <= pc && pc <= code + GetCodeSize());
}
- void AssertPcIsWithinCode(uintptr_t pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void AssertPcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint32_t GetOatCodeOffset() const;
-
- 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 @@
// 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 @@
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 @@
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 @@
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_;
- // Architecture-dependent register spill mask
- uint32_t core_spill_mask_;
+ // 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_;
- // 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_;
+ // 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_;
- // Called by the interpreter to execute this method.
- EntryPointFromInterpreter* entry_point_from_interpreter_;
+ // 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_;
- // Architecture-dependent register spill mask
- uint32_t fp_spill_mask_;
+ // --- Quick compiler meta-data. ---
+ // TODO: merge and place in native heap, such as done with the code size.
- // Total size in bytes of the frame
- size_t frame_size_in_bytes_;
-
- // Garbage collection map of native PC offsets (quick) or dex PCs (portable) to reference bitmaps.
- const uint8_t* gc_map_;
-
- // 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 method_dex_index_;
-
- // 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.
- uint32_t method_index_;
-
- // The target native method registered with this method
- const void* native_method_;
+ // 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.
- const uint16_t* vmap_table_;
+ uint64_t quick_vmap_table_;
+
+ // --- End of quick compiler meta-data. ---
+
+ // Access flags; low 16 bits are defined by spec.
+ uint32_t access_flags_;
+
+ /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
+
+ // Offset to the CodeItem.
+ uint32_t dex_code_item_offset_;
+
+ // Index into method_ids of the dex file associated with this method.
+ uint32_t dex_method_index_;
+
+ /* End of dex file fields. */
+
+ // 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_;
+
+ // --- Quick compiler meta-data. ---
+ // TODO: merge and place in native heap, such as done with the code size.
+
+ // 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 @@
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 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 @@
// 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 @@
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 @@
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::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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 Signature& signature) const {
+ const Signature& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
ArtMethod* method = GetVirtualMethod(i);
@@ -461,7 +461,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
// 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 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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* 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 @@
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 @@
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 @@
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 @@
// 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 @@
}
// 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 @@
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 @@
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 @@
// 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 @@
//
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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::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);
}
-inline void Object::VerifyObject(const Object* obj) {
+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(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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
void Wait(Thread* self, int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsClass() const;
+ bool IsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Class* AsClass();
+ Class* AsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const Class* AsClass() const;
-
- 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;
+ bool IsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* AsArtMethod();
+ ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const ArtMethod* AsArtMethod() const;
-
- 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() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsReferenceInstance() const;
+ bool IsWeakReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsWeakReferenceInstance() const;
+ bool IsSoftReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSoftReferenceInstance() const;
+ bool IsFinalizerReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsFinalizerReferenceInstance() const;
+ bool IsPhantomReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsPhantomReferenceInstance() const;
+ // 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_);
- // 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);
- }
- }
-
- 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 @@
// 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
// 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_);
- // 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_);
+ T* GetWithoutChecks(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- T* GetWithoutChecks(int32_t i) const 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_);
- static void Copy(const ObjectArray<T>* src, int src_pos,
- ObjectArray<T>* dst, int dst_pos,
- size_t length)
+ // 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_);
+
+ // 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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 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 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 @@
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 @@
}
// 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 @@
}
#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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
}
Monitor::~Monitor() {
+ MonitorPool::ReleaseMonitorId(monitor_id_);
// Deflated monitors have a null object.
}
@@ -219,7 +221,7 @@
// 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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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,151 +24,15 @@
#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.
- */
-
-/*
- * 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
- */
-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 {
+/*
+ * 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.
+ */
+
static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string actualType(PrettyTypeOf(array));
@@ -178,168 +42,132 @@
"%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;
- }
+ mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
+ mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
+ Primitive::Type dstComponentPrimitiveType = dstComponentType->GetPrimitiveType();
- 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;
+ 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;
-}
-
-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->CasField32(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_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jlong expectedValue, jlong newValue) {
+ ScopedFastNativeObjectAccess soa(env);
+ mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ 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) {
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 @@
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 @@
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 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 be882048..0f380ad 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -66,16 +66,16 @@
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 @@
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_)));
- } else {
- VmapTable vmap_table(reinterpret_cast<const uint8_t*>(begin_ + vmap_table_offset_));
+ 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_));
- DCHECK_EQ(vmap_table.Size(), static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
- __builtin_popcount(fp_spill_mask_)));
+ CHECK_EQ(vmap_table.Size(), static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
+ __builtin_popcount(fp_spill_mask_)));
+ }
+ } else {
+ 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 @@
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 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
}
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 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 @@
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 @@
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 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 @@
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 @@
}
uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (shorty_ == NULL) {
+ if (shorty_ == nullptr) {
GetShorty();
}
return shorty_len_;
@@ -529,15 +526,15 @@
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 @@
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 @@
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 @@
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 @@
};
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 @@
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 @@
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 @@
}
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 @@
// 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 @@
}
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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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::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 @@
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 InternTable;
struct JavaVMExt;
class MonitorList;
+class MonitorPool;
class SignalCatcher;
class ThreadList;
class Trace;
@@ -314,6 +315,10 @@
return monitor_list_;
}
+ MonitorPool* GetMonitorPool() const {
+ return monitor_pool_;
+ }
+
mirror::Throwable* GetPreAllocatedOutOfMemoryError() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -524,6 +529,7 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
public:
explicit StackIndirectReferenceTable(mirror::Object* object) :
number_of_references_(1), link_(NULL) {
- references_[0] = object;
+ references_[0].Assign(object);
}
~StackIndirectReferenceTable() {}
@@ -53,17 +54,17 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
}
} 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 @@
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 @@
// 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 @@
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 @@
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 @@
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::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 @@
} 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::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::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::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::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 @@
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 @@
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 @@
}
}
-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 @@
/*
* 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 @@
}
}
-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 @@
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 @@
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 @@
return result;
}
-std::string PrettyTypeOf(const mirror::Object* obj) {
+std::string PrettyTypeOf(mirror::Object* obj) {
if (obj == NULL) {
return "null";
}
@@ -417,7 +417,7 @@
return result;
}
-std::string PrettyClass(const mirror::Class* c) {
+std::string PrettyClass(mirror::Class* c) {
if (c == NULL) {
return "null";
}
@@ -428,7 +428,7 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 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 @@
}
}
-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 @@
/* 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 @@
/* 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 @@
// 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 @@
};
/* 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 @@
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 @@
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 @@
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;