summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2014-02-27 12:26:20 -0800
committerAndreas Gampe <agampe@google.com>2014-03-03 23:27:12 +0000
commit2da882315a61072664f7ce3c212307342e907207 (patch)
tree67d777be044f5b60e2f13ab7968b63c581904ea9 /compiler
parent762d4e5b9e777ae64c4ba581af9c84b78a5e96a6 (diff)
downloadart-2da882315a61072664f7ce3c212307342e907207.zip
art-2da882315a61072664f7ce3c212307342e907207.tar.gz
art-2da882315a61072664f7ce3c212307342e907207.tar.bz2
Initial changes towards Generic JNI option
Some initial changes that lead to an UNIMPLEMENTED. Works by not compiling for JNI right now and tracking native methods which have neither quick nor portable code. Uses new trampoline. Change-Id: I5448654044eb2717752fd7359f4ef8bd5c17be6e
Diffstat (limited to 'compiler')
-rw-r--r--compiler/common_compiler_test.h7
-rw-r--r--compiler/dex/compiler_ir.h1
-rw-r--r--compiler/dex/frontend.cc2
-rw-r--r--compiler/dex/quick/codegen_util.cc30
-rw-r--r--compiler/driver/compiler_driver.cc9
-rw-r--r--compiler/driver/compiler_driver.h2
-rw-r--r--compiler/image_writer.cc19
-rw-r--r--compiler/image_writer.h5
-rw-r--r--compiler/oat_test.cc2
-rw-r--r--compiler/oat_writer.cc5
-rw-r--r--compiler/oat_writer.h2
11 files changed, 61 insertions, 23 deletions
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index d034b79..3bdc95e 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -203,8 +203,11 @@ class CommonCompilerTest : public CommonRuntimeTest {
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
} else {
// No code? You must mean to go into the interpreter.
- const void* method_code = kUsePortableCompiler ? GetPortableToInterpreterBridge()
- : GetQuickToInterpreterBridge();
+ // Or the generic JNI...
+ const void* method_code = method->IsNative() ? GetQuickGenericJniTrampoline()
+ : (kUsePortableCompiler
+ ? GetPortableToInterpreterBridge()
+ : GetQuickToInterpreterBridge());
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
kStackAlignment,
0,
diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h
index b9a26d6..ee88041 100644
--- a/compiler/dex/compiler_ir.h
+++ b/compiler/dex/compiler_ir.h
@@ -63,6 +63,7 @@ struct CompilationUnit {
bool verbose;
const CompilerBackend* compiler_backend;
InstructionSet instruction_set;
+ bool target64;
InstructionSetFeatures GetInstructionSetFeatures() {
return compiler_driver->GetInstructionSetFeatures();
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 2619258..b55b471 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -148,7 +148,9 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver,
cu.compiler_driver = &driver;
cu.class_linker = class_linker;
cu.instruction_set = driver.GetInstructionSet();
+ cu.target64 = cu.instruction_set == kX86_64;
cu.compiler_backend = compiler_backend;
+ // TODO: x86_64 is not yet implemented.
DCHECK((cu.instruction_set == kThumb2) ||
(cu.instruction_set == kX86) ||
(cu.instruction_set == kMips));
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index db7bdc8..eb6f9d1 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -374,21 +374,21 @@ LIR* Mir2Lir::AddWideData(LIR* *constant_list_p, int val_lo, int val_hi) {
return AddWordData(constant_list_p, val_lo);
}
-static void PushWord(std::vector<uint8_t>&buf, int data) {
+static void Push32(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);
}
-// Push 8 bytes on 64-bit systems; 4 on 32-bit systems.
-static void PushPointer(std::vector<uint8_t>&buf, void const* pointer) {
- uintptr_t data = reinterpret_cast<uintptr_t>(pointer);
- if (sizeof(void*) == sizeof(uint64_t)) {
- PushWord(buf, (data >> (sizeof(void*) * 4)) & 0xFFFFFFFF);
- PushWord(buf, data & 0xFFFFFFFF);
+// Push 8 bytes on 64-bit target systems; 4 on 32-bit target systems.
+static void PushPointer(std::vector<uint8_t>&buf, const void* pointer, bool target64) {
+ uint64_t data = reinterpret_cast<uintptr_t>(pointer);
+ if (target64) {
+ Push32(buf, data & 0xFFFFFFFF);
+ Push32(buf, (data >> 32) & 0xFFFFFFFF);
} else {
- PushWord(buf, data);
+ Push32(buf, static_cast<uint32_t>(data));
}
}
@@ -403,7 +403,7 @@ void Mir2Lir::InstallLiteralPools() {
AlignBuffer(code_buffer_, data_offset_);
LIR* data_lir = literal_list_;
while (data_lir != NULL) {
- PushWord(code_buffer_, data_lir->operands[0]);
+ Push32(code_buffer_, data_lir->operands[0]);
data_lir = NEXT_LIR(data_lir);
}
// Push code and method literals, record offsets for the compiler to patch.
@@ -419,7 +419,7 @@ void Mir2Lir::InstallLiteralPools() {
code_buffer_.size());
const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
// unique value based on target to ensure code deduplication works
- PushPointer(code_buffer_, &id);
+ PushPointer(code_buffer_, &id, cu_->target64);
data_lir = NEXT_LIR(data_lir);
}
data_lir = method_literal_list_;
@@ -434,7 +434,7 @@ void Mir2Lir::InstallLiteralPools() {
code_buffer_.size());
const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
// unique value based on target to ensure code deduplication works
- PushPointer(code_buffer_, &id);
+ PushPointer(code_buffer_, &id, cu_->target64);
data_lir = NEXT_LIR(data_lir);
}
// Push class literals.
@@ -448,7 +448,7 @@ void Mir2Lir::InstallLiteralPools() {
code_buffer_.size());
const DexFile::TypeId& id = cu_->dex_file->GetTypeId(target);
// unique value based on target to ensure code deduplication works
- PushPointer(code_buffer_, &id);
+ PushPointer(code_buffer_, &id, cu_->target64);
data_lir = NEXT_LIR(data_lir);
}
}
@@ -492,8 +492,8 @@ void Mir2Lir::InstallSwitchTables() {
<< std::hex << keys[elems] << ", disp: 0x"
<< std::hex << disp;
}
- PushWord(code_buffer_, keys[elems]);
- PushWord(code_buffer_,
+ Push32(code_buffer_, keys[elems]);
+ Push32(code_buffer_,
tab_rec->targets[elems]->offset - bx_offset);
}
} else {
@@ -505,7 +505,7 @@ void Mir2Lir::InstallSwitchTables() {
LOG(INFO) << " Case[" << elems << "] disp: 0x"
<< std::hex << disp;
}
- PushWord(code_buffer_, tab_rec->targets[elems]->offset - bx_offset);
+ Push32(code_buffer_, tab_rec->targets[elems]->offset - bx_offset);
}
}
}
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 501ea7c..fc22add 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -440,6 +440,11 @@ const std::vector<uint8_t>* CompilerDriver::CreatePortableToInterpreterBridge()
PORTABLE_ENTRYPOINT_OFFSET(pPortableToInterpreterBridge));
}
+const std::vector<uint8_t>* CompilerDriver::CreateQuickGenericJniTrampoline() const {
+ return CreateTrampoline(instruction_set_, kQuickAbi,
+ QUICK_ENTRYPOINT_OFFSET(pQuickGenericJniTrampoline));
+}
+
const std::vector<uint8_t>* CompilerDriver::CreateQuickImtConflictTrampoline() const {
return CreateTrampoline(instruction_set_, kQuickAbi,
QUICK_ENTRYPOINT_OFFSET(pQuickImtConflictTrampoline));
@@ -1920,8 +1925,12 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t
uint64_t start_ns = NanoTime();
if ((access_flags & kAccNative) != 0) {
+#if defined(__x86_64__)
+ // leaving this empty will trigger the generic JNI version
+#else
compiled_method = compiler_backend_->JniCompile(*this, access_flags, method_idx, dex_file);
CHECK(compiled_method != NULL);
+#endif
} else if ((access_flags & kAccAbstract) != 0) {
} else {
MethodReference method_ref(&dex_file, method_idx);
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 57c2908..80a6796 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -164,6 +164,8 @@ class CompilerDriver {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const std::vector<uint8_t>* CreatePortableToInterpreterBridge() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const std::vector<uint8_t>* CreateQuickGenericJniTrampoline() const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const std::vector<uint8_t>* CreateQuickImtConflictTrampoline() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const std::vector<uint8_t>* CreateQuickResolutionTrampoline() const
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index aa16885..964cfe9 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -104,6 +104,8 @@ bool ImageWriter::Write(const std::string& image_filename,
portable_to_interpreter_bridge_offset_ =
oat_file_->GetOatHeader().GetPortableToInterpreterBridgeOffset();
+ quick_generic_jni_trampoline_offset_ =
+ oat_file_->GetOatHeader().GetQuickGenericJniTrampolineOffset();
quick_imt_conflict_trampoline_offset_ =
oat_file_->GetOatHeader().GetQuickImtConflictTrampolineOffset();
quick_resolution_trampoline_offset_ =
@@ -638,7 +640,12 @@ void ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) {
if (quick_code != nullptr) {
copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(quick_code);
} else {
- copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_resolution_trampoline_offset_));
+ if (orig->IsNative() && !orig->IsStatic()) {
+ // non-static native method missing compiled code, use generic JNI version
+ copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_generic_jni_trampoline_offset_));
+ } else {
+ copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_resolution_trampoline_offset_));
+ }
}
const byte* portable_code = GetOatAddress(orig->GetPortableOatCodeOffset());
if (portable_code != nullptr) {
@@ -807,6 +814,12 @@ void ImageWriter::PatchOatCodeAndMethods() {
uintptr_t value = quick_code - patch_location + patch->RelativeOffset();
SetPatchLocation(patch, value);
} else {
+ // generic JNI, not interpreter bridge from GetQuickOatCodeFor().
+ if (target->IsNative() &&
+ quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge())) {
+ code_offset = quick_generic_jni_trampoline_offset_;
+ }
+
SetPatchLocation(patch, PointerToLowMemUInt32(GetOatAddress(code_offset)));
}
}
@@ -845,7 +858,7 @@ void ImageWriter::SetPatchLocation(const CompilerDriver::PatchInformation* patch
if (patch->IsCall()) {
const CompilerDriver::CallPatchInformation* cpatch = patch->AsCall();
const DexFile::MethodId& id = cpatch->GetDexFile().GetMethodId(cpatch->GetTargetMethodIdx());
- uintptr_t expected = reinterpret_cast<uintptr_t>(&id);
+ uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
uint32_t actual = *patch_location;
CHECK(actual == expected || actual == value) << std::hex
<< "actual=" << actual
@@ -855,7 +868,7 @@ void ImageWriter::SetPatchLocation(const CompilerDriver::PatchInformation* patch
if (patch->IsType()) {
const CompilerDriver::TypePatchInformation* tpatch = patch->AsType();
const DexFile::TypeId& id = tpatch->GetDexFile().GetTypeId(tpatch->GetTargetTypeIdx());
- uintptr_t expected = reinterpret_cast<uintptr_t>(&id);
+ uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
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 a1504ee..dff33ba 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -41,8 +41,8 @@ class ImageWriter {
: compiler_driver_(compiler_driver), oat_file_(NULL), image_end_(0), image_begin_(NULL),
oat_data_begin_(NULL), interpreter_to_interpreter_bridge_offset_(0),
interpreter_to_compiled_code_bridge_offset_(0), portable_imt_conflict_trampoline_offset_(0),
- portable_resolution_trampoline_offset_(0), quick_imt_conflict_trampoline_offset_(0),
- quick_resolution_trampoline_offset_(0) {}
+ portable_resolution_trampoline_offset_(0), quick_generic_jni_trampoline_offset_(0),
+ quick_imt_conflict_trampoline_offset_(0), quick_resolution_trampoline_offset_(0) {}
~ImageWriter() {}
@@ -195,6 +195,7 @@ class ImageWriter {
uint32_t portable_imt_conflict_trampoline_offset_;
uint32_t portable_resolution_trampoline_offset_;
uint32_t portable_to_interpreter_bridge_offset_;
+ uint32_t quick_generic_jni_trampoline_offset_;
uint32_t quick_imt_conflict_trampoline_offset_;
uint32_t quick_resolution_trampoline_offset_;
uint32_t quick_to_interpreter_bridge_offset_;
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 6dbba9f..93c3502 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -175,7 +175,7 @@ TEST_F(OatTest, WriteRead) {
TEST_F(OatTest, OatHeaderSizeCheck) {
// If this test is failing and you have to update these constants,
// it is time to update OatHeader::kOatVersion
- EXPECT_EQ(76U, sizeof(OatHeader));
+ EXPECT_EQ(80U, sizeof(OatHeader));
EXPECT_EQ(28U, sizeof(OatMethodOffsets));
}
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index a400bdd..181240e 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -60,6 +60,7 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
size_portable_imt_conflict_trampoline_(0),
size_portable_resolution_trampoline_(0),
size_portable_to_interpreter_bridge_(0),
+ size_quick_generic_jni_trampoline_(0),
size_quick_imt_conflict_trampoline_(0),
size_quick_resolution_trampoline_(0),
size_quick_to_interpreter_bridge_(0),
@@ -256,6 +257,7 @@ size_t OatWriter::InitOatCode(size_t offset) {
DO_TRAMPOLINE(portable_imt_conflict_trampoline_, PortableImtConflictTrampoline);
DO_TRAMPOLINE(portable_resolution_trampoline_, PortableResolutionTrampoline);
DO_TRAMPOLINE(portable_to_interpreter_bridge_, PortableToInterpreterBridge);
+ DO_TRAMPOLINE(quick_generic_jni_trampoline_, QuickGenericJniTrampoline);
DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline);
DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline);
DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge);
@@ -268,6 +270,7 @@ size_t OatWriter::InitOatCode(size_t offset) {
oat_header_->SetPortableImtConflictTrampolineOffset(0);
oat_header_->SetPortableResolutionTrampolineOffset(0);
oat_header_->SetPortableToInterpreterBridgeOffset(0);
+ oat_header_->SetQuickGenericJniTrampolineOffset(0);
oat_header_->SetQuickImtConflictTrampolineOffset(0);
oat_header_->SetQuickResolutionTrampolineOffset(0);
oat_header_->SetQuickToInterpreterBridgeOffset(0);
@@ -576,6 +579,7 @@ bool OatWriter::Write(OutputStream* out) {
DO_STAT(size_portable_imt_conflict_trampoline_);
DO_STAT(size_portable_resolution_trampoline_);
DO_STAT(size_portable_to_interpreter_bridge_);
+ DO_STAT(size_quick_generic_jni_trampoline_);
DO_STAT(size_quick_imt_conflict_trampoline_);
DO_STAT(size_quick_resolution_trampoline_);
DO_STAT(size_quick_to_interpreter_bridge_);
@@ -675,6 +679,7 @@ size_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset) {
DO_TRAMPOLINE(portable_imt_conflict_trampoline_);
DO_TRAMPOLINE(portable_resolution_trampoline_);
DO_TRAMPOLINE(portable_to_interpreter_bridge_);
+ DO_TRAMPOLINE(quick_generic_jni_trampoline_);
DO_TRAMPOLINE(quick_imt_conflict_trampoline_);
DO_TRAMPOLINE(quick_resolution_trampoline_);
DO_TRAMPOLINE(quick_to_interpreter_bridge_);
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 3d4b48a..bab1a26 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -243,6 +243,7 @@ class OatWriter {
UniquePtr<const std::vector<uint8_t> > portable_imt_conflict_trampoline_;
UniquePtr<const std::vector<uint8_t> > portable_resolution_trampoline_;
UniquePtr<const std::vector<uint8_t> > portable_to_interpreter_bridge_;
+ UniquePtr<const std::vector<uint8_t> > quick_generic_jni_trampoline_;
UniquePtr<const std::vector<uint8_t> > quick_imt_conflict_trampoline_;
UniquePtr<const std::vector<uint8_t> > quick_resolution_trampoline_;
UniquePtr<const std::vector<uint8_t> > quick_to_interpreter_bridge_;
@@ -259,6 +260,7 @@ class OatWriter {
uint32_t size_portable_imt_conflict_trampoline_;
uint32_t size_portable_resolution_trampoline_;
uint32_t size_portable_to_interpreter_bridge_;
+ uint32_t size_quick_generic_jni_trampoline_;
uint32_t size_quick_imt_conflict_trampoline_;
uint32_t size_quick_resolution_trampoline_;
uint32_t size_quick_to_interpreter_bridge_;