Merge "Add missing header necessary for libc++."
diff --git a/Android.mk b/Android.mk
index 2196d59..57185ca 100644
--- a/Android.mk
+++ b/Android.mk
@@ -151,7 +151,7 @@
# host test targets
.PHONY: test-art-host-vixl
-ifneq ($(BUILD_HOST_64bit),)
+ifneq ($(HOST_IS_64_BIT),)
test-art-host-vixl: $(ANDROID_HOST_OUT)/bin/cctest_vixl
$(ANDROID_HOST_OUT)/bin/cctest_vixl --run_all
@echo vixl PASSED
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 39601e4..cc600bd 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -37,11 +37,7 @@
ART_BUILD_HOST_NDEBUG ?= $(WITH_HOST_DALVIK)
ART_BUILD_HOST_DEBUG ?= $(WITH_HOST_DALVIK)
-ifeq ($(BUILD_HOST_64bit),)
-ART_HOST_ARCH := x86
-else
-ART_HOST_ARCH := x86_64
-endif
+ART_HOST_ARCH := $(HOST_ARCH)
ifeq ($(ART_BUILD_TARGET_NDEBUG),false)
$(info Disabling ART_BUILD_TARGET_NDEBUG)
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index b157d8e..e9db47e 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -250,3 +250,9 @@
$(foreach file,$(COMPILER_GTEST_HOST_SRC_FILES), $(eval $(call build-art-test,host,$(file),art/compiler,libartd-compiler)))
endif
endif
+
+# Used outside the art project to get a list of the current tests
+RUNTIME_TARGET_GTEST_MAKE_TARGETS :=
+$(foreach file, $(RUNTIME_GTEST_TARGET_SRC_FILES), $(eval RUNTIME_TARGET_GTEST_MAKE_TARGETS += $$(notdir $$(basename $$(file)))))
+COMPILER_TARGET_GTEST_MAKE_TARGETS :=
+$(foreach file, $(COMPILER_GTEST_TARGET_SRC_FILES), $(eval COMPILER_TARGET_GTEST_MAKE_TARGETS += $$(notdir $$(basename $$(file)))))
diff --git a/compiler/compilers.cc b/compiler/compilers.cc
index 79a85db..76838d7 100644
--- a/compiler/compilers.cc
+++ b/compiler/compilers.cc
@@ -111,7 +111,7 @@
mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
break;
case kX86_64:
- mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+ mir_to_lir = X86_64CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
break;
default:
LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h
index 05ab8ca..5b4492f 100644
--- a/compiler/dex/compiler_enums.h
+++ b/compiler/dex/compiler_enums.h
@@ -126,6 +126,104 @@
kMirOpCheck,
kMirOpCheckPart2,
kMirOpSelect,
+
+ // Vector opcodes:
+ // TypeSize is an encoded field giving the element type and the vector size.
+ // It is encoded as OpSize << 16 | (number of bits in vector)
+ //
+ // Destination and source are integers that will be interpreted by the
+ // backend that supports Vector operations. Backends are permitted to support only
+ // certain vector register sizes.
+ //
+ // At this point, only two operand instructions are supported. Three operand instructions
+ // could be supported by using a bit in TypeSize and arg[0] where needed.
+
+ // @brief MIR to move constant data to a vector register
+ // vA: number of bits in register
+ // vB: destination
+ // args[0]~args[3]: up to 128 bits of data for initialization
+ kMirOpConstVector,
+
+ // @brief MIR to move a vectorized register to another
+ // vA: TypeSize
+ // vB: destination
+ // vC: source
+ kMirOpMoveVector,
+
+ // @brief Packed multiply of units in two vector registers: vB = vB .* vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: source
+ kMirOpPackedMultiply,
+
+ // @brief Packed addition of units in two vector registers: vB = vB .+ vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: source
+ kMirOpPackedAddition,
+
+ // @brief Packed subtraction of units in two vector registers: vB = vB .- vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: source
+ kMirOpPackedSubtract,
+
+ // @brief Packed shift left of units in two vector registers: vB = vB .<< vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: immediate
+ kMirOpPackedShiftLeft,
+
+ // @brief Packed signed shift right of units in two vector registers: vB = vB .>> vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: immediate
+ kMirOpPackedSignedShiftRight,
+
+ // @brief Packed unsigned shift right of units in two vector registers: vB = vB .>>> vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: immediate
+ kMirOpPackedUnsignedShiftRight,
+
+ // @brief Packed bitwise and of units in two vector registers: vB = vB .& vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: source
+ kMirOpPackedAnd,
+
+ // @brief Packed bitwise or of units in two vector registers: vB = vB .| vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: source
+ kMirOpPackedOr,
+
+ // @brief Packed bitwise xor of units in two vector registers: vB = vB .^ vC using vA to know the type of the vector.
+ // vA: TypeSize
+ // vB: destination and source
+ // vC: source
+ kMirOpPackedXor,
+
+ // @brief Reduce a 128-bit packed element into a single VR by taking lower bits
+ // @details Instruction does a horizontal addition of the packed elements and then adds it to VR
+ // vA: TypeSize
+ // vB: destination and source VR (not vector register)
+ // vC: source (vector register)
+ kMirOpPackedAddReduce,
+
+ // @brief Extract a packed element into a single VR.
+ // vA: TypeSize
+ // vB: destination VR (not vector register)
+ // vC: source (vector register)
+ // arg[0]: The index to use for extraction from vector register (which packed element)
+ kMirOpPackedReduce,
+
+ // @brief Create a vector value, with all TypeSize values equal to vC
+ // vA: TypeSize
+ // vB: destination vector register
+ // vC: source VR (not vector register)
+ kMirOpPackedSet,
+
kMirOpLast,
};
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index ca90a83..ba4224e 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -45,6 +45,20 @@
"Check1",
"Check2",
"Select",
+ "ConstVector",
+ "MoveVector",
+ "PackedMultiply",
+ "PackedAddition",
+ "PackedSubtract",
+ "PackedShiftLeft",
+ "PackedSignedShiftRight",
+ "PackedUnsignedShiftRight",
+ "PackedAnd",
+ "PackedOr",
+ "PackedXor",
+ "PackedAddReduce",
+ "PackedReduce",
+ "PackedSet",
};
MIRGraph::MIRGraph(CompilationUnit* cu, ArenaAllocator* arena)
@@ -798,13 +812,35 @@
bb->first_mir_insn ? " | " : " ");
for (mir = bb->first_mir_insn; mir; mir = mir->next) {
int opcode = mir->dalvikInsn.opcode;
- fprintf(file, " {%04x %s %s %s\\l}%s\\\n", mir->offset,
- mir->ssa_rep ? GetDalvikDisassembly(mir) :
- (opcode < kMirOpFirst) ? Instruction::Name(mir->dalvikInsn.opcode) :
- extended_mir_op_names_[opcode - kMirOpFirst],
- (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
- (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
- mir->next ? " | " : " ");
+ if (opcode > kMirOpSelect && opcode < kMirOpLast) {
+ if (opcode == kMirOpConstVector) {
+ fprintf(file, " {%04x %s %d %d %d %d %d %d\\l}%s\\\n", mir->offset,
+ extended_mir_op_names_[kMirOpConstVector - kMirOpFirst],
+ mir->dalvikInsn.vA,
+ mir->dalvikInsn.vB,
+ mir->dalvikInsn.arg[0],
+ mir->dalvikInsn.arg[1],
+ mir->dalvikInsn.arg[2],
+ mir->dalvikInsn.arg[3],
+ mir->next ? " | " : " ");
+ } else {
+ fprintf(file, " {%04x %s %d %d %d\\l}%s\\\n", mir->offset,
+ extended_mir_op_names_[opcode - kMirOpFirst],
+ mir->dalvikInsn.vA,
+ mir->dalvikInsn.vB,
+ mir->dalvikInsn.vC,
+ mir->next ? " | " : " ");
+ }
+ } else {
+ fprintf(file, " {%04x %s %s %s\\l}%s\\\n", mir->offset,
+ mir->ssa_rep ? GetDalvikDisassembly(mir) :
+ (opcode < kMirOpFirst) ?
+ Instruction::Name(mir->dalvikInsn.opcode) :
+ extended_mir_op_names_[opcode - kMirOpFirst],
+ (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
+ (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
+ mir->next ? " | " : " ");
+ }
}
fprintf(file, " }\"];\n\n");
} else if (bb->block_type == kExceptionHandling) {
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 784dfaf..6f81238 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -1203,4 +1203,8 @@
return loc;
}
+void Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
+ LOG(FATAL) << "Unknown MIR opcode not supported on this architecture";
+}
+
} // namespace art
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 2c4ca88..10c2459 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -975,7 +975,18 @@
case kMirOpSelect:
GenSelect(bb, mir);
break;
+ case kMirOpPhi:
+ case kMirOpNop:
+ case kMirOpNullCheck:
+ case kMirOpRangeCheck:
+ case kMirOpDivZeroCheck:
+ case kMirOpCheck:
+ case kMirOpCheckPart2:
+ // Ignore these known opcodes
+ break;
default:
+ // Give the backends a chance to handle unknown extended MIR opcodes.
+ GenMachineSpecificExtendedMethodMIR(bb, mir);
break;
}
}
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 836d2ac..3201b60 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -174,6 +174,8 @@
ArenaAllocator* const arena);
Mir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
ArenaAllocator* const arena);
+Mir2Lir* X86_64CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
+ ArenaAllocator* const arena);
// Utility macros to traverse the LIR list.
#define NEXT_LIR(lir) (lir->next)
@@ -1178,6 +1180,14 @@
virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) = 0;
virtual void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) = 0;
+ /*
+ * @brief Handle Machine Specific MIR Extended opcodes.
+ * @param bb The basic block in which the MIR is from.
+ * @param mir The MIR whose opcode is not standard extended MIR.
+ * @note Base class implementation will abort for unknown opcodes.
+ */
+ virtual void GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir);
+
/**
* @brief Lowers the kMirOpSelect MIR into LIR.
* @param bb The basic block in which the MIR is from.
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index b8481e2..9200106 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -63,17 +63,24 @@
{ kX86 ## opname ## 16TI8, kThreadImm, mem_use | IS_BINARY_OP | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0x66, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "16TI8", "fs:[!0d],!1d" }, \
\
{ kX86 ## opname ## 32MR, kMemReg, mem_use | IS_TERTIARY_OP | REG_USE02 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "32MR", "[!0r+!1d],!2r" }, \
+{ kX86 ## opname ## 64MR, kMemReg64, mem_use | IS_TERTIARY_OP | REG_USE02 | SETS_CCODES | uses_ccodes, { REX_W, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "64MR", "[!0r+!1d],!2r" }, \
{ kX86 ## opname ## 32AR, kArrayReg, mem_use | IS_QUIN_OP | REG_USE014 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "32AR", "[!0r+!1r<<!2d+!3d],!4r" }, \
+{ kX86 ## opname ## 64AR, kArrayReg64, mem_use | IS_QUIN_OP | REG_USE014 | SETS_CCODES | uses_ccodes, { REX_W, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "64AR", "[!0r+!1r<<!2d+!3d],!4r" }, \
{ kX86 ## opname ## 32TR, kThreadReg, mem_use | IS_BINARY_OP | REG_USE1 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "32TR", "fs:[!0d],!1r" }, \
{ kX86 ## opname ## 32RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "32RR", "!0r,!1r" }, \
{ kX86 ## opname ## 32RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "32RM", "!0r,[!1r+!2d]" }, \
+{ kX86 ## opname ## 64RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { REX_W, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "64RM", "!0r,[!1r+!2d]" }, \
{ kX86 ## opname ## 32RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE012 | SETS_CCODES | uses_ccodes, { 0, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "32RA", "!0r,[!1r+!2r<<!3d+!4d]" }, \
+{ kX86 ## opname ## 64RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE012 | SETS_CCODES | uses_ccodes, { REX_W, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "64RA", "!0r,[!1r+!2r<<!3d+!4d]" }, \
{ kX86 ## opname ## 32RT, kRegThread, IS_LOAD | IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "32RT", "!0r,fs:[!1d]" }, \
+{ kX86 ## opname ## 64RT, kReg64Thread, IS_LOAD | IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, REX_W, r32_rm32, 0, 0, 0, 0, 0 }, #opname "64RT", "!0r,fs:[!1d]" }, \
{ kX86 ## opname ## 32RI, kRegImm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i32, 0, 0, rm32_i32_modrm, ax32_i32, 4 }, #opname "32RI", "!0r,!1d" }, \
+{ kX86 ## opname ## 64RI, kReg64Imm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { REX_W, 0, rm32_i32, 0, 0, rm32_i32_modrm, ax32_i32, 4 }, #opname "32RI", "!0r,!1d" }, \
{ kX86 ## opname ## 32MI, kMemImm, mem_use | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i32, 0, 0, rm32_i32_modrm, 0, 4 }, #opname "32MI", "[!0r+!1d],!2d" }, \
{ kX86 ## opname ## 32AI, kArrayImm, mem_use | IS_QUIN_OP | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i32, 0, 0, rm32_i32_modrm, 0, 4 }, #opname "32AI", "[!0r+!1r<<!2d+!3d],!4d" }, \
{ kX86 ## opname ## 32TI, kThreadImm, mem_use | IS_BINARY_OP | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, rm32_i32, 0, 0, rm32_i32_modrm, 0, 4 }, #opname "32TI", "fs:[!0d],!1d" }, \
{ kX86 ## opname ## 32RI8, kRegImm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "32RI8", "!0r,!1d" }, \
+{ kX86 ## opname ## 64RI8, kReg64Imm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { REX_W, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "64RI8", "!0r,!1d" }, \
{ kX86 ## opname ## 32MI8, kMemImm, mem_use | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "32MI8", "[!0r+!1d],!2d" }, \
{ kX86 ## opname ## 32AI8, kArrayImm, mem_use | IS_QUIN_OP | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "32AI8", "[!0r+!1r<<!2d+!3d],!4d" }, \
{ kX86 ## opname ## 32TI8, kThreadImm, mem_use | IS_BINARY_OP | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "32TI8", "fs:[!0d],!1d" }
@@ -164,16 +171,22 @@
{ kX86Mov16TI, kThreadImm, IS_STORE | IS_BINARY_OP, { THREAD_PREFIX, 0x66, 0xC7, 0, 0, 0, 0, 2 }, "Mov16TI", "fs:[!0d],!1d" },
{ kX86Mov32MR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov32MR", "[!0r+!1d],!2r" },
+ { kX86Mov64MR, kMemReg64, IS_STORE | IS_TERTIARY_OP | REG_USE02, { REX_W, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov64MR", "[!0r+!1d],!2r" },
{ kX86Mov32AR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov32AR", "[!0r+!1r<<!2d+!3d],!4r" },
+ { kX86Mov64AR, kArrayReg64, IS_STORE | IS_QUIN_OP | REG_USE014, { REX_W, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov64AR", "[!0r+!1r<<!2d+!3d],!4r" },
{ kX86Mov32TR, kThreadReg, IS_STORE | IS_BINARY_OP | REG_USE1, { THREAD_PREFIX, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov32TR", "fs:[!0d],!1r" },
{ kX86Mov32RR, kRegReg, IS_BINARY_OP | REG_DEF0_USE1, { 0, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov32RR", "!0r,!1r" },
{ kX86Mov32RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | REG_DEF0_USE1, { 0, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov32RM", "!0r,[!1r+!2d]" },
+ { kX86Mov64RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | REG_DEF0_USE1, { REX_W, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov64RM", "!0r,[!1r+!2d]" },
{ kX86Mov32RA, kRegArray, IS_LOAD | IS_QUIN_OP | REG_DEF0_USE12, { 0, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov32RA", "!0r,[!1r+!2r<<!3d+!4d]" },
+ { kX86Mov64RA, kRegArray, IS_LOAD | IS_QUIN_OP | REG_DEF0_USE12, { REX_W, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov64RA", "!0r,[!1r+!2r<<!3d+!4d]" },
{ kX86Mov32RT, kRegThread, IS_LOAD | IS_BINARY_OP | REG_DEF0, { THREAD_PREFIX, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov32RT", "!0r,fs:[!1d]" },
+ { kX86Mov64RT, kRegThread, IS_LOAD | IS_BINARY_OP | REG_DEF0, { THREAD_PREFIX, REX_W, 0x8B, 0, 0, 0, 0, 0 }, "Mov64RT", "!0r,fs:[!1d]" },
{ kX86Mov32RI, kMovRegImm, IS_BINARY_OP | REG_DEF0, { 0, 0, 0xB8, 0, 0, 0, 0, 4 }, "Mov32RI", "!0r,!1d" },
{ kX86Mov32MI, kMemImm, IS_STORE | IS_TERTIARY_OP | REG_USE0, { 0, 0, 0xC7, 0, 0, 0, 0, 4 }, "Mov32MI", "[!0r+!1d],!2d" },
{ kX86Mov32AI, kArrayImm, IS_STORE | IS_QUIN_OP | REG_USE01, { 0, 0, 0xC7, 0, 0, 0, 0, 4 }, "Mov32AI", "[!0r+!1r<<!2d+!3d],!4d" },
{ kX86Mov32TI, kThreadImm, IS_STORE | IS_BINARY_OP, { THREAD_PREFIX, 0, 0xC7, 0, 0, 0, 0, 4 }, "Mov32TI", "fs:[!0d],!1d" },
+ { kX86Mov64TI, kThreadImm, IS_STORE | IS_BINARY_OP, { THREAD_PREFIX, REX_W, 0xC7, 0, 0, 0, 0, 4 }, "Mov64TI", "fs:[!0d],!1d" },
{ kX86Lea32RM, kRegMem, IS_TERTIARY_OP | IS_LOAD | REG_DEF0_USE1, { 0, 0, 0x8D, 0, 0, 0, 0, 0 }, "Lea32RM", "!0r,[!1r+!2d]" },
@@ -307,6 +320,11 @@
{ kX86Fstp32M, kMem, IS_STORE | IS_UNARY_OP | REG_USE0 | USE_FP_STACK, { 0x0, 0, 0xD9, 0x00, 0, 3, 0, 0 }, "FstpsM", "[!0r,!1d]" },
{ kX86Fstp64M, kMem, IS_STORE | IS_UNARY_OP | REG_USE0 | USE_FP_STACK, { 0x0, 0, 0xDD, 0x00, 0, 3, 0, 0 }, "FstpdM", "[!0r,!1d]" },
+ EXT_0F_ENCODING_MAP(Mova128, 0x66, 0x6F, REG_DEF0),
+ { kX86Mova128MR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x66, 0, 0x0F, 0x6F, 0, 0, 0, 0 }, "Mova128MR", "[!0r+!1d],!2r" },
+ { kX86Mova128AR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0x66, 0, 0x0F, 0x6F, 0, 0, 0, 0 }, "Mova128AR", "[!0r+!1r<<!2d+!3d],!4r" },
+
+
EXT_0F_ENCODING_MAP(Movups, 0x0, 0x10, REG_DEF0),
{ kX86MovupsMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x0, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovupsMR", "[!0r+!1d],!2r" },
{ kX86MovupsAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0x0, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovupsAR", "[!0r+!1r<<!2d+!3d],!4r" },
@@ -376,7 +394,7 @@
{ kX86RepneScasw, kPrefix2Nullary, NO_OPERAND | REG_USEA | REG_USEC | SETS_CCODES, { 0x66, 0xF2, 0xAF, 0, 0, 0, 0, 0 }, "RepNE ScasW", "" },
};
-static size_t ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib) {
+size_t X86Mir2Lir::ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib) {
size_t size = 0;
if (entry->skeleton.prefix1 > 0) {
++size;
@@ -392,8 +410,10 @@
}
}
++size; // modrm
- if (has_sib || RegStorage::RegNum(base) == rs_rX86_SP.GetRegNum()) {
+ if (has_sib || RegStorage::RegNum(base) == rs_rX86_SP.GetRegNum()
+ || (Gen64Bit() && entry->skeleton.prefix1 == THREAD_PREFIX)) {
// SP requires a SIB byte.
+ // GS access also needs a SIB byte for absolute adressing in 64-bit mode.
++size;
}
if (displacement != 0 || RegStorage::RegNum(base) == rs_rBP.GetRegNum()) {
@@ -421,16 +441,19 @@
return 3; // 1 byte of opcode + 2 prefixes
case kRegOpcode: // lir operands - 0: reg
return ComputeSize(entry, 0, 0, false) - 1; // substract 1 for modrm
+ case kReg64:
case kReg: // lir operands - 0: reg
return ComputeSize(entry, 0, 0, false);
case kMem: // lir operands - 0: base, 1: disp
return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
case kArray: // lir operands - 0: base, 1: index, 2: scale, 3: disp
return ComputeSize(entry, lir->operands[0], lir->operands[3], true);
+ case kMemReg64:
case kMemReg: // lir operands - 0: base, 1: disp, 2: reg
return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
case kMemRegImm: // lir operands - 0: base, 1: disp, 2: reg 3: immediate
return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
+ case kArrayReg64:
case kArrayReg: // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
return ComputeSize(entry, lir->operands[0], lir->operands[3], true);
case kThreadReg: // lir operands - 0: disp, 1: reg
@@ -443,8 +466,10 @@
return ComputeSize(entry, lir->operands[1], lir->operands[2], false);
case kRegArray: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
return ComputeSize(entry, lir->operands[1], lir->operands[4], true);
+ case kReg64Thread: // lir operands - 0: reg, 1: disp
case kRegThread: // lir operands - 0: reg, 1: disp
return ComputeSize(entry, 0, 0x12345678, false); // displacement size is always 32bit
+ case kReg64Imm:
case kRegImm: { // lir operands - 0: reg, 1: immediate
size_t size = ComputeSize(entry, 0, 0, false);
if (entry->skeleton.ax_opcode == 0) {
@@ -551,7 +576,12 @@
void X86Mir2Lir::EmitPrefix(const X86EncodingMap* entry) {
if (entry->skeleton.prefix1 != 0) {
- code_buffer_.push_back(entry->skeleton.prefix1);
+ if (Gen64Bit() && entry->skeleton.prefix1 == THREAD_PREFIX) {
+ // 64 bit adresses by GS, not FS
+ code_buffer_.push_back(THREAD_PREFIX_GS);
+ } else {
+ code_buffer_.push_back(entry->skeleton.prefix1);
+ }
if (entry->skeleton.prefix2 != 0) {
code_buffer_.push_back(entry->skeleton.prefix2);
}
@@ -605,6 +635,19 @@
}
}
+void X86Mir2Lir::EmitModrmThread(uint8_t reg_or_opcode) {
+ if (Gen64Bit()) {
+ // Absolute adressing for GS access.
+ uint8_t modrm = (0 << 6) | (reg_or_opcode << 3) | rs_rX86_SP.GetRegNum();
+ code_buffer_.push_back(modrm);
+ uint8_t sib = (0/*TIMES_1*/ << 6) | (rs_rX86_SP.GetRegNum() << 3) | rs_rBP.GetRegNum();
+ code_buffer_.push_back(sib);
+ } else {
+ uint8_t modrm = (0 << 6) | (reg_or_opcode << 3) | rs_rBP.GetRegNum();
+ code_buffer_.push_back(modrm);
+ }
+}
+
void X86Mir2Lir::EmitModrmDisp(uint8_t reg_or_opcode, uint8_t base, int disp) {
DCHECK_LT(RegStorage::RegNum(reg_or_opcode), 8);
DCHECK_LT(RegStorage::RegNum(base), 8);
@@ -754,8 +797,7 @@
<< " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
}
DCHECK_LT(RegStorage::RegNum(reg), 8);
- uint8_t modrm = (0 << 6) | (RegStorage::RegNum(reg) << 3) | rs_rBP.GetRegNum();
- code_buffer_.push_back(modrm);
+ EmitModrmThread(RegStorage::RegNum(reg));
code_buffer_.push_back(disp & 0xFF);
code_buffer_.push_back((disp >> 8) & 0xFF);
code_buffer_.push_back((disp >> 16) & 0xFF);
@@ -810,14 +852,7 @@
}
void X86Mir2Lir::EmitRegImm(const X86EncodingMap* entry, uint8_t reg, int imm) {
- if (entry->skeleton.prefix1 != 0) {
- code_buffer_.push_back(entry->skeleton.prefix1);
- if (entry->skeleton.prefix2 != 0) {
- code_buffer_.push_back(entry->skeleton.prefix2);
- }
- } else {
- DCHECK_EQ(0, entry->skeleton.prefix2);
- }
+ EmitPrefix(entry);
if (RegStorage::RegNum(reg) == rs_rAX.GetRegNum() && entry->skeleton.ax_opcode != 0) {
code_buffer_.push_back(entry->skeleton.ax_opcode);
} else {
@@ -837,8 +872,7 @@
void X86Mir2Lir::EmitThreadImm(const X86EncodingMap* entry, int disp, int imm) {
EmitPrefixAndOpcode(entry);
- uint8_t modrm = (0 << 6) | (entry->skeleton.modrm_opcode << 3) | rs_rBP.GetRegNum();
- code_buffer_.push_back(modrm);
+ EmitModrmThread(entry->skeleton.modrm_opcode);
code_buffer_.push_back(disp & 0xFF);
code_buffer_.push_back((disp >> 8) & 0xFF);
code_buffer_.push_back((disp >> 16) & 0xFF);
@@ -931,14 +965,7 @@
}
void X86Mir2Lir::EmitRegCond(const X86EncodingMap* entry, uint8_t reg, uint8_t condition) {
- if (entry->skeleton.prefix1 != 0) {
- code_buffer_.push_back(entry->skeleton.prefix1);
- if (entry->skeleton.prefix2 != 0) {
- code_buffer_.push_back(entry->skeleton.prefix2);
- }
- } else {
- DCHECK_EQ(0, entry->skeleton.prefix2);
- }
+ EmitPrefix(entry);
DCHECK_EQ(0, entry->skeleton.ax_opcode);
DCHECK_EQ(0x0F, entry->skeleton.opcode);
code_buffer_.push_back(0x0F);
@@ -1075,8 +1102,7 @@
void X86Mir2Lir::EmitCallThread(const X86EncodingMap* entry, int disp) {
DCHECK_NE(entry->skeleton.prefix1, 0);
EmitPrefixAndOpcode(entry);
- uint8_t modrm = (0 << 6) | (entry->skeleton.modrm_opcode << 3) | rs_rBP.GetRegNum();
- code_buffer_.push_back(modrm);
+ EmitModrmThread(entry->skeleton.modrm_opcode);
code_buffer_.push_back(disp & 0xFF);
code_buffer_.push_back((disp >> 8) & 0xFF);
code_buffer_.push_back((disp >> 16) & 0xFF);
@@ -1317,6 +1343,7 @@
case kRegOpcode: // lir operands - 0: reg
EmitOpRegOpcode(entry, lir->operands[0]);
break;
+ case kReg64:
case kReg: // lir operands - 0: reg
EmitOpReg(entry, lir->operands[0]);
break;
@@ -1326,6 +1353,7 @@
case kArray: // lir operands - 0: base, 1: index, 2: scale, 3: disp
EmitOpArray(entry, lir->operands[0], lir->operands[1], lir->operands[2], lir->operands[3]);
break;
+ case kMemReg64:
case kMemReg: // lir operands - 0: base, 1: disp, 2: reg
EmitMemReg(entry, lir->operands[0], lir->operands[1], lir->operands[2]);
break;
@@ -1336,6 +1364,7 @@
EmitArrayImm(entry, lir->operands[0], lir->operands[1], lir->operands[2],
lir->operands[3], lir->operands[4]);
break;
+ case kArrayReg64:
case kArrayReg: // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
EmitArrayReg(entry, lir->operands[0], lir->operands[1], lir->operands[2],
lir->operands[3], lir->operands[4]);
@@ -1347,6 +1376,7 @@
EmitRegArray(entry, lir->operands[0], lir->operands[1], lir->operands[2],
lir->operands[3], lir->operands[4]);
break;
+ case kReg64Thread: // lir operands - 0: reg, 1: disp
case kRegThread: // lir operands - 0: reg, 1: disp
EmitRegThread(entry, lir->operands[0], lir->operands[1]);
break;
@@ -1370,6 +1400,7 @@
EmitRegMemImm(entry, lir->operands[0], lir->operands[1], lir->operands[2],
lir->operands[3]);
break;
+ case kReg64Imm:
case kRegImm: // lir operands - 0: reg, 1: immediate
EmitRegImm(entry, lir->operands[0], lir->operands[1]);
break;
@@ -1482,6 +1513,26 @@
void X86Mir2Lir::AssignOffsets() {
int offset = AssignInsnOffsets();
+ if (const_vectors_ != nullptr) {
+ /* assign offsets to vector literals */
+
+ // First, get offset to 12 mod 16 to align to 16 byte boundary.
+ // This will ensure that the vector is 16 byte aligned, as the procedure is
+ // always aligned at at 4 mod 16.
+ int align_size = (16-4) - (offset & 0xF);
+ if (align_size < 0) {
+ align_size += 16;
+ }
+
+ offset += align_size;
+
+ // Now assign each literal the right offset.
+ for (LIR *p = const_vectors_; p != nullptr; p = p->next) {
+ p->offset = offset;
+ offset += 16;
+ }
+ }
+
/* Const values have to be word aligned */
offset = RoundUp(offset, 4);
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index cf2b10a..4673cc0 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -156,8 +156,13 @@
}
NewLIR2(kX86PcRelAdr, rs_rX86_ARG1.GetReg(), WrapPointer(tab_rec));
NewLIR2(kX86Add32RR, rs_rX86_ARG1.GetReg(), rs_rX86_ARG2.GetReg());
- CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pHandleFillArrayData), rs_rX86_ARG0,
- rs_rX86_ARG1, true);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pHandleFillArrayData), rs_rX86_ARG0,
+ rs_rX86_ARG1, true);
+ } else {
+ CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pHandleFillArrayData), rs_rX86_ARG0,
+ rs_rX86_ARG1, true);
+ }
}
void X86Mir2Lir::GenMoveException(RegLocation rl_dest) {
@@ -180,7 +185,11 @@
int ct_offset = Is64BitInstructionSet(cu_->instruction_set) ?
Thread::CardTableOffset<8>().Int32Value() :
Thread::CardTableOffset<4>().Int32Value();
- NewLIR2(kX86Mov32RT, reg_card_base.GetReg(), ct_offset);
+ if (Gen64Bit()) {
+ NewLIR2(kX86Mov64RT, reg_card_base.GetReg(), ct_offset);
+ } else {
+ NewLIR2(kX86Mov32RT, reg_card_base.GetReg(), ct_offset);
+ }
OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte);
LIR* target = NewLIR0(kPseudoTargetLabel);
@@ -201,8 +210,7 @@
LockTemp(rs_rX86_ARG2);
/* Build frame, return address already on stack */
- // TODO: 64 bit.
- stack_decrement_ = OpRegImm(kOpSub, rs_rX86_SP, frame_size_ - 4);
+ stack_decrement_ = OpRegImm(kOpSub, rs_rX86_SP, frame_size_ - GetInstructionSetPointerSize(cu_->instruction_set));
/*
* We can safely skip the stack overflow check if we're
@@ -233,7 +241,7 @@
false /* MarkSafepointPC */, false /* UseLink */);
} else {
m2l_->CallHelper(RegStorage::InvalidReg(), QUICK_ENTRYPOINT_OFFSET(4, pThrowStackOverflow),
- false /* MarkSafepointPC */, false /* UseLink */);
+ false /* MarkSafepointPC */, false /* UseLink */);
}
}
@@ -248,7 +256,7 @@
// mov esp, ebp
// in case a signal comes in that's not using an alternate signal stack and the large frame may
// have moved us outside of the reserved area at the end of the stack.
- // cmp rX86_SP, fs:[stack_end_]; jcc throw_slowpath
+ // cmp rs_rX86_SP, fs:[stack_end_]; jcc throw_slowpath
if (Is64BitInstructionSet(cu_->instruction_set)) {
OpRegThreadMem(kOpCmp, rs_rX86_SP, Thread::StackEndOffset<8>());
} else {
@@ -286,7 +294,7 @@
NewLIR0(kPseudoMethodExit);
UnSpillCoreRegs();
/* Remove frame except for return address */
- stack_increment_ = OpRegImm(kOpAdd, rs_rX86_SP, frame_size_ - 4);
+ stack_increment_ = OpRegImm(kOpAdd, rs_rX86_SP, frame_size_ - GetInstructionSetPointerSize(cu_->instruction_set));
NewLIR0(kX86Ret);
}
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index ef8c33c..cc0e1f2 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -24,7 +24,7 @@
class X86Mir2Lir FINAL : public Mir2Lir {
public:
- X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
+ X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena, bool gen64bit);
// Required for target - codegen helpers.
bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
@@ -325,10 +325,12 @@
std::vector<uint8_t>* ReturnCallFrameInformation();
private:
+ size_t ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib);
void EmitPrefix(const X86EncodingMap* entry);
void EmitOpcode(const X86EncodingMap* entry);
void EmitPrefixAndOpcode(const X86EncodingMap* entry);
void EmitDisp(uint8_t base, int disp);
+ void EmitModrmThread(uint8_t reg_or_opcode);
void EmitModrmDisp(uint8_t reg_or_opcode, uint8_t base, int disp);
void EmitModrmSibDisp(uint8_t reg_or_opcode, uint8_t base, uint8_t index, int scale, int disp);
void EmitImm(const X86EncodingMap* entry, int imm);
@@ -406,6 +408,22 @@
bool GenInlinedIndexOf(CallInfo* info, bool zero_based);
/*
+ * @brief Load 128 bit constant into vector register.
+ * @param bb The basic block in which the MIR is from.
+ * @param mir The MIR whose opcode is kMirConstVector
+ * @note vA is the TypeSize for the register.
+ * @note vB is the destination XMM register. arg[0..3] are 32 bit constant values.
+ */
+ void GenConst128(BasicBlock* bb, MIR* mir);
+
+ /*
+ * @brief Generate code for a vector opcode.
+ * @param bb The basic block in which the MIR is from.
+ * @param mir The MIR whose opcode is a non-standard opcode.
+ */
+ void GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir);
+
+ /*
* @brief Return the correct x86 opcode for the Dex operation
* @param op Dex opcode for the operation
* @param loc Register location of the operand
@@ -578,6 +596,8 @@
*/
void AnalyzeDoubleUse(RegLocation rl_use);
+ bool Gen64Bit() const { return gen64bit_; }
+
// Information derived from analysis of MIR
// The compiler temporary for the code address of the method.
@@ -606,6 +626,25 @@
// Epilogue increment of stack pointer.
LIR* stack_increment_;
+
+ // 64-bit mode
+ bool gen64bit_;
+
+ // The list of const vector literals.
+ LIR *const_vectors_;
+
+ /*
+ * @brief Search for a matching vector literal
+ * @param mir A kMirOpConst128b MIR instruction to match.
+ * @returns pointer to matching LIR constant, or nullptr if not found.
+ */
+ LIR *ScanVectorLiteral(MIR *mir);
+
+ /*
+ * @brief Add a constant vector literal
+ * @param mir A kMirOpConst128b MIR instruction to match.
+ */
+ LIR *AddVectorLiteral(MIR *mir);
};
} // namespace art
diff --git a/compiler/dex/quick/x86/fp_x86.cc b/compiler/dex/quick/x86/fp_x86.cc
index 22e554e..aec39ab 100644
--- a/compiler/dex/quick/x86/fp_x86.cc
+++ b/compiler/dex/quick/x86/fp_x86.cc
@@ -49,8 +49,13 @@
case Instruction::REM_FLOAT_2ADDR:
case Instruction::REM_FLOAT:
FlushAllRegs(); // Send everything to home location
- CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmodf), rl_src1, rl_src2,
- false);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(8, pFmodf), rl_src1, rl_src2,
+ false);
+ } else {
+ CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmodf), rl_src1, rl_src2,
+ false);
+ }
rl_result = GetReturn(true);
StoreValue(rl_dest, rl_result);
return;
@@ -106,8 +111,13 @@
case Instruction::REM_DOUBLE_2ADDR:
case Instruction::REM_DOUBLE:
FlushAllRegs(); // Send everything to home location
- CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmod), rl_src1, rl_src2,
- false);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(8, pFmod), rl_src1, rl_src2,
+ false);
+ } else {
+ CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmod), rl_src1, rl_src2,
+ false);
+ }
rl_result = GetReturnWide(true);
StoreValueWide(rl_dest, rl_result);
return;
@@ -268,10 +278,18 @@
GenLongToFP(rl_dest, rl_src, false /* is_double */);
return;
case Instruction::FLOAT_TO_LONG:
- GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2l), rl_dest, rl_src);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ GenConversionCall(QUICK_ENTRYPOINT_OFFSET(8, pF2l), rl_dest, rl_src);
+ } else {
+ GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2l), rl_dest, rl_src);
+ }
return;
case Instruction::DOUBLE_TO_LONG:
- GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2l), rl_dest, rl_src);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ GenConversionCall(QUICK_ENTRYPOINT_OFFSET(8, pD2l), rl_dest, rl_src);
+ } else {
+ GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2l), rl_dest, rl_src);
+ }
return;
default:
LOG(INFO) << "Unexpected opcode: " << opcode;
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 368234e..fbb1785 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -909,8 +909,13 @@
}
// Load array length to kArg1.
m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_);
- m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
- new_index, m2l_->TargetReg(kArg1), true);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pThrowArrayBounds),
+ new_index, m2l_->TargetReg(kArg1), true);
+ } else {
+ m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
+ new_index, m2l_->TargetReg(kArg1), true);
+ }
}
private:
@@ -944,8 +949,13 @@
// Load array length to kArg1.
m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_);
m2l_->LoadConstant(m2l_->TargetReg(kArg0), index_);
- m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
- m2l_->TargetReg(kArg0), m2l_->TargetReg(kArg1), true);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pThrowArrayBounds),
+ m2l_->TargetReg(kArg0), m2l_->TargetReg(kArg1), true);
+ } else {
+ m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
+ m2l_->TargetReg(kArg0), m2l_->TargetReg(kArg1), true);
+ }
}
private:
@@ -1390,12 +1400,22 @@
void X86Mir2Lir::OpRegThreadMem(OpKind op, RegStorage r_dest, ThreadOffset<8> thread_offset) {
DCHECK_EQ(kX86_64, cu_->instruction_set);
X86OpCode opcode = kX86Bkpt;
- switch (op) {
- case kOpCmp: opcode = kX86Cmp32RT; break;
- case kOpMov: opcode = kX86Mov32RT; break;
- default:
- LOG(FATAL) << "Bad opcode: " << op;
- break;
+ if (Gen64Bit() && r_dest.Is64BitSolo()) {
+ switch (op) {
+ case kOpCmp: opcode = kX86Cmp64RT; break;
+ case kOpMov: opcode = kX86Mov64RT; break;
+ default:
+ LOG(FATAL) << "Bad opcode(OpRegThreadMem 64): " << op;
+ break;
+ }
+ } else {
+ switch (op) {
+ case kOpCmp: opcode = kX86Cmp32RT; break;
+ case kOpMov: opcode = kX86Mov32RT; break;
+ default:
+ LOG(FATAL) << "Bad opcode: " << op;
+ break;
+ }
}
NewLIR2(opcode, r_dest.GetReg(), thread_offset.Int32Value());
}
@@ -1862,8 +1882,8 @@
// If Method* is already in a register, we can save a copy.
RegLocation rl_method = mir_graph_->GetMethodLoc();
- int32_t offset_of_type = mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() +
- (sizeof(mirror::Class*) * type_idx);
+ int32_t offset_of_type = mirror::Array::DataOffset(sizeof(mirror::HeapReference<mirror::Class*>)).Int32Value() +
+ (sizeof(mirror::HeapReference<mirror::Class*>) * type_idx);
if (rl_method.location == kLocPhysReg) {
if (use_declaring_class) {
@@ -1917,8 +1937,13 @@
if (needs_access_check) {
// Check we have access to type_idx and if not throw IllegalAccessError,
// Caller function returns Class* in kArg0.
- CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeTypeAndVerifyAccess),
- type_idx, true);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(8, pInitializeTypeAndVerifyAccess),
+ type_idx, true);
+ } else {
+ CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeTypeAndVerifyAccess),
+ type_idx, true);
+ }
OpRegCopy(class_reg, TargetReg(kRet0));
LoadValueDirectFixed(rl_src, TargetReg(kArg0));
} else if (use_declaring_class) {
@@ -1931,14 +1956,18 @@
LoadRefDisp(TargetReg(kArg1), mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
class_reg);
int32_t offset_of_type =
- mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
+ mirror::Array::DataOffset(sizeof(mirror::HeapReference<mirror::Class*>)).Int32Value() + (sizeof(mirror::HeapReference<mirror::Class*>)
* type_idx);
LoadRefDisp(class_reg, offset_of_type, class_reg);
if (!can_assume_type_is_in_dex_cache) {
// Need to test presence of type in dex cache at runtime.
LIR* hop_branch = OpCmpImmBranch(kCondNe, class_reg, 0, NULL);
// Type is not resolved. Call out to helper, which will return resolved type in kRet0/kArg0.
- CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeType), type_idx, true);
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(8, pInitializeType), type_idx, true);
+ } else {
+ CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeType), type_idx, true);
+ }
OpRegCopy(TargetReg(kArg2), TargetReg(kRet0)); // Align usage with fast path.
LoadValueDirectFixed(rl_src, TargetReg(kArg0)); /* Reload Ref. */
// Rejoin code paths
@@ -1972,7 +2001,11 @@
branchover = OpCmpBranch(kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL);
}
OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));
- OpThreadMem(kOpBlx, QUICK_ENTRYPOINT_OFFSET(4, pInstanceofNonTrivial));
+ if (Is64BitInstructionSet(cu_->instruction_set)) {
+ OpThreadMem(kOpBlx, QUICK_ENTRYPOINT_OFFSET(8, pInstanceofNonTrivial));
+ } else {
+ OpThreadMem(kOpBlx, QUICK_ENTRYPOINT_OFFSET(4, pInstanceofNonTrivial));
+ }
}
// TODO: only clobber when type isn't final?
ClobberCallerSave();
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index e3312a2..237c68c 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -26,53 +26,117 @@
namespace art {
-static const RegStorage core_regs_arr[] = {
- rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP, rs_rBP, rs_rSI, rs_rDI
+static const RegStorage core_regs_arr_32[] = {
+ rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI,
+};
+static const RegStorage core_regs_arr_64[] = {
+ rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_64, rs_rBP, rs_rSI, rs_rDI,
#ifdef TARGET_REX_SUPPORT
rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15
#endif
};
-static const RegStorage sp_regs_arr[] = {
+static const RegStorage sp_regs_arr_32[] = {
+ rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
+};
+static const RegStorage sp_regs_arr_64[] = {
rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
#ifdef TARGET_REX_SUPPORT
rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15
#endif
};
-static const RegStorage dp_regs_arr[] = {
+static const RegStorage dp_regs_arr_32[] = {
+ rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7,
+};
+static const RegStorage dp_regs_arr_64[] = {
rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7,
#ifdef TARGET_REX_SUPPORT
rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15
#endif
};
-static const RegStorage reserved_regs_arr[] = {rs_rX86_SP};
-static const RegStorage core_temps_arr[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX};
-static const RegStorage sp_temps_arr[] = {
+static const RegStorage reserved_regs_arr_32[] = {rs_rX86_SP_32};
+static const RegStorage reserved_regs_arr_64[] = {rs_rX86_SP_64};
+static const RegStorage core_temps_arr_32[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX};
+static const RegStorage core_temps_arr_64[] = {
+ rs_rAX, rs_rCX, rs_rDX, rs_rSI, rs_rDI,
+#ifdef TARGET_REX_SUPPORT
+ rs_r8, rs_r9, rs_r10, rs_r11
+#endif
+};
+static const RegStorage sp_temps_arr_32[] = {
+ rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
+};
+static const RegStorage sp_temps_arr_64[] = {
rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
#ifdef TARGET_REX_SUPPORT
rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15
#endif
};
-static const RegStorage dp_temps_arr[] = {
+static const RegStorage dp_temps_arr_32[] = {
+ rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7,
+};
+static const RegStorage dp_temps_arr_64[] = {
rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7,
#ifdef TARGET_REX_SUPPORT
rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15
#endif
};
-static const std::vector<RegStorage> core_regs(core_regs_arr,
- core_regs_arr + sizeof(core_regs_arr) / sizeof(core_regs_arr[0]));
-static const std::vector<RegStorage> sp_regs(sp_regs_arr,
- sp_regs_arr + sizeof(sp_regs_arr) / sizeof(sp_regs_arr[0]));
-static const std::vector<RegStorage> dp_regs(dp_regs_arr,
- dp_regs_arr + sizeof(dp_regs_arr) / sizeof(dp_regs_arr[0]));
-static const std::vector<RegStorage> reserved_regs(reserved_regs_arr,
- reserved_regs_arr + sizeof(reserved_regs_arr) / sizeof(reserved_regs_arr[0]));
-static const std::vector<RegStorage> core_temps(core_temps_arr,
- core_temps_arr + sizeof(core_temps_arr) / sizeof(core_temps_arr[0]));
-static const std::vector<RegStorage> sp_temps(sp_temps_arr,
- sp_temps_arr + sizeof(sp_temps_arr) / sizeof(sp_temps_arr[0]));
-static const std::vector<RegStorage> dp_temps(dp_temps_arr,
- dp_temps_arr + sizeof(dp_temps_arr) / sizeof(dp_temps_arr[0]));
+static const std::vector<RegStorage> core_regs_32(core_regs_arr_32,
+ core_regs_arr_32 + sizeof(core_regs_arr_32) / sizeof(core_regs_arr_32[0]));
+static const std::vector<RegStorage> core_regs_64(core_regs_arr_64,
+ core_regs_arr_64 + sizeof(core_regs_arr_64) / sizeof(core_regs_arr_64[0]));
+static const std::vector<RegStorage> sp_regs_32(sp_regs_arr_32,
+ sp_regs_arr_32 + sizeof(sp_regs_arr_32) / sizeof(sp_regs_arr_32[0]));
+static const std::vector<RegStorage> sp_regs_64(sp_regs_arr_64,
+ sp_regs_arr_64 + sizeof(sp_regs_arr_64) / sizeof(sp_regs_arr_64[0]));
+static const std::vector<RegStorage> dp_regs_32(dp_regs_arr_32,
+ dp_regs_arr_32 + sizeof(dp_regs_arr_32) / sizeof(dp_regs_arr_32[0]));
+static const std::vector<RegStorage> dp_regs_64(dp_regs_arr_64,
+ dp_regs_arr_64 + sizeof(dp_regs_arr_64) / sizeof(dp_regs_arr_64[0]));
+static const std::vector<RegStorage> reserved_regs_32(reserved_regs_arr_32,
+ reserved_regs_arr_32 + sizeof(reserved_regs_arr_32) / sizeof(reserved_regs_arr_32[0]));
+static const std::vector<RegStorage> reserved_regs_64(reserved_regs_arr_64,
+ reserved_regs_arr_64 + sizeof(reserved_regs_arr_64) / sizeof(reserved_regs_arr_64[0]));
+static const std::vector<RegStorage> core_temps_32(core_temps_arr_32,
+ core_temps_arr_32 + sizeof(core_temps_arr_32) / sizeof(core_temps_arr_32[0]));
+static const std::vector<RegStorage> core_temps_64(core_temps_arr_64,
+ core_temps_arr_64 + sizeof(core_temps_arr_64) / sizeof(core_temps_arr_64[0]));
+static const std::vector<RegStorage> sp_temps_32(sp_temps_arr_32,
+ sp_temps_arr_32 + sizeof(sp_temps_arr_32) / sizeof(sp_temps_arr_32[0]));
+static const std::vector<RegStorage> sp_temps_64(sp_temps_arr_64,
+ sp_temps_arr_64 + sizeof(sp_temps_arr_64) / sizeof(sp_temps_arr_64[0]));
+static const std::vector<RegStorage> dp_temps_32(dp_temps_arr_32,
+ dp_temps_arr_32 + sizeof(dp_temps_arr_32) / sizeof(dp_temps_arr_32[0]));
+static const std::vector<RegStorage> dp_temps_64(dp_temps_arr_64,
+ dp_temps_arr_64 + sizeof(dp_temps_arr_64) / sizeof(dp_temps_arr_64[0]));
+
+RegStorage rs_rX86_SP;
+
+X86NativeRegisterPool rX86_ARG0;
+X86NativeRegisterPool rX86_ARG1;
+X86NativeRegisterPool rX86_ARG2;
+X86NativeRegisterPool rX86_ARG3;
+X86NativeRegisterPool rX86_FARG0;
+X86NativeRegisterPool rX86_FARG1;
+X86NativeRegisterPool rX86_FARG2;
+X86NativeRegisterPool rX86_FARG3;
+X86NativeRegisterPool rX86_RET0;
+X86NativeRegisterPool rX86_RET1;
+X86NativeRegisterPool rX86_INVOKE_TGT;
+X86NativeRegisterPool rX86_COUNT;
+
+RegStorage rs_rX86_ARG0;
+RegStorage rs_rX86_ARG1;
+RegStorage rs_rX86_ARG2;
+RegStorage rs_rX86_ARG3;
+RegStorage rs_rX86_FARG0;
+RegStorage rs_rX86_FARG1;
+RegStorage rs_rX86_FARG2;
+RegStorage rs_rX86_FARG3;
+RegStorage rs_rX86_RET0;
+RegStorage rs_rX86_RET1;
+RegStorage rs_rX86_INVOKE_TGT;
+RegStorage rs_rX86_COUNT;
RegLocation X86Mir2Lir::LocCReturn() {
return x86_loc_c_return;
@@ -478,8 +542,13 @@
}
void X86Mir2Lir::CompilerInitializeRegAlloc() {
- reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, sp_regs, dp_regs, reserved_regs,
- core_temps, sp_temps, dp_temps);
+ if (Gen64Bit()) {
+ reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_64, sp_regs_64, dp_regs_64, reserved_regs_64,
+ core_temps_64, sp_temps_64, dp_temps_64);
+ } else {
+ reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_32, sp_regs_32, dp_regs_32, reserved_regs_32,
+ core_temps_32, sp_temps_32, dp_temps_32);
+ }
// Target-specific adjustments.
@@ -523,11 +592,11 @@
}
// Spill mask not including fake return address register
uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum());
- int offset = frame_size_ - (4 * num_core_spills_);
+ int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_);
for (int reg = 0; mask; mask >>= 1, reg++) {
if (mask & 0x1) {
StoreWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg));
- offset += 4;
+ offset += GetInstructionSetPointerSize(cu_->instruction_set);
}
}
}
@@ -538,11 +607,11 @@
}
// Spill mask not including fake return address register
uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum());
- int offset = frame_size_ - (4 * num_core_spills_);
+ int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_);
for (int reg = 0; mask; mask >>= 1, reg++) {
if (mask & 0x1) {
LoadWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg));
- offset += 4;
+ offset += GetInstructionSetPointerSize(cu_->instruction_set);
}
}
}
@@ -566,27 +635,74 @@
return RegClassBySize(size);
}
-X86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
+X86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena, bool gen64bit)
: Mir2Lir(cu, mir_graph, arena),
base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false),
method_address_insns_(arena, 100, kGrowableArrayMisc),
class_type_address_insns_(arena, 100, kGrowableArrayMisc),
call_method_insns_(arena, 100, kGrowableArrayMisc),
- stack_decrement_(nullptr), stack_increment_(nullptr) {
+ stack_decrement_(nullptr), stack_increment_(nullptr), gen64bit_(gen64bit),
+ const_vectors_(nullptr) {
+ store_method_addr_used_ = false;
if (kIsDebugBuild) {
for (int i = 0; i < kX86Last; i++) {
if (X86Mir2Lir::EncodingMap[i].opcode != i) {
LOG(FATAL) << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name
- << " is wrong: expecting " << i << ", seeing "
- << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode);
+ << " is wrong: expecting " << i << ", seeing "
+ << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode);
}
}
}
+ if (Gen64Bit()) {
+ rs_rX86_SP = rs_rX86_SP_64;
+
+ rs_rX86_ARG0 = rs_rDI;
+ rs_rX86_ARG1 = rs_rSI;
+ rs_rX86_ARG2 = rs_rDX;
+ rs_rX86_ARG3 = rs_rCX;
+ rX86_ARG0 = rDI;
+ rX86_ARG1 = rSI;
+ rX86_ARG2 = rDX;
+ rX86_ARG3 = rCX;
+ // TODO: ARG4(r8), ARG5(r9), floating point args.
+ } else {
+ rs_rX86_SP = rs_rX86_SP_32;
+
+ rs_rX86_ARG0 = rs_rAX;
+ rs_rX86_ARG1 = rs_rCX;
+ rs_rX86_ARG2 = rs_rDX;
+ rs_rX86_ARG3 = rs_rBX;
+ rX86_ARG0 = rAX;
+ rX86_ARG1 = rCX;
+ rX86_ARG2 = rDX;
+ rX86_ARG3 = rBX;
+ }
+ rs_rX86_FARG0 = rs_rAX;
+ rs_rX86_FARG1 = rs_rCX;
+ rs_rX86_FARG2 = rs_rDX;
+ rs_rX86_FARG3 = rs_rBX;
+ rs_rX86_RET0 = rs_rAX;
+ rs_rX86_RET1 = rs_rDX;
+ rs_rX86_INVOKE_TGT = rs_rAX;
+ rs_rX86_COUNT = rs_rCX;
+ rX86_FARG0 = rAX;
+ rX86_FARG1 = rCX;
+ rX86_FARG2 = rDX;
+ rX86_FARG3 = rBX;
+ rX86_RET0 = rAX;
+ rX86_RET1 = rDX;
+ rX86_INVOKE_TGT = rAX;
+ rX86_COUNT = rCX;
}
Mir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
ArenaAllocator* const arena) {
- return new X86Mir2Lir(cu, mir_graph, arena);
+ return new X86Mir2Lir(cu, mir_graph, arena, false);
+}
+
+Mir2Lir* X86_64CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
+ ArenaAllocator* const arena) {
+ return new X86Mir2Lir(cu, mir_graph, arena, true);
}
// Not used in x86
@@ -724,12 +840,46 @@
return call;
}
+/*
+ * @brief Enter a 32 bit quantity into a buffer
+ * @param buf buffer.
+ * @param data Data value.
+ */
+
+static void PushWord(std::vector<uint8_t>&buf, int32_t data) {
+ buf.push_back(data & 0xff);
+ buf.push_back((data >> 8) & 0xff);
+ buf.push_back((data >> 16) & 0xff);
+ buf.push_back((data >> 24) & 0xff);
+}
+
void X86Mir2Lir::InstallLiteralPools() {
// These are handled differently for x86.
DCHECK(code_literal_list_ == nullptr);
DCHECK(method_literal_list_ == nullptr);
DCHECK(class_literal_list_ == nullptr);
+ // Align to 16 byte boundary. We have implicit knowledge that the start of the method is
+ // on a 4 byte boundary. How can I check this if it changes (other than aligned loads
+ // will fail at runtime)?
+ if (const_vectors_ != nullptr) {
+ int align_size = (16-4) - (code_buffer_.size() & 0xF);
+ if (align_size < 0) {
+ align_size += 16;
+ }
+
+ while (align_size > 0) {
+ code_buffer_.push_back(0);
+ align_size--;
+ }
+ for (LIR *p = const_vectors_; p != nullptr; p = p->next) {
+ PushWord(code_buffer_, p->operands[0]);
+ PushWord(code_buffer_, p->operands[1]);
+ PushWord(code_buffer_, p->operands[2]);
+ PushWord(code_buffer_, p->operands[3]);
+ }
+ }
+
// Handle the fixups for methods.
for (uint32_t i = 0; i < method_address_insns_.Size(); i++) {
LIR* p = method_address_insns_.Get(i);
@@ -960,18 +1110,6 @@
}
/*
- * @brief Enter a 32 bit quantity into the FDE buffer
- * @param buf FDE buffer.
- * @param data Data value.
- */
-static void PushWord(std::vector<uint8_t>&buf, int data) {
- buf.push_back(data & 0xff);
- buf.push_back((data >> 8) & 0xff);
- buf.push_back((data >> 16) & 0xff);
- buf.push_back((data >> 24) & 0xff);
-}
-
-/*
* @brief Enter an 'advance LOC' into the FDE buffer
* @param buf FDE buffer.
* @param increment Amount by which to increase the current location.
@@ -1121,4 +1259,73 @@
return cfi_info;
}
+void X86Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
+ switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
+ case kMirOpConstVector:
+ GenConst128(bb, mir);
+ break;
+ default:
+ break;
+ }
+}
+
+void X86Mir2Lir::GenConst128(BasicBlock* bb, MIR* mir) {
+ int type_size = mir->dalvikInsn.vA;
+ // We support 128 bit vectors.
+ DCHECK_EQ(type_size & 0xFFFF, 128);
+ int reg = mir->dalvikInsn.vB;
+ DCHECK_LT(reg, 8);
+ uint32_t *args = mir->dalvikInsn.arg;
+ // Check for all 0 case.
+ if (args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0) {
+ NewLIR2(kX86XorpsRR, reg, reg);
+ return;
+ }
+ // Okay, load it from the constant vector area.
+ LIR *data_target = ScanVectorLiteral(mir);
+ if (data_target == nullptr) {
+ data_target = AddVectorLiteral(mir);
+ }
+
+ // Address the start of the method.
+ RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
+ rl_method = LoadValue(rl_method, kCoreReg);
+
+ // Load the proper value from the literal area.
+ // We don't know the proper offset for the value, so pick one that will force
+ // 4 byte offset. We will fix this up in the assembler later to have the right
+ // value.
+ LIR *load = NewLIR3(kX86Mova128RM, reg, rl_method.reg.GetReg(), 256 /* bogus */);
+ load->flags.fixup = kFixupLoad;
+ load->target = data_target;
+ SetMemRefType(load, true, kLiteral);
+}
+
+LIR *X86Mir2Lir::ScanVectorLiteral(MIR *mir) {
+ int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg);
+ for (LIR *p = const_vectors_; p != nullptr; p = p->next) {
+ if (args[0] == p->operands[0] && args[1] == p->operands[1] &&
+ args[2] == p->operands[2] && args[3] == p->operands[3]) {
+ return p;
+ }
+ }
+ return nullptr;
+}
+
+LIR *X86Mir2Lir::AddVectorLiteral(MIR *mir) {
+ LIR* new_value = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocData));
+ int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg);
+ new_value->operands[0] = args[0];
+ new_value->operands[1] = args[1];
+ new_value->operands[2] = args[2];
+ new_value->operands[3] = args[3];
+ new_value->next = const_vectors_;
+ if (const_vectors_ == nullptr) {
+ estimated_native_code_size_ += 12; // Amount needed to align to 16 byte boundary.
+ }
+ estimated_native_code_size_ += 16; // Space for one vector.
+ const_vectors_ = new_value;
+ return new_value;
+}
+
} // namespace art
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index 1da4f17..e9592a6 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -130,32 +130,42 @@
X86OpCode opcode = kX86Bkpt;
bool byte_imm = IS_SIMM8(value);
DCHECK(!r_dest_src1.IsFloat());
- switch (op) {
- case kOpLsl: opcode = kX86Sal32RI; break;
- case kOpLsr: opcode = kX86Shr32RI; break;
- case kOpAsr: opcode = kX86Sar32RI; break;
- case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
- case kOpOr: opcode = byte_imm ? kX86Or32RI8 : kX86Or32RI; break;
- case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
- // case kOpSbb: opcode = kX86Sbb32RI; break;
- case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
- case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
- case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
- case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
- case kOpMov:
- /*
- * Moving the constant zero into register can be specialized as an xor of the register.
- * However, that sets eflags while the move does not. For that reason here, always do
- * the move and if caller is flexible, they should be calling LoadConstantNoClobber instead.
- */
- opcode = kX86Mov32RI;
- break;
- case kOpMul:
- opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
- return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), value);
- default:
- LOG(FATAL) << "Bad case in OpRegImm " << op;
+ if (r_dest_src1.Is64Bit()) {
+ switch (op) {
+ case kOpAdd: opcode = byte_imm ? kX86Add64RI8 : kX86Add64RI; break;
+ case kOpSub: opcode = byte_imm ? kX86Sub64RI8 : kX86Sub64RI; break;
+ default:
+ LOG(FATAL) << "Bad case in OpRegImm (64-bit) " << op;
+ }
+ } else {
+ switch (op) {
+ case kOpLsl: opcode = kX86Sal32RI; break;
+ case kOpLsr: opcode = kX86Shr32RI; break;
+ case kOpAsr: opcode = kX86Sar32RI; break;
+ case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
+ case kOpOr: opcode = byte_imm ? kX86Or32RI8 : kX86Or32RI; break;
+ case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
+ // case kOpSbb: opcode = kX86Sbb32RI; break;
+ case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
+ case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
+ case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
+ case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
+ case kOpMov:
+ /*
+ * Moving the constant zero into register can be specialized as an xor of the register.
+ * However, that sets eflags while the move does not. For that reason here, always do
+ * the move and if caller is flexible, they should be calling LoadConstantNoClobber instead.
+ */
+ opcode = kX86Mov32RI;
+ break;
+ case kOpMul:
+ opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
+ return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), value);
+ default:
+ LOG(FATAL) << "Bad case in OpRegImm " << op;
+ }
}
+ CHECK(!r_dest_src1.Is64Bit() || X86Mir2Lir::EncodingMap[opcode].kind == kReg64Imm) << "OpRegImm(" << op << ")";
return NewLIR2(opcode, r_dest_src1.GetReg(), value);
}
@@ -464,7 +474,7 @@
r_src.GetReg() /* index */, value /* scale */, 0 /* disp */);
} else if (op == kOpAdd) { // lea add special case
return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r_src.GetReg() /* base */,
- r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
+ rs_rX86_SP.GetReg()/*r4sib_no_index*/ /* index */, 0 /* scale */, value /* disp */);
}
OpRegCopy(r_dest, r_src);
}
@@ -578,6 +588,13 @@
// TODO: double store is to unaligned address
DCHECK_EQ((displacement & 0x3), 0);
break;
+ case kWord:
+ if (Gen64Bit()) {
+ opcode = is_array ? kX86Mov64RA : kX86Mov64RM;
+ CHECK_EQ(is_array, false);
+ CHECK_EQ(r_dest.IsFloat(), false);
+ break;
+ } // else fall-through to k32 case
case k32:
case kSingle:
case kReference: // TODO: update for reference decompression on 64-bit targets.
@@ -689,10 +706,6 @@
LIR* X86Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
OpSize size) {
- // TODO: base this on target.
- if (size == kWord) {
- size = k32;
- }
return LoadBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_dest,
size);
}
@@ -711,11 +724,23 @@
if (r_src.IsFloat()) {
opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
} else {
- opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
+ if (Gen64Bit()) {
+ opcode = is_array ? kX86Mov64AR : kX86Mov64MR;
+ } else {
+ // TODO(64): pair = true;
+ opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
+ }
}
// TODO: double store is to unaligned address
DCHECK_EQ((displacement & 0x3), 0);
break;
+ case kWord:
+ if (Gen64Bit()) {
+ opcode = is_array ? kX86Mov64AR : kX86Mov64MR;
+ CHECK_EQ(is_array, false);
+ CHECK_EQ(r_src.IsFloat(), false);
+ break;
+ } // else fall-through to k32 case
case k32:
case kSingle:
case kReference:
@@ -785,10 +810,6 @@
LIR* X86Mir2Lir::StoreBaseDisp(RegStorage r_base, int displacement,
RegStorage r_src, OpSize size) {
- // TODO: base this on target.
- if (size == kWord) {
- size = k32;
- }
return StoreBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_src, size);
}
@@ -845,6 +866,9 @@
case kMirOpFusedCmpgDouble:
AnalyzeFPInstruction(opcode, bb, mir);
break;
+ case kMirOpConstVector:
+ store_method_addr_ = true;
+ break;
default:
// Ignore the rest.
break;
diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h
index 77d716f..adfed0c 100644
--- a/compiler/dex/quick/x86/x86_lir.h
+++ b/compiler/dex/quick/x86/x86_lir.h
@@ -124,9 +124,10 @@
rDX = r2,
r3 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 3,
rBX = r3,
- r4sp = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 4,
- rX86_SP = r4sp,
- r4sib_no_index = r4sp,
+ r4sp_32 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 4,
+ rX86_SP_32 = r4sp_32,
+ r4sp_64 = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 4,
+ rX86_SP_64 = r4sp_64,
r5 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 5,
rBP = r5,
r5sib_no_base = r5,
@@ -191,8 +192,9 @@
constexpr RegStorage rs_rDX = rs_r2;
constexpr RegStorage rs_r3(RegStorage::kValid | r3);
constexpr RegStorage rs_rBX = rs_r3;
-constexpr RegStorage rs_r4sp(RegStorage::kValid | r4sp);
-constexpr RegStorage rs_rX86_SP = rs_r4sp;
+constexpr RegStorage rs_rX86_SP_64(RegStorage::kValid | r4sp_64);
+constexpr RegStorage rs_rX86_SP_32(RegStorage::kValid | r4sp_32);
+extern RegStorage rs_rX86_SP;
constexpr RegStorage rs_r5(RegStorage::kValid | r5);
constexpr RegStorage rs_rBP = rs_r5;
constexpr RegStorage rs_r6(RegStorage::kValid | r6);
@@ -228,35 +230,31 @@
constexpr RegStorage rs_qr6(RegStorage::kValid | qr6);
constexpr RegStorage rs_qr7(RegStorage::kValid | qr7);
-// TODO: elminate these #defines?
-#define rX86_ARG0 rAX
-#define rs_rX86_ARG0 rs_rAX
-#define rX86_ARG1 rCX
-#define rs_rX86_ARG1 rs_rCX
-#define rX86_ARG2 rDX
-#define rs_rX86_ARG2 rs_rDX
-#define rX86_ARG3 rBX
-#define rs_rX86_ARG3 rs_rBX
-#define rX86_FARG0 rAX
-#define rs_rX86_FARG0 rs_rAX
-#define rX86_FARG1 rCX
-#define rs_rX86_FARG1 rs_rCX
-#define rX86_FARG2 rDX
-#define rs_rX86_FARG2 rs_rDX
-#define rX86_FARG3 rBX
-#define rs_rX86_FARG3 rs_rBX
-#define rX86_RET0 rAX
-#define rs_rX86_RET0 rs_rAX
-#define rX86_RET1 rDX
-#define rs_rX86_RET1 rs_rDX
-#define rX86_INVOKE_TGT rAX
-#define rs_rX86_INVOKE_TGT rs_rAX
-#define rX86_LR RegStorage::kInvalidRegVal
-#define rX86_SUSPEND RegStorage::kInvalidRegVal
-#define rX86_SELF RegStorage::kInvalidRegVal
-#define rX86_COUNT rCX
-#define rs_rX86_COUNT rs_rCX
-#define rX86_PC RegStorage::kInvalidRegVal
+extern X86NativeRegisterPool rX86_ARG0;
+extern X86NativeRegisterPool rX86_ARG1;
+extern X86NativeRegisterPool rX86_ARG2;
+extern X86NativeRegisterPool rX86_ARG3;
+extern X86NativeRegisterPool rX86_FARG0;
+extern X86NativeRegisterPool rX86_FARG1;
+extern X86NativeRegisterPool rX86_FARG2;
+extern X86NativeRegisterPool rX86_FARG3;
+extern X86NativeRegisterPool rX86_RET0;
+extern X86NativeRegisterPool rX86_RET1;
+extern X86NativeRegisterPool rX86_INVOKE_TGT;
+extern X86NativeRegisterPool rX86_COUNT;
+
+extern RegStorage rs_rX86_ARG0;
+extern RegStorage rs_rX86_ARG1;
+extern RegStorage rs_rX86_ARG2;
+extern RegStorage rs_rX86_ARG3;
+extern RegStorage rs_rX86_FARG0;
+extern RegStorage rs_rX86_FARG1;
+extern RegStorage rs_rX86_FARG2;
+extern RegStorage rs_rX86_FARG3;
+extern RegStorage rs_rX86_RET0;
+extern RegStorage rs_rX86_RET1;
+extern RegStorage rs_rX86_INVOKE_TGT;
+extern RegStorage rs_rX86_COUNT;
// RegisterLocation templates return values (r_V0, or r_V0/r_V1).
const RegLocation x86_loc_c_return
@@ -313,10 +311,10 @@
opcode ## 16RR, opcode ## 16RM, opcode ## 16RA, opcode ## 16RT, \
opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, opcode ## 16TI, \
opcode ## 16RI8, opcode ## 16MI8, opcode ## 16AI8, opcode ## 16TI8, \
- opcode ## 32MR, opcode ## 32AR, opcode ## 32TR, \
- opcode ## 32RR, opcode ## 32RM, opcode ## 32RA, opcode ## 32RT, \
- opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, opcode ## 32TI, \
- opcode ## 32RI8, opcode ## 32MI8, opcode ## 32AI8, opcode ## 32TI8
+ opcode ## 32MR, opcode ## 64MR, opcode ## 32AR, opcode ## 64AR, opcode ## 32TR, \
+ opcode ## 32RR, opcode ## 32RM, opcode ## 64RM, opcode ## 32RA, opcode ## 64RA, opcode ## 32RT, opcode ## 64RT, \
+ opcode ## 32RI, opcode ## 64RI, opcode ## 32MI, opcode ## 32AI, opcode ## 32TI, \
+ opcode ## 32RI8, opcode ## 64RI8, opcode ## 32MI8, opcode ## 32AI8, opcode ## 32TI8
BinaryOpCode(kX86Add),
BinaryOpCode(kX86Or),
BinaryOpCode(kX86Adc),
@@ -335,9 +333,9 @@
kX86Mov16MR, kX86Mov16AR, kX86Mov16TR,
kX86Mov16RR, kX86Mov16RM, kX86Mov16RA, kX86Mov16RT,
kX86Mov16RI, kX86Mov16MI, kX86Mov16AI, kX86Mov16TI,
- kX86Mov32MR, kX86Mov32AR, kX86Mov32TR,
- kX86Mov32RR, kX86Mov32RM, kX86Mov32RA, kX86Mov32RT,
- kX86Mov32RI, kX86Mov32MI, kX86Mov32AI, kX86Mov32TI,
+ kX86Mov32MR, kX86Mov64MR, kX86Mov32AR, kX86Mov64AR, kX86Mov32TR,
+ kX86Mov32RR, kX86Mov32RM, kX86Mov64RM, kX86Mov32RA, kX86Mov64RA, kX86Mov32RT, kX86Mov64RT,
+ kX86Mov32RI, kX86Mov32MI, kX86Mov32AI, kX86Mov32TI, kX86Mov64TI,
kX86Lea32RM,
kX86Lea32RA,
// RRC - Register Register ConditionCode - cond_opcode reg1, reg2
@@ -427,6 +425,8 @@
kX86Fild64M, // push 64-bit integer on x87 stack
kX86Fstp32M, // pop top x87 fp stack and do 32-bit store
kX86Fstp64M, // pop top x87 fp stack and do 64-bit store
+ Binary0fOpCode(kX86Mova128), // move 128 bits aligned
+ kX86Mova128MR, kX86Mova128AR, // store 128 bit aligned from xmm1 to m128
Binary0fOpCode(kX86Movups), // load unaligned packed single FP values from xmm2/m128 to xmm1
kX86MovupsMR, kX86MovupsAR, // store unaligned packed single FP values from xmm1 to m128
Binary0fOpCode(kX86Movaps), // load aligned packed single FP values from xmm2/m128 to xmm1
@@ -479,11 +479,11 @@
kNullary, // Opcode that takes no arguments.
kPrefix2Nullary, // Opcode that takes no arguments, but 2 prefixes.
kRegOpcode, // Shorter form of R instruction kind (opcode+rd)
- kReg, kMem, kArray, // R, M and A instruction kinds.
- kMemReg, kArrayReg, kThreadReg, // MR, AR and TR instruction kinds.
- kRegReg, kRegMem, kRegArray, kRegThread, // RR, RM, RA and RT instruction kinds.
+ kReg, kReg64, kMem, kArray, // R, M and A instruction kinds.
+ kMemReg, kMemReg64, kArrayReg, kArrayReg64, kThreadReg, // MR, AR and TR instruction kinds.
+ kRegReg, kRegMem, kRegArray, kRegThread, kReg64Thread, // RR, RM, RA and RT instruction kinds.
kRegRegStore, // RR following the store modrm reg-reg encoding rather than the load.
- kRegImm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
+ kRegImm, kReg64Imm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
kRegRegImm, kRegMemImm, kRegArrayImm, // RRI, RMI and RAI instruction kinds.
kMovRegImm, // Shorter form move RI.
kRegRegImmRev, // RRI with first reg in r/m
@@ -532,6 +532,11 @@
// Segment override instruction prefix used for quick TLS access to Thread::Current().
#define THREAD_PREFIX 0x64
+#define THREAD_PREFIX_GS 0x65
+
+// 64 Bit Operand Size
+#define REX_W 0x48
+// Extension of the ModR/M reg field
#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 127))
#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32767))
diff --git a/compiler/dex/reg_storage.h b/compiler/dex/reg_storage.h
index 979f516..3387c50 100644
--- a/compiler/dex/reg_storage.h
+++ b/compiler/dex/reg_storage.h
@@ -137,6 +137,10 @@
return ((reg_ & k64BitMask) == k64Bits);
}
+ bool Is64BitSolo() const {
+ return ((reg_ & kShapeMask) == k64BitSolo);
+ }
+
bool IsPair() const {
return ((reg_ & kShapeMask) == k64BitPair);
}
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 55ba643..b48be58 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1706,7 +1706,7 @@
// We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
// than use a special Object for the purpose we use the Class of java.lang.Class.
Handle<mirror::Class> h_klass(hs.NewHandle(klass->GetClass()));
- ObjectLock<mirror::Class> lock(soa.Self(), &h_klass);
+ ObjectLock<mirror::Class> lock(soa.Self(), h_klass);
// Attempt to initialize allowing initialization of parent classes but still not static
// fields.
manager->GetClassLinker()->EnsureInitialized(klass, false, true);
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 052d12e..4a23263 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -226,7 +226,7 @@
monitor_pool.cc \
arch/arm64/fault_handler_arm64.cc
-LIBART_TARGET_SRC_FILES_x86 := \
+LIBART_SRC_FILES_x86 := \
arch/x86/context_x86.cc \
arch/x86/entrypoints_init_x86.cc \
arch/x86/jni_entrypoints_x86.S \
@@ -235,7 +235,10 @@
arch/x86/thread_x86.cc \
arch/x86/fault_handler_x86.cc
-LIBART_TARGET_SRC_FILES_x86_64 := \
+LIBART_TARGET_SRC_FILES_x86 := \
+ $(LIBART_SRC_FILES_x86)
+
+LIBART_SRC_FILES_x86_64 := \
arch/x86_64/context_x86_64.cc \
arch/x86_64/entrypoints_init_x86_64.cc \
arch/x86_64/jni_entrypoints_x86_64.S \
@@ -245,6 +248,8 @@
monitor_pool.cc \
arch/x86_64/fault_handler_x86_64.cc
+LIBART_TARGET_SRC_FILES_x86_64 := \
+ $(LIBART_SRC_FILES_x86_64) \
LIBART_TARGET_SRC_FILES_mips := \
arch/mips/context_mips.cc \
@@ -270,31 +275,11 @@
runtime_linux.cc \
thread_linux.cc
-ifeq ($(HOST_ARCH),x86_64)
-LIBART_HOST_SRC_FILES += \
- arch/x86_64/context_x86_64.cc \
- arch/x86_64/entrypoints_init_x86_64.cc \
- arch/x86_64/jni_entrypoints_x86_64.S \
- arch/x86_64/portable_entrypoints_x86_64.S \
- arch/x86_64/quick_entrypoints_x86_64.S \
- arch/x86_64/thread_x86_64.cc \
- arch/x86_64/fault_handler_x86_64.cc \
- monitor_pool.cc
-else
- ifeq ($(HOST_ARCH),x86)
-LIBART_HOST_SRC_FILES += \
- arch/x86/context_x86.cc \
- arch/x86/entrypoints_init_x86.cc \
- arch/x86/jni_entrypoints_x86.S \
- arch/x86/portable_entrypoints_x86.S \
- arch/x86/quick_entrypoints_x86.S \
- arch/x86/fault_handler_x86.cc \
- arch/x86/thread_x86.cc
- else # HOST_ARCH != x86 && HOST_ARCH != x86_64
-$(error unsupported HOST_ARCH=$(HOST_ARCH))
- endif
-endif
+LIBART_HOST_SRC_FILES_32 := \
+ $(LIBART_SRC_FILES_x86)
+LIBART_HOST_SRC_FILES_64 := \
+ $(LIBART_SRC_FILES_x86_64)
LIBART_ENUM_OPERATOR_OUT_HEADER_FILES := \
arch/x86_64/registers_x86_64.h \
@@ -363,6 +348,8 @@
LOCAL_SRC_FILES_$(arch) := $$(LIBART_TARGET_SRC_FILES_$(arch)))
else # host
LOCAL_SRC_FILES := $(LIBART_HOST_SRC_FILES)
+ LOCAL_SRC_FILES_32 := $(LIBART_HOST_SRC_FILES_32)
+ LOCAL_SRC_FILES_64 := $(LIBART_HOST_SRC_FILES_64)
LOCAL_IS_HOST_MODULE := true
endif
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c7f3a20..6b98da9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1325,8 +1325,8 @@
// Wait for the class if it has not already been linked.
if (!klass->IsResolved() && !klass->IsErroneous()) {
StackHandleScope<1> hs(self);
- Handle<mirror::Class> h_class(hs.NewHandle(klass));
- ObjectLock<mirror::Class> lock(self, &h_class);
+ HandleWrapper<mirror::Class> h_class(hs.NewHandleWrapper(&klass));
+ ObjectLock<mirror::Class> lock(self, h_class);
// Check for circular dependencies between classes.
if (!h_class->IsResolved() && h_class->GetClinitThreadId() == self->GetTid()) {
ThrowClassCircularityError(h_class.Get());
@@ -1337,7 +1337,6 @@
while (!h_class->IsResolved() && !h_class->IsErroneous()) {
lock.WaitIgnoringInterrupts();
}
- klass = h_class.Get();
}
if (klass->IsErroneous()) {
ThrowEarlierClassFailure(klass);
@@ -1471,7 +1470,7 @@
klass->SetStatus(mirror::Class::kStatusError, self);
return NULL;
}
- ObjectLock<mirror::Class> lock(self, &klass);
+ ObjectLock<mirror::Class> lock(self, klass);
klass->SetClinitThreadId(self->GetTid());
// Add the newly loaded class to the loaded classes table.
mirror::Class* existing = InsertClass(descriptor, klass.Get(), Hash(descriptor));
@@ -2182,7 +2181,7 @@
Thread* self = Thread::Current();
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_class(hs.NewHandle(primitive_class));
- ObjectLock<mirror::Class> lock(self, &h_class);
+ ObjectLock<mirror::Class> lock(self, h_class);
primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
primitive_class->SetPrimitiveType(type);
primitive_class->SetStatus(mirror::Class::kStatusInitialized, self);
@@ -2279,7 +2278,7 @@
}
new_class->SetComponentType(component_type.Get());
}
- ObjectLock<mirror::Class> lock(self, &new_class); // Must hold lock on object when initializing.
+ ObjectLock<mirror::Class> lock(self, new_class); // Must hold lock on object when initializing.
DCHECK(new_class->GetComponentType() != NULL);
mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject);
new_class->SetSuperClass(java_lang_Object);
@@ -2554,7 +2553,7 @@
void ClassLinker::VerifyClass(const Handle<mirror::Class>& klass) {
// TODO: assert that the monitor on the Class is held
Thread* self = Thread::Current();
- ObjectLock<mirror::Class> lock(self, &klass);
+ ObjectLock<mirror::Class> lock(self, klass);
// Don't attempt to re-verify if already sufficiently verified.
if (klass->IsVerified() ||
@@ -2589,7 +2588,7 @@
Handle<mirror::Class> super(hs.NewHandle(klass->GetSuperClass()));
if (super.Get() != NULL) {
// Acquire lock to prevent races on verifying the super class.
- ObjectLock<mirror::Class> lock(self, &super);
+ ObjectLock<mirror::Class> lock(self, super);
if (!super->IsVerified() && !super->IsErroneous()) {
VerifyClass(super);
@@ -2903,7 +2902,7 @@
self->AssertNoPendingException();
{
- ObjectLock<mirror::Class> lock(self, &klass); // Must hold lock on object when resolved.
+ ObjectLock<mirror::Class> lock(self, klass); // Must hold lock on object when resolved.
// Link the fields and virtual methods, creating vtable and iftables
Handle<mirror::ObjectArray<mirror::Class> > h_interfaces(
hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces)));
@@ -3121,7 +3120,7 @@
Thread* self = Thread::Current();
uint64_t t0;
{
- ObjectLock<mirror::Class> lock(self, &klass);
+ ObjectLock<mirror::Class> lock(self, klass);
// Re-check under the lock in case another thread initialized ahead of us.
if (klass->IsInitialized()) {
@@ -3198,7 +3197,7 @@
<< " that has unexpected status " << handle_scope_super->GetStatus()
<< "\nPending exception:\n"
<< (self->GetException(NULL) != NULL ? self->GetException(NULL)->Dump() : "");
- ObjectLock<mirror::Class> lock(self, &klass);
+ ObjectLock<mirror::Class> lock(self, klass);
// Initialization failed because the super-class is erroneous.
klass->SetStatus(mirror::Class::kStatusError, self);
return false;
@@ -3242,7 +3241,7 @@
bool success = true;
{
- ObjectLock<mirror::Class> lock(self, &klass);
+ ObjectLock<mirror::Class> lock(self, klass);
if (self->IsExceptionPending()) {
WrapExceptionInInitializer();
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index 27c1bdc..f2e059d 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -144,19 +144,18 @@
// A wrapper which wraps around Object** and restores the pointer in the destructor.
// TODO: Add more functionality.
template<class T>
-class HandleWrapper {
+class HandleWrapper : public Handle<T> {
public:
HandleWrapper(T** obj, const Handle<T>& handle)
- : obj_(obj), handle_(handle) {
+ : Handle<T>(handle), obj_(obj) {
}
~HandleWrapper() {
- *obj_ = handle_.Get();
+ *obj_ = Handle<T>::Get();
}
private:
T** obj_;
- Handle<T> handle_;
};
// Scoped handle storage of a fixed size that is usually stack allocated.
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 64edba8..53e4a6f 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -625,8 +625,13 @@
// Allocate and acquire a new monitor.
UniquePtr<Monitor> m(new Monitor(self, owner, obj, hash_code));
if (m->Install(self)) {
- VLOG(monitor) << "monitor: thread " << owner->GetThreadId()
- << " created monitor " << m.get() << " for object " << obj;
+ if (owner != nullptr) {
+ VLOG(monitor) << "monitor: thread" << owner->GetThreadId()
+ << " created monitor " << m.get() << " for object " << obj;
+ } else {
+ VLOG(monitor) << "monitor: Inflate with hashcode " << hash_code
+ << " created monitor " << m.get() << " for object " << obj;
+ }
Runtime::Current()->GetMonitorList()->Add(m.release());
CHECK_EQ(obj->GetLockWord(true).GetState(), LockWord::kFatLocked);
}
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 0dd6ca1..b1e8c09 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -38,33 +38,31 @@
template <typename T>
class ObjectLock {
public:
- explicit ObjectLock(Thread* self, const Handle<T>* object)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ ObjectLock(Thread* self, Handle<T> object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: self_(self), obj_(object) {
- CHECK(object != nullptr);
- CHECK(object->Get() != nullptr);
- obj_->Get()->MonitorEnter(self_);
+ CHECK(object.Get() != nullptr);
+ obj_->MonitorEnter(self_);
}
~ObjectLock() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->Get()->MonitorExit(self_);
+ obj_->MonitorExit(self_);
}
void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Monitor::Wait(self_, obj_->Get(), 0, 0, false, kWaiting);
+ Monitor::Wait(self_, obj_.Get(), 0, 0, false, kWaiting);
}
void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->Get()->Notify(self_);
+ obj_->Notify(self_);
}
void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->Get()->NotifyAll(self_);
+ obj_->NotifyAll(self_);
}
private:
Thread* const self_;
- const Handle<T>* const obj_;
+ Handle<T> const obj_;
DISALLOW_COPY_AND_ASSIGN(ObjectLock);
};
diff --git a/runtime/thread.cc b/runtime/thread.cc
index d535118..415cc0b 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1105,7 +1105,7 @@
if (lock != nullptr) {
StackHandleScope<1> hs(self);
Handle<mirror::Object> h_obj(hs.NewHandle(lock));
- ObjectLock<mirror::Object> locker(self, &h_obj);
+ ObjectLock<mirror::Object> locker(self, h_obj);
locker.NotifyAll();
}
}