Quick: PC-relative loads from dex cache arrays on x86.
Rewrite all PC-relative addressing on x86 and implement
PC-relative loads from dex cache arrays. Don't adjust the
base to point to the start of the method, let it point to
the anchor, i.e. the target of the "call +0" insn.
Change-Id: Ic22544a8bc0c5e49eb00a75154dc8f3ead816989
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index a98a99e..72580a3 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -28,7 +28,7 @@
namespace art {
-class X86Mir2Lir : public Mir2Lir {
+class X86Mir2Lir FINAL : public Mir2Lir {
protected:
class InToRegStorageX86_64Mapper : public InToRegStorageMapper {
public:
@@ -375,6 +375,10 @@
*/
LIR* GenCallInsn(const MirMethodLoweringInfo& method_info) OVERRIDE;
+ void AnalyzeMIR(RefCounts* core_counts, MIR* mir, uint32_t weight) OVERRIDE;
+ void CountRefs(RefCounts* core_counts, RefCounts* fp_counts, size_t num_regs) OVERRIDE;
+ void DoPromotion() OVERRIDE;
+
/*
* @brief Handle x86 specific literals
*/
@@ -488,7 +492,6 @@
void EmitCallThread(const X86EncodingMap* entry, int32_t disp);
void EmitPcRel(const X86EncodingMap* entry, int32_t raw_reg, int32_t raw_base_or_table,
int32_t raw_index, int scale, int32_t table_or_disp);
- void EmitMacro(const X86EncodingMap* entry, int32_t raw_reg, int32_t offset);
void EmitUnimplemented(const X86EncodingMap* entry, LIR* lir);
void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1,
int64_t val, ConditionCode ccode);
@@ -859,12 +862,6 @@
void SpillFPRegs();
/*
- * @brief Perform MIR analysis before compiling method.
- * @note Invokes Mir2LiR::Materialize after analysis.
- */
- void Materialize();
-
- /*
* Mir2Lir's UpdateLoc() looks to see if the Dalvik value is currently live in any temp register
* without regard to data type. In practice, this can result in UpdateLoc returning a
* location record for a Dalvik float value in a core register, and vis-versa. For targets
@@ -878,67 +875,39 @@
RegLocation UpdateLocWideTyped(RegLocation loc);
/*
- * @brief Analyze MIR before generating code, to prepare for the code generation.
- */
- void AnalyzeMIR();
-
- /*
- * @brief Analyze one basic block.
- * @param bb Basic block to analyze.
- */
- void AnalyzeBB(BasicBlock* bb);
-
- /*
- * @brief Analyze one extended MIR instruction
- * @param opcode MIR instruction opcode.
- * @param bb Basic block containing instruction.
- * @param mir Extended instruction to analyze.
- */
- void AnalyzeExtendedMIR(int opcode, BasicBlock* bb, MIR* mir);
-
- /*
- * @brief Analyze one MIR instruction
- * @param opcode MIR instruction opcode.
- * @param bb Basic block containing instruction.
- * @param mir Instruction to analyze.
- */
- virtual void AnalyzeMIR(int opcode, BasicBlock* bb, MIR* mir);
-
- /*
* @brief Analyze one MIR float/double instruction
* @param opcode MIR instruction opcode.
- * @param bb Basic block containing instruction.
* @param mir Instruction to analyze.
+ * @return true iff the instruction needs to load a literal using PC-relative addressing.
*/
- virtual void AnalyzeFPInstruction(int opcode, BasicBlock* bb, MIR* mir);
+ bool AnalyzeFPInstruction(int opcode, MIR* mir);
/*
* @brief Analyze one use of a double operand.
* @param rl_use Double RegLocation for the operand.
+ * @return true iff the instruction needs to load a literal using PC-relative addressing.
*/
- void AnalyzeDoubleUse(RegLocation rl_use);
+ bool AnalyzeDoubleUse(RegLocation rl_use);
/*
* @brief Analyze one invoke-static MIR instruction
- * @param opcode MIR instruction opcode.
- * @param bb Basic block containing instruction.
* @param mir Instruction to analyze.
+ * @return true iff the instruction needs to load a literal using PC-relative addressing.
*/
- void AnalyzeInvokeStatic(int opcode, BasicBlock* bb, MIR* mir);
+ bool AnalyzeInvokeStaticIntrinsic(MIR* mir);
// Information derived from analysis of MIR
- // The compiler temporary for the code address of the method.
- CompilerTemp *base_of_code_;
+ // The base register for PC-relative addressing if promoted (32-bit only).
+ RegStorage pc_rel_base_reg_;
- // Have we decided to compute a ptr to code and store in temporary VR?
- bool store_method_addr_;
+ // Have we actually used the pc_rel_base_reg_?
+ bool pc_rel_base_reg_used_;
- // Have we used the stored method address?
- bool store_method_addr_used_;
-
- // Instructions to remove if we didn't use the stored method address.
- LIR* setup_method_address_[2];
+ // Pointer to the "call +0" insn that sets up the promoted register for PC-relative addressing.
+ // The anchor "pop" insn is NEXT_LIR(setup_pc_rel_base_reg_). The whole "call +0; pop <reg>"
+ // sequence will be removed in AssembleLIR() if we do not actually use PC-relative addressing.
+ LIR* setup_pc_rel_base_reg_; // There are 2 chained insns (no reordering allowed).
// Instructions needing patching with Method* values.
ArenaVector<LIR*> method_address_insns_;
@@ -992,6 +961,14 @@
uintptr_t direct_code, uintptr_t direct_method,
InvokeType type);
+ LIR* OpLoadPc(RegStorage r_dest);
+ RegStorage GetPcAndAnchor(LIR** anchor, RegStorage r_tmp = RegStorage::InvalidReg());
+
+ // When we don't know the proper offset for the value, pick one that will force
+ // 4 byte offset. We will fix this up in the assembler or linker later to have
+ // the right value.
+ static constexpr int kDummy32BitOffset = 256;
+
static const X86EncodingMap EncodingMap[kX86Last];
friend std::ostream& operator<<(std::ostream& os, const X86OpCode& rhs);