summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/Android.mk9
-rw-r--r--compiler/dex/dex_to_dex_compiler.cc4
-rw-r--r--compiler/dex/portable/mir_to_gbc.cc2
-rw-r--r--compiler/dex/quick/gen_common.cc26
-rw-r--r--compiler/dex/quick/gen_invoke.cc10
-rw-r--r--compiler/driver/compiler_driver.cc55
-rw-r--r--compiler/driver/compiler_driver.h6
-rw-r--r--compiler/driver/compiler_driver_test.cc6
-rw-r--r--compiler/elf_writer.cc2
-rw-r--r--compiler/elf_writer_mclinker.cc6
-rw-r--r--compiler/image_writer.cc46
-rw-r--r--compiler/image_writer.h2
-rw-r--r--compiler/jni/jni_compiler_test.cc4
-rw-r--r--compiler/jni/portable/jni_compiler.cc6
-rw-r--r--compiler/jni/portable/jni_compiler.h2
-rw-r--r--compiler/jni/quick/jni_compiler.cc4
-rw-r--r--compiler/llvm/compiler_llvm.h2
-rw-r--r--compiler/llvm/gbc_expander.cc20
-rw-r--r--compiler/llvm/llvm_compilation_unit.cc4
-rw-r--r--compiler/llvm/runtime_support_builder_thumb2.cc4
-rw-r--r--compiler/oat_writer.cc8
-rw-r--r--compiler/sea_ir/code_gen/code_gen.cc (renamed from compiler/sea_ir/code_gen.cc)26
-rw-r--r--compiler/sea_ir/code_gen/code_gen.h (renamed from compiler/sea_ir/code_gen.h)14
-rw-r--r--compiler/sea_ir/debug/dot_gen.cc173
-rw-r--r--compiler/sea_ir/debug/dot_gen.h119
-rw-r--r--compiler/sea_ir/frontend.cc23
-rw-r--r--compiler/sea_ir/ir/instruction_nodes.h (renamed from compiler/sea_ir/instruction_nodes.h)46
-rw-r--r--compiler/sea_ir/ir/instruction_tools.cc (renamed from compiler/sea_ir/instruction_tools.cc)2
-rw-r--r--compiler/sea_ir/ir/instruction_tools.h (renamed from compiler/sea_ir/instruction_tools.h)6
-rw-r--r--compiler/sea_ir/ir/regions_test.cc59
-rw-r--r--compiler/sea_ir/ir/sea.cc (renamed from compiler/sea_ir/sea.cc)145
-rw-r--r--compiler/sea_ir/ir/sea.h (renamed from compiler/sea_ir/sea.h)110
-rw-r--r--compiler/sea_ir/ir/sea_node.h (renamed from compiler/sea_ir/sea_node.h)10
-rw-r--r--compiler/sea_ir/ir/visitor.h (renamed from compiler/sea_ir/visitor.h)21
-rw-r--r--compiler/sea_ir/types/type_data_test.cc41
-rw-r--r--compiler/sea_ir/types/type_inference.cc180
-rw-r--r--compiler/sea_ir/types/type_inference.h94
-rw-r--r--compiler/sea_ir/types/type_inference_visitor.cc103
-rw-r--r--compiler/sea_ir/types/type_inference_visitor.h81
-rw-r--r--compiler/sea_ir/types/type_inference_visitor_test.cc133
-rw-r--r--compiler/sea_ir/types/types.h58
-rw-r--r--compiler/utils/scoped_hashtable_test.cc2
42 files changed, 1311 insertions, 363 deletions
diff --git a/compiler/Android.mk b/compiler/Android.mk
index f81b460ee4..5caf688d29 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -94,9 +94,12 @@ LIBART_COMPILER_SRC_FILES := \
ifeq ($(ART_SEA_IR_MODE),true)
LIBART_COMPILER_SRC_FILES += \
sea_ir/frontend.cc \
- sea_ir/instruction_tools.cc \
- sea_ir/sea.cc \
- sea_ir/code_gen.cc
+ sea_ir/ir/instruction_tools.cc \
+ sea_ir/ir/sea.cc \
+ sea_ir/code_gen/code_gen.cc \
+ sea_ir/types/type_inference.cc \
+ sea_ir/types/type_inference_visitor.cc \
+ sea_ir/debug/dot_gen.cc
endif
LIBART_COMPILER_CFLAGS :=
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 60e638c584..a0e2c1e9aa 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -20,10 +20,10 @@
#include "dex_instruction-inl.h"
#include "driver/compiler_driver.h"
#include "driver/dex_compilation_unit.h"
-#include "mirror/abstract_method-inl.h"
+#include "mirror/art_field-inl.h"
+#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
-#include "mirror/field-inl.h"
namespace art {
namespace optimizer {
diff --git a/compiler/dex/portable/mir_to_gbc.cc b/compiler/dex/portable/mir_to_gbc.cc
index 90cec75039..7831cf6f7a 100644
--- a/compiler/dex/portable/mir_to_gbc.cc
+++ b/compiler/dex/portable/mir_to_gbc.cc
@@ -1972,7 +1972,7 @@ void MirConverter::MethodMIR2Bitcode() {
::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
new ::llvm::tool_output_file(fname.c_str(), errmsg,
- ::llvm::sys::fs::F_Binary));
+ ::llvm::raw_fd_ostream::F_Binary));
if (!errmsg.empty()) {
LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 298d3898c8..e5c7fb150e 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -347,7 +347,7 @@ void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_do
RegLocation rl_method = LoadCurrMethod();
rBase = AllocTemp();
LoadWordDisp(rl_method.low_reg,
- mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), rBase);
+ mirror::ArtMethod::DeclaringClassOffset().Int32Value(), rBase);
if (IsTemp(rl_method.low_reg)) {
FreeTemp(rl_method.low_reg);
}
@@ -365,7 +365,7 @@ void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_do
rBase = TargetReg(kArg0);
LockTemp(rBase);
LoadWordDisp(r_method,
- mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
+ mirror::ArtMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
rBase);
LoadWordDisp(rBase,
mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
@@ -433,7 +433,7 @@ void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest,
RegLocation rl_method = LoadCurrMethod();
rBase = AllocTemp();
LoadWordDisp(rl_method.low_reg,
- mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), rBase);
+ mirror::ArtMethod::DeclaringClassOffset().Int32Value(), rBase);
} else {
// Medium path, static storage base in a different class which requires checks that the other
// class is initialized
@@ -448,7 +448,7 @@ void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest,
rBase = TargetReg(kArg0);
LockTemp(rBase);
LoadWordDisp(r_method,
- mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
+ mirror::ArtMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
rBase);
LoadWordDisp(rBase, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
sizeof(int32_t*) * ssb_index, rBase);
@@ -746,7 +746,7 @@ void Mir2Lir::GenConstClass(uint32_t type_idx, RegLocation rl_dest) {
} else {
// We're don't need access checks, load type from dex cache
int32_t dex_cache_offset =
- mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value();
+ mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
LoadWordDisp(rl_method.low_reg, dex_cache_offset, res_reg);
int32_t offset_of_type =
mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
@@ -799,7 +799,7 @@ void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
LockCallTemps(); // Using explicit registers
LoadCurrMethodDirect(TargetReg(kArg2));
LoadWordDisp(TargetReg(kArg2),
- mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), TargetReg(kArg0));
+ mirror::ArtMethod::DexCacheStringsOffset().Int32Value(), TargetReg(kArg0));
// Might call out to helper, which will return resolved string in kRet0
int r_tgt = CallHelperSetup(QUICK_ENTRYPOINT_OFFSET(pResolveString));
LoadWordDisp(TargetReg(kArg0), offset_of_string, TargetReg(kRet0));
@@ -835,7 +835,7 @@ void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
int res_reg = AllocTemp();
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
LoadWordDisp(rl_method.low_reg,
- mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), res_reg);
+ mirror::ArtMethod::DexCacheStringsOffset().Int32Value(), res_reg);
LoadWordDisp(res_reg, offset_of_string, rl_result.low_reg);
StoreValue(rl_dest, rl_result);
}
@@ -884,11 +884,11 @@ void Mir2Lir::GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx, Re
LoadCurrMethodDirect(check_class);
if (use_declaring_class) {
- LoadWordDisp(check_class, mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+ LoadWordDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
check_class);
LoadWordDisp(object.low_reg, mirror::Object::ClassOffset().Int32Value(), object_class);
} else {
- LoadWordDisp(check_class, mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(),
+ LoadWordDisp(check_class, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
check_class);
LoadWordDisp(object.low_reg, mirror::Object::ClassOffset().Int32Value(), object_class);
int32_t offset_of_type =
@@ -940,12 +940,12 @@ void Mir2Lir::GenInstanceofCallingHelper(bool needs_access_check, bool type_know
} else if (use_declaring_class) {
LoadValueDirectFixed(rl_src, TargetReg(kArg0)); // kArg0 <= ref
LoadWordDisp(TargetReg(kArg1),
- mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), class_reg);
+ mirror::ArtMethod::DeclaringClassOffset().Int32Value(), class_reg);
} else {
// Load dex cache entry into class_reg (kArg2)
LoadValueDirectFixed(rl_src, TargetReg(kArg0)); // kArg0 <= ref
LoadWordDisp(TargetReg(kArg1),
- mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
+ mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
int32_t offset_of_type =
mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
* type_idx);
@@ -1078,11 +1078,11 @@ void Mir2Lir::GenCheckCast(uint32_t insn_idx, uint32_t type_idx, RegLocation rl_
OpRegCopy(class_reg, TargetReg(kRet0)); // Align usage with fast path
} else if (use_declaring_class) {
LoadWordDisp(TargetReg(kArg1),
- mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), class_reg);
+ mirror::ArtMethod::DeclaringClassOffset().Int32Value(), class_reg);
} else {
// Load dex cache entry into class_reg (kArg2)
LoadWordDisp(TargetReg(kArg1),
- mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
+ mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
int32_t offset_of_type =
mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() +
(sizeof(mirror::Class*) * type_idx);
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 20d683a947..073b550d78 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -365,7 +365,7 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
break;
case 1: // Get method->dex_cache_resolved_methods_
cg->LoadWordDisp(cg->TargetReg(kArg0),
- mirror::AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0));
+ mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0));
// Set up direct code if known.
if (direct_code != 0) {
if (direct_code != static_cast<unsigned int>(-1)) {
@@ -395,7 +395,7 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
if (cu->instruction_set != kX86) {
if (direct_code == 0) {
cg->LoadWordDisp(cg->TargetReg(kArg0),
- mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
cg->TargetReg(kInvokeTgt));
}
break;
@@ -448,7 +448,7 @@ static int NextVCallInsn(CompilationUnit* cu, CallInfo* info,
case 4: // Get the compiled code address [uses kArg0, sets kInvokeTgt]
if (cu->instruction_set != kX86) {
cg->LoadWordDisp(cg->TargetReg(kArg0),
- mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
cg->TargetReg(kInvokeTgt));
break;
}
@@ -514,7 +514,7 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state,
break;
case 1: // Get method->dex_cache_resolved_methods_ [set/use kArg0]
cg->LoadWordDisp(cg->TargetReg(kArg0),
- mirror::AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(),
+ mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
cg->TargetReg(kArg0));
break;
case 2: // Grab target method* [set/use kArg0]
@@ -1407,7 +1407,7 @@ void Mir2Lir::GenInvoke(CallInfo* info) {
} else {
if (fast_path && info->type != kInterface) {
call_inst = OpMem(kOpBlx, TargetReg(kArg0),
- mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value());
+ mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value());
} else {
ThreadOffset trampoline(-1);
switch (info->type) {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 56b629c576..b8727fe103 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -16,8 +16,10 @@
#include "compiler_driver.h"
-#include <vector>
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include <utils/Trace.h>
+#include <vector>
#include <unistd.h>
#include "base/stl_util.h"
@@ -31,11 +33,11 @@
#include "gc/accounting/card_table-inl.h"
#include "gc/accounting/heap_bitmap.h"
#include "gc/space/space.h"
+#include "mirror/art_field-inl.h"
+#include "mirror/art_method-inl.h"
#include "mirror/class_loader.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
-#include "mirror/field-inl.h"
-#include "mirror/abstract_method-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/throwable.h"
@@ -62,7 +64,7 @@ static void DumpStat(size_t x, size_t y, const char* str) {
if (x == 0 && y == 0) {
return;
}
- LOG(INFO) << Percentage(x, y) << "% of " << str << " for " << (x + y) << " cases";
+ VLOG(compiler) << Percentage(x, y) << "% of " << str << " for " << (x + y) << " cases";
}
class AOTCompilationStats {
@@ -513,7 +515,7 @@ static DexToDexCompilationLevel GetDexToDexCompilationlevel(mirror::ClassLoader*
}
}
-void CompilerDriver::CompileOne(const mirror::AbstractMethod* method, base::TimingLogger& timings) {
+void CompilerDriver::CompileOne(const mirror::ArtMethod* method, base::TimingLogger& timings) {
DCHECK(!Runtime::Current()->IsStarted());
Thread* self = Thread::Current();
jobject jclass_loader;
@@ -630,12 +632,12 @@ static bool ResolveCatchBlockExceptionsClassVisitor(mirror::Class* c, void* arg)
reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*> >*>(arg);
MethodHelper mh;
for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
- mirror::AbstractMethod* m = c->GetVirtualMethod(i);
+ mirror::ArtMethod* m = c->GetVirtualMethod(i);
mh.ChangeMethod(m);
ResolveExceptionsForMethod(&mh, *exceptions_to_resolve);
}
for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
- mirror::AbstractMethod* m = c->GetDirectMethod(i);
+ mirror::ArtMethod* m = c->GetDirectMethod(i);
mh.ChangeMethod(m);
ResolveExceptionsForMethod(&mh, *exceptions_to_resolve);
}
@@ -722,7 +724,7 @@ static void MaybeAddToImageClasses(mirror::Class* klass, CompilerDriver::Descrip
std::pair<CompilerDriver::DescriptorSet::iterator, bool> result =
image_classes->insert(descriptor);
if (result.second) {
- LOG(INFO) << "Adding " << descriptor << " to image classes";
+ VLOG(compiler) << "Adding " << descriptor << " to image classes";
} else {
return;
}
@@ -893,7 +895,7 @@ static mirror::Class* ComputeCompilingMethodsClass(ScopedObjectAccess& soa,
dex_cache, class_loader);
}
-static mirror::Field* ComputeFieldReferencedFromCompilingMethod(ScopedObjectAccess& soa,
+static mirror::ArtField* ComputeFieldReferencedFromCompilingMethod(ScopedObjectAccess& soa,
const DexCompilationUnit* mUnit,
uint32_t field_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -903,7 +905,7 @@ static mirror::Field* ComputeFieldReferencedFromCompilingMethod(ScopedObjectAcce
class_loader, false);
}
-static mirror::AbstractMethod* ComputeMethodReferencedFromCompilingMethod(ScopedObjectAccess& soa,
+static mirror::ArtMethod* ComputeMethodReferencedFromCompilingMethod(ScopedObjectAccess& soa,
const DexCompilationUnit* mUnit,
uint32_t method_idx,
InvokeType type)
@@ -921,7 +923,7 @@ bool CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompi
field_offset = -1;
is_volatile = true;
// Try to resolve field and ignore if an Incompatible Class Change Error (ie is static).
- mirror::Field* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx);
+ mirror::ArtField* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx);
if (resolved_field != NULL && !resolved_field->IsStatic()) {
mirror::Class* referrer_class =
ComputeCompilingMethodsClass(soa, resolved_field->GetDeclaringClass()->GetDexCache(),
@@ -972,7 +974,7 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila
is_referrers_class = false;
is_volatile = true;
// Try to resolve field and ignore if an Incompatible Class Change Error (ie isn't static).
- mirror::Field* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx);
+ mirror::ArtField* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx);
if (resolved_field != NULL && resolved_field->IsStatic()) {
mirror::Class* referrer_class =
ComputeCompilingMethodsClass(soa, resolved_field->GetDeclaringClass()->GetDexCache(),
@@ -1049,7 +1051,7 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila
void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type,
mirror::Class* referrer_class,
- mirror::AbstractMethod* method,
+ mirror::ArtMethod* method,
uintptr_t& direct_code,
uintptr_t& direct_method,
bool update_stats) {
@@ -1112,7 +1114,7 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui
vtable_idx = -1;
direct_code = 0;
direct_method = 0;
- mirror::AbstractMethod* resolved_method =
+ mirror::ArtMethod* resolved_method =
ComputeMethodReferencedFromCompilingMethod(soa, mUnit, target_method.dex_method_index,
invoke_type);
if (resolved_method != NULL) {
@@ -1177,7 +1179,7 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui
mUnit->GetClassLinker()->FindDexCache(*devirt_map_target->dex_file);
mirror::ClassLoader* class_loader =
soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader());
- mirror::AbstractMethod* called_method =
+ mirror::ArtMethod* called_method =
mUnit->GetClassLinker()->ResolveMethod(*devirt_map_target->dex_file,
devirt_map_target->dex_method_index,
target_dex_cache, class_loader, NULL,
@@ -1469,7 +1471,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag
mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file);
ClassDataItemIterator it(dex_file, class_data);
while (it.HasNextStaticField()) {
- mirror::Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
+ mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
class_loader, true);
if (field == NULL) {
CHECK(self->IsExceptionPending());
@@ -1485,7 +1487,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag
requires_constructor_barrier = true;
}
- mirror::Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
+ mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
class_loader, false);
if (field == NULL) {
CHECK(self->IsExceptionPending());
@@ -1498,7 +1500,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag
class_def_index);
}
while (it.HasNextDirectMethod()) {
- mirror::AbstractMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
+ mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
dex_cache, class_loader, NULL,
it.GetMethodInvokeType(class_def));
if (method == NULL) {
@@ -1508,7 +1510,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag
it.Next();
}
while (it.HasNextVirtualMethod()) {
- mirror::AbstractMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
+ mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
dex_cache, class_loader, NULL,
it.GetMethodInvokeType(class_def));
if (method == NULL) {
@@ -1562,14 +1564,14 @@ void CompilerDriver::Verify(jobject class_loader, const std::vector<const DexFil
static void VerifyClass(const ParallelCompilationManager* manager, size_t class_def_index)
LOCKS_EXCLUDED(Locks::mutator_lock_) {
+ ATRACE_CALL();
ScopedObjectAccess soa(Thread::Current());
const DexFile::ClassDef& class_def = manager->GetDexFile()->GetClassDef(class_def_index);
const char* descriptor = manager->GetDexFile()->GetClassDescriptor(class_def);
mirror::Class* klass =
manager->GetClassLinker()->FindClass(descriptor,
soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()));
- if (klass == NULL) {
- CHECK(soa.Self()->IsExceptionPending());
+ if (klass == NULL) { CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
/*
@@ -1600,6 +1602,7 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_
soa.Self()->ClearException();
}
+
CHECK(klass->IsCompileTimeVerified() || klass->IsErroneous())
<< PrettyDescriptor(klass) << ": state=" << klass->GetStatus();
soa.Self()->AssertNoPendingException();
@@ -2067,10 +2070,10 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
}
}
if (!is_black_listed) {
- LOG(INFO) << "Initializing: " << descriptor;
+ VLOG(compiler) << "Initializing: " << descriptor;
if (StringPiece(descriptor) == "Ljava/lang/Void;") {
// Hand initialize j.l.Void to avoid Dex file operations in un-started runtime.
- mirror::ObjectArray<mirror::Field>* fields = klass->GetSFields();
+ mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
CHECK_EQ(fields->GetLength(), 1);
fields->Get(0)->SetObj(klass, manager->GetClassLinker()->FindPrimitiveClass('V'));
klass->SetStatus(mirror::Class::kStatusInitialized);
@@ -2135,6 +2138,7 @@ void CompilerDriver::Compile(jobject class_loader, const std::vector<const DexFi
}
void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, size_t class_def_index) {
+ ATRACE_CALL();
jobject jclass_loader = manager->GetClassLoader();
const DexFile& dex_file = *manager->GetDexFile();
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
@@ -2155,6 +2159,7 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz
// empty class, probably a marker interface
return;
}
+
// Can we run DEX-to-DEX compiler on this class ?
DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile;
{
@@ -2227,10 +2232,6 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t
} else {
bool compile = verifier::MethodVerifier::IsCandidateForCompilation(code_item, access_flags);
if (compile) {
- // If we're doing the image, override the compiler filter to force full compilation.
- if ((image_classes_.get() != NULL) && (image_classes_->size() != 0)) {
- Runtime::Current()->SetCompilerFilter(Runtime::kSpeed);
- }
CompilerFn compiler = compiler_;
#ifdef ART_SEA_IR_MODE
bool use_sea = Runtime::Current()->IsSeaIRMode();
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index b5222c99b8..21a44eaf12 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -99,7 +99,7 @@ class CompilerDriver {
LOCKS_EXCLUDED(Locks::mutator_lock_);
// Compile a single Method
- void CompileOne(const mirror::AbstractMethod* method, base::TimingLogger& timings)
+ void CompileOne(const mirror::ArtMethod* method, base::TimingLogger& timings)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
InstructionSet GetInstructionSet() const {
@@ -301,7 +301,7 @@ class CompilerDriver {
// Compute constant code and method pointers when possible
void GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type,
mirror::Class* referrer_class,
- mirror::AbstractMethod* method,
+ mirror::ArtMethod* method,
uintptr_t& direct_code, uintptr_t& direct_method,
bool update_stats)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -425,7 +425,7 @@ class CompilerDriver {
CompilerEnableAutoElfLoadingFn compiler_enable_auto_elf_loading_;
typedef const void* (*CompilerGetMethodCodeAddrFn)
- (const CompilerDriver& driver, const CompiledMethod* cm, const mirror::AbstractMethod* method);
+ (const CompilerDriver& driver, const CompiledMethod* cm, const mirror::ArtMethod* method);
CompilerGetMethodCodeAddrFn compiler_get_method_code_addr_;
bool support_boot_image_fixup_;
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 8ee9cf6442..c6687bb4aa 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -24,10 +24,10 @@
#include "common_test.h"
#include "dex_file.h"
#include "gc/heap.h"
+#include "mirror/art_method-inl.h"
#include "mirror/class.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
-#include "mirror/abstract_method-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
@@ -115,7 +115,7 @@ TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
}
EXPECT_EQ(dex->NumMethodIds(), dex_cache->NumResolvedMethods());
for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
- mirror::AbstractMethod* method = dex_cache->GetResolvedMethod(i);
+ mirror::ArtMethod* method = dex_cache->GetResolvedMethod(i);
EXPECT_TRUE(method != NULL) << "method_idx=" << i
<< " " << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
<< " " << dex->GetMethodName(dex->GetMethodId(i));
@@ -126,7 +126,7 @@ TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
}
EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumResolvedFields());
for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
- mirror::Field* field = dex_cache->GetResolvedField(i);
+ mirror::ArtField* field = dex_cache->GetResolvedField(i);
EXPECT_TRUE(field != NULL) << "field_idx=" << i
<< " " << dex->GetFieldDeclaringClassDescriptor(dex->GetFieldId(i))
<< " " << dex->GetFieldName(dex->GetFieldId(i));
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index 70d17de102..d3c13dd791 100644
--- a/compiler/elf_writer.cc
+++ b/compiler/elf_writer.cc
@@ -24,7 +24,7 @@
#include "elf_file.h"
#include "invoke_type.h"
#include "llvm/utils_llvm.h"
-#include "mirror/abstract_method-inl.h"
+#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
#include "oat.h"
#include "scoped_thread_state_change.h"
diff --git a/compiler/elf_writer_mclinker.cc b/compiler/elf_writer_mclinker.cc
index 2a9bc35559..e496ace27a 100644
--- a/compiler/elf_writer_mclinker.cc
+++ b/compiler/elf_writer_mclinker.cc
@@ -33,8 +33,8 @@
#include "driver/compiler_driver.h"
#include "elf_file.h"
#include "globals.h"
-#include "mirror/abstract_method.h"
-#include "mirror/abstract_method-inl.h"
+#include "mirror/art_method.h"
+#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
#include "oat_writer.h"
#include "scoped_thread_state_change.h"
@@ -353,7 +353,7 @@ void ElfWriterMclinker::FixupOatMethodOffsets(const std::vector<const DexFile*>&
const DexFile& dex_file = it.GetDexFile();
uint32_t method_idx = it.GetMemberIndex();
InvokeType invoke_type = it.GetInvokeType();
- mirror::AbstractMethod* method = NULL;
+ mirror::ArtMethod* method = NULL;
if (compiler_driver_->IsImage()) {
ClassLinker* linker = Runtime::Current()->GetClassLinker();
mirror::DexCache* dex_cache = linker->FindDexCache(dex_file);
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 3432c8cbee..a40e3fc149 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -35,12 +35,12 @@
#include "globals.h"
#include "image.h"
#include "intern_table.h"
+#include "mirror/art_field-inl.h"
+#include "mirror/art_method-inl.h"
#include "mirror/array-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
-#include "mirror/field-inl.h"
-#include "mirror/abstract_method-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "oat.h"
@@ -52,11 +52,11 @@
#include "UniquePtr.h"
#include "utils.h"
-using ::art::mirror::AbstractMethod;
+using ::art::mirror::ArtField;
+using ::art::mirror::ArtMethod;
using ::art::mirror::Class;
using ::art::mirror::DexCache;
using ::art::mirror::EntryPointFromInterpreter;
-using ::art::mirror::Field;
using ::art::mirror::Object;
using ::art::mirror::ObjectArray;
using ::art::mirror::String;
@@ -257,7 +257,7 @@ void ImageWriter::PruneNonImageClasses() {
}
// Clear references to removed classes from the DexCaches.
- AbstractMethod* resolution_method = runtime->GetResolutionMethod();
+ ArtMethod* resolution_method = runtime->GetResolutionMethod();
typedef Set::const_iterator CacheIt; // TODO: C++0x auto
for (CacheIt it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) {
DexCache* dex_cache = *it;
@@ -269,13 +269,13 @@ void ImageWriter::PruneNonImageClasses() {
}
}
for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
- AbstractMethod* method = dex_cache->GetResolvedMethod(i);
+ ArtMethod* method = dex_cache->GetResolvedMethod(i);
if (method != NULL && !IsImageClass(method->GetDeclaringClass())) {
dex_cache->SetResolvedMethod(i, resolution_method);
}
}
for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
- Field* field = dex_cache->GetResolvedField(i);
+ ArtField* field = dex_cache->GetResolvedField(i);
if (field != NULL && !IsImageClass(field->GetDeclaringClass())) {
dex_cache->SetResolvedField(i, NULL);
}
@@ -487,8 +487,8 @@ void ImageWriter::FixupObject(const Object* orig, Object* copy) {
FixupClass(orig->AsClass(), down_cast<Class*>(copy));
} else if (orig->IsObjectArray()) {
FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy));
- } else if (orig->IsMethod()) {
- FixupMethod(orig->AsMethod(), down_cast<AbstractMethod*>(copy));
+ } else if (orig->IsArtMethod()) {
+ FixupMethod(orig->AsArtMethod(), down_cast<ArtMethod*>(copy));
} else {
FixupInstanceFields(orig, copy);
}
@@ -499,7 +499,7 @@ void ImageWriter::FixupClass(const Class* orig, Class* copy) {
FixupStaticFields(orig, copy);
}
-void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) {
+void ImageWriter::FixupMethod(const ArtMethod* orig, ArtMethod* copy) {
FixupInstanceFields(orig, copy);
// OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
@@ -614,9 +614,9 @@ void ImageWriter::FixupFields(const Object* orig,
? klass->NumReferenceStaticFields()
: klass->NumReferenceInstanceFields());
for (size_t i = 0; i < num_reference_fields; ++i) {
- Field* field = (is_static
- ? klass->GetStaticField(i)
- : klass->GetInstanceField(i));
+ ArtField* field = (is_static
+ ? 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.
@@ -626,7 +626,7 @@ void ImageWriter::FixupFields(const Object* orig,
}
if (!is_static && orig->IsReferenceInstance()) {
// Fix-up referent, that isn't marked as an object field, for References.
- Field* field = orig->GetClass()->FindInstanceField("referent", "Ljava/lang/Object;");
+ 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.
@@ -634,16 +634,16 @@ void ImageWriter::FixupFields(const Object* orig,
}
}
-static AbstractMethod* GetTargetMethod(const CompilerDriver::PatchInformation* patch)
+static ArtMethod* GetTargetMethod(const CompilerDriver::PatchInformation* patch)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
DexCache* dex_cache = class_linker->FindDexCache(patch->GetDexFile());
- AbstractMethod* method = class_linker->ResolveMethod(patch->GetDexFile(),
- patch->GetTargetMethodIdx(),
- dex_cache,
- NULL,
- NULL,
- patch->GetTargetInvokeType());
+ ArtMethod* method = class_linker->ResolveMethod(patch->GetDexFile(),
+ patch->GetTargetMethodIdx(),
+ dex_cache,
+ NULL,
+ NULL,
+ patch->GetTargetInvokeType());
CHECK(method != NULL)
<< patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx();
CHECK(!method->IsRuntimeMethod())
@@ -664,7 +664,7 @@ void ImageWriter::PatchOatCodeAndMethods() {
const Patches& code_to_patch = compiler_driver_.GetCodeToPatch();
for (size_t i = 0; i < code_to_patch.size(); i++) {
const CompilerDriver::PatchInformation* patch = code_to_patch[i];
- AbstractMethod* target = GetTargetMethod(patch);
+ 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;
@@ -674,7 +674,7 @@ void ImageWriter::PatchOatCodeAndMethods() {
const Patches& methods_to_patch = compiler_driver_.GetMethodsToPatch();
for (size_t i = 0; i < methods_to_patch.size(); i++) {
const CompilerDriver::PatchInformation* patch = methods_to_patch[i];
- AbstractMethod* target = GetTargetMethod(patch);
+ ArtMethod* target = GetTargetMethod(patch);
SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target)));
}
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 545534fff7..750109d1d9 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -152,7 +152,7 @@ class ImageWriter {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void FixupClass(const mirror::Class* orig, mirror::Class* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupMethod(const mirror::AbstractMethod* orig, mirror::AbstractMethod* copy)
+ void FixupMethod(const mirror::ArtMethod* orig, mirror::ArtMethod* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void FixupObject(const mirror::Object* orig, mirror::Object* copy)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 4b6967faa0..a653ab42a9 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -21,9 +21,9 @@
#include "indirect_reference_table.h"
#include "jni_internal.h"
#include "mem_map.h"
+#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
-#include "mirror/abstract_method-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "mirror/stack_trace_element.h"
@@ -51,7 +51,7 @@ class JniCompilerTest : public CommonTest {
// Compile the native method before starting the runtime
mirror::Class* c = class_linker_->FindClass("LMyClassNatives;",
soa.Decode<mirror::ClassLoader*>(class_loader));
- mirror::AbstractMethod* method;
+ mirror::ArtMethod* method;
if (direct) {
method = c->FindDirectMethod(method_name, method_sig);
} else {
diff --git a/compiler/jni/portable/jni_compiler.cc b/compiler/jni/portable/jni_compiler.cc
index e05f291a73..58ee1c1602 100644
--- a/compiler/jni/portable/jni_compiler.cc
+++ b/compiler/jni/portable/jni_compiler.cc
@@ -27,7 +27,7 @@
#include "llvm/llvm_compilation_unit.h"
#include "llvm/runtime_support_llvm_func.h"
#include "llvm/utils_llvm.h"
-#include "mirror/abstract_method.h"
+#include "mirror/art_method.h"
#include "runtime.h"
#include "stack.h"
#include "thread.h"
@@ -91,7 +91,7 @@ CompiledMethod* JniCompiler::Compile() {
// Load class object
this_object_or_class_object =
irb_.LoadFromObjectOffset(method_object_addr,
- mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+ mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
irb_.getJObjectTy(),
kTBAAConstJObject);
}
@@ -135,7 +135,7 @@ CompiledMethod* JniCompiler::Compile() {
// Get callee code_addr
::llvm::Value* code_addr =
irb_.LoadFromObjectOffset(method_object_addr,
- mirror::AbstractMethod::NativeMethodOffset().Int32Value(),
+ mirror::ArtMethod::NativeMethodOffset().Int32Value(),
GetFunctionType(dex_compilation_unit_->GetDexMethodIndex(),
is_static, true)->getPointerTo(),
kTBAARuntimeInfo);
diff --git a/compiler/jni/portable/jni_compiler.h b/compiler/jni/portable/jni_compiler.h
index 9bdf35ef10..49cc9f4abf 100644
--- a/compiler/jni/portable/jni_compiler.h
+++ b/compiler/jni/portable/jni_compiler.h
@@ -28,7 +28,7 @@ namespace art {
class DexFile;
class DexCompilationUnit;
namespace mirror {
- class AbstractMethod;
+ class ArtMethod;
class ClassLoader;
class DexCache;
} // namespace mirror
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 9713fe9da9..069def60f9 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -119,7 +119,7 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver& compiler,
// Check sirt offset is within frame
CHECK_LT(sirt_offset.Uint32Value(), frame_size);
__ LoadRef(main_jni_conv->InterproceduralScratchRegister(),
- mr_conv->MethodRegister(), mirror::AbstractMethod::DeclaringClassOffset());
+ mr_conv->MethodRegister(), mirror::ArtMethod::DeclaringClassOffset());
__ VerifyObject(main_jni_conv->InterproceduralScratchRegister(), false);
__ StoreRef(sirt_offset, main_jni_conv->InterproceduralScratchRegister());
main_jni_conv->Next(); // in SIRT so move to next argument
@@ -270,7 +270,7 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver& compiler,
}
// 9. Plant call to native code associated with method.
- __ Call(main_jni_conv->MethodStackOffset(), mirror::AbstractMethod::NativeMethodOffset(),
+ __ Call(main_jni_conv->MethodStackOffset(), mirror::ArtMethod::NativeMethodOffset(),
mr_conv->InterproceduralScratchRegister());
// 10. Fix differences in result widths.
diff --git a/compiler/llvm/compiler_llvm.h b/compiler/llvm/compiler_llvm.h
index 20934ab209..65bc16bcd8 100644
--- a/compiler/llvm/compiler_llvm.h
+++ b/compiler/llvm/compiler_llvm.h
@@ -34,7 +34,7 @@ namespace art {
class CompilerDriver;
class DexCompilationUnit;
namespace mirror {
- class AbstractMethod;
+ class ArtMethod;
class ClassLoader;
} // namespace mirror
} // namespace art
diff --git a/compiler/llvm/gbc_expander.cc b/compiler/llvm/gbc_expander.cc
index a727d06cb2..4f6fa0a2df 100644
--- a/compiler/llvm/gbc_expander.cc
+++ b/compiler/llvm/gbc_expander.cc
@@ -20,7 +20,7 @@
#include "intrinsic_helper.h"
#include "ir_builder.h"
#include "method_reference.h"
-#include "mirror/abstract_method.h"
+#include "mirror/art_method.h"
#include "mirror/array.h"
#include "mirror/string.h"
#include "thread.h"
@@ -722,7 +722,7 @@ llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
llvm::Value*
GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
llvm::Value* static_storage_dex_cache_addr =
- EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset());
+ EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheInitializedStaticStorageOffset());
llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
@@ -732,7 +732,7 @@ GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
llvm::Value*
GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
llvm::Value* resolved_type_dex_cache_addr =
- EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedTypesOffset());
+ EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheResolvedTypesOffset());
llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
@@ -742,7 +742,7 @@ GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
llvm::Value* GBCExpanderPass::
EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
llvm::Value* resolved_method_dex_cache_addr =
- EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedMethodsOffset());
+ EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheResolvedMethodsOffset());
llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
@@ -752,7 +752,7 @@ EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
llvm::Value* GBCExpanderPass::
EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
llvm::Value* string_dex_cache_addr =
- EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheStringsOffset());
+ EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheStringsOffset());
llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
@@ -911,7 +911,7 @@ llvm::Value* GBCExpanderPass::EmitInvoke(llvm::CallInst& call_inst) {
} else {
code_addr =
irb_.LoadFromObjectOffset(callee_method_object_addr,
- art::mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ art::mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
func_type->getPointerTo(), kTBAARuntimeInfo);
}
@@ -1207,7 +1207,7 @@ void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
llvm::Value*
GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
return irb_.LoadFromObjectOffset(method_object_addr,
- art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+ art::mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
irb_.getJObjectTy(),
kTBAAConstJObject);
}
@@ -1259,7 +1259,7 @@ llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
llvm::Value* code_addr =
irb_.LoadFromObjectOffset(callee_method_object_addr,
- art::mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+ art::mirror::ArtMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
callee_method_type->getPointerTo(),
kTBAARuntimeInfo);
@@ -1938,7 +1938,7 @@ llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
static_storage_addr =
irb_.LoadFromObjectOffset(method_object_addr,
- art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+ art::mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
irb_.getJObjectTy(),
kTBAAConstJObject);
} else {
@@ -2023,7 +2023,7 @@ void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
static_storage_addr =
irb_.LoadFromObjectOffset(method_object_addr,
- art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+ art::mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
irb_.getJObjectTy(),
kTBAAConstJObject);
} else {
diff --git a/compiler/llvm/llvm_compilation_unit.cc b/compiler/llvm/llvm_compilation_unit.cc
index 7542b841a1..9296fc7050 100644
--- a/compiler/llvm/llvm_compilation_unit.cc
+++ b/compiler/llvm/llvm_compilation_unit.cc
@@ -214,6 +214,7 @@ bool LlvmCompilationUnit::MaterializeToRawOStream(::llvm::raw_ostream& out_strea
::llvm::TargetOptions target_options;
target_options.FloatABIType = ::llvm::FloatABI::Soft;
target_options.NoFramePointerElim = true;
+ target_options.NoFramePointerElimNonLeaf = true;
target_options.UseSoftFloat = false;
target_options.EnableFastISel = false;
@@ -257,7 +258,7 @@ bool LlvmCompilationUnit::MaterializeToRawOStream(::llvm::raw_ostream& out_strea
::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
new ::llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
- ::llvm::sys::fs::F_Binary));
+ ::llvm::raw_fd_ostream::F_Binary));
if (!errmsg.empty()) {
@@ -277,6 +278,7 @@ bool LlvmCompilationUnit::MaterializeToRawOStream(::llvm::raw_ostream& out_strea
// pm_builder.Inliner = ::llvm::createAlwaysInlinerPass();
// pm_builder.Inliner = ::llvm::createPartialInliningPass();
pm_builder.OptLevel = 3;
+ pm_builder.DisableSimplifyLibCalls = 1;
pm_builder.DisableUnitAtATime = 1;
pm_builder.populateFunctionPassManager(fpm);
pm_builder.populateModulePassManager(pm);
diff --git a/compiler/llvm/runtime_support_builder_thumb2.cc b/compiler/llvm/runtime_support_builder_thumb2.cc
index f0cb4a2d7b..eff29c8b04 100644
--- a/compiler/llvm/runtime_support_builder_thumb2.cc
+++ b/compiler/llvm/runtime_support_builder_thumb2.cc
@@ -51,8 +51,8 @@ void RuntimeSupportBuilderThumb2::EmitLockObject(Value* object) {
// $2: temp
// $3: temp
std::string asms;
- StringAppendF(&asms, "add $3, $1, #%"PRId32"\n", mirror::Object::MonitorOffset().Int32Value());
- StringAppendF(&asms, "ldr $2, [r9, #%"PRId32"]\n", Thread::ThinLockIdOffset().Int32Value());
+ StringAppendF(&asms, "add $3, $1, #%" PRId32 "\n", mirror::Object::MonitorOffset().Int32Value());
+ StringAppendF(&asms, "ldr $2, [r9, #%" PRId32 "]\n", Thread::ThinLockIdOffset().Int32Value());
StringAppendF(&asms, "ldrex $0, [$3]\n");
StringAppendF(&asms, "lsl $2, $2, %d\n", LW_LOCK_OWNER_SHIFT);
StringAppendF(&asms, "bfi $2, $0, #0, #%d\n", LW_LOCK_OWNER_SHIFT - 1);
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index ce88cf6dd6..f9d6e4192d 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -23,7 +23,7 @@
#include "class_linker.h"
#include "dex_file-inl.h"
#include "gc/space/space.h"
-#include "mirror/abstract_method-inl.h"
+#include "mirror/art_method-inl.h"
#include "mirror/array.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
@@ -400,7 +400,7 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file);
// Unchecked as we hold mutator_lock_ on entry.
ScopedObjectAccessUnchecked soa(Thread::Current());
- mirror::AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache,
+ mirror::ArtMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache,
NULL, NULL, invoke_type);
CHECK(method != NULL);
method->SetFrameSizeInBytes(frame_size_in_bytes);
@@ -464,7 +464,7 @@ bool OatWriter::Write(OutputStream& out) {
if (kIsDebugBuild) {
uint32_t size_total = 0;
#define DO_STAT(x) \
- LOG(INFO) << #x "=" << PrettySize(x) << " (" << x << "B)"; \
+ VLOG(compiler) << #x "=" << PrettySize(x) << " (" << x << "B)"; \
size_total += x;
DO_STAT(size_dex_file_alignment_);
@@ -495,7 +495,7 @@ bool OatWriter::Write(OutputStream& out) {
DO_STAT(size_oat_class_method_offsets_);
#undef DO_STAT
- LOG(INFO) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)"; \
+ VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)"; \
CHECK_EQ(file_offset + size_total, static_cast<uint32_t>(out.Seek(0, kSeekCurrent)));
CHECK_EQ(size_, size_total);
}
diff --git a/compiler/sea_ir/code_gen.cc b/compiler/sea_ir/code_gen/code_gen.cc
index a513907b38..cb150e58fa 100644
--- a/compiler/sea_ir/code_gen.cc
+++ b/compiler/sea_ir/code_gen/code_gen.cc
@@ -15,8 +15,8 @@
*/
#include <llvm/Support/raw_ostream.h>
-#include "sea.h"
-#include "code_gen.h"
+#include "sea_ir/ir/sea.h"
+#include "sea_ir/code_gen/code_gen.h"
namespace sea_ir {
@@ -114,6 +114,14 @@ void CodeGenVisitor::Visit(InstructionNode* instruction) {
std::string instr = instruction->GetInstruction()->DumpString(NULL);
DCHECK(0); // This whole function is useful only during development.
}
+
+void CodeGenVisitor::Visit(UnnamedConstInstructionNode* instruction) {
+ std::string instr = instruction->GetInstruction()->DumpString(NULL);
+ std::cout << "1.Instruction: " << instr << std::endl;
+ llvm_data_->AddValue(instruction,
+ llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
+}
+
void CodeGenVisitor::Visit(ConstInstructionNode* instruction) {
std::string instr = instruction->GetInstruction()->DumpString(NULL);
std::cout << "1.Instruction: " << instr << std::endl;
@@ -123,14 +131,14 @@ void CodeGenVisitor::Visit(ConstInstructionNode* instruction) {
void CodeGenVisitor::Visit(ReturnInstructionNode* instruction) {
std::string instr = instruction->GetInstruction()->DumpString(NULL);
std::cout << "2.Instruction: " << instr << std::endl;
- DCHECK_GT(instruction->GetSSAUses().size(), 0u);
- llvm::Value* return_value = llvm_data_->GetValue(instruction->GetSSAUses().at(0));
+ DCHECK_GT(instruction->GetSSAProducers().size(), 0u);
+ llvm::Value* return_value = llvm_data_->GetValue(instruction->GetSSAProducers().at(0));
llvm_data_->builder_.CreateRet(return_value);
}
void CodeGenVisitor::Visit(IfNeInstructionNode* instruction) {
std::string instr = instruction->GetInstruction()->DumpString(NULL);
std::cout << "3.Instruction: " << instr << std::endl;
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
+ std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
DCHECK_GT(ssa_uses.size(), 1u);
InstructionNode* use_l = ssa_uses.at(0);
llvm::Value* left = llvm_data_->GetValue(use_l);
@@ -171,7 +179,7 @@ void CodeGenVisitor::Visit(MoveResultInstructionNode* instruction) {
// since their purpose of minimizing the number of opcodes in dex is
// not relevant for the IR. (Will need to have different
// instruction subclasses for functions and procedures.)
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
+ std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
InstructionNode* use_l = ssa_uses.at(0);
llvm::Value* left = llvm_data_->GetValue(use_l);
llvm::Value* right = llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0));
@@ -187,7 +195,7 @@ void CodeGenVisitor::Visit(InvokeStaticInstructionNode* invoke) {
// TODO: Add proper checking of the matching between formal and actual signature.
DCHECK(NULL != callee);
std::vector<llvm::Value*> parameter_values;
- std::vector<InstructionNode*> parameter_sources = invoke->GetSSAUses();
+ std::vector<InstructionNode*> parameter_sources = invoke->GetSSAProducers();
for (std::vector<InstructionNode*>::const_iterator cit = parameter_sources.begin();
cit != parameter_sources.end(); ++cit) {
llvm::Value* parameter_value = llvm_data_->GetValue((*cit));
@@ -201,7 +209,7 @@ void CodeGenVisitor::Visit(InvokeStaticInstructionNode* invoke) {
void CodeGenVisitor::Visit(AddIntInstructionNode* instruction) {
std::string instr = instruction->GetInstruction()->DumpString(NULL);
std::cout << "7.Instruction: " << instr << std::endl;
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
+ std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
DCHECK_GT(ssa_uses.size(), 1u);
InstructionNode* use_l = ssa_uses.at(0);
InstructionNode* use_r = ssa_uses.at(1);
@@ -221,7 +229,7 @@ void CodeGenVisitor::Visit(GotoInstructionNode* instruction) {
void CodeGenVisitor::Visit(IfEqzInstructionNode* instruction) {
std::string instr = instruction->GetInstruction()->DumpString(NULL);
std::cout << "9. Instruction: " << instr << "; Id: " <<instruction << std::endl;
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
+ std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
DCHECK_GT(ssa_uses.size(), 0u);
InstructionNode* use_l = ssa_uses.at(0);
llvm::Value* left = llvm_data_->GetValue(use_l);
diff --git a/compiler/sea_ir/code_gen.h b/compiler/sea_ir/code_gen/code_gen.h
index aba8d5c7f8..b1bc4dc2da 100644
--- a/compiler/sea_ir/code_gen.h
+++ b/compiler/sea_ir/code_gen/code_gen.h
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-#ifndef ART_COMPILER_SEA_IR_CODE_GEN_H_
-#define ART_COMPILER_SEA_IR_CODE_GEN_H_
+#ifndef ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
+#define ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
+#include "llvm/Analysis/Verifier.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Analysis/Verifier.h"
-#include "visitor.h"
+#include "sea_ir/ir/visitor.h"
namespace sea_ir {
// Abstracts away the containers we use to map SEA IR objects to LLVM IR objects.
@@ -100,6 +101,8 @@ class CodeGenPrepassVisitor: public CodeGenPassVisitor {
void Visit(SignatureNode* region);
void Visit(Region* region);
void Visit(InstructionNode* instruction) { }
+
+ void Visit(UnnamedConstInstructionNode* instruction) { }
void Visit(ConstInstructionNode* instruction) { }
void Visit(ReturnInstructionNode* instruction) { }
void Visit(IfNeInstructionNode* instruction) { }
@@ -119,6 +122,7 @@ class CodeGenPostpassVisitor: public CodeGenPassVisitor {
void Visit(SignatureNode* region);
void Visit(Region* region);
void Visit(InstructionNode* region) { }
+ void Visit(UnnamedConstInstructionNode* instruction) { }
void Visit(ConstInstructionNode* instruction) { }
void Visit(ReturnInstructionNode* instruction) { }
void Visit(IfNeInstructionNode* instruction) { }
@@ -138,10 +142,10 @@ class CodeGenVisitor: public CodeGenPassVisitor {
void Visit(SignatureNode* region);
void Visit(Region* region);
void Visit(InstructionNode* region);
+ void Visit(UnnamedConstInstructionNode* instruction);
void Visit(ConstInstructionNode* instruction);
void Visit(ReturnInstructionNode* instruction);
void Visit(IfNeInstructionNode* instruction);
- // void Visit(AddIntLitInstructionNode* instruction);
void Visit(MoveResultInstructionNode* instruction);
void Visit(InvokeStaticInstructionNode* instruction);
void Visit(AddIntInstructionNode* instruction);
@@ -150,4 +154,4 @@ class CodeGenVisitor: public CodeGenPassVisitor {
void Visit(PhiInstructionNode* region) { }
};
} // namespace sea_ir
-#endif // ART_COMPILER_SEA_IR_CODE_GEN_H_
+#endif // ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
diff --git a/compiler/sea_ir/debug/dot_gen.cc b/compiler/sea_ir/debug/dot_gen.cc
new file mode 100644
index 0000000000..9442684a52
--- /dev/null
+++ b/compiler/sea_ir/debug/dot_gen.cc
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+
+#include "scoped_thread_state_change.h"
+#include "sea_ir/debug/dot_gen.h"
+
+namespace sea_ir {
+
+void DotGenerationVisitor::Initialize(SeaGraph* graph) {
+ graph_ = graph;
+ Region* root_region;
+ ordered_regions_.clear();
+ for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
+ cit != graph->GetRegions()->end(); cit++ ) {
+ if ((*cit)->GetIDominator() == (*cit)) {
+ root_region = *cit;
+ }
+ }
+ ordered_regions_.push_back(root_region);
+ for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
+ Region* current_region = ordered_regions_.at(id);
+ const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
+ for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
+ cit != dominated_regions->end(); cit++ ) {
+ ordered_regions_.push_back(*cit);
+ }
+ }
+}
+
+void DotGenerationVisitor::ToDotSSAEdges(InstructionNode* instruction) {
+ std::map<int, InstructionNode*>* definition_edges = instruction->GetSSAProducersMap();
+ // SSA definitions:
+ for (std::map<int, InstructionNode*>::const_iterator
+ def_it = definition_edges->begin();
+ def_it != definition_edges->end(); def_it++) {
+ if (NULL != def_it->second) {
+ dot_text_ += def_it->second->StringId() + " -> ";
+ dot_text_ += instruction->StringId() + "[color=gray,label=\"";
+ dot_text_ += art::StringPrintf("vR = %d", def_it->first);
+ art::SafeMap<int, const Type*>::const_iterator type_it = types_->find(def_it->second->Id());
+ if (type_it != types_->end()) {
+ art::ScopedObjectAccess soa(art::Thread::Current());
+ dot_text_ += "(" + type_it->second->Dump() + ")";
+ } else {
+ dot_text_ += "()";
+ }
+ dot_text_ += "\"] ; // SSA edge\n";
+ }
+ }
+
+ // SSA used-by:
+ if (options_->WillSaveUseEdges()) {
+ std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
+ for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
+ cit != used_in->end(); cit++) {
+ dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
+ dot_text_ += "\"] ; // SSA used-by edge\n";
+ }
+ }
+}
+
+void DotGenerationVisitor::ToDotSSAEdges(PhiInstructionNode* instruction) {
+ std::vector<InstructionNode*> definition_edges = instruction->GetSSAProducers();
+ // SSA definitions:
+ for (std::vector<InstructionNode*>::const_iterator
+ def_it = definition_edges.begin();
+ def_it != definition_edges.end(); def_it++) {
+ if (NULL != *def_it) {
+ dot_text_ += (*def_it)->StringId() + " -> ";
+ dot_text_ += instruction->StringId() + "[color=gray,label=\"";
+ dot_text_ += art::StringPrintf("vR = %d", instruction->GetRegisterNumber());
+ art::SafeMap<int, const Type*>::const_iterator type_it = types_->find((*def_it)->Id());
+ if (type_it != types_->end()) {
+ art::ScopedObjectAccess soa(art::Thread::Current());
+ dot_text_ += "(" + type_it->second->Dump() + ")";
+ } else {
+ dot_text_ += "()";
+ }
+ dot_text_ += "\"] ; // SSA edge\n";
+ }
+ }
+
+ // SSA used-by:
+ if (options_->WillSaveUseEdges()) {
+ std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
+ for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
+ cit != used_in->end(); cit++) {
+ dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
+ dot_text_ += "\"] ; // SSA used-by edge\n";
+ }
+ }
+}
+
+void DotGenerationVisitor::Visit(SignatureNode* parameter) {
+ dot_text_ += parameter->StringId() +" [label=\"[" + parameter->StringId() + "] signature:";
+ dot_text_ += art::StringPrintf("r%d", parameter->GetResultRegister());
+ dot_text_ += "\"] // signature node\n";
+ ToDotSSAEdges(parameter);
+}
+
+// Appends to @result a dot language formatted string representing the node and
+// (by convention) outgoing edges, so that the composition of theToDot() of all nodes
+// builds a complete dot graph (without prolog and epilog though).
+void DotGenerationVisitor::Visit(Region* region) {
+ dot_text_ += "\n// Region: \nsubgraph " + region->StringId();
+ dot_text_ += " { label=\"region " + region->StringId() + "(rpo=";
+ dot_text_ += art::StringPrintf("%d", region->GetRPO());
+ if (NULL != region->GetIDominator()) {
+ dot_text_ += " dom=" + region->GetIDominator()->StringId();
+ }
+ dot_text_ += ")\";\n";
+
+ std::vector<PhiInstructionNode*>* phi_instructions = region->GetPhiNodes();
+ for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions->begin();
+ cit != phi_instructions->end(); cit++) {
+ dot_text_ += (*cit)->StringId() +";\n";
+ }
+ std::vector<InstructionNode*>* instructions = region->GetInstructions();
+ for (std::vector<InstructionNode*>::const_iterator cit = instructions->begin();
+ cit != instructions->end(); cit++) {
+ dot_text_ += (*cit)->StringId() +";\n";
+ }
+
+ dot_text_ += "} // End Region.\n";
+ std::vector<Region*>* successors = region->GetSuccessors();
+ for (std::vector<Region*>::const_iterator cit = successors->begin(); cit != successors->end();
+ cit++) {
+ DCHECK(NULL != *cit) << "Null successor found for SeaNode" <<
+ region->GetLastChild()->StringId() << ".";
+ dot_text_ += region->GetLastChild()->StringId() + " -> " +
+ (*cit)->GetLastChild()->StringId() +
+ "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + region->StringId() + "];\n\n";
+ }
+}
+void DotGenerationVisitor::Visit(InstructionNode* instruction) {
+ dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
+ " [label=\"[" + instruction->StringId() + "] " +
+ instruction->GetInstruction()->DumpString(graph_->GetDexFile()) + "\"";
+ dot_text_ += "];\n";
+ ToDotSSAEdges(instruction);
+}
+
+void DotGenerationVisitor::Visit(UnnamedConstInstructionNode* instruction) {
+ dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
+ " [label=\"[" + instruction->StringId() + "] const/x v-3, #" +
+ art::StringPrintf("%d", instruction->GetConstValue()) + "\"";
+ dot_text_ += "];\n";
+ ToDotSSAEdges(instruction);
+}
+
+void DotGenerationVisitor::Visit(PhiInstructionNode* phi) {
+ dot_text_ += "// PhiInstruction: \n" + phi->StringId() +
+ " [label=\"[" + phi->StringId() + "] PHI(";
+ dot_text_ += art::StringPrintf("%d", phi->GetRegisterNumber());
+ dot_text_ += ")\"";
+ dot_text_ += "];\n";
+ ToDotSSAEdges(phi);
+}
+} // namespace sea_ir
diff --git a/compiler/sea_ir/debug/dot_gen.h b/compiler/sea_ir/debug/dot_gen.h
new file mode 100644
index 0000000000..675d83d515
--- /dev/null
+++ b/compiler/sea_ir/debug/dot_gen.h
@@ -0,0 +1,119 @@
+/*
+ * 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_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
+#define ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
+
+#include "safe_map.h"
+#include "base/stringprintf.h"
+#include "file_output_stream.h"
+#include "sea_ir/ir/sea.h"
+#include "sea_ir/types/type_inference.h"
+
+namespace sea_ir {
+
+class DotConversionOptions {
+ public:
+ DotConversionOptions(): save_use_edges_(false) { }
+ bool WillSaveUseEdges() const {
+ return save_use_edges_;
+ }
+ private:
+ bool save_use_edges_;
+};
+
+class DotGenerationVisitor: public IRVisitor {
+ public:
+ explicit DotGenerationVisitor(const DotConversionOptions* const options,
+ art::SafeMap<int, const Type*>* types): graph_(), types_(types), options_(options) { }
+
+ virtual void Initialize(SeaGraph* graph);
+ // Saves the ssa def->use edges corresponding to @instruction.
+ void ToDotSSAEdges(InstructionNode* instruction);
+ void ToDotSSAEdges(PhiInstructionNode* instruction);
+ void Visit(SeaGraph* graph) {
+ dot_text_ += "digraph seaOfNodes {\ncompound=true\n";
+ }
+ void Visit(SignatureNode* parameter);
+
+ // Appends to @result a dot language formatted string representing the node and
+ // (by convention) outgoing edges, so that the composition of theToDot() of all nodes
+ // builds a complete dot graph (without prolog and epilog though).
+ void Visit(Region* region);
+ void Visit(InstructionNode* instruction);
+ void Visit(PhiInstructionNode* phi);
+ void Visit(UnnamedConstInstructionNode* instruction);
+
+ void Visit(ConstInstructionNode* instruction) {
+ Visit(reinterpret_cast<InstructionNode*>(instruction));
+ }
+ void Visit(ReturnInstructionNode* instruction) {
+ Visit(reinterpret_cast<InstructionNode*>(instruction));
+ }
+ void Visit(IfNeInstructionNode* instruction) {
+ Visit(reinterpret_cast<InstructionNode*>(instruction));
+ }
+ void Visit(MoveResultInstructionNode* instruction) {
+ Visit(reinterpret_cast<InstructionNode*>(instruction));
+ }
+ void Visit(InvokeStaticInstructionNode* instruction) {
+ Visit(reinterpret_cast<InstructionNode*>(instruction));
+ }
+ void Visit(AddIntInstructionNode* instruction) {
+ Visit(reinterpret_cast<InstructionNode*>(instruction));
+ }
+ void Visit(GotoInstructionNode* instruction) {
+ Visit(reinterpret_cast<InstructionNode*>(instruction));
+ }
+ void Visit(IfEqzInstructionNode* instruction) {
+ Visit(reinterpret_cast<InstructionNode*>(instruction));
+ }
+
+ std::string GetResult() const {
+ return dot_text_;
+ }
+
+ private:
+ std::string dot_text_;
+ SeaGraph* graph_;
+ art::SafeMap<int, const Type*>* types_;
+ const DotConversionOptions* const options_;
+};
+
+// Stores options for turning a SEA IR graph to a .dot file.
+class DotConversion {
+ public:
+ DotConversion(): options_() { }
+ // Saves to @filename the .dot representation of @graph with the options @options.
+ void DumpSea(SeaGraph* graph, std::string filename,
+ art::SafeMap<int, const Type*>* types) const {
+ LOG(INFO) << "Starting to write SEA string to file.";
+ DotGenerationVisitor dgv = DotGenerationVisitor(&options_, types);
+ graph->Accept(&dgv);
+ art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
+ art::FileOutputStream fos(file);
+ std::string graph_as_string = dgv.GetResult();
+ graph_as_string += "}";
+ fos.WriteFully(graph_as_string.c_str(), graph_as_string.size());
+ LOG(INFO) << "Written SEA string to file.";
+ }
+
+ private:
+ DotConversionOptions options_;
+};
+
+} // namespace sea_ir
+#endif // ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
diff --git a/compiler/sea_ir/frontend.cc b/compiler/sea_ir/frontend.cc
index 5843388c42..e24d07d50c 100644
--- a/compiler/sea_ir/frontend.cc
+++ b/compiler/sea_ir/frontend.cc
@@ -23,14 +23,17 @@
#include "llvm/llvm_compilation_unit.h"
#include "mirror/object.h"
#include "runtime.h"
-#include "sea_ir/sea.h"
+#include "safe_map.h"
+#include "sea_ir/ir/sea.h"
+#include "sea_ir/debug/dot_gen.h"
+#include "sea_ir/types/types.h"
namespace art {
static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler,
const CompilerBackend compiler_backend,
const DexFile::CodeItem* code_item,
- uint32_t access_flags, InvokeType invoke_type,
+ uint32_t method_access_flags, InvokeType invoke_type,
uint32_t class_def_idx, uint32_t method_idx,
jobject class_loader, const DexFile& dex_file
#if defined(ART_USE_PORTABLE_COMPILER)
@@ -40,9 +43,11 @@ static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler,
// NOTE: Instead of keeping the convention from the Dalvik frontend.cc
// and silencing the cpplint.py warning, I just corrected the formatting.
VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
- sea_ir::SeaGraph* sg = sea_ir::SeaGraph::GetCurrentGraph(dex_file);
- sg->CompileMethod(code_item, class_def_idx, method_idx, dex_file);
- sg->DumpSea("/tmp/temp.dot");
+ sea_ir::SeaGraph* ir_graph = sea_ir::SeaGraph::GetGraph(dex_file);
+ ir_graph->CompileMethod(code_item, class_def_idx, method_idx, method_access_flags, dex_file);
+ sea_ir::DotConversion dc;
+ SafeMap<int, const sea_ir::Type*>* types = ir_graph->ti_->GetTypeMap();
+ dc.DumpSea(ir_graph, "/tmp/temp.dot", types);
CHECK(0 && "No SEA compiled function exists yet.");
return NULL;
}
@@ -50,14 +55,14 @@ static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler,
CompiledMethod* SeaIrCompileOneMethod(CompilerDriver& compiler,
const CompilerBackend backend,
const DexFile::CodeItem* code_item,
- uint32_t access_flags,
+ uint32_t method_access_flags,
InvokeType invoke_type,
uint32_t class_def_idx,
uint32_t method_idx,
jobject class_loader,
const DexFile& dex_file,
llvm::LlvmCompilationUnit* llvm_compilation_unit) {
- return CompileMethodWithSeaIr(compiler, backend, code_item, access_flags, invoke_type,
+ return CompileMethodWithSeaIr(compiler, backend, code_item, method_access_flags, invoke_type,
class_def_idx, method_idx, class_loader, dex_file
#if defined(ART_USE_PORTABLE_COMPILER)
, llvm_compilation_unit
@@ -68,13 +73,13 @@ CompiledMethod* SeaIrCompileOneMethod(CompilerDriver& compiler,
extern "C" art::CompiledMethod*
SeaIrCompileMethod(art::CompilerDriver& compiler,
const art::DexFile::CodeItem* code_item,
- uint32_t access_flags, art::InvokeType invoke_type,
+ uint32_t method_access_flags, art::InvokeType invoke_type,
uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
const art::DexFile& dex_file) {
// TODO: Check method fingerprint here to determine appropriate backend type.
// Until then, use build default
art::CompilerBackend backend = compiler.GetCompilerBackend();
- return art::SeaIrCompileOneMethod(compiler, backend, code_item, access_flags, invoke_type,
+ return art::SeaIrCompileOneMethod(compiler, backend, code_item, method_access_flags, invoke_type,
class_def_idx, method_idx, class_loader, dex_file,
NULL /* use thread llvm_info */);
}
diff --git a/compiler/sea_ir/instruction_nodes.h b/compiler/sea_ir/ir/instruction_nodes.h
index 6f9bdddf77..906a10fe27 100644
--- a/compiler/sea_ir/instruction_nodes.h
+++ b/compiler/sea_ir/ir/instruction_nodes.h
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-#ifndef ART_COMPILER_SEA_IR_INSTRUCTION_NODES_H_
-#define ART_COMPILER_SEA_IR_INSTRUCTION_NODES_H_
-#include "sea_node.h"
-#include "visitor.h"
+#ifndef ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
+#define ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
#include "dex_instruction-inl.h"
+#include "sea_ir/ir/sea_node.h"
+#include "sea_ir/ir/visitor.h"
+
namespace sea_ir {
@@ -48,9 +49,7 @@ class InstructionNode: public SeaNode {
// Returns the set of registers defined by the current instruction.
virtual std::vector<int> GetDefinitions() const;
// Returns the set of register numbers that are used by the instruction.
- virtual std::vector<int> GetUses();
- // Appends to @result the .dot string representation of the instruction.
- virtual void ToDot(std::string& result, const art::DexFile& dex_file) const;
+ virtual std::vector<int> GetUses() const;
// Mark the current instruction as a downward exposed definition.
void MarkAsDEDef();
// Rename the use of @reg_no to refer to the instruction @definition,
@@ -61,7 +60,7 @@ class InstructionNode: public SeaNode {
}
// Returns the ordered set of Instructions that define the input operands of this instruction.
// Precondition: SeaGraph.ConvertToSSA().
- std::vector<InstructionNode*> GetSSAUses() {
+ virtual std::vector<InstructionNode*> GetSSAProducers() {
std::vector<int> uses = GetUses();
std::vector<InstructionNode*> ssa_uses;
for (std::vector<int>::const_iterator cit = uses.begin(); cit != uses.end(); cit++) {
@@ -69,11 +68,15 @@ class InstructionNode: public SeaNode {
}
return ssa_uses;
}
-
+ std::map<int, InstructionNode* >* GetSSAProducersMap() {
+ return &definition_edges_;
+ }
+ std::vector<InstructionNode*>* GetSSAConsumers() {
+ return &used_in_;
+ }
virtual void AddSSAUse(InstructionNode* use) {
used_in_.push_back(use);
}
-
void Accept(IRVisitor* v) {
v->Visit(this);
v->Traverse(this);
@@ -91,11 +94,10 @@ class InstructionNode: public SeaNode {
protected:
explicit InstructionNode(const art::Instruction* in):
SeaNode(), instruction_(in), used_in_(), de_def_(false), region_(NULL) { }
- void ToDotSSAEdges(std::string& result) const;
protected:
const art::Instruction* const instruction_;
- std::map<int, InstructionNode* > definition_edges_;
+ std::map<int, InstructionNode* > definition_edges_; // Maps used registers to their definitions.
// Stores pointers to instructions that use the result of the current instruction.
std::vector<InstructionNode*> used_in_;
bool de_def_;
@@ -121,6 +123,7 @@ class UnnamedConstInstructionNode: public ConstInstructionNode {
public:
explicit UnnamedConstInstructionNode(const art::Instruction* inst, int32_t value):
ConstInstructionNode(inst), value_(value) { }
+
void Accept(IRVisitor* v) {
v->Visit(this);
v->Traverse(this);
@@ -134,19 +137,6 @@ class UnnamedConstInstructionNode: public ConstInstructionNode {
return value_;
}
- void ToDot(std::string& result, const art::DexFile& dex_file) const {
- std::ostringstream sstream;
- sstream << GetConstValue();
- const std::string value_as_string(sstream.str());
- result += "// Instruction ("+StringId()+"): \n" + StringId() +
- " [label=\"const/x v-3, #"+ value_as_string + "\"";
- if (de_def_) {
- result += "style=bold";
- }
- result += "];\n";
- ToDotSSAEdges(result);
- }
-
private:
const int32_t value_;
};
@@ -176,7 +166,7 @@ class IfNeInstructionNode: public InstructionNode {
class MoveResultInstructionNode: public InstructionNode {
public:
explicit MoveResultInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
- std::vector<int> GetUses() {
+ std::vector<int> GetUses() const {
std::vector<int> uses; // Using vector<> instead of set<> because order matters.
uses.push_back(RETURN_REGISTER);
return uses;
@@ -213,7 +203,7 @@ class AddIntLitInstructionNode: public AddIntInstructionNode {
explicit AddIntLitInstructionNode(const art::Instruction* inst):
AddIntInstructionNode(inst) { }
- std::vector<int> GetUses() {
+ std::vector<int> GetUses() const {
std::vector<int> uses = AddIntInstructionNode::GetUses();
uses.push_back(UNNAMED_CONST_REGISTER);
return uses;
@@ -245,4 +235,4 @@ class IfEqzInstructionNode: public InstructionNode {
}
};
} // namespace sea_ir
-#endif // ART_COMPILER_SEA_IR_INSTRUCTION_NODES_H_
+#endif // ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
diff --git a/compiler/sea_ir/instruction_tools.cc b/compiler/sea_ir/ir/instruction_tools.cc
index 9627497805..143209de75 100644
--- a/compiler/sea_ir/instruction_tools.cc
+++ b/compiler/sea_ir/ir/instruction_tools.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "instruction_tools.h"
+#include "sea_ir/ir/instruction_tools.h"
namespace sea_ir {
diff --git a/compiler/sea_ir/instruction_tools.h b/compiler/sea_ir/ir/instruction_tools.h
index d3871008a4..895e01732a 100644
--- a/compiler/sea_ir/instruction_tools.h
+++ b/compiler/sea_ir/ir/instruction_tools.h
@@ -17,8 +17,8 @@
#include "sea.h"
#include "dex_instruction.h"
-#ifndef ART_COMPILER_SEA_IR_INSTRUCTION_TOOLS_H_
-#define ART_COMPILER_SEA_IR_INSTRUCTION_TOOLS_H_
+#ifndef ART_COMPILER_SEA_IR_IR_INSTRUCTION_TOOLS_H_
+#define ART_COMPILER_SEA_IR_IR_INSTRUCTION_TOOLS_H_
// Note: This file has content cannibalized for SEA_IR from the MIR implementation,
@@ -122,4 +122,4 @@ class InstructionTools {
static const int instruction_attributes_[];
};
} // namespace sea_ir
-#endif // ART_COMPILER_SEA_IR_INSTRUCTION_TOOLS_H_
+#endif // ART_COMPILER_SEA_IR_IR_INSTRUCTION_TOOLS_H_
diff --git a/compiler/sea_ir/ir/regions_test.cc b/compiler/sea_ir/ir/regions_test.cc
new file mode 100644
index 0000000000..9813465db8
--- /dev/null
+++ b/compiler/sea_ir/ir/regions_test.cc
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#include "common_test.h"
+#include "sea_ir/ir/sea.h"
+
+using utils::ScopedHashtable;
+
+namespace sea_ir {
+
+class RegionsTest : public art::CommonTest {
+};
+
+TEST_F(RegionsTest, Basics) {
+ sea_ir::SeaGraph sg(*java_lang_dex_file_);
+ sea_ir::Region* root = sg.GetNewRegion();
+ sea_ir::Region* then_region = sg.GetNewRegion();
+ sea_ir::Region* else_region = sg.GetNewRegion();
+ std::vector<sea_ir::Region*>* regions = sg.GetRegions();
+ // Test that regions have been registered correctly as children of the graph.
+ EXPECT_TRUE(std::find(regions->begin(), regions->end(), root) != regions->end());
+ EXPECT_TRUE(std::find(regions->begin(), regions->end(), then_region) != regions->end());
+ EXPECT_TRUE(std::find(regions->begin(), regions->end(), else_region) != regions->end());
+ // Check that an edge recorded correctly in both the head and the tail.
+ sg.AddEdge(root, then_region);
+ std::vector<sea_ir::Region*>* succs = root->GetSuccessors();
+ EXPECT_EQ(1U, succs->size());
+ EXPECT_EQ(then_region, succs->at(0));
+ std::vector<sea_ir::Region*>* preds = then_region->GetPredecessors();
+ EXPECT_EQ(1U, preds->size());
+ EXPECT_EQ(root, preds->at(0));
+ // Check that two edges are recorded properly for both head and tail.
+ sg.AddEdge(root, else_region);
+ succs = root->GetSuccessors();
+ EXPECT_EQ(2U, succs->size());
+ EXPECT_TRUE(std::find(succs->begin(), succs->end(), then_region) != succs->end());
+ EXPECT_TRUE(std::find(succs->begin(), succs->end(), else_region) != succs->end());
+ preds = then_region->GetPredecessors();
+ EXPECT_EQ(1U, preds->size());
+ EXPECT_EQ(root, preds->at(0));
+ preds = else_region->GetPredecessors();
+ EXPECT_EQ(1U, preds->size());
+ EXPECT_EQ(root, preds->at(0));
+}
+
+} // namespace art
diff --git a/compiler/sea_ir/sea.cc b/compiler/sea_ir/ir/sea.cc
index 99b21f8771..08fe0e1fac 100644
--- a/compiler/sea_ir/sea.cc
+++ b/compiler/sea_ir/ir/sea.cc
@@ -14,10 +14,10 @@
* limitations under the License.
*/
#include "base/stringprintf.h"
-#include "file_output_stream.h"
-#include "instruction_tools.h"
-#include "sea.h"
-#include "code_gen.h"
+#include "sea_ir/ir/instruction_tools.h"
+#include "sea_ir/ir/sea.h"
+#include "sea_ir/code_gen/code_gen.h"
+#include "sea_ir/types/type_inference.h"
#define MAX_REACHING_DEF_ITERERATIONS (10)
// TODO: When development is done, this define should not
@@ -35,7 +35,6 @@ void IRVisitor::Traverse(Region* region) {
cit != phis->end(); cit++) {
(*cit)->Accept(this);
}
-
std::vector<InstructionNode*>* instructions = region->GetInstructions();
for (std::vector<InstructionNode*>::const_iterator cit = instructions->begin();
cit != instructions->end(); cit++) {
@@ -50,24 +49,10 @@ void IRVisitor::Traverse(SeaGraph* graph) {
}
}
-SeaGraph* SeaGraph::GetCurrentGraph(const art::DexFile& dex_file) {
+SeaGraph* SeaGraph::GetGraph(const art::DexFile& dex_file) {
return new SeaGraph(dex_file);
}
-void SeaGraph::DumpSea(std::string filename) const {
- LOG(INFO) << "Starting to write SEA string to file.";
- std::string result;
- result += "digraph seaOfNodes {\ncompound=true\n";
- for (std::vector<Region*>::const_iterator cit = regions_.begin(); cit != regions_.end(); cit++) {
- (*cit)->ToDot(result, dex_file_);
- }
- result += "}\n";
- art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
- art::FileOutputStream fos(file);
- fos.WriteFully(result.c_str(), result.size());
- LOG(INFO) << "Written SEA string to file.";
-}
-
void SeaGraph::AddEdge(Region* src, Region* dst) const {
src->AddSuccessor(dst);
dst->AddPredecessor(src);
@@ -191,10 +176,12 @@ void SeaGraph::ComputeReachingDefs() {
void SeaGraph::BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item,
- const art::DexFile& dex_file, uint32_t class_def_idx, uint32_t method_idx) {
+ const art::DexFile& dex_file, uint32_t class_def_idx,
+ uint32_t method_idx, uint32_t method_access_flags) {
+ code_item_ = code_item;
class_def_idx_ = class_def_idx;
method_idx_ = method_idx;
-
+ method_access_flags_ = method_access_flags;
const uint16_t* code = code_item->insns_;
const size_t size_in_code_units = code_item->insns_size_in_code_units_;
// This maps target instruction pointers to their corresponding region objects.
@@ -225,8 +212,9 @@ void SeaGraph::BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item,
// Insert one SignatureNode per function argument,
// to serve as placeholder definitions in dataflow analysis.
for (unsigned int crt_offset = 0; crt_offset < code_item->ins_size_; crt_offset++) {
+ int position = crt_offset; // TODO: Is this the correct offset in the signature?
SignatureNode* parameter_def_node =
- new sea_ir::SignatureNode(code_item->registers_size_ - 1 - crt_offset);
+ new sea_ir::SignatureNode(code_item->registers_size_ - 1 - crt_offset, position);
AddParameterNode(parameter_def_node);
r->AddChild(parameter_def_node);
}
@@ -260,12 +248,8 @@ void SeaGraph::BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item,
}
r = nextRegion;
}
- bool definesRegister = (0 != InstructionTools::instruction_attributes_[inst->Opcode()]
- && (1 << kDA));
- LOG(INFO)<< inst->GetDexPc(code) << "*** " << inst->DumpString(&dex_file)
- << " region:" <<r->StringId() << "Definition?" << definesRegister << std::endl;
r->AddChild(node);
- }
+ }
i += inst->SizeInCodeUnits();
}
}
@@ -417,10 +401,10 @@ void SeaGraph::GenerateLLVM() {
code_gen_postpass_visitor.Write(std::string("my_file.llvm"));
}
-void SeaGraph::CompileMethod(const art::DexFile::CodeItem* code_item,
- uint32_t class_def_idx, uint32_t method_idx, const art::DexFile& dex_file) {
+void SeaGraph::CompileMethod(const art::DexFile::CodeItem* code_item, uint32_t class_def_idx,
+ uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file) {
// Two passes: Builds the intermediate structure (non-SSA) of the sea-ir for the function.
- BuildMethodSeaGraph(code_item, dex_file, class_def_idx, method_idx);
+ BuildMethodSeaGraph(code_item, dex_file, class_def_idx, method_idx, method_access_flags);
// Pass: Compute reverse post-order of regions.
ComputeRPO();
// Multiple passes: compute immediate dominators.
@@ -433,6 +417,8 @@ void SeaGraph::CompileMethod(const art::DexFile::CodeItem* code_item,
ComputeDominanceFrontier();
// Two Passes: Phi node insertion.
ConvertToSSA();
+ // Pass: type inference
+ ti_->ComputeTypes(this);
// Pass: Generate LLVM IR.
GenerateLLVM();
}
@@ -465,18 +451,10 @@ void SeaGraph::AddRegion(Region* r) {
regions_.push_back(r);
}
-/*
-void SeaNode::AddSuccessor(Region* successor) {
- DCHECK(successor) << "Tried to add NULL successor to SEA node.";
- successors_.push_back(successor);
- return;
-}
+SeaGraph::SeaGraph(const art::DexFile& df)
+ :ti_(new TypeInference()), class_def_idx_(0), method_idx_(0), method_access_flags_(),
+ regions_(), parameters_(), dex_file_(df), code_item_(NULL) { }
-void SeaNode::AddPredecessor(Region* predecessor) {
- DCHECK(predecessor) << "Tried to add NULL predecessor to SEA node.";
- predecessors_.push_back(predecessor);
-}
-*/
void Region::AddChild(sea_ir::InstructionNode* instruction) {
DCHECK(instruction) << "Tried to add NULL instruction to region node.";
instructions_.push_back(instruction);
@@ -490,46 +468,6 @@ SeaNode* Region::GetLastChild() const {
return NULL;
}
-void Region::ToDot(std::string& result, const art::DexFile& dex_file) const {
- result += "\n// Region: \nsubgraph " + StringId() + " { label=\"region " + StringId() + "(rpo=";
- result += art::StringPrintf("%d", rpo_number_);
- if (NULL != GetIDominator()) {
- result += " dom=" + GetIDominator()->StringId();
- }
- result += ")\";\n";
-
- for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions_.begin();
- cit != phi_instructions_.end(); cit++) {
- result += (*cit)->StringId() +";\n";
- }
-
- for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
- cit != instructions_.end(); cit++) {
- result += (*cit)->StringId() +";\n";
- }
-
- result += "} // End Region.\n";
-
- // Save phi-nodes.
- for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions_.begin();
- cit != phi_instructions_.end(); cit++) {
- (*cit)->ToDot(result, dex_file);
- }
-
- // Save instruction nodes.
- for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
- cit != instructions_.end(); cit++) {
- (*cit)->ToDot(result, dex_file);
- }
-
- for (std::vector<Region*>::const_iterator cit = successors_.begin(); cit != successors_.end();
- cit++) {
- DCHECK(NULL != *cit) << "Null successor found for SeaNode" << GetLastChild()->StringId() << ".";
- result += GetLastChild()->StringId() + " -> " + (*cit)->GetLastChild()->StringId() +
- "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + StringId() + "];\n\n";
- }
-}
-
void Region::ComputeDownExposedDefs() {
for (std::vector<InstructionNode*>::const_iterator inst_it = instructions_.begin();
inst_it != instructions_.end(); inst_it++) {
@@ -692,38 +630,6 @@ std::vector<InstructionNode*> InstructionNode::Create(const art::Instruction* in
return sea_instructions;
}
-void InstructionNode::ToDotSSAEdges(std::string& result) const {
- // SSA definitions:
- for (std::map<int, InstructionNode*>::const_iterator def_it = definition_edges_.begin();
- def_it != definition_edges_.end(); def_it++) {
- if (NULL != def_it->second) {
- result += def_it->second->StringId() + " -> " + StringId() + "[color=gray,label=\"";
- result += art::StringPrintf("vR = %d", def_it->first);
- result += "\"] ; // ssa edge\n";
- }
- }
-
- // SSA used-by:
- if (DotConversion::SaveUseEdges()) {
- for (std::vector<InstructionNode*>::const_iterator cit = used_in_.begin();
- cit != used_in_.end(); cit++) {
- result += (*cit)->StringId() + " -> " + StringId() + "[color=gray,label=\"";
- result += "\"] ; // SSA used-by edge\n";
- }
- }
-}
-
-void InstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
- result += "// Instruction ("+StringId()+"): \n" + StringId() +
- " [label=\"" + instruction_->DumpString(&dex_file) + "\"";
- if (de_def_) {
- result += "style=bold";
- }
- result += "];\n";
-
- ToDotSSAEdges(result);
-}
-
void InstructionNode::MarkAsDEDef() {
de_def_ = true;
}
@@ -747,7 +653,7 @@ std::vector<int> InstructionNode::GetDefinitions() const {
return definitions;
}
-std::vector<int> InstructionNode::GetUses() {
+std::vector<int> InstructionNode::GetUses() const {
std::vector<int> uses; // Using vector<> instead of set<> because order matters.
if (!InstructionTools::IsDefinition(instruction_) && (instruction_->HasVRegA())) {
int vA = instruction_->VRegA();
@@ -763,13 +669,4 @@ std::vector<int> InstructionNode::GetUses() {
}
return uses;
}
-
-void PhiInstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
- result += "// PhiInstruction: \n" + StringId() +
- " [label=\"" + "PHI(";
- result += art::StringPrintf("%d", register_no_);
- result += ")\"";
- result += "];\n";
- ToDotSSAEdges(result);
-}
} // namespace sea_ir
diff --git a/compiler/sea_ir/sea.h b/compiler/sea_ir/ir/sea.h
index 5cb84240ae..0b20ed7d74 100644
--- a/compiler/sea_ir/sea.h
+++ b/compiler/sea_ir/ir/sea.h
@@ -15,17 +15,18 @@
*/
-#ifndef ART_COMPILER_SEA_IR_SEA_H_
-#define ART_COMPILER_SEA_IR_SEA_H_
+#ifndef ART_COMPILER_SEA_IR_IR_SEA_H_
+#define ART_COMPILER_SEA_IR_IR_SEA_H_
#include <set>
#include <map>
+#include "utils/scoped_hashtable.h"
+#include "gtest/gtest_prod.h"
#include "dex_file.h"
#include "dex_instruction.h"
-#include "instruction_tools.h"
-#include "instruction_nodes.h"
-#include "utils/scoped_hashtable.h"
+#include "sea_ir/ir/instruction_tools.h"
+#include "sea_ir/ir/instruction_nodes.h"
namespace sea_ir {
@@ -35,19 +36,9 @@ enum RegionNumbering {
VISITING = -2
};
-// Stores options for turning a SEA IR graph to a .dot file.
-class DotConversion {
- public:
- static bool SaveUseEdges() {
- return save_use_edges_;
- }
-
- private:
- static const bool save_use_edges_ = false; // TODO: Enable per-sea graph configuration.
-};
+class TypeInference;
class Region;
-
class InstructionNode;
class PhiInstructionNode;
class SignatureNode;
@@ -57,21 +48,20 @@ class SignatureNode;
// can return from the GetSSAUses() calls, instead of having missing SSA edges.
class SignatureNode: public InstructionNode {
public:
- explicit SignatureNode(unsigned int parameter_register):InstructionNode(NULL),
- parameter_register_(parameter_register) { }
-
- void ToDot(std::string& result, const art::DexFile& dex_file) const {
- result += StringId() +" [label=\"signature:";
- result += art::StringPrintf("r%d", GetResultRegister());
- result += "\"] // signature node\n";
- ToDotSSAEdges(result);
- }
+ // Creates a new signature node representing the initial definition of the
+ // register @parameter_register which is the @position-th argument to the method.
+ explicit SignatureNode(unsigned int parameter_register, unsigned int position):
+ InstructionNode(NULL), parameter_register_(parameter_register), position_(position) { }
int GetResultRegister() const {
return parameter_register_;
}
- std::vector<int> GetUses() {
+ unsigned int GetPositionInSignature() const {
+ return position_;
+ }
+
+ std::vector<int> GetUses() const {
return std::vector<int>();
}
@@ -81,15 +71,15 @@ class SignatureNode: public InstructionNode {
}
private:
- unsigned int parameter_register_;
+ const unsigned int parameter_register_;
+ const unsigned int position_; // The position of this parameter node is
+ // in the function parameter list.
};
class PhiInstructionNode: public InstructionNode {
public:
explicit PhiInstructionNode(int register_no):
InstructionNode(NULL), register_no_(register_no), definition_edges_() {}
- // Appends to @result the .dot string representation of the instruction.
- void ToDot(std::string& result, const art::DexFile& dex_file) const;
// Returns the register on which this phi-function is used.
int GetRegisterNumber() const {
return register_no_;
@@ -113,6 +103,17 @@ class PhiInstructionNode: public InstructionNode {
definition->AddSSAUse(this);
}
+ // Returns the ordered set of Instructions that define the input operands of this instruction.
+ // Precondition: SeaGraph.ConvertToSSA().
+ std::vector<InstructionNode*> GetSSAProducers() {
+ std::vector<InstructionNode*> producers;
+ for (std::vector<std::vector<InstructionNode*>*>::const_iterator
+ cit = definition_edges_.begin(); cit != definition_edges_.end(); cit++) {
+ producers.insert(producers.end(), (*cit)->begin(), (*cit)->end());
+ }
+ return producers;
+ }
+
// Returns the instruction that defines the phi register from predecessor
// on position @predecessor_pos. Note that the return value is vector<> just
// for consistency with the return value of GetSSAUses() on regular instructions,
@@ -128,6 +129,9 @@ class PhiInstructionNode: public InstructionNode {
private:
int register_no_;
+ // This vector has one entry for each predecessors, each with a single
+ // element, storing the id of the instruction that defines the register
+ // corresponding to this phi function.
std::vector<std::vector<InstructionNode*>*> definition_edges_;
};
@@ -150,10 +154,7 @@ class Region : public SeaNode {
std::vector<InstructionNode*>* GetInstructions() {
return &instructions_;
}
- // Appends to @result a dot language formatted string representing the node and
- // (by convention) outgoing edges, so that the composition of theToDot() of all nodes
- // builds a complete dot graph (without prolog and epilog though).
- virtual void ToDot(std::string& result, const art::DexFile& dex_file) const;
+
// Computes Downward Exposed Definitions for the current node.
void ComputeDownExposedDefs();
const std::map<int, sea_ir::InstructionNode*>* GetDownExposedDefs() const;
@@ -257,16 +258,14 @@ class Region : public SeaNode {
// and acts as starting point for visitors (ex: during code generation).
class SeaGraph: IVisitable {
public:
- static SeaGraph* GetCurrentGraph(const art::DexFile&);
+ static SeaGraph* GetGraph(const art::DexFile&);
- void CompileMethod(const art::DexFile::CodeItem* code_item,
- uint32_t class_def_idx, uint32_t method_idx, const art::DexFile& dex_file);
+ void CompileMethod(const art::DexFile::CodeItem* code_item, uint32_t class_def_idx,
+ uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file);
// Returns all regions corresponding to this SeaGraph.
std::vector<Region*>* GetRegions() {
return &regions_;
}
- // Returns a string representation of the region and its Instruction children.
- void DumpSea(std::string filename) const;
// Recursively computes the reverse postorder value for @crt_bb and successors.
static void ComputeRPO(Region* crt_bb, int& crt_rpo);
// Returns the "lowest common ancestor" of @i and @j in the dominator tree.
@@ -275,13 +274,28 @@ class SeaGraph: IVisitable {
std::vector<SignatureNode*>* GetParameterNodes() {
return &parameters_;
}
+
+ const art::DexFile* GetDexFile() const {
+ return &dex_file_;
+ }
+
+ virtual void Accept(IRVisitor* visitor) {
+ visitor->Initialize(this);
+ visitor->Visit(this);
+ visitor->Traverse(this);
+ }
+
+ TypeInference* ti_;
uint32_t class_def_idx_;
uint32_t method_idx_;
+ uint32_t method_access_flags_;
+
+ protected:
+ explicit SeaGraph(const art::DexFile& df);
+ virtual ~SeaGraph() { }
private:
- explicit SeaGraph(const art::DexFile& df):
- class_def_idx_(0), method_idx_(0), regions_(), parameters_(), dex_file_(df) {
- }
+ FRIEND_TEST(RegionsTest, Basics);
// Registers @childReg as a region belonging to the SeaGraph instance.
void AddRegion(Region* childReg);
// Returns new region and registers it with the SeaGraph instance.
@@ -295,7 +309,8 @@ class SeaGraph: IVisitable {
// Builds the non-SSA sea-ir representation of the function @code_item from @dex_file
// with class id @class_def_idx and method id @method_idx.
void BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item,
- const art::DexFile& dex_file, uint32_t class_def_idx, uint32_t method_idx);
+ const art::DexFile& dex_file, uint32_t class_def_idx,
+ uint32_t method_idx, uint32_t method_access_flags);
// Computes immediate dominators for each region.
// Precondition: ComputeMethodSeaGraph()
void ComputeIDominators();
@@ -320,14 +335,6 @@ class SeaGraph: IVisitable {
// Identifies the definitions corresponding to uses for region @node
// by using the scoped hashtable of names @ scoped_table.
void RenameAsSSA(Region* node, utils::ScopedHashtable<int, InstructionNode*>* scoped_table);
-
- virtual void Accept(IRVisitor* visitor) {
- visitor->Initialize(this);
- visitor->Visit(this);
- visitor->Traverse(this);
- }
-
- virtual ~SeaGraph() {}
// Generate LLVM IR for the method.
// Precondition: ConvertToSSA().
void GenerateLLVM();
@@ -336,6 +343,7 @@ class SeaGraph: IVisitable {
std::vector<Region*> regions_;
std::vector<SignatureNode*> parameters_;
const art::DexFile& dex_file_;
+ const art::DexFile::CodeItem* code_item_;
};
} // namespace sea_ir
-#endif // ART_COMPILER_SEA_IR_SEA_H_
+#endif // ART_COMPILER_SEA_IR_IR_SEA_H_
diff --git a/compiler/sea_ir/sea_node.h b/compiler/sea_ir/ir/sea_node.h
index c13e5d6aba..4dab5cba83 100644
--- a/compiler/sea_ir/sea_node.h
+++ b/compiler/sea_ir/ir/sea_node.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_COMPILER_SEA_IR_SEA_NODE_H_
-#define ART_COMPILER_SEA_IR_SEA_NODE_H_
+#ifndef ART_COMPILER_SEA_IR_IR_SEA_NODE_H_
+#define ART_COMPILER_SEA_IR_IR_SEA_NODE_H_
#include "base/stringprintf.h"
@@ -56,10 +56,6 @@ class SeaNode: public IVisitable {
int Id() const {
return id_;
}
- // Appends to @result a dot language formatted string representing the node and
- // (by convention) outgoing edges, so that the composition of theToDot() of all nodes
- // builds a complete dot graph, but without prolog ("digraph {") and epilog ("}").
- virtual void ToDot(std::string& result, const art::DexFile& dex_file) const = 0;
virtual ~SeaNode() { }
@@ -78,4 +74,4 @@ class SeaNode: public IVisitable {
DISALLOW_COPY_AND_ASSIGN(SeaNode);
};
} // namespace sea_ir
-#endif // ART_COMPILER_SEA_IR_SEA_NODE_H_
+#endif // ART_COMPILER_SEA_IR_IR_SEA_NODE_H_
diff --git a/compiler/sea_ir/visitor.h b/compiler/sea_ir/ir/visitor.h
index a4fec7b8a9..cc7b5d153f 100644
--- a/compiler/sea_ir/visitor.h
+++ b/compiler/sea_ir/ir/visitor.h
@@ -14,16 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_COMPILER_SEA_IR_VISITOR_H_
-#define ART_COMPILER_SEA_IR_VISITOR_H_
-
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Analysis/Verifier.h"
-// TODO: Separating the root visitor from the code_gen visitor
-// would allow me to not include llvm headers here.
-
+#ifndef ART_COMPILER_SEA_IR_IR_VISITOR_H_
+#define ART_COMPILER_SEA_IR_IR_VISITOR_H_
namespace sea_ir {
@@ -32,6 +24,7 @@ class Region;
class InstructionNode;
class PhiInstructionNode;
class SignatureNode;
+class UnnamedConstInstructionNode;
class ConstInstructionNode;
class ReturnInstructionNode;
class IfNeInstructionNode;
@@ -48,7 +41,7 @@ class IfEqzInstructionNode;
class IRVisitor {
public:
- explicit IRVisitor():ordered_regions_() { }
+ explicit IRVisitor(): ordered_regions_() { }
virtual void Initialize(SeaGraph* graph) = 0;
virtual void Visit(SeaGraph* graph) = 0;
virtual void Visit(Region* region) = 0;
@@ -57,16 +50,16 @@ class IRVisitor {
virtual void Visit(InstructionNode* region) = 0;
virtual void Visit(ConstInstructionNode* instruction) = 0;
+ virtual void Visit(UnnamedConstInstructionNode* instruction) = 0;
virtual void Visit(ReturnInstructionNode* instruction) = 0;
virtual void Visit(IfNeInstructionNode* instruction) = 0;
- // virtual void Visit(AddIntLitInstructionNode* instruction) = 0;
virtual void Visit(MoveResultInstructionNode* instruction) = 0;
virtual void Visit(InvokeStaticInstructionNode* instruction) = 0;
virtual void Visit(AddIntInstructionNode* instruction) = 0;
virtual void Visit(GotoInstructionNode* instruction) = 0;
virtual void Visit(IfEqzInstructionNode* instruction) = 0;
- // Note: This favor of visitor separates the traversal functions from the actual visiting part
+ // Note: This flavor of visitor separates the traversal functions from the actual visiting part
// so that the Visitor subclasses don't duplicate code and can't get the traversal wrong.
// The disadvantage is the increased number of functions (and calls).
virtual void Traverse(SeaGraph* graph);
@@ -91,4 +84,4 @@ class IRVisitor {
std::vector<Region*> ordered_regions_;
};
} // namespace sea_ir
-#endif // ART_COMPILER_SEA_IR_VISITOR_H_
+#endif // ART_COMPILER_SEA_IR_IR_VISITOR_H_
diff --git a/compiler/sea_ir/types/type_data_test.cc b/compiler/sea_ir/types/type_data_test.cc
new file mode 100644
index 0000000000..a66ebce38f
--- /dev/null
+++ b/compiler/sea_ir/types/type_data_test.cc
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "common_test.h"
+#include "sea_ir/types/types.h"
+
+namespace sea_ir {
+
+class TypeDataTest : public art::CommonTest {
+};
+
+TEST_F(TypeDataTest, Basics) {
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ int first_instruction_id = 1;
+ int second_instruction_id = 3;
+ EXPECT_TRUE(NULL == td.FindTypeOf(first_instruction_id));
+ const Type* int_type = &type_cache.Integer();
+ const Type* byte_type = &type_cache.Byte();
+ td.SetTypeOf(first_instruction_id, int_type);
+ EXPECT_TRUE(int_type == td.FindTypeOf(first_instruction_id));
+ EXPECT_TRUE(NULL == td.FindTypeOf(second_instruction_id));
+ td.SetTypeOf(second_instruction_id, byte_type);
+ EXPECT_TRUE(int_type == td.FindTypeOf(first_instruction_id));
+ EXPECT_TRUE(byte_type == td.FindTypeOf(second_instruction_id));
+}
+
+} // namespace art
diff --git a/compiler/sea_ir/types/type_inference.cc b/compiler/sea_ir/types/type_inference.cc
new file mode 100644
index 0000000000..31d7f0f8b6
--- /dev/null
+++ b/compiler/sea_ir/types/type_inference.cc
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+#include "scoped_thread_state_change.h"
+#include "sea_ir/types/type_inference.h"
+#include "sea_ir/types/type_inference_visitor.h"
+#include "sea_ir/ir/sea.h"
+
+namespace sea_ir {
+
+bool TypeInference::IsPrimitiveDescriptor(char descriptor) {
+ switch (descriptor) {
+ case 'I':
+ case 'C':
+ case 'S':
+ case 'B':
+ case 'Z':
+ case 'F':
+ case 'D':
+ case 'J':
+ return true;
+ default:
+ return false;
+ }
+}
+
+FunctionTypeInfo::FunctionTypeInfo(const SeaGraph* graph, art::verifier::RegTypeCache* types)
+ : dex_file_(graph->GetDexFile()), dex_method_idx_(graph->method_idx_), type_cache_(types),
+ method_access_flags_(graph->method_access_flags_) {
+ const art::DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
+ const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
+ declaring_class_ = &(type_cache_->FromDescriptor(NULL, descriptor, false));
+}
+
+FunctionTypeInfo::FunctionTypeInfo(const SeaGraph* graph, InstructionNode* inst,
+ art::verifier::RegTypeCache* types): dex_file_(graph->GetDexFile()),
+ dex_method_idx_(inst->GetInstruction()->VRegB_35c()), type_cache_(types),
+ method_access_flags_(0) {
+ // TODO: Test that GetDeclaredArgumentTypes() works correctly when using this constructor.
+ const art::DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
+ const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
+ declaring_class_ = &(type_cache_->FromDescriptor(NULL, descriptor, false));
+}
+
+const Type* FunctionTypeInfo::GetReturnValueType() {
+ const art::DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
+ uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
+ const char* descriptor = dex_file_->StringByTypeIdx(return_type_idx);
+ art::ScopedObjectAccess soa(art::Thread::Current());
+ const Type& return_type = type_cache_->FromDescriptor(NULL, descriptor, false);
+ return &return_type;
+}
+
+
+
+std::vector<const Type*> FunctionTypeInfo::GetDeclaredArgumentTypes() {
+ art::ScopedObjectAccess soa(art::Thread::Current());
+ std::vector<const Type*> argument_types;
+ // Include the "this" pointer.
+ size_t cur_arg = 0;
+ if (!IsStatic()) {
+ // If this is a constructor for a class other than java.lang.Object, mark the first ("this")
+ // argument as uninitialized. This restricts field access until the superclass constructor is
+ // called.
+ const art::verifier::RegType& declaring_class = GetDeclaringClass();
+ if (IsConstructor() && !declaring_class.IsJavaLangObject()) {
+ argument_types.push_back(&(type_cache_->UninitializedThisArgument(declaring_class)));
+ } else {
+ argument_types.push_back(&declaring_class);
+ }
+ cur_arg++;
+ }
+
+ const art::DexFile::ProtoId& proto_id =
+ dex_file_->GetMethodPrototype(dex_file_->GetMethodId(dex_method_idx_));
+ art::DexFileParameterIterator iterator(*dex_file_, proto_id);
+
+ for (; iterator.HasNext(); iterator.Next()) {
+ const char* descriptor = iterator.GetDescriptor();
+ if (descriptor == NULL) {
+ LOG(FATAL) << "Error: Encountered null type descriptor for function argument.";
+ }
+ switch (descriptor[0]) {
+ case 'L':
+ case '[':
+ // We assume that reference arguments are initialized. The only way it could be otherwise
+ // (assuming the caller was verified) is if the current method is <init>, but in that case
+ // it's effectively considered initialized the instant we reach here (in the sense that we
+ // can return without doing anything or call virtual methods).
+ {
+ const Type& reg_type = type_cache_->FromDescriptor(NULL, descriptor, false);
+ argument_types.push_back(&reg_type);
+ }
+ break;
+ case 'Z':
+ argument_types.push_back(&type_cache_->Boolean());
+ break;
+ case 'C':
+ argument_types.push_back(&type_cache_->Char());
+ break;
+ case 'B':
+ argument_types.push_back(&type_cache_->Byte());
+ break;
+ case 'I':
+ argument_types.push_back(&type_cache_->Integer());
+ break;
+ case 'S':
+ argument_types.push_back(&type_cache_->Short());
+ break;
+ case 'F':
+ argument_types.push_back(&type_cache_->Float());
+ break;
+ case 'J':
+ case 'D': {
+ // TODO: Figure out strategy for two-register operands (double, long)
+ LOG(FATAL) << "Error: Type inference for 64-bit variables has not been implemented.";
+ break;
+ }
+ default:
+ LOG(FATAL) << "Error: Unexpected signature encountered during type inference.";
+ }
+ cur_arg++;
+ }
+ return argument_types;
+}
+
+// TODO: Lock is only used for dumping types (during development). Remove this for performance.
+void TypeInference::ComputeTypes(SeaGraph* graph) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ std::vector<Region*>* regions = graph->GetRegions();
+ std::list<InstructionNode*> worklist;
+ // Fill the work-list with all instructions.
+ for (std::vector<Region*>::const_iterator region_it = regions->begin();
+ region_it != regions->end(); region_it++) {
+ std::vector<PhiInstructionNode*>* phi_instructions = (*region_it)->GetPhiNodes();
+ std::copy(phi_instructions->begin(), phi_instructions->end(), std::back_inserter(worklist));
+ std::vector<InstructionNode*>* instructions = (*region_it)->GetInstructions();
+ std::copy(instructions->begin(), instructions->end(), std::back_inserter(worklist));
+ }
+ TypeInferenceVisitor tiv(graph, &type_data_, type_cache_);
+ // Sparse (SSA) fixed-point algorithm that processes each instruction in the work-list,
+ // adding consumers of instructions whose result changed type back into the work-list.
+ // Note: According to [1] list iterators should not be invalidated on insertion,
+ // which simplifies the implementation; not 100% sure other STL implementations
+ // maintain this invariant, but they should.
+ // [1] http://www.sgi.com/tech/stl/List.html
+ // TODO: Making this conditional (as in sparse conditional constant propagation) would be good.
+ // TODO: Remove elements as I go.
+ for (std::list<InstructionNode*>::const_iterator instruction_it = worklist.begin();
+ instruction_it != worklist.end(); instruction_it++) {
+ std::cout << "[TI] Instruction: " << (*instruction_it)->Id() << std::endl;
+ (*instruction_it)->Accept(&tiv);
+ const Type* old_type = type_data_.FindTypeOf((*instruction_it)->Id());
+ const Type* new_type = tiv.GetType();
+ bool type_changed = (old_type != new_type);
+ if (type_changed) {
+ std::cout << " New type:" << new_type->IsIntegralTypes() << std::endl;
+ std::cout << " Descrip:" << new_type->Dump()<< " on " << (*instruction_it)->Id() << std::endl;
+ type_data_.SetTypeOf((*instruction_it)->Id(), new_type);
+ // Add SSA consumers of the current instruction to the work-list.
+ std::vector<InstructionNode*>* consumers = (*instruction_it)->GetSSAConsumers();
+ for (std::vector<InstructionNode*>::iterator consumer = consumers->begin();
+ consumer != consumers->end(); consumer++) {
+ worklist.push_back(*consumer);
+ }
+ }
+ }
+}
+} // namespace sea_ir
diff --git a/compiler/sea_ir/types/type_inference.h b/compiler/sea_ir/types/type_inference.h
new file mode 100644
index 0000000000..d951d82071
--- /dev/null
+++ b/compiler/sea_ir/types/type_inference.h
@@ -0,0 +1,94 @@
+/*
+ * 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_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_H_
+#define ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_H_
+
+#include "safe_map.h"
+#include "dex_file-inl.h"
+#include "sea_ir/types/types.h"
+
+namespace sea_ir {
+
+class SeaGraph;
+class InstructionNode;
+
+// The type inference in SEA IR is different from the verifier in that it is concerned
+// with a rich type hierarchy (TODO) usable in optimization and does not perform
+// precise verification (which is the job of the verifier).
+class TypeInference {
+ public:
+ TypeInference() {
+ type_cache_ = new art::verifier::RegTypeCache(false);
+ }
+
+ // Computes the types for the method with SEA IR representation provided by @graph.
+ void ComputeTypes(SeaGraph* graph);
+
+ art::SafeMap<int, const Type*>* GetTypeMap() {
+ return type_data_.GetTypeMap();
+ }
+ // Returns true if @descriptor corresponds to a primitive type.
+ static bool IsPrimitiveDescriptor(char descriptor);
+
+ protected:
+ art::verifier::RegTypeCache* type_cache_;
+ TypeData type_data_;
+};
+
+// Stores information about the exact type of a function.
+class FunctionTypeInfo {
+ public:
+ // Finds method information about the method encoded by a SEA IR graph.
+ // @graph provides the input method SEA IR representation.
+ // @types provides the input cache of types from which the
+ // parameter types of the function are found.
+ FunctionTypeInfo(const SeaGraph* graph, art::verifier::RegTypeCache* types);
+ // Finds method information about the method encoded by
+ // an invocation instruction in a SEA IR graph.
+ // @graph provides the input method SEA IR representation.
+ // @inst is an invocation instruction for the desired method.
+ // @types provides the input cache of types from which the
+ // parameter types of the function are found.
+ FunctionTypeInfo(const SeaGraph* graph, InstructionNode* inst,
+ art::verifier::RegTypeCache* types);
+ // Returns the ordered vector of types corresponding to the function arguments.
+ std::vector<const Type*> GetDeclaredArgumentTypes();
+ // Returns the declared return value type.
+ const Type* GetReturnValueType();
+ // Returns the type corresponding to the class that declared the method.
+ const Type& GetDeclaringClass() {
+ return *declaring_class_;
+ }
+
+ bool IsConstructor() const {
+ return (method_access_flags_ & kAccConstructor) != 0;
+ }
+
+ bool IsStatic() const {
+ return (method_access_flags_ & kAccStatic) != 0;
+ }
+
+ protected:
+ const Type* declaring_class_;
+ const art::DexFile* dex_file_;
+ const uint32_t dex_method_idx_;
+ art::verifier::RegTypeCache* type_cache_;
+ const uint32_t method_access_flags_; // Method's access flags.
+};
+} // namespace sea_ir
+
+#endif // ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_H_
diff --git a/compiler/sea_ir/types/type_inference_visitor.cc b/compiler/sea_ir/types/type_inference_visitor.cc
new file mode 100644
index 0000000000..3da2fc1e2c
--- /dev/null
+++ b/compiler/sea_ir/types/type_inference_visitor.cc
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#include "scoped_thread_state_change.h"
+#include "sea_ir/types/type_inference_visitor.h"
+#include "sea_ir/types/type_inference.h"
+#include "sea_ir/ir/sea.h"
+
+namespace sea_ir {
+
+void TypeInferenceVisitor::Visit(SignatureNode* parameter) {
+ FunctionTypeInfo fti(graph_, type_cache_);
+ std::vector<const Type*> arguments = fti.GetDeclaredArgumentTypes();
+ DCHECK_LT(parameter->GetPositionInSignature(), arguments.size())
+ << "Signature node position not present in signature.";
+ crt_type_.push_back(arguments.at(parameter->GetPositionInSignature()));
+}
+
+void TypeInferenceVisitor::Visit(UnnamedConstInstructionNode* instruction) {
+ crt_type_.push_back(&type_cache_->Integer());
+}
+
+void TypeInferenceVisitor::Visit(PhiInstructionNode* instruction) {
+ std::vector<const Type*> types_to_merge = GetOperandTypes(instruction);
+ const Type* result_type = MergeTypes(types_to_merge);
+ crt_type_.push_back(result_type);
+}
+
+void TypeInferenceVisitor::Visit(AddIntInstructionNode* instruction) {
+ std::vector<const Type*> operand_types = GetOperandTypes(instruction);
+ for (std::vector<const Type*>::const_iterator cit = operand_types.begin();
+ cit != operand_types.end(); cit++) {
+ if (*cit != NULL) {
+ DCHECK((*cit)->IsInteger());
+ }
+ }
+ crt_type_.push_back(&type_cache_->Integer());
+}
+
+void TypeInferenceVisitor::Visit(MoveResultInstructionNode* instruction) {
+ std::vector<const Type*> operand_types = GetOperandTypes(instruction);
+ const Type* operand_type = operand_types.at(0);
+ crt_type_.push_back(operand_type);
+}
+
+void TypeInferenceVisitor::Visit(InvokeStaticInstructionNode* instruction) {
+ FunctionTypeInfo fti(graph_, instruction, type_cache_);
+ const Type* result_type = fti.GetReturnValueType();
+ crt_type_.push_back(result_type);
+}
+
+std::vector<const Type*> TypeInferenceVisitor::GetOperandTypes(
+ InstructionNode* instruction) const {
+ std::vector<InstructionNode*> sources = instruction->GetSSAProducers();
+ std::vector<const Type*> types_to_merge;
+ for (std::vector<InstructionNode*>::const_iterator cit = sources.begin(); cit != sources.end();
+ cit++) {
+ const Type* source_type = type_data_->FindTypeOf((*cit)->Id());
+ if (source_type != NULL) {
+ types_to_merge.push_back(source_type);
+ }
+ }
+ return types_to_merge;
+}
+
+const Type* TypeInferenceVisitor::MergeTypes(std::vector<const Type*>& types) const {
+ const Type* type = NULL;
+ if (types.size()>0) {
+ type = *(types.begin());
+ if (types.size()>1) {
+ for (std::vector<const Type*>::const_iterator cit = types.begin();
+ cit != types.end(); cit++) {
+ if (!type->Equals(**cit)) {
+ type = MergeTypes(type, *cit);
+ }
+ }
+ }
+ }
+ return type;
+}
+
+const Type* TypeInferenceVisitor::MergeTypes(const Type* t1, const Type* t2) const {
+ DCHECK(t2 != NULL);
+ DCHECK(t1 != NULL);
+ art::ScopedObjectAccess soa(art::Thread::Current());
+ const Type* result = &(t1->Merge(*t2, type_cache_));
+ return result;
+}
+
+} // namespace sea_ir
diff --git a/compiler/sea_ir/types/type_inference_visitor.h b/compiler/sea_ir/types/type_inference_visitor.h
new file mode 100644
index 0000000000..200b9f0253
--- /dev/null
+++ b/compiler/sea_ir/types/type_inference_visitor.h
@@ -0,0 +1,81 @@
+/*
+ * 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_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_VISITOR_H_
+#define ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_VISITOR_H_
+
+
+#include "dex_file-inl.h"
+#include "sea_ir/ir/visitor.h"
+#include "sea_ir/types/types.h"
+
+namespace sea_ir {
+
+// The TypeInferenceVisitor visits each instruction and computes its type taking into account
+// the current type of the operands. The type is stored in the visitor.
+// We may be better off by using a separate visitor type hierarchy that has return values
+// or that passes data as parameters, than to use fields to store information that should
+// in fact be returned after visiting each element. Ideally, I would prefer to use templates
+// to specify the returned value type, but I am not aware of a possible implementation
+// that does not horribly duplicate the visitor infrastructure code (version 1: no return value,
+// version 2: with template return value).
+class TypeInferenceVisitor: public IRVisitor {
+ public:
+ TypeInferenceVisitor(SeaGraph* graph, TypeData* type_data,
+ art::verifier::RegTypeCache* types):
+ graph_(graph), type_data_(type_data), type_cache_(types), crt_type_() {
+ }
+ // There are no type related actions to be performed on these classes.
+ void Initialize(SeaGraph* graph) { }
+ void Visit(SeaGraph* graph) { }
+ void Visit(Region* region) { }
+
+ void Visit(PhiInstructionNode* instruction);
+ void Visit(SignatureNode* parameter);
+ void Visit(InstructionNode* instruction) { }
+ void Visit(UnnamedConstInstructionNode* instruction);
+ void Visit(ConstInstructionNode* instruction) { }
+ void Visit(ReturnInstructionNode* instruction) { }
+ void Visit(IfNeInstructionNode* instruction) { }
+ void Visit(MoveResultInstructionNode* instruction);
+ void Visit(InvokeStaticInstructionNode* instruction);
+ void Visit(AddIntInstructionNode* instruction);
+ void Visit(GotoInstructionNode* instruction) { }
+ void Visit(IfEqzInstructionNode* instruction) { }
+
+ const Type* MergeTypes(std::vector<const Type*>& types) const;
+ const Type* MergeTypes(const Type* t1, const Type* t2) const;
+ std::vector<const Type*> GetOperandTypes(InstructionNode* instruction) const;
+ const Type* GetType() {
+ // TODO: Currently multiple defined types are not supported.
+ if (crt_type_.size()>0) {
+ const Type* single_type = crt_type_.at(0);
+ crt_type_.clear();
+ return single_type;
+ }
+ return NULL;
+ }
+
+ protected:
+ const SeaGraph* const graph_;
+ TypeData* type_data_;
+ art::verifier::RegTypeCache* type_cache_;
+ std::vector<const Type*> crt_type_; // Stored temporarily between two calls to Visit.
+};
+
+} // namespace sea_ir
+
+#endif // ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_VISITOR_H_
diff --git a/compiler/sea_ir/types/type_inference_visitor_test.cc b/compiler/sea_ir/types/type_inference_visitor_test.cc
new file mode 100644
index 0000000000..8a249ebceb
--- /dev/null
+++ b/compiler/sea_ir/types/type_inference_visitor_test.cc
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#include "common_test.h"
+#include "sea_ir/types/type_inference_visitor.h"
+#include "sea_ir/ir/sea.h"
+
+namespace sea_ir {
+
+class TestInstructionNode:public InstructionNode {
+ public:
+ explicit TestInstructionNode(std::vector<InstructionNode*> prods): InstructionNode(NULL),
+ producers_(prods) { }
+ std::vector<InstructionNode*> GetSSAProducers() {
+ return producers_;
+ }
+ protected:
+ std::vector<InstructionNode*> producers_;
+};
+
+class TypeInferenceVisitorTest : public art::CommonTest {
+};
+
+TEST_F(TypeInferenceVisitorTest, MergeIntWithByte) {
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ const Type* int_type = &type_cache.Integer();
+ const Type* byte_type = &type_cache.Byte();
+ const Type* ib_type = tiv.MergeTypes(int_type, byte_type);
+ const Type* bi_type = tiv.MergeTypes(byte_type, int_type);
+ EXPECT_TRUE(ib_type == int_type);
+ EXPECT_TRUE(bi_type == int_type);
+}
+
+TEST_F(TypeInferenceVisitorTest, MergeIntWithShort) {
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ const Type* int_type = &type_cache.Integer();
+ const Type* short_type = &type_cache.Short();
+ const Type* is_type = tiv.MergeTypes(int_type, short_type);
+ const Type* si_type = tiv.MergeTypes(short_type, int_type);
+ EXPECT_TRUE(is_type == int_type);
+ EXPECT_TRUE(si_type == int_type);
+}
+
+TEST_F(TypeInferenceVisitorTest, MergeMultipleInts) {
+ int N = 10; // Number of types to merge.
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ std::vector<const Type*> types;
+ for (int i = 0; i < N; i++) {
+ const Type* new_type = &type_cache.Integer();
+ types.push_back(new_type);
+ }
+ const Type* merged_type = tiv.MergeTypes(types);
+ EXPECT_TRUE(merged_type == &type_cache.Integer());
+}
+
+TEST_F(TypeInferenceVisitorTest, MergeMultipleShorts) {
+ int N = 10; // Number of types to merge.
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ std::vector<const Type*> types;
+ for (int i = 0; i < N; i++) {
+ const Type* new_type = &type_cache.Short();
+ types.push_back(new_type);
+ }
+ const Type* merged_type = tiv.MergeTypes(types);
+ EXPECT_TRUE(merged_type == &type_cache.Short());
+}
+
+TEST_F(TypeInferenceVisitorTest, MergeMultipleIntsWithShorts) {
+ int N = 10; // Number of types to merge.
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ std::vector<const Type*> types;
+ for (int i = 0; i < N; i++) {
+ const Type* short_type = &type_cache.Short();
+ const Type* int_type = &type_cache.Integer();
+ types.push_back(short_type);
+ types.push_back(int_type);
+ }
+ const Type* merged_type = tiv.MergeTypes(types);
+ EXPECT_TRUE(merged_type == &type_cache.Integer());
+}
+
+TEST_F(TypeInferenceVisitorTest, GetOperandTypes) {
+ int N = 10; // Number of types to merge.
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ std::vector<const Type*> types;
+ std::vector<InstructionNode*> preds;
+ for (int i = 0; i < N; i++) {
+ const Type* short_type = &type_cache.Short();
+ const Type* int_type = &type_cache.Integer();
+ TestInstructionNode* short_inst =
+ new TestInstructionNode(std::vector<InstructionNode*>());
+ TestInstructionNode* int_inst =
+ new TestInstructionNode(std::vector<InstructionNode*>());
+ preds.push_back(short_inst);
+ preds.push_back(int_inst);
+ td.SetTypeOf(short_inst->Id(), short_type);
+ td.SetTypeOf(int_inst->Id(), int_type);
+ types.push_back(short_type);
+ types.push_back(int_type);
+ }
+ TestInstructionNode* inst_to_test = new TestInstructionNode(preds);
+ std::vector<const Type*> result = tiv.GetOperandTypes(inst_to_test);
+ EXPECT_TRUE(result.size() == types.size());
+ EXPECT_TRUE(true == std::equal(types.begin(), types.begin() + 2, result.begin()));
+}
+
+
+} // namespace art
diff --git a/compiler/sea_ir/types/types.h b/compiler/sea_ir/types/types.h
new file mode 100644
index 0000000000..64f25243d0
--- /dev/null
+++ b/compiler/sea_ir/types/types.h
@@ -0,0 +1,58 @@
+/*
+ * 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_COMPILER_SEA_IR_TYPES_TYPES_H_
+#define ART_COMPILER_SEA_IR_TYPES_TYPES_H_
+
+#include "safe_map.h"
+#include "verifier/reg_type.h"
+#include "verifier/reg_type_cache.h"
+
+namespace sea_ir {
+
+// TODO: Replace typedef with an actual class implementation when we have more types.
+typedef art::verifier::RegType Type;
+
+// Stores information about the result type of each instruction.
+// Note: Main purpose is to encapsulate the map<instruction id, type*>,
+// so that we can replace the underlying storage at any time.
+class TypeData {
+ public:
+ art::SafeMap<int, const Type*>* GetTypeMap() {
+ return &type_map_;
+ }
+ // Returns the type associated with instruction with @instruction_id.
+ const Type* FindTypeOf(int instruction_id) {
+ art::SafeMap<int, const Type*>::const_iterator result_it = type_map_.find(instruction_id);
+ if (type_map_.end() != result_it) {
+ return result_it->second;
+ }
+ return NULL;
+ }
+
+ // Saves the fact that instruction @instruction_id produces a value of type @type.
+ void SetTypeOf(int instruction_id, const Type* type) {
+ type_map_.Overwrite(instruction_id, type);
+ }
+
+ private:
+ art::SafeMap<int, const Type*> type_map_;
+};
+
+
+
+} // namespace sea_ir
+#endif // ART_COMPILER_SEA_IR_TYPES_TYPES_H_
diff --git a/compiler/utils/scoped_hashtable_test.cc b/compiler/utils/scoped_hashtable_test.cc
index d5f9f7d035..68608f01d1 100644
--- a/compiler/utils/scoped_hashtable_test.cc
+++ b/compiler/utils/scoped_hashtable_test.cc
@@ -15,7 +15,7 @@
*/
#include "common_test.h"
-#include "scoped_hashtable.h"
+#include "utils/scoped_hashtable.h"
using utils::ScopedHashtable;