summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk5
-rw-r--r--compiler/compilers.cc14
-rw-r--r--compiler/compilers.h11
-rw-r--r--compiler/dex/quick/codegen_util.cc21
-rw-r--r--compiler/dex/quick/dex_file_method_inliner.cc12
-rw-r--r--compiler/dex/quick/dex_file_method_inliner.h2
-rw-r--r--compiler/dex/quick/gen_common.cc4
-rwxr-xr-xcompiler/dex/quick/gen_invoke.cc55
-rw-r--r--compiler/dex/quick/mir_to_lir.h7
-rw-r--r--compiler/dex/quick/x86/codegen_x86.h10
-rwxr-xr-xcompiler/dex/quick/x86/target_x86.cc97
-rw-r--r--compiler/driver/compiler_driver.cc112
-rw-r--r--compiler/driver/compiler_driver.h34
-rw-r--r--compiler/elf_patcher.cc10
-rw-r--r--compiler/elf_writer_quick.cc222
-rw-r--r--compiler/elf_writer_quick.h6
-rw-r--r--compiler/oat_writer.cc48
-rw-r--r--compiler/oat_writer.h14
-rw-r--r--runtime/common_runtime_test.cc12
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h8
-rw-r--r--runtime/entrypoints/quick/quick_alloc_entrypoints.cc61
-rw-r--r--runtime/gc/heap.h2
-rw-r--r--runtime/quick/inline_method_analyser.h2
-rwxr-xr-xtest/run-test6
24 files changed, 463 insertions, 312 deletions
diff --git a/Android.mk b/Android.mk
index 451edf1..15e8308 100644
--- a/Android.mk
+++ b/Android.mk
@@ -67,8 +67,13 @@ ifdef TARGET_2ND_ARCH
rm -f $(2ND_TARGET_OUT_INTERMEDIATES)/JAVA_LIBRARIES/*_intermediates/javalib.odex
rm -f $(2ND_TARGET_OUT_INTERMEDIATES)/APPS/*_intermediates/*.odex
endif
+ifneq ($(TMPDIR),)
+ rm -rf $(TMPDIR)/$(USER)/test-*/dalvik-cache/*
+ rm -rf $(TMPDIR)/android-data/dalvik-cache/*
+else
rm -rf /tmp/$(USER)/test-*/dalvik-cache/*
rm -rf /tmp/android-data/dalvik-cache/*
+endif
.PHONY: clean-oat-target
clean-oat-target:
diff --git a/compiler/compilers.cc b/compiler/compilers.cc
index 250924a..5cf846f 100644
--- a/compiler/compilers.cc
+++ b/compiler/compilers.cc
@@ -38,9 +38,6 @@ extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver* dr
uint32_t access_flags, uint32_t method_idx,
const art::DexFile& dex_file);
-// Hack for CFI CIE initialization
-extern std::vector<uint8_t>* X86CFIInitialization(bool is_x86_64);
-
void QuickCompiler::Init() const {
ArtInitQuickCompilerContext(GetCompilerDriver());
}
@@ -126,17 +123,6 @@ Backend* QuickCompiler::GetCodeGenerator(CompilationUnit* cu, void* compilation_
return mir_to_lir;
}
-std::vector<uint8_t>* QuickCompiler::GetCallFrameInformationInitialization(
- const CompilerDriver& driver) const {
- if (driver.GetInstructionSet() == kX86) {
- return X86CFIInitialization(false);
- }
- if (driver.GetInstructionSet() == kX86_64) {
- return X86CFIInitialization(true);
- }
- return nullptr;
-}
-
CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
uint32_t access_flags,
InvokeType invoke_type,
diff --git a/compiler/compilers.h b/compiler/compilers.h
index 2c231e1..151bf6f 100644
--- a/compiler/compilers.h
+++ b/compiler/compilers.h
@@ -56,17 +56,6 @@ class QuickCompiler : public Compiler {
void InitCompilationUnit(CompilationUnit& cu) const OVERRIDE {}
- /*
- * @brief Generate and return Dwarf CFI initialization, if supported by the
- * backend.
- * @param driver CompilerDriver for this compile.
- * @returns nullptr if not supported by backend or a vector of bytes for CFI DWARF
- * information.
- * @note This is used for backtrace information in generated code.
- */
- std::vector<uint8_t>* GetCallFrameInformationInitialization(const CompilerDriver& driver) const
- OVERRIDE;
-
private:
DISALLOW_COPY_AND_ASSIGN(QuickCompiler);
};
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 2a51b49..9f60427 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -394,6 +394,18 @@ LIR* Mir2Lir::ScanLiteralPoolMethod(LIR* data_target, const MethodReference& met
return nullptr;
}
+/* Search the existing constants in the literal pool for an exact class match */
+LIR* Mir2Lir::ScanLiteralPoolClass(LIR* data_target, const DexFile& dex_file, uint32_t type_idx) {
+ while (data_target) {
+ if (static_cast<uint32_t>(data_target->operands[0]) == type_idx &&
+ UnwrapPointer(data_target->operands[1]) == &dex_file) {
+ return data_target;
+ }
+ data_target = data_target->next;
+ }
+ return nullptr;
+}
+
/*
* The following are building blocks to insert constants into the pool or
* instruction streams.
@@ -492,10 +504,13 @@ void Mir2Lir::InstallLiteralPools() {
data_lir = class_literal_list_;
while (data_lir != NULL) {
uint32_t target_method_idx = data_lir->operands[0];
+ const DexFile* class_dex_file =
+ reinterpret_cast<const DexFile*>(UnwrapPointer(data_lir->operands[1]));
cu_->compiler_driver->AddClassPatch(cu_->dex_file,
cu_->class_def_idx,
cu_->method_idx,
target_method_idx,
+ class_dex_file,
code_buffer_.size());
const DexFile::TypeId& target_method_id = cu_->dex_file->GetTypeId(target_method_idx);
// unique value based on target to ensure code deduplication works
@@ -1222,12 +1237,14 @@ void Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType
DCHECK_NE(cu_->instruction_set, kMips) << reinterpret_cast<void*>(data_target);
}
-void Mir2Lir::LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg) {
+void Mir2Lir::LoadClassType(const DexFile& dex_file, uint32_t type_idx,
+ SpecialTargetRegister symbolic_reg) {
// Use the literal pool and a PC-relative load from a data word.
- LIR* data_target = ScanLiteralPool(class_literal_list_, type_idx, 0);
+ LIR* data_target = ScanLiteralPoolClass(class_literal_list_, dex_file, type_idx);
if (data_target == nullptr) {
data_target = AddWordData(&class_literal_list_, type_idx);
}
+ data_target->operands[1] = WrapPointer(const_cast<DexFile*>(&dex_file));
// Loads a Class pointer, which is a reference as it lives in the heap.
LIR* load_pc_rel = OpPcRelLoad(TargetReg(symbolic_reg, kRef), data_target);
AppendLIR(load_pc_rel);
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 7abf3e7..dbceaff 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -53,7 +53,7 @@ static constexpr bool kIntrinsicIsStatic[] = {
true, // kIntrinsicRint
true, // kIntrinsicRoundFloat
true, // kIntrinsicRoundDouble
- false, // kIntrinsicGet
+ false, // kIntrinsicReferenceGet
false, // kIntrinsicCharAt
false, // kIntrinsicCompareTo
false, // kIntrinsicIsEmptyOrLength
@@ -85,7 +85,7 @@ COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicFloor], Floor_must_be_static);
COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicRint], Rint_must_be_static);
COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicRoundFloat], RoundFloat_must_be_static);
COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicRoundDouble], RoundDouble_must_be_static);
-COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicGet], Get_must_not_be_static);
+COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicReferenceGet], Get_must_not_be_static);
COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCharAt], CharAt_must_not_be_static);
COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCompareTo], CompareTo_must_not_be_static);
COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicIsEmptyOrLength], IsEmptyOrLength_must_not_be_static);
@@ -169,7 +169,7 @@ const char* const DexFileMethodInliner::kNameCacheNames[] = {
"floor", // kNameCacheFloor
"rint", // kNameCacheRint
"round", // kNameCacheRound
- "get", // kNameCacheGet
+ "get", // kNameCacheReferenceGet
"charAt", // kNameCacheCharAt
"compareTo", // kNameCacheCompareTo
"isEmpty", // kNameCacheIsEmpty
@@ -339,7 +339,7 @@ const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods
INTRINSIC(JavaLangMath, Round, D_J, kIntrinsicRoundDouble, 0),
INTRINSIC(JavaLangStrictMath, Round, D_J, kIntrinsicRoundDouble, 0),
- INTRINSIC(JavaLangRefReference, Get, _Object, kIntrinsicGet, 0),
+ INTRINSIC(JavaLangRefReference, ReferenceGet, _Object, kIntrinsicReferenceGet, 0),
INTRINSIC(JavaLangString, CharAt, I_C, kIntrinsicCharAt, 0),
INTRINSIC(JavaLangString, CompareTo, String_I, kIntrinsicCompareTo, 0),
@@ -471,8 +471,8 @@ bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) {
return backend->GenInlinedRound(info, false /* is_double */);
case kIntrinsicRoundDouble:
return backend->GenInlinedRound(info, true /* is_double */);
- case kIntrinsicGet:
- return backend->GenInlinedGet(info);
+ case kIntrinsicReferenceGet:
+ return backend->GenInlinedReferenceGet(info);
case kIntrinsicCharAt:
return backend->GenInlinedCharAt(info);
case kIntrinsicCompareTo:
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
index 1bd3c48..b875e2b 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -145,7 +145,7 @@ class DexFileMethodInliner {
kNameCacheFloor,
kNameCacheRint,
kNameCacheRound,
- kNameCacheGet,
+ kNameCacheReferenceGet,
kNameCacheCharAt,
kNameCacheCompareTo,
kNameCacheIsEmpty,
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index f6c77fc..3f22913 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -361,7 +361,7 @@ void Mir2Lir::GenNewArray(uint32_t type_idx, RegLocation rl_dest,
&direct_type_ptr, &is_finalizable)) {
// The fast path.
if (!use_direct_type_ptr) {
- LoadClassType(type_idx, kArg0);
+ LoadClassType(*dex_file, type_idx, kArg0);
CallRuntimeHelperRegMethodRegLocation(kQuickAllocArrayResolved, TargetReg(kArg0, kNotWide),
rl_src, true);
} else {
@@ -961,7 +961,7 @@ void Mir2Lir::GenNewInstance(uint32_t type_idx, RegLocation rl_dest) {
!is_finalizable) {
// The fast path.
if (!use_direct_type_ptr) {
- LoadClassType(type_idx, kArg0);
+ LoadClassType(*dex_file, type_idx, kArg0);
if (!is_type_initialized) {
CallRuntimeHelperRegMethod(kQuickAllocObjectResolved, TargetReg(kArg0, kRef), true);
} else {
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index e70b0c5..3cfc9a6 100755
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -25,10 +25,8 @@
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
#include "mirror/object_array-inl.h"
-#include "mirror/reference-inl.h"
#include "mirror/string.h"
#include "mir_to_lir-inl.h"
-#include "scoped_thread_state_change.h"
#include "x86/codegen_x86.h"
namespace art {
@@ -1129,63 +1127,32 @@ RegLocation Mir2Lir::InlineTargetWide(CallInfo* info) {
return res;
}
-bool Mir2Lir::GenInlinedGet(CallInfo* info) {
+bool Mir2Lir::GenInlinedReferenceGet(CallInfo* info) {
if (cu_->instruction_set == kMips) {
// TODO - add Mips implementation
return false;
}
- // the refrence class is stored in the image dex file which might not be the same as the cu's
- // dex file. Query the reference class for the image dex file then reset to starting dex file
- // in after loading class type.
- uint16_t type_idx = 0;
- const DexFile* ref_dex_file = nullptr;
- {
- ScopedObjectAccess soa(Thread::Current());
- type_idx = mirror::Reference::GetJavaLangRefReference()->GetDexTypeIndex();
- ref_dex_file = mirror::Reference::GetJavaLangRefReference()->GetDexCache()->GetDexFile();
- }
- CHECK(LIKELY(ref_dex_file != nullptr));
-
- // address is either static within the image file, or needs to be patched up after compilation.
- bool unused_type_initialized;
bool use_direct_type_ptr;
uintptr_t direct_type_ptr;
- bool is_finalizable;
- const DexFile* old_dex = cu_->dex_file;
- cu_->dex_file = ref_dex_file;
+ ClassReference ref;
+ if (!cu_->compiler_driver->CanEmbedReferenceTypeInCode(&ref,
+ &use_direct_type_ptr, &direct_type_ptr)) {
+ return false;
+ }
+
RegStorage reg_class = TargetReg(kArg1, kRef);
Clobber(reg_class);
LockTemp(reg_class);
- if (!cu_->compiler_driver->CanEmbedTypeInCode(*ref_dex_file, type_idx, &unused_type_initialized,
- &use_direct_type_ptr, &direct_type_ptr,
- &is_finalizable) || is_finalizable) {
- cu_->dex_file = old_dex;
- // address is not known and post-compile patch is not possible, cannot insert intrinsic.
- return false;
- }
if (use_direct_type_ptr) {
LoadConstant(reg_class, direct_type_ptr);
- } else if (cu_->dex_file == old_dex) {
- // TODO: Bug 16656190 If cu_->dex_file != old_dex the patching could retrieve the wrong class
- // since the load class is indexed only by the type_idx. We should include which dex file a
- // class is from in the LoadClassType LIR.
- LoadClassType(type_idx, kArg1);
} else {
- cu_->dex_file = old_dex;
- return false;
+ uint16_t type_idx = ref.first->GetClassDef(ref.second).class_idx_;
+ LoadClassType(*ref.first, type_idx, kArg1);
}
- cu_->dex_file = old_dex;
- // get the offset for flags in reference class.
- uint32_t slow_path_flag_offset = 0;
- uint32_t disable_flag_offset = 0;
- {
- ScopedObjectAccess soa(Thread::Current());
- mirror::Class* reference_class = mirror::Reference::GetJavaLangRefReference();
- slow_path_flag_offset = reference_class->GetSlowPathFlagOffset().Uint32Value();
- disable_flag_offset = reference_class->GetDisableIntrinsicFlagOffset().Uint32Value();
- }
+ uint32_t slow_path_flag_offset = cu_->compiler_driver->GetReferenceSlowFlagOffset();
+ uint32_t disable_flag_offset = cu_->compiler_driver->GetReferenceDisableFlagOffset();
CHECK(slow_path_flag_offset && disable_flag_offset &&
(slow_path_flag_offset != disable_flag_offset));
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 0e6f36b..2221bb5 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -685,6 +685,7 @@ class Mir2Lir : public Backend {
LIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta);
LIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi);
LIR* ScanLiteralPoolMethod(LIR* data_target, const MethodReference& method);
+ LIR* ScanLiteralPoolClass(LIR* data_target, const DexFile& dex_file, uint32_t type_idx);
LIR* AddWordData(LIR* *constant_list_p, int value);
LIR* AddWideData(LIR* *constant_list_p, int val_lo, int val_hi);
void ProcessSwitchTables();
@@ -958,7 +959,7 @@ class Mir2Lir : public Backend {
*/
RegLocation InlineTargetWide(CallInfo* info);
- bool GenInlinedGet(CallInfo* info);
+ bool GenInlinedReferenceGet(CallInfo* info);
virtual bool GenInlinedCharAt(CallInfo* info);
bool GenInlinedStringIsEmptyOrLength(CallInfo* info, bool is_empty);
virtual bool GenInlinedReverseBits(CallInfo* info, OpSize size);
@@ -1113,11 +1114,13 @@ class Mir2Lir : public Backend {
/*
* @brief Load the Class* of a Dex Class type into the register.
+ * @param dex DexFile that contains the class type.
* @param type How the method will be invoked.
* @param register that will contain the code address.
* @note register will be passed to TargetReg to get physical register.
*/
- virtual void LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg);
+ virtual void LoadClassType(const DexFile& dex_file, uint32_t type_idx,
+ SpecialTargetRegister symbolic_reg);
// Routines that work for the generic case, but may be overriden by target.
/*
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index d74caae..d3ed48d 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -319,11 +319,13 @@ class X86Mir2Lir : public Mir2Lir {
/*
* @brief Load the Class* of a Dex Class type into the register.
+ * @param dex DexFile that contains the class type.
* @param type How the method will be invoked.
* @param register that will contain the code address.
* @note register will be passed to TargetReg to get physical register.
*/
- void LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg) OVERRIDE;
+ void LoadClassType(const DexFile& dex_file, uint32_t type_idx,
+ SpecialTargetRegister symbolic_reg) OVERRIDE;
void FlushIns(RegLocation* ArgLocs, RegLocation rl_method) OVERRIDE;
@@ -355,12 +357,6 @@ class X86Mir2Lir : public Mir2Lir {
void InstallLiteralPools() OVERRIDE;
/*
- * @brief Generate the debug_frame CFI information.
- * @returns pointer to vector containing CFE information
- */
- static std::vector<uint8_t>* ReturnCommonCallFrameInformation(bool is_x86_64);
-
- /*
* @brief Generate the debug_frame FDE information.
* @returns pointer to vector containing CFE information
*/
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index bd2e0f3..69f3e67 100755
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -971,19 +971,21 @@ void X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeT
method_address_insns_.Insert(move);
}
-void X86Mir2Lir::LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg) {
+void X86Mir2Lir::LoadClassType(const DexFile& dex_file, uint32_t type_idx,
+ SpecialTargetRegister symbolic_reg) {
/*
* For x86, just generate a 32 bit move immediate instruction, that will be filled
* in at 'link time'. For now, put a unique value based on target to ensure that
* code deduplication works.
*/
- const DexFile::TypeId& id = cu_->dex_file->GetTypeId(type_idx);
+ const DexFile::TypeId& id = dex_file.GetTypeId(type_idx);
uintptr_t ptr = reinterpret_cast<uintptr_t>(&id);
// Generate the move instruction with the unique pointer and save index and type.
LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI,
TargetReg(symbolic_reg, kNotWide).GetReg(),
- static_cast<int>(ptr), type_idx);
+ static_cast<int>(ptr), type_idx,
+ WrapPointer(const_cast<DexFile*>(&dex_file)));
AppendLIR(move);
class_type_address_insns_.Insert(move);
}
@@ -1068,12 +1070,16 @@ void X86Mir2Lir::InstallLiteralPools() {
for (uint32_t i = 0; i < class_type_address_insns_.Size(); i++) {
LIR* p = class_type_address_insns_.Get(i);
DCHECK_EQ(p->opcode, kX86Mov32RI);
+
+ const DexFile* class_dex_file =
+ reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3]));
uint32_t target_method_idx = p->operands[2];
// The offset to patch is the last 4 bytes of the instruction.
int patch_offset = p->offset + p->flags.size - 4;
cu_->compiler_driver->AddClassPatch(cu_->dex_file, cu_->class_def_idx,
- cu_->method_idx, target_method_idx, patch_offset);
+ cu_->method_idx, target_method_idx, class_dex_file,
+ patch_offset);
}
// And now the PC-relative calls to methods.
@@ -1437,11 +1443,6 @@ static void AdvanceLoc(std::vector<uint8_t>&buf, uint32_t increment) {
}
}
-
-std::vector<uint8_t>* X86CFIInitialization(bool is_x86_64) {
- return X86Mir2Lir::ReturnCommonCallFrameInformation(is_x86_64);
-}
-
static void EncodeUnsignedLeb128(std::vector<uint8_t>& buf, uint32_t value) {
uint8_t buffer[12];
uint8_t *ptr = EncodeUnsignedLeb128(buffer, value);
@@ -1458,84 +1459,6 @@ static void EncodeSignedLeb128(std::vector<uint8_t>& buf, int32_t value) {
}
}
-std::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation(bool is_x86_64) {
- std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
-
- // Length (will be filled in later in this routine).
- PushWord(*cfi_info, 0);
-
- // CIE id: always 0.
- PushWord(*cfi_info, 0);
-
- // Version: always 1.
- cfi_info->push_back(0x01);
-
- // Augmentation: 'zR\0'
- cfi_info->push_back(0x7a);
- cfi_info->push_back(0x52);
- cfi_info->push_back(0x0);
-
- // Code alignment: 1.
- EncodeUnsignedLeb128(*cfi_info, 1);
-
- // Data alignment.
- if (is_x86_64) {
- EncodeSignedLeb128(*cfi_info, -8);
- } else {
- EncodeSignedLeb128(*cfi_info, -4);
- }
-
- // Return address register.
- if (is_x86_64) {
- // R16(RIP)
- cfi_info->push_back(0x10);
- } else {
- // R8(EIP)
- cfi_info->push_back(0x08);
- }
-
- // Augmentation length: 1.
- cfi_info->push_back(1);
-
- // Augmentation data: 0x03 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
- cfi_info->push_back(0x03);
-
- // Initial instructions.
- if (is_x86_64) {
- // DW_CFA_def_cfa R7(RSP) 8.
- cfi_info->push_back(0x0c);
- cfi_info->push_back(0x07);
- cfi_info->push_back(0x08);
-
- // DW_CFA_offset R16(RIP) 1 (* -8).
- cfi_info->push_back(0x90);
- cfi_info->push_back(0x01);
- } else {
- // DW_CFA_def_cfa R4(ESP) 4.
- cfi_info->push_back(0x0c);
- cfi_info->push_back(0x04);
- cfi_info->push_back(0x04);
-
- // DW_CFA_offset R8(EIP) 1 (* -4).
- cfi_info->push_back(0x88);
- cfi_info->push_back(0x01);
- }
-
- // Padding to a multiple of 4
- while ((cfi_info->size() & 3) != 0) {
- // DW_CFA_nop is encoded as 0.
- cfi_info->push_back(0);
- }
-
- // Set the length of the CIE inside the generated bytes.
- uint32_t length = cfi_info->size() - 4;
- (*cfi_info)[0] = length;
- (*cfi_info)[1] = length >> 8;
- (*cfi_info)[2] = length >> 16;
- (*cfi_info)[3] = length >> 24;
- return cfi_info;
-}
-
static bool ARTRegIDToDWARFRegID(bool is_x86_64, int art_reg_id, int* dwarf_reg_id) {
if (is_x86_64) {
switch (art_reg_id) {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 6b0cc50..1233a0d 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -353,7 +353,6 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
compiler_enable_auto_elf_loading_(NULL),
compiler_get_method_code_addr_(NULL),
support_boot_image_fixup_(instruction_set != kMips),
- cfi_info_(nullptr),
dedupe_code_("dedupe code"),
dedupe_mapping_table_("dedupe mapping table"),
dedupe_vmap_table_("dedupe vmap table"),
@@ -376,11 +375,6 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
CHECK(image_classes_.get() == nullptr);
}
- // Are we generating CFI information?
- if (compiler_options->GetGenerateGDBInformation()) {
- cfi_info_.reset(compiler_->GetCallFrameInformationInitialization(*this));
- }
-
// Read the profile file if one is provided.
if (!profile_file.empty()) {
profile_present_ = profile_file_.LoadFile(profile_file);
@@ -597,7 +591,7 @@ void CompilerDriver::Resolve(jobject class_loader, const std::vector<const DexFi
for (size_t i = 0; i != dex_files.size(); ++i) {
const DexFile* dex_file = dex_files[i];
CHECK(dex_file != nullptr);
- ResolveDexFile(class_loader, *dex_file, thread_pool, timings);
+ ResolveDexFile(class_loader, *dex_file, dex_files, thread_pool, timings);
}
}
@@ -973,6 +967,43 @@ bool CompilerDriver::CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_i
}
}
+bool CompilerDriver::CanEmbedReferenceTypeInCode(ClassReference* ref,
+ bool* use_direct_ptr,
+ uintptr_t* direct_type_ptr) {
+ CHECK(ref != nullptr);
+ CHECK(use_direct_ptr != nullptr);
+ CHECK(direct_type_ptr != nullptr);
+
+ ScopedObjectAccess soa(Thread::Current());
+ mirror::Class* reference_class = mirror::Reference::GetJavaLangRefReference();
+ bool is_initialized;
+ bool unused_finalizable;
+ // Make sure we have a finished Reference class object before attempting to use it.
+ if (!CanEmbedTypeInCode(*reference_class->GetDexCache()->GetDexFile(),
+ reference_class->GetDexTypeIndex(), &is_initialized,
+ use_direct_ptr, direct_type_ptr, &unused_finalizable) ||
+ !is_initialized) {
+ return false;
+ }
+ ref->first = &reference_class->GetDexFile();
+ ref->second = reference_class->GetDexClassDefIndex();
+ return true;
+}
+
+uint32_t CompilerDriver::GetReferenceSlowFlagOffset() const {
+ ScopedObjectAccess soa(Thread::Current());
+ mirror::Class* klass = mirror::Reference::GetJavaLangRefReference();
+ DCHECK(klass->IsInitialized());
+ return klass->GetSlowPathFlagOffset().Uint32Value();
+}
+
+uint32_t CompilerDriver::GetReferenceDisableFlagOffset() const {
+ ScopedObjectAccess soa(Thread::Current());
+ mirror::Class* klass = mirror::Reference::GetJavaLangRefReference();
+ DCHECK(klass->IsInitialized());
+ return klass->GetDisableIntrinsicFlagOffset().Uint32Value();
+}
+
void CompilerDriver::ProcessedInstanceField(bool resolved) {
if (!resolved) {
stats_->UnresolvedInstanceField();
@@ -1344,12 +1375,14 @@ void CompilerDriver::AddClassPatch(const DexFile* dex_file,
uint16_t referrer_class_def_idx,
uint32_t referrer_method_idx,
uint32_t target_type_idx,
+ const DexFile* target_type_dex_file,
size_t literal_offset) {
MutexLock mu(Thread::Current(), compiled_methods_lock_);
classes_to_patch_.push_back(new TypePatchInformation(dex_file,
referrer_class_def_idx,
referrer_method_idx,
target_type_idx,
+ target_type_dex_file,
literal_offset));
}
@@ -1361,12 +1394,14 @@ class ParallelCompilationManager {
jobject class_loader,
CompilerDriver* compiler,
const DexFile* dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool)
: index_(0),
class_linker_(class_linker),
class_loader_(class_loader),
compiler_(compiler),
dex_file_(dex_file),
+ dex_files_(dex_files),
thread_pool_(thread_pool) {}
ClassLinker* GetClassLinker() const {
@@ -1388,6 +1423,10 @@ class ParallelCompilationManager {
return dex_file_;
}
+ const std::vector<const DexFile*>& GetDexFiles() const {
+ return dex_files_;
+ }
+
void ForAll(size_t begin, size_t end, Callback callback, size_t work_units) {
Thread* self = Thread::Current();
self->AssertNoPendingException();
@@ -1445,11 +1484,24 @@ class ParallelCompilationManager {
const jobject class_loader_;
CompilerDriver* const compiler_;
const DexFile* const dex_file_;
+ const std::vector<const DexFile*>& dex_files_;
ThreadPool* const thread_pool_;
DISALLOW_COPY_AND_ASSIGN(ParallelCompilationManager);
};
+static bool SkipClassCheckClassPath(const char* descriptor, const DexFile& dex_file,
+ const std::vector<const DexFile*>& classpath) {
+ DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, classpath);
+ CHECK(pair.second != NULL);
+ if (pair.first != &dex_file) {
+ LOG(WARNING) << "Skipping class " << descriptor << " from " << dex_file.GetLocation()
+ << " previously found in " << pair.first->GetLocation();
+ return true;
+ }
+ return false;
+}
+
// Return true if the class should be skipped during compilation.
//
// The first case where we skip is for redundant class definitions in
@@ -1458,20 +1510,23 @@ class ParallelCompilationManager {
// The second case where we skip is when an app bundles classes found
// in the boot classpath. Since at runtime we will select the class from
// the boot classpath, we ignore the one from the app.
+//
+// The third case is if the app itself has the class defined in multiple dex files. Then we skip
+// it if it is not the first occurrence.
static bool SkipClass(ClassLinker* class_linker, jobject class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
const DexFile::ClassDef& class_def) {
const char* descriptor = dex_file.GetClassDescriptor(class_def);
+
if (class_loader == NULL) {
- DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, class_linker->GetBootClassPath());
- CHECK(pair.second != NULL);
- if (pair.first != &dex_file) {
- LOG(WARNING) << "Skipping class " << descriptor << " from " << dex_file.GetLocation()
- << " previously found in " << pair.first->GetLocation();
- return true;
- }
- return false;
+ return SkipClassCheckClassPath(descriptor, dex_file, class_linker->GetBootClassPath());
+ }
+
+ if (class_linker->IsInBootClassPath(descriptor)) {
+ return true;
}
- return class_linker->IsInBootClassPath(descriptor);
+
+ return SkipClassCheckClassPath(descriptor, dex_file, dex_files);
}
// A fast version of SkipClass above if the class pointer is available
@@ -1529,7 +1584,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag
// definitions, since many of them many never be referenced by
// generated code.
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- if (!SkipClass(class_linker, jclass_loader, dex_file, class_def)) {
+ if (!SkipClass(class_linker, jclass_loader, dex_file, manager->GetDexFiles(), class_def)) {
ScopedObjectAccess soa(self);
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
@@ -1636,13 +1691,15 @@ static void ResolveType(const ParallelCompilationManager* manager, size_t type_i
}
void CompilerDriver::ResolveDexFile(jobject class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
// TODO: we could resolve strings here, although the string table is largely filled with class
// and method names.
- ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, thread_pool);
+ ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files,
+ thread_pool);
if (IsImage()) {
// For images we resolve all types, such as array, whereas for applications just those with
// classdefs are resolved by ResolveClassFieldsAndMethods.
@@ -1659,7 +1716,7 @@ void CompilerDriver::Verify(jobject class_loader, const std::vector<const DexFil
for (size_t i = 0; i != dex_files.size(); ++i) {
const DexFile* dex_file = dex_files[i];
CHECK(dex_file != NULL);
- VerifyDexFile(class_loader, *dex_file, thread_pool, timings);
+ VerifyDexFile(class_loader, *dex_file, dex_files, thread_pool, timings);
}
}
@@ -1711,10 +1768,12 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_
}
void CompilerDriver::VerifyDexFile(jobject class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings) {
TimingLogger::ScopedTiming t("Verify Dex File", timings);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, thread_pool);
+ ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files,
+ thread_pool);
context.ForAll(0, dex_file.NumClassDefs(), VerifyClass, thread_count_);
}
@@ -1804,10 +1863,12 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
}
void CompilerDriver::InitializeClasses(jobject jni_class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings) {
TimingLogger::ScopedTiming t("InitializeNoClinit", timings);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ParallelCompilationManager context(class_linker, jni_class_loader, this, &dex_file, thread_pool);
+ ParallelCompilationManager context(class_linker, jni_class_loader, this, &dex_file, dex_files,
+ thread_pool);
size_t thread_count;
if (IsImage()) {
// TODO: remove this when transactional mode supports multithreading.
@@ -1828,7 +1889,7 @@ void CompilerDriver::InitializeClasses(jobject class_loader,
for (size_t i = 0; i != dex_files.size(); ++i) {
const DexFile* dex_file = dex_files[i];
CHECK(dex_file != NULL);
- InitializeClasses(class_loader, *dex_file, thread_pool, timings);
+ InitializeClasses(class_loader, *dex_file, dex_files, thread_pool, timings);
}
}
@@ -1837,7 +1898,7 @@ void CompilerDriver::Compile(jobject class_loader, const std::vector<const DexFi
for (size_t i = 0; i != dex_files.size(); ++i) {
const DexFile* dex_file = dex_files[i];
CHECK(dex_file != NULL);
- CompileDexFile(class_loader, *dex_file, thread_pool, timings);
+ CompileDexFile(class_loader, *dex_file, dex_files, thread_pool, timings);
}
}
@@ -1847,7 +1908,7 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz
const DexFile& dex_file = *manager->GetDexFile();
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
ClassLinker* class_linker = manager->GetClassLinker();
- if (SkipClass(class_linker, jclass_loader, dex_file, class_def)) {
+ if (SkipClass(class_linker, jclass_loader, dex_file, manager->GetDexFiles(), class_def)) {
return;
}
ClassReference ref(&dex_file, class_def_index);
@@ -1916,10 +1977,11 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz
}
void CompilerDriver::CompileDexFile(jobject class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings) {
TimingLogger::ScopedTiming t("Compile Dex File", timings);
ParallelCompilationManager context(Runtime::Current()->GetClassLinker(), class_loader, this,
- &dex_file, thread_pool);
+ &dex_file, dex_files, thread_pool);
context.ForAll(0, dex_file.NumClassDefs(), CompilerDriver::CompileClass, thread_count_);
}
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 6dae398..2a5cdb9 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -213,6 +213,12 @@ class CompilerDriver {
bool* is_type_initialized, bool* use_direct_type_ptr,
uintptr_t* direct_type_ptr, bool* out_is_finalizable);
+ // Query methods for the java.lang.ref.Reference class.
+ bool CanEmbedReferenceTypeInCode(ClassReference* ref,
+ bool* use_direct_type_ptr, uintptr_t* direct_type_ptr);
+ uint32_t GetReferenceSlowFlagOffset() const;
+ uint32_t GetReferenceDisableFlagOffset() const;
+
// Get the DexCache for the
mirror::DexCache* GetDexCache(const DexCompilationUnit* mUnit)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -356,6 +362,7 @@ class CompilerDriver {
uint16_t referrer_class_def_idx,
uint32_t referrer_method_idx,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
size_t literal_offset)
LOCKS_EXCLUDED(compiled_methods_lock_);
@@ -402,10 +409,6 @@ class CompilerDriver {
return dump_passes_;
}
- bool DidIncludeDebugSymbols() const {
- return compiler_options_->GetIncludeDebugSymbols();
- }
-
CumulativeLogger* GetTimingsLogger() const {
return timings_logger_;
}
@@ -549,6 +552,10 @@ class CompilerDriver {
class TypePatchInformation : public PatchInformation {
public:
+ const DexFile& GetTargetTypeDexFile() const {
+ return *target_type_dex_file_;
+ }
+
uint32_t GetTargetTypeIdx() const {
return target_type_idx_;
}
@@ -565,13 +572,15 @@ class CompilerDriver {
uint16_t referrer_class_def_idx,
uint32_t referrer_method_idx,
uint32_t target_type_idx,
+ const DexFile* target_type_dex_file,
size_t literal_offset)
: PatchInformation(dex_file, referrer_class_def_idx,
referrer_method_idx, literal_offset),
- target_type_idx_(target_type_idx) {
+ target_type_idx_(target_type_idx), target_type_dex_file_(target_type_dex_file) {
}
const uint32_t target_type_idx_;
+ const DexFile* target_type_dex_file_;
friend class CompilerDriver;
DISALLOW_COPY_AND_ASSIGN(TypePatchInformation);
@@ -599,14 +608,6 @@ class CompilerDriver {
std::vector<uint8_t>* DeduplicateGCMap(const std::vector<uint8_t>& code);
std::vector<uint8_t>* DeduplicateCFIInfo(const std::vector<uint8_t>* cfi_info);
- /*
- * @brief return the pointer to the Call Frame Information.
- * @return pointer to call frame information for this compilation.
- */
- std::vector<uint8_t>* GetCallFrameInformation() const {
- return cfi_info_.get();
- }
-
ProfileFile profile_file_;
bool profile_present_;
@@ -658,12 +659,14 @@ class CompilerDriver {
ThreadPool* thread_pool, TimingLogger* timings)
LOCKS_EXCLUDED(Locks::mutator_lock_);
void ResolveDexFile(jobject class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings)
LOCKS_EXCLUDED(Locks::mutator_lock_);
void Verify(jobject class_loader, const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings);
void VerifyDexFile(jobject class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings)
LOCKS_EXCLUDED(Locks::mutator_lock_);
@@ -671,6 +674,7 @@ class CompilerDriver {
ThreadPool* thread_pool, TimingLogger* timings)
LOCKS_EXCLUDED(Locks::mutator_lock_);
void InitializeClasses(jobject class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings)
LOCKS_EXCLUDED(Locks::mutator_lock_, compiled_classes_lock_);
@@ -681,6 +685,7 @@ class CompilerDriver {
void Compile(jobject class_loader, const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings);
void CompileDexFile(jobject class_loader, const DexFile& dex_file,
+ const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings)
LOCKS_EXCLUDED(Locks::mutator_lock_);
void CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
@@ -766,9 +771,6 @@ class CompilerDriver {
bool support_boot_image_fixup_;
- // Call Frame Information, which might be generated to help stack tracebacks.
- std::unique_ptr<std::vector<uint8_t>> cfi_info_;
-
// DeDuplication data structures, these own the corresponding byte arrays.
class DedupeHashFunc {
public:
diff --git a/compiler/elf_patcher.cc b/compiler/elf_patcher.cc
index 137110f..9ae755d 100644
--- a/compiler/elf_patcher.cc
+++ b/compiler/elf_patcher.cc
@@ -99,11 +99,13 @@ mirror::ArtMethod* ElfPatcher::GetTargetMethod(const CompilerDriver::CallPatchIn
mirror::Class* ElfPatcher::GetTargetType(const CompilerDriver::TypePatchInformation* patch) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(patch->GetDexFile())));
- mirror::Class* klass = class_linker->ResolveType(patch->GetDexFile(), patch->GetTargetTypeIdx(),
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(
+ patch->GetTargetTypeDexFile())));
+ mirror::Class* klass = class_linker->ResolveType(patch->GetTargetTypeDexFile(),
+ patch->GetTargetTypeIdx(),
dex_cache, NullHandle<mirror::ClassLoader>());
CHECK(klass != NULL)
- << patch->GetDexFile().GetLocation() << " " << patch->GetTargetTypeIdx();
+ << patch->GetTargetTypeDexFile().GetLocation() << " " << patch->GetTargetTypeIdx();
CHECK(dex_cache->GetResolvedTypes()->Get(patch->GetTargetTypeIdx()) == klass)
<< patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
<< PrettyClass(dex_cache->GetResolvedTypes()->Get(patch->GetTargetTypeIdx())) << " "
@@ -152,7 +154,7 @@ void ElfPatcher::SetPatchLocation(const CompilerDriver::PatchInformation* patch,
}
if (patch->IsType()) {
const CompilerDriver::TypePatchInformation* tpatch = patch->AsType();
- const DexFile::TypeId& id = tpatch->GetDexFile().GetTypeId(tpatch->GetTargetTypeIdx());
+ const DexFile::TypeId& id = tpatch->GetTargetTypeDexFile().GetTypeId(tpatch->GetTargetTypeIdx());
uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
uint32_t actual = *patch_location;
CHECK(actual == expected || actual == value) << "Patching type failed: " << std::hex
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 1fde12e..71f02d3 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -24,6 +24,7 @@
#include "elf_utils.h"
#include "file_output_stream.h"
#include "globals.h"
+#include "leb128.h"
#include "oat.h"
#include "oat_writer.h"
#include "utils.h"
@@ -38,6 +39,25 @@ static uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
return ((binding) << 4) + ((type) & 0xf);
}
+static void UpdateWord(std::vector<uint8_t>* buf, int offset, int data) {
+ (*buf)[offset+0] = data;
+ (*buf)[offset+1] = data >> 8;
+ (*buf)[offset+2] = data >> 16;
+ (*buf)[offset+3] = data >> 24;
+}
+
+static void PushWord(std::vector<uint8_t>* buf, int data) {
+ buf->push_back(data & 0xff);
+ buf->push_back((data >> 8) & 0xff);
+ buf->push_back((data >> 16) & 0xff);
+ buf->push_back((data >> 24) & 0xff);
+}
+
+static void PushHalf(std::vector<uint8_t>* buf, int data) {
+ buf->push_back(data & 0xff);
+ buf->push_back((data >> 8) & 0xff);
+}
+
bool ElfWriterQuick::ElfBuilder::Write() {
// The basic layout of the elf file. Order may be different in final output.
// +-------------------------+
@@ -822,37 +842,131 @@ void ElfWriterQuick::ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug)
}
}
+static void EncodeUnsignedLeb128(uint32_t data, std::vector<uint8_t>* dst) {
+ size_t encoded_size = UnsignedLeb128Size(data);
+ size_t cur_index = dst->size();
+ dst->resize(dst->size() + encoded_size);
+ uint8_t* write_pos = &((*dst)[cur_index]);
+ uint8_t* write_pos_after = EncodeUnsignedLeb128(write_pos, data);
+ DCHECK_EQ(static_cast<size_t>(write_pos_after - write_pos), encoded_size);
+}
+
+static void EncodeSignedLeb128(int32_t data, std::vector<uint8_t>* dst) {
+ size_t encoded_size = SignedLeb128Size(data);
+ size_t cur_index = dst->size();
+ dst->resize(dst->size() + encoded_size);
+ uint8_t* write_pos = &((*dst)[cur_index]);
+ uint8_t* write_pos_after = EncodeSignedLeb128(write_pos, data);
+ DCHECK_EQ(static_cast<size_t>(write_pos_after - write_pos), encoded_size);
+}
+
+std::vector<uint8_t>* ConstructCIEFrameX86(bool is_x86_64) {
+ std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
+
+ // Length (will be filled in later in this routine).
+ PushWord(cfi_info, 0);
+
+ // CIE id: always 0.
+ PushWord(cfi_info, 0);
+
+ // Version: always 1.
+ cfi_info->push_back(0x01);
+
+ // Augmentation: 'zR\0'
+ cfi_info->push_back(0x7a);
+ cfi_info->push_back(0x52);
+ cfi_info->push_back(0x0);
+
+ // Code alignment: 1.
+ EncodeUnsignedLeb128(1, cfi_info);
+
+ // Data alignment.
+ if (is_x86_64) {
+ EncodeSignedLeb128(-8, cfi_info);
+ } else {
+ EncodeSignedLeb128(-4, cfi_info);
+ }
+
+ // Return address register.
+ if (is_x86_64) {
+ // R16(RIP)
+ cfi_info->push_back(0x10);
+ } else {
+ // R8(EIP)
+ cfi_info->push_back(0x08);
+ }
+
+ // Augmentation length: 1.
+ cfi_info->push_back(1);
+
+ // Augmentation data: 0x03 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
+ cfi_info->push_back(0x03);
+
+ // Initial instructions.
+ if (is_x86_64) {
+ // DW_CFA_def_cfa R7(RSP) 8.
+ cfi_info->push_back(0x0c);
+ cfi_info->push_back(0x07);
+ cfi_info->push_back(0x08);
+
+ // DW_CFA_offset R16(RIP) 1 (* -8).
+ cfi_info->push_back(0x90);
+ cfi_info->push_back(0x01);
+ } else {
+ // DW_CFA_def_cfa R4(ESP) 4.
+ cfi_info->push_back(0x0c);
+ cfi_info->push_back(0x04);
+ cfi_info->push_back(0x04);
+
+ // DW_CFA_offset R8(EIP) 1 (* -4).
+ cfi_info->push_back(0x88);
+ cfi_info->push_back(0x01);
+ }
+
+ // Padding to a multiple of 4
+ while ((cfi_info->size() & 3) != 0) {
+ // DW_CFA_nop is encoded as 0.
+ cfi_info->push_back(0);
+ }
+
+ // Set the length of the CIE inside the generated bytes.
+ uint32_t length = cfi_info->size() - 4;
+ (*cfi_info)[0] = length;
+ (*cfi_info)[1] = length >> 8;
+ (*cfi_info)[2] = length >> 16;
+ (*cfi_info)[3] = length >> 24;
+ return cfi_info;
+}
+
+std::vector<uint8_t>* ConstructCIEFrame(InstructionSet isa) {
+ switch (isa) {
+ case kX86:
+ return ConstructCIEFrameX86(false);
+ case kX86_64:
+ return ConstructCIEFrameX86(true);
+
+ default:
+ // Not implemented.
+ return nullptr;
+ }
+}
+
bool ElfWriterQuick::Write(OatWriter* oat_writer,
const std::vector<const DexFile*>& dex_files_unused,
const std::string& android_root_unused,
bool is_host_unused) {
- const bool debug = false;
- const bool add_symbols = oat_writer->DidAddSymbols();
+ constexpr bool debug = false;
const OatHeader& oat_header = oat_writer->GetOatHeader();
Elf32_Word oat_data_size = oat_header.GetExecutableOffset();
uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
ElfBuilder builder(oat_writer, elf_file_, compiler_driver_->GetInstructionSet(), 0,
- oat_data_size, oat_data_size, oat_exec_size, add_symbols, debug);
+ oat_data_size, oat_data_size, oat_exec_size,
+ compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
+ debug);
- if (add_symbols) {
- AddDebugSymbols(builder, oat_writer, debug);
- }
-
- bool generateDebugInformation = compiler_driver_->GetCallFrameInformation() != nullptr;
- if (generateDebugInformation) {
- ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
- ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
- ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
- ElfRawSectionBuilder eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
- eh_frame.SetBuffer(*compiler_driver_->GetCallFrameInformation());
-
- FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
- debug_abbrev.GetBuffer(), debug_str.GetBuffer());
- builder.RegisterRawSection(debug_info);
- builder.RegisterRawSection(debug_abbrev);
- builder.RegisterRawSection(eh_frame);
- builder.RegisterRawSection(debug_str);
+ if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
+ WriteDebugSymbols(builder, oat_writer);
}
if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
@@ -865,32 +979,62 @@ bool ElfWriterQuick::Write(OatWriter* oat_writer,
return builder.Write();
}
-void ElfWriterQuick::AddDebugSymbols(ElfBuilder& builder, OatWriter* oat_writer, bool debug) {
+void ElfWriterQuick::WriteDebugSymbols(ElfBuilder& builder, OatWriter* oat_writer) {
+ std::unique_ptr<std::vector<uint8_t>> cfi_info(
+ ConstructCIEFrame(compiler_driver_->GetInstructionSet()));
+
+ // Iterate over the compiled methods.
const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
ElfSymtabBuilder* symtab = &builder.symtab_builder_;
for (auto it = method_info.begin(); it != method_info.end(); ++it) {
symtab->AddSymbol(it->method_name_, &builder.text_builder_, it->low_pc_, true,
it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
- }
-}
-static void UpdateWord(std::vector<uint8_t>*buf, int offset, int data) {
- (*buf)[offset+0] = data;
- (*buf)[offset+1] = data >> 8;
- (*buf)[offset+2] = data >> 16;
- (*buf)[offset+3] = data >> 24;
-}
+ // Include CFI for compiled method, if possible.
+ if (cfi_info.get() != nullptr) {
+ DCHECK(it->compiled_method_ != nullptr);
+
+ // Copy in the FDE, if present
+ const std::vector<uint8_t>* fde = it->compiled_method_->GetCFIInfo();
+ if (fde != nullptr) {
+ // Copy the information into cfi_info and then fix the address in the new copy.
+ int cur_offset = cfi_info->size();
+ cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
+
+ // Set the 'CIE_pointer' field to cur_offset+4.
+ uint32_t CIE_pointer = cur_offset + 4;
+ uint32_t offset_to_update = cur_offset + sizeof(uint32_t);
+ (*cfi_info)[offset_to_update+0] = CIE_pointer;
+ (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
+ (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
+ (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
+
+ // Set the 'initial_location' field to address the start of the method.
+ offset_to_update = cur_offset + 2*sizeof(uint32_t);
+ const uint32_t quick_code_start = it->low_pc_;
+ (*cfi_info)[offset_to_update+0] = quick_code_start;
+ (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
+ (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
+ (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
+ }
+ }
+ }
-static void PushWord(std::vector<uint8_t>*buf, int data) {
- buf->push_back(data & 0xff);
- buf->push_back((data >> 8) & 0xff);
- buf->push_back((data >> 16) & 0xff);
- buf->push_back((data >> 24) & 0xff);
-}
+ if (cfi_info.get() != nullptr) {
+ // Now lay down the Elf sections.
+ ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
+ eh_frame.SetBuffer(std::move(*cfi_info.get()));
-static void PushHalf(std::vector<uint8_t>*buf, int data) {
- buf->push_back(data & 0xff);
- buf->push_back((data >> 8) & 0xff);
+ FillInCFIInformation(oat_writer, debug_info.GetBuffer(), debug_abbrev.GetBuffer(),
+ debug_str.GetBuffer());
+ builder.RegisterRawSection(debug_info);
+ builder.RegisterRawSection(debug_abbrev);
+ builder.RegisterRawSection(eh_frame);
+ builder.RegisterRawSection(debug_str);
+ }
}
void ElfWriterQuick::FillInCFIInformation(OatWriter* oat_writer,
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
index a0d36df..8cfe550 100644
--- a/compiler/elf_writer_quick.h
+++ b/compiler/elf_writer_quick.h
@@ -48,9 +48,7 @@ class ElfWriterQuick FINAL : public ElfWriter {
~ElfWriterQuick() {}
class ElfBuilder;
- void AddDebugSymbols(ElfBuilder& builder,
- OatWriter* oat_writer,
- bool debug);
+ void WriteDebugSymbols(ElfBuilder& builder, OatWriter* oat_writer);
void ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug);
class ElfSectionBuilder {
@@ -126,7 +124,7 @@ class ElfWriterQuick FINAL : public ElfWriter {
: ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {}
~ElfRawSectionBuilder() {}
std::vector<uint8_t>* GetBuffer() { return &buf_; }
- void SetBuffer(std::vector<uint8_t> buf) { buf_ = buf; }
+ void SetBuffer(std::vector<uint8_t>&& buf) { buf_ = buf; }
protected:
std::vector<uint8_t> buf_;
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 9da59ab..1ba5d32 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -357,7 +357,6 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
uint32_t thumb_offset = compiled_method->CodeDelta();
quick_code_offset = offset_ + sizeof(OatQuickMethodHeader) + thumb_offset;
- bool force_debug_capture = false;
bool deduped = false;
// Deduplicate code arrays.
@@ -400,47 +399,22 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
offset_ += code_size;
}
- uint32_t quick_code_start = quick_code_offset - writer_->oat_header_->GetExecutableOffset();
- std::vector<uint8_t>* cfi_info = writer_->compiler_driver_->GetCallFrameInformation();
- if (cfi_info != nullptr) {
- // Copy in the FDE, if present
- const std::vector<uint8_t>* fde = compiled_method->GetCFIInfo();
- if (fde != nullptr) {
- // Copy the information into cfi_info and then fix the address in the new copy.
- int cur_offset = cfi_info->size();
- cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
-
- // Set the 'CIE_pointer' field to cur_offset+4.
- uint32_t CIE_pointer = cur_offset + 4;
- uint32_t offset_to_update = cur_offset + sizeof(uint32_t);
- (*cfi_info)[offset_to_update+0] = CIE_pointer;
- (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
- (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
- (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
-
- // Set the 'initial_location' field to address the start of the method.
- offset_to_update = cur_offset + 2*sizeof(uint32_t);
- (*cfi_info)[offset_to_update+0] = quick_code_start;
- (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
- (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
- (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
- force_debug_capture = true;
- }
- }
+ if (writer_->compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
+ // Record debug information for this function if we are doing that.
-
- if (writer_->compiler_driver_->DidIncludeDebugSymbols() || force_debug_capture) {
- // Record debug information for this function if we are doing that or
- // we have CFI and so need it.
std::string name = PrettyMethod(it.GetMemberIndex(), *dex_file_, true);
if (deduped) {
- // TODO We should place the DEDUPED tag on the first instance of a
- // deduplicated symbol so that it will show up in a debuggerd crash
- // report.
+ // TODO We should place the DEDUPED tag on the first instance of a deduplicated symbol
+ // so that it will show up in a debuggerd crash report.
name += " [ DEDUPED ]";
}
- writer_->method_info_.push_back(DebugInfo(name, quick_code_start,
- quick_code_start + code_size));
+
+ const uint32_t quick_code_start = quick_code_offset -
+ writer_->oat_header_->GetExecutableOffset();
+ writer_->method_info_.push_back(DebugInfo(name,
+ quick_code_start,
+ quick_code_start + code_size,
+ compiled_method));
}
}
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 945048e..ef5fd6b 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -30,6 +30,7 @@
namespace art {
class BitVector;
+class CompiledMethod;
class OutputStream;
// OatHeader variable length with count of D OatDexFiles
@@ -97,22 +98,21 @@ class OatWriter {
~OatWriter();
struct DebugInfo {
- DebugInfo(const std::string& method_name, uint32_t low_pc, uint32_t high_pc)
- : method_name_(method_name), low_pc_(low_pc), high_pc_(high_pc) {
+ DebugInfo(const std::string& method_name, uint32_t low_pc, uint32_t high_pc,
+ CompiledMethod* compiled_method)
+ : method_name_(method_name), low_pc_(low_pc), high_pc_(high_pc),
+ compiled_method_(compiled_method) {
}
- std::string method_name_;
+ std::string method_name_; // Note: this name is a pretty-printed name.
uint32_t low_pc_;
uint32_t high_pc_;
+ CompiledMethod* compiled_method_;
};
const std::vector<DebugInfo>& GetCFIMethodInfo() const {
return method_info_;
}
- bool DidAddSymbols() const {
- return compiler_driver_->DidIncludeDebugSymbols();
- }
-
private:
// The DataAccess classes are helper classes that provide access to members related to
// a given map, i.e. GC map, mapping table or vmap table. By abstracting these away
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 6cf5619..9972362 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -137,7 +137,17 @@ void CommonRuntimeTest::SetEnvironmentVariables(std::string& android_data) {
}
// On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
- android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX");
+ if (IsHost()) {
+ const char* tmpdir = getenv("TMPDIR");
+ if (tmpdir != nullptr && tmpdir[0] != 0) {
+ android_data = tmpdir;
+ } else {
+ android_data = "/tmp";
+ }
+ } else {
+ android_data = "/data/dalvik-cache";
+ }
+ android_data += "/art-data-XXXXXX";
if (mkdtemp(&android_data[0]) == nullptr) {
PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
}
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index af71c19..b874a74 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -37,6 +37,7 @@ namespace art {
// TODO: Fix no thread safety analysis when GCC can handle template specialization.
template <const bool kAccessCheck>
+ALWAYS_INLINE
static inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
mirror::ArtMethod* method,
Thread* self, bool* slow_path) {
@@ -86,6 +87,7 @@ static inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
}
// TODO: Fix no thread safety analysis when annotalysis is smarter.
+ALWAYS_INLINE
static inline mirror::Class* CheckClassInitializedForObjectAlloc(mirror::Class* klass,
Thread* self,
bool* slow_path) {
@@ -116,6 +118,7 @@ static inline mirror::Class* CheckClassInitializedForObjectAlloc(mirror::Class*
// check.
// TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter.
template <bool kAccessCheck, bool kInstrumented>
+ALWAYS_INLINE
static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx,
mirror::ArtMethod* method,
Thread* self,
@@ -135,6 +138,7 @@ static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx,
// Given the context of a calling Method and a resolved class, create an instance.
// TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter.
template <bool kInstrumented>
+ALWAYS_INLINE
static inline mirror::Object* AllocObjectFromCodeResolved(mirror::Class* klass,
mirror::ArtMethod* method,
Thread* self,
@@ -157,6 +161,7 @@ static inline mirror::Object* AllocObjectFromCodeResolved(mirror::Class* klass,
// Given the context of a calling Method and an initialized class, create an instance.
// TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter.
template <bool kInstrumented>
+ALWAYS_INLINE
static inline mirror::Object* AllocObjectFromCodeInitialized(mirror::Class* klass,
mirror::ArtMethod* method,
Thread* self,
@@ -169,6 +174,7 @@ static inline mirror::Object* AllocObjectFromCodeInitialized(mirror::Class* klas
// TODO: Fix no thread safety analysis when GCC can handle template specialization.
template <bool kAccessCheck>
+ALWAYS_INLINE
static inline mirror::Class* CheckArrayAlloc(uint32_t type_idx,
mirror::ArtMethod* method,
int32_t component_count,
@@ -205,6 +211,7 @@ static inline mirror::Class* CheckArrayAlloc(uint32_t type_idx,
// check.
// TODO: Fix no thread safety analysis when GCC can handle template specialization.
template <bool kAccessCheck, bool kInstrumented>
+ALWAYS_INLINE
static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx,
mirror::ArtMethod* method,
int32_t component_count,
@@ -227,6 +234,7 @@ static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx,
}
template <bool kAccessCheck, bool kInstrumented>
+ALWAYS_INLINE
static inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass,
mirror::ArtMethod* method,
int32_t component_count,
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index 1f2713a..7d4da18 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -25,11 +25,34 @@
namespace art {
+static constexpr bool kUseTlabFastPath = true;
+
#define GENERATE_ENTRYPOINTS_FOR_ALLOCATOR_INST(suffix, suffix2, instrumented_bool, allocator_type) \
extern "C" mirror::Object* artAllocObjectFromCode ##suffix##suffix2( \
uint32_t type_idx, mirror::ArtMethod* method, Thread* self, \
StackReference<mirror::ArtMethod>* sp) \
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
+ if (kUseTlabFastPath && !instrumented_bool && allocator_type == gc::kAllocatorTypeTLAB) { \
+ mirror::Class* klass = method->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx); \
+ if (LIKELY(klass != nullptr && klass->IsInitialized() && !klass->IsFinalizable())) { \
+ size_t byte_count = klass->GetObjectSize(); \
+ byte_count = RoundUp(byte_count, gc::space::BumpPointerSpace::kAlignment); \
+ mirror::Object* obj; \
+ if (LIKELY(byte_count < self->TlabSize())) { \
+ obj = self->AllocTlab(byte_count); \
+ DCHECK(obj != nullptr) << "AllocTlab can't fail"; \
+ obj->SetClass(klass); \
+ if (kUseBakerOrBrooksReadBarrier) { \
+ if (kUseBrooksReadBarrier) { \
+ obj->SetReadBarrierPointer(obj); \
+ } \
+ obj->AssertReadBarrierPointer(); \
+ } \
+ QuasiAtomic::ThreadFenceForConstructor(); \
+ return obj; \
+ } \
+ } \
+ } \
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \
return AllocObjectFromCode<false, instrumented_bool>(type_idx, method, self, allocator_type); \
} \
@@ -37,6 +60,26 @@ extern "C" mirror::Object* artAllocObjectFromCodeResolved##suffix##suffix2( \
mirror::Class* klass, mirror::ArtMethod* method, Thread* self, \
StackReference<mirror::ArtMethod>* sp) \
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
+ if (kUseTlabFastPath && !instrumented_bool && allocator_type == gc::kAllocatorTypeTLAB) { \
+ if (LIKELY(klass->IsInitialized())) { \
+ size_t byte_count = klass->GetObjectSize(); \
+ byte_count = RoundUp(byte_count, gc::space::BumpPointerSpace::kAlignment); \
+ mirror::Object* obj; \
+ if (LIKELY(byte_count < self->TlabSize())) { \
+ obj = self->AllocTlab(byte_count); \
+ DCHECK(obj != nullptr) << "AllocTlab can't fail"; \
+ obj->SetClass(klass); \
+ if (kUseBakerOrBrooksReadBarrier) { \
+ if (kUseBrooksReadBarrier) { \
+ obj->SetReadBarrierPointer(obj); \
+ } \
+ obj->AssertReadBarrierPointer(); \
+ } \
+ QuasiAtomic::ThreadFenceForConstructor(); \
+ return obj; \
+ } \
+ } \
+ } \
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \
return AllocObjectFromCodeResolved<instrumented_bool>(klass, method, self, allocator_type); \
} \
@@ -44,6 +87,24 @@ extern "C" mirror::Object* artAllocObjectFromCodeInitialized##suffix##suffix2( \
mirror::Class* klass, mirror::ArtMethod* method, Thread* self, \
StackReference<mirror::ArtMethod>* sp) \
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
+ if (kUseTlabFastPath && !instrumented_bool && allocator_type == gc::kAllocatorTypeTLAB) { \
+ size_t byte_count = klass->GetObjectSize(); \
+ byte_count = RoundUp(byte_count, gc::space::BumpPointerSpace::kAlignment); \
+ mirror::Object* obj; \
+ if (LIKELY(byte_count < self->TlabSize())) { \
+ obj = self->AllocTlab(byte_count); \
+ DCHECK(obj != nullptr) << "AllocTlab can't fail"; \
+ obj->SetClass(klass); \
+ if (kUseBakerOrBrooksReadBarrier) { \
+ if (kUseBrooksReadBarrier) { \
+ obj->SetReadBarrierPointer(obj); \
+ } \
+ obj->AssertReadBarrierPointer(); \
+ } \
+ QuasiAtomic::ThreadFenceForConstructor(); \
+ return obj; \
+ } \
+ } \
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \
return AllocObjectFromCodeInitialized<instrumented_bool>(klass, method, self, allocator_type); \
} \
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 8ffadd5..a82392a 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -662,7 +662,7 @@ class Heap {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template <bool kGrow>
- bool IsOutOfMemoryOnAllocation(AllocatorType allocator_type, size_t alloc_size);
+ ALWAYS_INLINE bool IsOutOfMemoryOnAllocation(AllocatorType allocator_type, size_t alloc_size);
// Returns true if the address passed in is within the address range of a continuous space.
bool IsValidContinuousSpaceObjectAddress(const mirror::Object* obj) const
diff --git a/runtime/quick/inline_method_analyser.h b/runtime/quick/inline_method_analyser.h
index 23b9aed..c4d51cb 100644
--- a/runtime/quick/inline_method_analyser.h
+++ b/runtime/quick/inline_method_analyser.h
@@ -53,7 +53,7 @@ enum InlineMethodOpcode : uint16_t {
kIntrinsicRint,
kIntrinsicRoundFloat,
kIntrinsicRoundDouble,
- kIntrinsicGet,
+ kIntrinsicReferenceGet,
kIntrinsicCharAt,
kIntrinsicCompareTo,
kIntrinsicIsEmptyOrLength,
diff --git a/test/run-test b/test/run-test
index aef7c52..ca7e68c 100755
--- a/test/run-test
+++ b/test/run-test
@@ -33,7 +33,11 @@ cd "${progdir}"
progdir=`pwd`
prog="${progdir}"/`basename "${prog}"`
test_dir="test-$$"
-tmp_dir="/tmp/$USER/${test_dir}"
+if [ -z "$TMPDIR" ]; then
+ tmp_dir="/tmp/$USER/${test_dir}"
+else
+ tmp_dir="${TMPDIR}/$USER/${test_dir}"
+fi
export JAVA="java"
export JAVAC="javac -g"