offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, register_map_header_), "shadow$_register_map_header_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, shorty_), "shadow$_shorty_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, signature_), "shadow$_signature_"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, vmap_table_), "shadow$_vmap_table_"));
// alphabetical 32-bit
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_types_are_initialized_), "genericTypesAreInitialized"));
void CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
void CompileClass(Class* klass);
void CompileMethod(Method* klass);
+ int oatVRegOffsetFromMethod(Method* method, int reg);
// After compiling, walk all the DexCaches and set the code and
// method pointers of CodeAndDirectMethods entries in the DexCaches.
int assemblerRetries;
std::vector<short> codeBuffer;
std::vector<uint32_t> mappingTable;
+ std::vector<uint32_t> coreVmapTable;
+ std::vector<short> fpVmapTable;
bool printMe;
bool printMeVerbose;
bool dumpCFG;
memcpy(mapping_table->GetData(),
reinterpret_cast<const int32_t*>(&cUnit.mappingTable[0]),
mapping_table->GetLength() * sizeof(cUnit.mappingTable[0]));
- method->SetCode(managed_code, art::kThumb2, mapping_table);
+ // Add a marker to take place of lr
+ cUnit.coreVmapTable.push_back(-1);
+ // Combine vmap tables - core regs, then fp regs
+ for (uint32_t i = 0; i < cUnit.fpVmapTable.size(); i++) {
+ cUnit.coreVmapTable.push_back(cUnit.fpVmapTable[i]);
+ }
+ DCHECK(cUnit.coreVmapTable.size() == (uint32_t)
+ (__builtin_popcount(cUnit.coreSpillMask) +
+ __builtin_popcount(cUnit.fpSpillMask)));
+ art::ShortArray* vmap_table =
+ art::ShortArray::Alloc(cUnit.coreVmapTable.size());
+ memcpy(vmap_table->GetData(),
+ reinterpret_cast<const int16_t*>(&cUnit.coreVmapTable[0]),
+ vmap_table->GetLength() * sizeof(cUnit.coreVmapTable[0]));
+ method->SetCode(managed_code, art::kThumb2, mapping_table, vmap_table);
method->SetFrameSizeInBytes(cUnit.frameSize);
method->SetReturnPcOffsetInBytes(cUnit.frameSize - sizeof(intptr_t));
method->SetCoreSpillMask(cUnit.coreSpillMask);
res = coreRegs[i].reg;
coreRegs[i].inUse = true;
cUnit->coreSpillMask |= (1 << res);
+ cUnit->coreVmapTable.push_back(sReg);
cUnit->numSpills++;
cUnit->regLocation[sReg].location = kLocPhysReg;
cUnit->regLocation[sReg].lowReg = res;
res = FPRegs[i].reg;
FPRegs[i].inUse = true;
cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
+ cUnit->fpVmapTable.push_back(sReg);
cUnit->numSpills++;
cUnit->numFPSpills++;
cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
}
- int linebreak = 0;
std::string signature = method->GetSignature()->ToModifiedUtf8();
std::string name = method->GetName()->ToModifiedUtf8();
std::string descriptor = method->GetDeclaringClass()->GetDescriptor()->
ToModifiedUtf8();
char buf[256];
+#if 0
+ int linebreak = 0;
+ //TODO: delete when we're sure it's no longer necessary
LOG(INFO) << "*/";
sprintf(buf,"\n u1 %s%s_%s_code[] = {", descriptor.c_str(),
name.c_str(), signature.c_str());
LOG(INFO) << buf;
}
LOG(INFO) << " };\n\n";
+#endif
// Dump mapping table
if (cUnit->mappingTable.size() > 0) {
}
LOG(INFO) <<" };\n\n";
}
+
+ // Dump vmap table
}
cUnit->insOffset + ((reg - cUnit->numRegs) << 2);
}
+/* Return sp-relative offset in bytes using Method* */
+extern int oatVRegOffsetFromMethod(Method* method, int reg)
+{
+ int numIns = method->NumIns();
+ int numRegs = method->NumRegisters() - numIns;
+ int numOuts = method->NumOuts();
+ int numSpills = __builtin_popcount(method->GetCoreSpillMask()) +
+ __builtin_popcount(method->GetFpSpillMask());
+ int numPadding = (STACK_ALIGN_WORDS -
+ (numSpills + numRegs + numOuts + 2)) & (STACK_ALIGN_WORDS-1);
+ int regsOffset = (numOuts + numPadding + 1) * 4;
+ int insOffset = method->GetFrameSizeInBytes() + 4;
+ return (reg < numRegs) ? regsOffset + (reg << 2) :
+ insOffset + ((reg - numRegs) << 2);
+}
/* Clobber all regs that might be used by an external C call */
extern void oatClobberCallRegs(CompilationUnit *cUnit)
}
void Method::SetCode(ByteArray* code_array, InstructionSet instruction_set,
- IntArray* mapping_table) {
+ IntArray* mapping_table, ShortArray* vmap_table) {
CHECK(GetCode() == NULL || IsNative());
SetFieldPtr<ByteArray*>(OFFSET_OF_OBJECT_MEMBER(Method, code_array_), code_array, false);
SetFieldPtr<IntArray*>(OFFSET_OF_OBJECT_MEMBER(Method, mapping_table_),
mapping_table, false);
+ SetFieldPtr<ShortArray*>(OFFSET_OF_OBJECT_MEMBER(Method, vmap_table_),
+ vmap_table, false);
int8_t* code = code_array->GetData();
uintptr_t address = reinterpret_cast<uintptr_t>(code);
if (instruction_set == kThumb2) {
}
void SetCode(ByteArray* code_array, InstructionSet instruction_set,
- IntArray* mapping_table = NULL);
+ IntArray* mapping_table = NULL, ShortArray* vmap_table = NULL);
static MemberOffset GetCodeOffset() {
return OFFSET_OF_OBJECT_MEMBER(Method, code_);
OFFSET_OF_OBJECT_MEMBER(Method, mapping_table_), false);
}
+ ShortArray* GetVMapTable() const {
+ return GetFieldObject<ShortArray*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, vmap_table_), false);
+ }
+
size_t GetFrameSizeInBytes() const {
DCHECK(sizeof(size_t) == sizeof(uint32_t));
size_t result = GetField32(
// (IDLjava/lang/Thread;)Ljava/lang/Object;
String* signature_;
+ // Storage for Dalvik virtual register mapping_table_
+ ShortArray* vmap_table_;
+
uint32_t java_generic_types_are_initialized_;
// Access flags; low 16 bits are defined by spec.