Merge "Build live ranges in preparation for register allocation."
diff --git a/Android.mk b/Android.mk
index 2196d59..0cd9166 100644
--- a/Android.mk
+++ b/Android.mk
@@ -151,17 +151,16 @@
# host test targets
.PHONY: test-art-host-vixl
-ifneq ($(BUILD_HOST_64bit),)
-test-art-host-vixl: $(ANDROID_HOST_OUT)/bin/cctest_vixl
- $(ANDROID_HOST_OUT)/bin/cctest_vixl --run_all
- @echo vixl PASSED
-
-else
-# vixl test needs 64b host.
-test-art-host-vixl:
- @echo vixl test only runnable with 64b host build.
-
+VIXL_TEST_DEPENDENCY :=
+# We can only run the vixl tests on 64-bit hosts (vixl testing issue) when its a
+# top-level build (to declare the vixl test rule).
+ifneq ($(HOST_IS_64_BIT),)
+ifeq ($(ONE_SHOT_MAKEFILE),)
+VIXL_TEST_DEPENDENCY := run-vixl-tests
endif
+endif
+
+test-art-host-vixl: $(VIXL_TEST_DEPENDENCY)
# "mm test-art-host" to build and run all host tests
.PHONY: test-art-host
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 7369928..226df98 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -251,3 +251,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/common_compiler_test.h b/compiler/common_compiler_test.h
index 586c442..7a91e47 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -130,6 +130,9 @@
return result;
}
+// Normally the ClassLinker supplies this.
+extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+
class CommonCompilerTest : public CommonRuntimeTest {
public:
// Create an OatMethod based on pointers (for unit tests).
@@ -217,7 +220,7 @@
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
} else {
- const void* method_code = GetQuickGenericJniTrampoline();
+ const void* method_code = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
oat_method.LinkMethod(method);
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/frontend.cc b/compiler/dex/frontend.cc
index 144594e..3bc060b 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -147,8 +147,8 @@
// Instruction::MOVE_RESULT,
// Instruction::MOVE_RESULT_WIDE,
// Instruction::MOVE_RESULT_OBJECT,
- // Instruction::MOVE_EXCEPTION,
- // Instruction::RETURN_VOID,
+ Instruction::MOVE_EXCEPTION,
+ Instruction::RETURN_VOID,
// Instruction::RETURN,
// Instruction::RETURN_WIDE,
// Instruction::RETURN_OBJECT,
@@ -163,8 +163,8 @@
// Instruction::CONST_STRING,
// Instruction::CONST_STRING_JUMBO,
// Instruction::CONST_CLASS,
- // Instruction::MONITOR_ENTER,
- // Instruction::MONITOR_EXIT,
+ Instruction::MONITOR_ENTER,
+ Instruction::MONITOR_EXIT,
// Instruction::CHECK_CAST,
// Instruction::INSTANCE_OF,
// Instruction::ARRAY_LENGTH,
@@ -173,7 +173,7 @@
// Instruction::FILLED_NEW_ARRAY,
// Instruction::FILLED_NEW_ARRAY_RANGE,
// Instruction::FILL_ARRAY_DATA,
- // Instruction::THROW,
+ Instruction::THROW,
// Instruction::GOTO,
// Instruction::GOTO_16,
// Instruction::GOTO_32,
@@ -230,14 +230,14 @@
// Instruction::IPUT_BYTE,
// Instruction::IPUT_CHAR,
// Instruction::IPUT_SHORT,
- // Instruction::SGET,
+ Instruction::SGET,
// Instruction::SGET_WIDE,
- // Instruction::SGET_OBJECT,
+ Instruction::SGET_OBJECT,
// Instruction::SGET_BOOLEAN,
// Instruction::SGET_BYTE,
// Instruction::SGET_CHAR,
// Instruction::SGET_SHORT,
- // Instruction::SPUT,
+ Instruction::SPUT,
// Instruction::SPUT_WIDE,
// Instruction::SPUT_OBJECT,
// Instruction::SPUT_BOOLEAN,
@@ -350,7 +350,7 @@
// Instruction::AND_INT_LIT16,
// Instruction::OR_INT_LIT16,
// Instruction::XOR_INT_LIT16,
- // Instruction::ADD_INT_LIT8,
+ Instruction::ADD_INT_LIT8,
// Instruction::RSUB_INT_LIT8,
// Instruction::MUL_INT_LIT8,
// Instruction::DIV_INT_LIT8,
@@ -403,7 +403,7 @@
// kMirOpNullCheck,
// kMirOpRangeCheck,
// kMirOpDivZeroCheck,
- // kMirOpCheck,
+ kMirOpCheck,
// kMirOpCheckPart2,
// kMirOpSelect,
// 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/arm64/arm64_lir.h b/compiler/dex/quick/arm64/arm64_lir.h
index 7ae4b02..f98e366 100644
--- a/compiler/dex/quick/arm64/arm64_lir.h
+++ b/compiler/dex/quick/arm64/arm64_lir.h
@@ -151,6 +151,9 @@
rxzr = rx31,
rwsp = rw31,
rsp = rx31,
+ // TODO: rx4 is an argument register in C ABI which is not a good idea,
+ // But we need to decide to use caller save register in C ABI or callee save register.
+ // Because it will result to different implementation in the trampoline.
rA64_SUSPEND = rx4,
rA64_SELF = rx18,
rA64_SP = rx31,
diff --git a/compiler/dex/quick/arm64/assemble_arm64.cc b/compiler/dex/quick/arm64/assemble_arm64.cc
index 8accd0a..93caf89 100644
--- a/compiler/dex/quick/arm64/assemble_arm64.cc
+++ b/compiler/dex/quick/arm64/assemble_arm64.cc
@@ -176,7 +176,7 @@
kFmtRegROrSp, 9, 5, kFmtBitBlt, 21, 10, kFmtBitBlt, 23, 22,
kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE0 | SETS_CCODES,
"cmn", "!0R, #!1d!2T", kFixupNone),
- ENCODING_MAP(WIDE(kA64Cmp3Rro), SF_VARIANTS(0x6b20001f),
+ ENCODING_MAP(WIDE(kA64Cmp3Rro), SF_VARIANTS(0x6b00001f),
kFmtRegROrSp, 9, 5, kFmtRegR, 20, 16, kFmtShift, -1, -1,
kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE01 | SETS_CCODES,
"cmp", "!0R, !1r!2o", kFixupNone),
@@ -637,7 +637,7 @@
}
// Now check that the requirements are satisfied.
- RegStorage reg(operand);
+ RegStorage reg(operand | RegStorage::kValid);
const char *expected = nullptr;
if (want_float) {
if (!reg.IsFloat()) {
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index 1bcf19b..136a04f 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -194,137 +194,101 @@
* details see monitor.cc.
*/
void Arm64Mir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) {
+ // x0/w0 = object
+ // w1 = thin lock thread id
+ // x2 = address of lock word
+ // w3 = lock word / store failure
+ // TUNING: How much performance we get when we inline this?
+ // Since we've already flush all register.
FlushAllRegs();
- // FIXME: need separate LoadValues for object references.
- LoadValueDirectFixed(rl_src, rs_x0); // Get obj
+ LoadValueDirectFixed(rl_src, rs_w0);
LockCallTemps(); // Prepare for explicit register usage
- constexpr bool kArchVariantHasGoodBranchPredictor = false; // TODO: true if cortex-A15.
- if (kArchVariantHasGoodBranchPredictor) {
- LIR* null_check_branch = nullptr;
- if ((opt_flags & MIR_IGNORE_NULL_CHECK) && !(cu_->disable_opt & (1 << kNullCheckElimination))) {
- null_check_branch = nullptr; // No null check.
- } else {
- // If the null-check fails its handled by the slow-path to reduce exception related meta-data.
- if (Runtime::Current()->ExplicitNullChecks()) {
- null_check_branch = OpCmpImmBranch(kCondEq, rs_x0, 0, NULL);
- }
- }
- Load32Disp(rs_rA64_SELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_x2);
- NewLIR3(kA64Ldxr2rX, rx1, rx0, mirror::Object::MonitorOffset().Int32Value() >> 2);
- MarkPossibleNullPointerException(opt_flags);
- LIR* not_unlocked_branch = OpCmpImmBranch(kCondNe, rs_x1, 0, NULL);
- NewLIR4(kA64Stxr3wrX, rx1, rx2, rx0, mirror::Object::MonitorOffset().Int32Value() >> 2);
- LIR* lock_success_branch = OpCmpImmBranch(kCondEq, rs_x1, 0, NULL);
-
-
- LIR* slow_path_target = NewLIR0(kPseudoTargetLabel);
- not_unlocked_branch->target = slow_path_target;
- if (null_check_branch != nullptr) {
- null_check_branch->target = slow_path_target;
- }
- // TODO: move to a slow path.
- // Go expensive route - artLockObjectFromCode(obj);
- LoadWordDisp(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pLockObject).Int32Value(), rs_rA64_LR);
- ClobberCallerSave();
- LIR* call_inst = OpReg(kOpBlx, rs_rA64_LR);
- MarkSafepointPC(call_inst);
-
- LIR* success_target = NewLIR0(kPseudoTargetLabel);
- lock_success_branch->target = success_target;
- GenMemBarrier(kLoadLoad);
+ LIR* null_check_branch = nullptr;
+ if ((opt_flags & MIR_IGNORE_NULL_CHECK) && !(cu_->disable_opt & (1 << kNullCheckElimination))) {
+ null_check_branch = nullptr; // No null check.
} else {
- // Explicit null-check as slow-path is entered using an IT.
- GenNullCheck(rs_x0, opt_flags);
- Load32Disp(rs_rA64_SELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_x2);
- MarkPossibleNullPointerException(opt_flags);
- NewLIR3(kA64Ldxr2rX, rx1, rx0, mirror::Object::MonitorOffset().Int32Value() >> 2);
- OpRegImm(kOpCmp, rs_x1, 0);
- OpIT(kCondEq, "");
- NewLIR4(kA64Stxr3wrX/*eq*/, rx1, rx2, rx0, mirror::Object::MonitorOffset().Int32Value() >> 2);
- OpRegImm(kOpCmp, rs_x1, 0);
- OpIT(kCondNe, "T");
- // Go expensive route - artLockObjectFromCode(self, obj);
- LoadWordDisp/*ne*/(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pLockObject).Int32Value(),
- rs_rA64_LR);
- ClobberCallerSave();
- LIR* call_inst = OpReg(kOpBlx/*ne*/, rs_rA64_LR);
- MarkSafepointPC(call_inst);
- GenMemBarrier(kLoadLoad);
+ // If the null-check fails its handled by the slow-path to reduce exception related meta-data.
+ if (Runtime::Current()->ExplicitNullChecks()) {
+ null_check_branch = OpCmpImmBranch(kCondEq, rs_x0, 0, NULL);
+ }
}
+ Load32Disp(rs_rA64_SELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_w1);
+ OpRegRegImm(kOpAdd, rs_x2, rs_x0, mirror::Object::MonitorOffset().Int32Value());
+ NewLIR2(kA64Ldxr2rX, rw3, rx2);
+ MarkPossibleNullPointerException(opt_flags);
+ LIR* not_unlocked_branch = OpCmpImmBranch(kCondNe, rs_x1, 0, NULL);
+ NewLIR3(kA64Stxr3wrX, rw3, rw1, rx2);
+ LIR* lock_success_branch = OpCmpImmBranch(kCondEq, rs_x1, 0, NULL);
+
+ LIR* slow_path_target = NewLIR0(kPseudoTargetLabel);
+ not_unlocked_branch->target = slow_path_target;
+ if (null_check_branch != nullptr) {
+ null_check_branch->target = slow_path_target;
+ }
+ // TODO: move to a slow path.
+ // Go expensive route - artLockObjectFromCode(obj);
+ LoadWordDisp(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pLockObject).Int32Value(), rs_rA64_LR);
+ ClobberCallerSave();
+ LIR* call_inst = OpReg(kOpBlx, rs_rA64_LR);
+ MarkSafepointPC(call_inst);
+
+ LIR* success_target = NewLIR0(kPseudoTargetLabel);
+ lock_success_branch->target = success_target;
+ GenMemBarrier(kLoadLoad);
}
/*
* Handle thin locked -> unlocked transition inline or else call out to quick entrypoint. For more
- * details see monitor.cc. Note the code below doesn't use ldrex/strex as the code holds the lock
+ * details see monitor.cc. Note the code below doesn't use ldxr/stxr as the code holds the lock
* and can only give away ownership if its suspended.
*/
void Arm64Mir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) {
+ // x0/w0 = object
+ // w1 = thin lock thread id
+ // w2 = lock word
+ // TUNING: How much performance we get when we inline this?
+ // Since we've already flush all register.
FlushAllRegs();
- LoadValueDirectFixed(rl_src, rs_x0); // Get obj
+ LoadValueDirectFixed(rl_src, rs_w0); // Get obj
LockCallTemps(); // Prepare for explicit register usage
LIR* null_check_branch = nullptr;
- Load32Disp(rs_rA64_SELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_x2);
- constexpr bool kArchVariantHasGoodBranchPredictor = false; // TODO: true if cortex-A15.
- if (kArchVariantHasGoodBranchPredictor) {
- if ((opt_flags & MIR_IGNORE_NULL_CHECK) && !(cu_->disable_opt & (1 << kNullCheckElimination))) {
- null_check_branch = nullptr; // No null check.
- } else {
- // If the null-check fails its handled by the slow-path to reduce exception related meta-data.
- if (Runtime::Current()->ExplicitNullChecks()) {
- null_check_branch = OpCmpImmBranch(kCondEq, rs_x0, 0, NULL);
- }
- }
- Load32Disp(rs_x0, mirror::Object::MonitorOffset().Int32Value(), rs_x1);
- MarkPossibleNullPointerException(opt_flags);
- LoadConstantNoClobber(rs_x3, 0);
- LIR* slow_unlock_branch = OpCmpBranch(kCondNe, rs_x1, rs_x2, NULL);
- GenMemBarrier(kStoreLoad);
- Store32Disp(rs_x0, mirror::Object::MonitorOffset().Int32Value(), rs_x3);
- LIR* unlock_success_branch = OpUnconditionalBranch(NULL);
-
- LIR* slow_path_target = NewLIR0(kPseudoTargetLabel);
- slow_unlock_branch->target = slow_path_target;
- if (null_check_branch != nullptr) {
- null_check_branch->target = slow_path_target;
- }
- // TODO: move to a slow path.
- // Go expensive route - artUnlockObjectFromCode(obj);
- LoadWordDisp(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pUnlockObject).Int32Value(), rs_rA64_LR);
- ClobberCallerSave();
- LIR* call_inst = OpReg(kOpBlx, rs_rA64_LR);
- MarkSafepointPC(call_inst);
-
- LIR* success_target = NewLIR0(kPseudoTargetLabel);
- unlock_success_branch->target = success_target;
+ if ((opt_flags & MIR_IGNORE_NULL_CHECK) && !(cu_->disable_opt & (1 << kNullCheckElimination))) {
+ null_check_branch = nullptr; // No null check.
} else {
- // Explicit null-check as slow-path is entered using an IT.
- GenNullCheck(rs_x0, opt_flags);
- Load32Disp(rs_x0, mirror::Object::MonitorOffset().Int32Value(), rs_x1); // Get lock
- MarkPossibleNullPointerException(opt_flags);
- Load32Disp(rs_rA64_SELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_x2);
- LoadConstantNoClobber(rs_x3, 0);
- // Is lock unheld on lock or held by us (==thread_id) on unlock?
- OpRegReg(kOpCmp, rs_x1, rs_x2);
- OpIT(kCondEq, "EE");
- Store32Disp/*eq*/(rs_x0, mirror::Object::MonitorOffset().Int32Value(), rs_x3);
- // Go expensive route - UnlockObjectFromCode(obj);
- LoadWordDisp/*ne*/(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pUnlockObject).Int32Value(),
- rs_rA64_LR);
- ClobberCallerSave();
- LIR* call_inst = OpReg(kOpBlx/*ne*/, rs_rA64_LR);
- MarkSafepointPC(call_inst);
- GenMemBarrier(kStoreLoad);
+ // If the null-check fails its handled by the slow-path to reduce exception related meta-data.
+ if (Runtime::Current()->ExplicitNullChecks()) {
+ null_check_branch = OpCmpImmBranch(kCondEq, rs_x0, 0, NULL);
+ }
}
+ Load32Disp(rs_rA64_SELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_w1);
+ Load32Disp(rs_x0, mirror::Object::MonitorOffset().Int32Value(), rs_w2);
+ MarkPossibleNullPointerException(opt_flags);
+ LIR* slow_unlock_branch = OpCmpBranch(kCondNe, rs_w1, rs_w2, NULL);
+ GenMemBarrier(kStoreLoad);
+ Store32Disp(rs_x0, mirror::Object::MonitorOffset().Int32Value(), rs_xzr);
+ LIR* unlock_success_branch = OpUnconditionalBranch(NULL);
+
+ LIR* slow_path_target = NewLIR0(kPseudoTargetLabel);
+ slow_unlock_branch->target = slow_path_target;
+ if (null_check_branch != nullptr) {
+ null_check_branch->target = slow_path_target;
+ }
+ // TODO: move to a slow path.
+ // Go expensive route - artUnlockObjectFromCode(obj);
+ LoadWordDisp(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pUnlockObject).Int32Value(), rs_rA64_LR);
+ ClobberCallerSave();
+ LIR* call_inst = OpReg(kOpBlx, rs_rA64_LR);
+ MarkSafepointPC(call_inst);
+
+ LIR* success_target = NewLIR0(kPseudoTargetLabel);
+ unlock_success_branch->target = success_target;
}
void Arm64Mir2Lir::GenMoveException(RegLocation rl_dest) {
int ex_offset = Thread::ExceptionOffset<8>().Int32Value();
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
- RegStorage reset_reg = AllocTemp();
Load32Disp(rs_rA64_SELF, ex_offset, rl_result.reg);
- LoadConstant(reset_reg, 0);
- Store32Disp(rs_rA64_SELF, ex_offset, reset_reg);
- FreeTemp(reset_reg);
+ Store32Disp(rs_rA64_SELF, ex_offset, rs_xzr);
StoreValue(rl_dest, rl_result);
}
diff --git a/compiler/dex/quick/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc
index 6caacc8..10be0d6 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -38,16 +38,27 @@
rs_f24, rs_f25, rs_f26, rs_f27, rs_f28, rs_f29, rs_f30, rs_f31};
static const RegStorage dp_regs_arr[] =
{rs_d0, rs_d1, rs_d2, rs_d3, rs_d4, rs_d5, rs_d6, rs_d7,
- rs_d8, rs_d9, rs_d10, rs_d11, rs_d12, rs_d13, rs_d14, rs_d15};
+ rs_d8, rs_d9, rs_d10, rs_d11, rs_d12, rs_d13, rs_d14, rs_d15,
+ rs_d16, rs_d17, rs_d18, rs_d19, rs_d20, rs_d21, rs_d22, rs_d23,
+ rs_d24, rs_d25, rs_d26, rs_d27, rs_d28, rs_d29, rs_d30, rs_d31};
static const RegStorage reserved_regs_arr[] =
{rs_rA64_SUSPEND, rs_rA64_SELF, rs_rA64_SP, rs_rA64_LR};
+// TUING: Are there too many temp registers and too less promote target?
+// This definition need to be matched with runtime.cc, quick entry assembly and JNI compiler
+// Note: we are not able to call to C function directly if it un-match C ABI.
+// Currently, rs_rA64_SELF is not a callee save register which does not match C ABI.
static const RegStorage core_temps_arr[] =
- {rs_x0, rs_x1, rs_x2, rs_x3, rs_x12};
+ {rs_x0, rs_x1, rs_x2, rs_x3, rs_x4, rs_x5, rs_x6, rs_x7,
+ rs_x8, rs_x9, rs_x10, rs_x11, rs_x12, rs_x13, rs_x14, rs_x15, rs_x16,
+ rs_x17};
static const RegStorage sp_temps_arr[] =
{rs_f0, rs_f1, rs_f2, rs_f3, rs_f4, rs_f5, rs_f6, rs_f7,
- rs_f8, rs_f9, rs_f10, rs_f11, rs_f12, rs_f13, rs_f14, rs_f15};
+ rs_f16, rs_f17, rs_f18, rs_f19, rs_f20, rs_f21, rs_f22, rs_f23,
+ rs_f24, rs_f25, rs_f26, rs_f27, rs_f28, rs_f29, rs_f30, rs_f31};
static const RegStorage dp_temps_arr[] =
- {rs_d0, rs_d1, rs_d2, rs_d3, rs_d4, rs_d5, rs_d6, rs_d7};
+ {rs_d0, rs_d1, rs_d2, rs_d3, rs_d4, rs_d5, rs_d6, rs_d7,
+ rs_d16, rs_d17, rs_d18, rs_d19, rs_d20, rs_d21, rs_d22, rs_d23,
+ rs_d24, rs_d25, rs_d26, rs_d27, rs_d28, rs_d29, rs_d30, rs_d31};
static const std::vector<RegStorage> core_regs(core_regs_arr,
core_regs_arr + arraysize(core_regs_arr));
@@ -877,12 +888,13 @@
rl_src.home = false;
MarkLive(rl_src);
- // TODO(Arm64): compress the Method pointer?
- StoreValueWide(rl_method, rl_src);
+ // rl_method might be 32-bit, but ArtMethod* on stack is 64-bit, so always flush it.
+ StoreWordDisp(TargetReg(kSp), 0, TargetReg(kArg0));
- // If Method* has been promoted, explicitly flush
+ // If Method* has been promoted, load it,
+ // otherwise, rl_method is the 32-bit value on [sp], and has already been loaded.
if (rl_method.location == kLocPhysReg) {
- StoreWordDisp(TargetReg(kSp), 0, TargetReg(kArg0));
+ StoreValue(rl_method, rl_src);
}
if (cu_->num_ins == 0) {
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..93feb29 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -685,7 +685,7 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CompilerDriver::DescriptorSet* image_classes =
reinterpret_cast<CompilerDriver::DescriptorSet*>(arg);
- image_classes->insert(ClassHelper(klass).GetDescriptor());
+ image_classes->insert(klass->GetDescriptor());
return true;
}
@@ -755,11 +755,15 @@
CHECK_NE(image_classes_->size(), 0U);
}
-static void MaybeAddToImageClasses(mirror::Class* klass, CompilerDriver::DescriptorSet* image_classes)
+static void MaybeAddToImageClasses(Handle<mirror::Class> c,
+ CompilerDriver::DescriptorSet* image_classes)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ // Make a copy of the handle so that we don't clobber it doing Assign.
+ Handle<mirror::Class> klass(hs.NewHandle(c.Get()));
while (!klass->IsObjectClass()) {
- ClassHelper kh(klass);
- const char* descriptor = kh.GetDescriptor();
+ std::string descriptor(klass->GetDescriptor());
std::pair<CompilerDriver::DescriptorSet::iterator, bool> result =
image_classes->insert(descriptor);
if (result.second) {
@@ -767,13 +771,16 @@
} else {
return;
}
- for (size_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- MaybeAddToImageClasses(kh.GetDirectInterface(i), image_classes);
+ for (size_t i = 0; i < klass->NumDirectInterfaces(); ++i) {
+ StackHandleScope<1> hs(self);
+ MaybeAddToImageClasses(hs.NewHandle(mirror::Class::GetDirectInterface(self, klass, i)),
+ image_classes);
}
if (klass->IsArrayClass()) {
- MaybeAddToImageClasses(klass->GetComponentType(), image_classes);
+ StackHandleScope<1> hs(self);
+ MaybeAddToImageClasses(hs.NewHandle(klass->GetComponentType()), image_classes);
}
- klass = klass->GetSuperClass();
+ klass.Assign(klass->GetSuperClass());
}
}
@@ -781,7 +788,8 @@
DCHECK(object != NULL);
DCHECK(arg != NULL);
CompilerDriver* compiler_driver = reinterpret_cast<CompilerDriver*>(arg);
- MaybeAddToImageClasses(object->GetClass(), compiler_driver->image_classes_.get());
+ StackHandleScope<1> hs(Thread::Current());
+ MaybeAddToImageClasses(hs.NewHandle(object->GetClass()), compiler_driver->image_classes_.get());
}
void CompilerDriver::UpdateImageClasses(TimingLogger* timings) {
@@ -1582,8 +1590,7 @@
CHECK(soa.Self()->IsExceptionPending());
mirror::Throwable* exception = soa.Self()->GetException(NULL);
VLOG(compiler) << "Exception during type resolution: " << exception->Dump();
- if (strcmp("Ljava/lang/OutOfMemoryError;",
- ClassHelper(exception->GetClass()).GetDescriptor()) == 0) {
+ if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) {
// There's little point continuing compilation if the heap is exhausted.
LOG(FATAL) << "Out of memory during type resolution for compilation";
}
@@ -1706,7 +1713,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/compiler/image_writer.cc b/compiler/image_writer.cc
index 20a66d4..e261ee6 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -251,7 +251,9 @@
}
bool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* c, void* /*arg*/) {
- c->ComputeName();
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ mirror::Class::ComputeName(hs.NewHandle(c));
return true;
}
@@ -285,7 +287,7 @@
}
bool ImageWriter::IsImageClass(Class* klass) {
- return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor());
+ return compiler_driver_.IsImageClass(klass->GetDescriptor().c_str());
}
struct NonImageClasses {
@@ -339,7 +341,7 @@
bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg);
if (!context->image_writer->IsImageClass(klass)) {
- context->non_image_classes->insert(ClassHelper(klass).GetDescriptor());
+ context->non_image_classes->insert(klass->GetDescriptor());
}
return true;
}
@@ -359,7 +361,7 @@
Class* klass = obj->AsClass();
if (!image_writer->IsImageClass(klass)) {
image_writer->DumpImageClasses();
- CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor()
+ CHECK(image_writer->IsImageClass(klass)) << klass->GetDescriptor()
<< " " << PrettyDescriptor(klass);
}
}
@@ -757,7 +759,8 @@
uintptr_t value = quick_code - patch_location + patch->RelativeOffset();
SetPatchLocation(patch, value);
} else {
- if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge())) {
+ if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge()) ||
+ quick_code == reinterpret_cast<uintptr_t>(class_linker->GetQuickGenericJniTrampoline())) {
if (target->IsNative()) {
// generic JNI, not interpreter bridge from GetQuickOatCodeFor().
code_offset = quick_generic_jni_trampoline_offset_;
diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc
index 4c819a2..f9ae529 100644
--- a/compiler/optimizing/linearize_test.cc
+++ b/compiler/optimizing/linearize_test.cc
@@ -53,17 +53,17 @@
}
TEST(LinearizeTest, CFG1) {
- // Structure of this graph (* are back edges)
+ // Structure of this graph (+ are back edges)
// Block0
// |
// Block1
// |
- // Block2 ******
- // / \ *
- // Block5 Block7 *
- // | | *
- // Block6 Block3 *
- // * / \ *
+ // Block2 ++++++
+ // / \ +
+ // Block5 Block7 +
+ // | | +
+ // Block6 Block3 +
+ // + / \ +
// Block4 Block8
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
@@ -78,17 +78,17 @@
}
TEST(LinearizeTest, CFG2) {
- // Structure of this graph (* are back edges)
+ // Structure of this graph (+ are back edges)
// Block0
// |
// Block1
// |
- // Block2 ******
- // / \ *
- // Block3 Block7 *
- // | | *
- // Block6 Block4 *
- // * / \ *
+ // Block2 ++++++
+ // / \ +
+ // Block3 Block7 +
+ // | | +
+ // Block6 Block4 +
+ // + / \ +
// Block5 Block8
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
@@ -103,20 +103,20 @@
}
TEST(LinearizeTest, CFG3) {
- // Structure of this graph (* are back edges)
+ // Structure of this graph (+ are back edges)
// Block0
// |
// Block1
// |
- // Block2 ******
- // / \ *
- // Block3 Block8 *
- // | | *
- // Block7 Block5 *
- // / * \ *
- // Block6 * Block9
- // | *
- // Block4 **
+ // Block2 ++++++
+ // / \ +
+ // Block3 Block8 +
+ // | | +
+ // Block7 Block5 +
+ // / + \ +
+ // Block6 + Block9
+ // | +
+ // Block4 ++
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 4,
@@ -130,22 +130,23 @@
}
TEST(LinearizeTest, CFG4) {
- // Structure of this graph (* are back edges)
+ /* Structure of this graph (+ are back edges)
// Block0
// |
// Block1
// |
// Block2
- // / * \
- // Block6 * Block8
- // | * |
- // Block7 * Block3 *******
- // * / \ *
- // Block9 Block10 *
- // | *
- // Block4 *
- // */ \ *
+ // / + \
+ // Block6 + Block8
+ // | + |
+ // Block7 + Block3 +++++++
+ // + / \ +
+ // Block9 Block10 +
+ // | +
+ // Block4 +
+ // + / \ +
// Block5 Block11
+ */
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 7,
@@ -159,22 +160,23 @@
}
TEST(LinearizeTest, CFG5) {
- // Structure of this graph (* are back edges)
+ /* Structure of this graph (+ are back edges)
// Block0
// |
// Block1
// |
// Block2
- // / * \
- // Block3 * Block8
- // | * |
- // Block7 * Block4 *******
- // * / \ *
- // Block9 Block10 *
- // | *
- // Block5 *
- // */ \ *
+ // / + \
+ // Block3 + Block8
+ // | + |
+ // Block7 + Block4 +++++++
+ // + / \ +
+ // Block9 Block10 +
+ // | +
+ // Block5 +
+ // +/ \ +
// Block6 Block11
+ */
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3,
diff --git a/dalvikvm/Android.mk b/dalvikvm/Android.mk
index 8076b61..e7ed9a7 100644
--- a/dalvikvm/Android.mk
+++ b/dalvikvm/Android.mk
@@ -28,10 +28,14 @@
LOCAL_SHARED_LIBRARIES := libdl libnativehelper
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := dalvikvm
+LOCAL_MODULE_STEM_32 := dalvikvm32
LOCAL_MODULE_STEM_64 := dalvikvm64
include art/build/Android.libcxx.mk
include $(BUILD_EXECUTABLE)
+
+# create symlink for the primary version target.
+include $(BUILD_SYSTEM)/executable_prefer_symlink.mk
+
ART_TARGET_EXECUTABLES += $(TARGET_OUT_EXECUTABLES)/$(LOCAL_MODULE)
ifeq ($(WITH_HOST_DALVIK),true)
diff --git a/dalvikvm/dalvikvm.cc b/dalvikvm/dalvikvm.cc
index 582adc0..3fa43dc 100644
--- a/dalvikvm/dalvikvm.cc
+++ b/dalvikvm/dalvikvm.cc
@@ -16,6 +16,7 @@
#include <signal.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <algorithm>
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index ad796f8..874c324 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1017,7 +1017,7 @@
}
if (compiler_filter_string == nullptr) {
- if (instruction_set == kX86_64 || instruction_set == kMips) {
+ if (instruction_set == kX86_64 || instruction_set == kArm64 || instruction_set == kMips) {
// TODO: implement/fix compilers for these architectures.
compiler_filter_string = "interpret-only";
} else if (image) {
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index fef25e0..aaf9ed5 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1147,7 +1147,7 @@
state->stats_.ComputeOutliers(total_size, expansion, method);
}
}
- state->stats_.Update(ClassHelper(obj_class).GetDescriptor(), object_bytes);
+ state->stats_.Update(obj_class->GetDescriptor().c_str(), object_bytes);
}
std::set<const void*> already_seen_;
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-inl.h b/runtime/class_linker-inl.h
index ce634e0..ac86014 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -49,7 +49,7 @@
}
DCHECK(!element_class->IsPrimitiveVoid());
std::string descriptor("[");
- descriptor += ClassHelper(element_class).GetDescriptor();
+ descriptor += element_class->GetDescriptor();
StackHandleScope<1> hs(Thread::Current());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
mirror::Class* array_class = FindClass(self, descriptor.c_str(), class_loader);
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c7f3a20..363e8b2 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -96,8 +96,8 @@
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
if (c->GetVerifyErrorClass() != NULL) {
// TODO: change the verifier to store an _instance_, with a useful detail message?
- ClassHelper ve_ch(c->GetVerifyErrorClass());
- self->ThrowNewException(throw_location, ve_ch.GetDescriptor(), PrettyDescriptor(c).c_str());
+ self->ThrowNewException(throw_location, c->GetVerifyErrorClass()->GetDescriptor().c_str(),
+ PrettyDescriptor(c).c_str());
} else {
self->ThrowNewException(throw_location, "Ljava/lang/NoClassDefFoundError;",
PrettyDescriptor(c).c_str());
@@ -191,6 +191,9 @@
memset(find_array_class_cache_, 0, kFindArrayCacheSize * sizeof(mirror::Class*));
}
+// To set a value for generic JNI. May be necessary in compiler tests.
+extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+
void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class_path) {
VLOG(startup) << "ClassLinker::Init";
CHECK(Runtime::Current()->IsCompiler());
@@ -343,6 +346,10 @@
runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod());
runtime->SetDefaultImt(runtime->CreateDefaultImt(this));
+ // Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that
+ // we do not need friend classes or a publicly exposed setter.
+ quick_generic_jni_trampoline_ = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
+
// Object, String and DexCache need to be rerun through FindSystemClass to finish init
java_lang_Object->SetStatus(mirror::Class::kStatusNotReady, self);
mirror::Class* Object_class = FindSystemClass(self, "Ljava/lang/Object;");
@@ -400,12 +407,10 @@
array_iftable_->SetInterface(1, java_io_Serializable);
// Sanity check Class[] and Object[]'s interfaces.
- ClassHelper kh(class_array_class.Get());
- CHECK_EQ(java_lang_Cloneable, kh.GetDirectInterface(0));
- CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
- kh.ChangeClass(object_array_class.Get());
- CHECK_EQ(java_lang_Cloneable, kh.GetDirectInterface(0));
- CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
+ CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, class_array_class, 0));
+ CHECK_EQ(java_io_Serializable, mirror::Class::GetDirectInterface(self, class_array_class, 1));
+ CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, object_array_class, 0));
+ CHECK_EQ(java_io_Serializable, mirror::Class::GetDirectInterface(self, object_array_class, 1));
// Run Class, ArtField, and ArtMethod through FindSystemClass. This initializes their
// dex_cache_ fields and register them in class_table_.
mirror::Class* Class_class = FindSystemClass(self, "Ljava/lang/Class;");
@@ -1325,8 +1330,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 +1342,6 @@
while (!h_class->IsResolved() && !h_class->IsErroneous()) {
lock.WaitIgnoringInterrupts();
}
- klass = h_class.Get();
}
if (klass->IsErroneous()) {
ThrowEarlierClassFailure(klass);
@@ -1471,7 +1475,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));
@@ -1724,9 +1728,8 @@
if (!runtime->IsStarted() || runtime->UseCompileTimeClassPath()) {
return; // OAT file unavailable.
}
- ClassHelper kh(klass);
- const DexFile& dex_file = kh.GetDexFile();
- const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
const byte* class_data = dex_file.GetClassData(*dex_class_def);
// There should always be class data if there were direct methods.
@@ -1777,9 +1780,10 @@
// Ignore virtual methods on the iterator.
}
-static void LinkCode(const Handle<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
- const DexFile& dex_file, uint32_t dex_method_index, uint32_t method_index)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void ClassLinker::LinkCode(const Handle<mirror::ArtMethod>& method,
+ const OatFile::OatClass* oat_class,
+ const DexFile& dex_file, uint32_t dex_method_index,
+ uint32_t method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Method shouldn't have already been linked.
DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
DCHECK(method->GetEntryPointFromPortableCompiledCode() == nullptr);
@@ -1810,8 +1814,8 @@
// For static methods excluding the class initializer, install the trampoline.
// It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines
// after initializing class (see ClassLinker::InitializeClass method).
- method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline(runtime->GetClassLinker()));
- method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline(runtime->GetClassLinker()));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline());
} else if (enter_interpreter) {
if (!method->IsNative()) {
// Set entry point from compiled code if there's no code or in interpreter only mode.
@@ -1837,8 +1841,7 @@
if (enter_interpreter) {
// We have a native method here without code. Then it should have either the GenericJni
// trampoline as entrypoint (non-static), or the Resolution trampoline (static).
- DCHECK(method->GetEntryPointFromQuickCompiledCode() ==
- GetQuickResolutionTrampoline(runtime->GetClassLinker())
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() == GetQuickResolutionTrampoline()
|| method->GetEntryPointFromQuickCompiledCode() == GetQuickGenericJniTrampoline());
}
}
@@ -2028,15 +2031,14 @@
if (klass->GetClassLoader() != NULL) { // All non-boot finalizer methods are flagged
klass->SetFinalizable();
} else {
- ClassHelper kh(klass.Get());
- const char* klass_descriptor = kh.GetDescriptor();
+ std::string klass_descriptor = klass->GetDescriptor();
// The Enum class declares a "final" finalize() method to prevent subclasses from
// introducing a finalizer. We don't want to set the finalizable flag for Enum or its
// subclasses, so we exclude it here.
// We also want to avoid setting the flag on Object, where we know that finalize() is
// empty.
- if ((strcmp("Ljava/lang/Object;", klass_descriptor) != 0) &&
- (strcmp("Ljava/lang/Enum;", klass_descriptor) != 0)) {
+ if (klass_descriptor.compare("Ljava/lang/Object;") != 0 &&
+ klass_descriptor.compare("Ljava/lang/Enum;") != 0) {
klass->SetFinalizable();
}
}
@@ -2182,7 +2184,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 +2281,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);
@@ -2397,9 +2399,7 @@
for (auto it = class_table_.lower_bound(hash), end = class_table_.end(); it != end && it->first == hash;
++it) {
mirror::Class* klass = it->second;
- ClassHelper kh(klass);
- if ((klass->GetClassLoader() == class_loader) &&
- (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
+ if (klass->GetClassLoader() == class_loader && descriptor == klass->GetDescriptor()) {
class_table_.erase(it);
return true;
}
@@ -2443,16 +2443,13 @@
auto end = class_table_.end();
for (auto it = class_table_.lower_bound(hash); it != end && it->first == hash; ++it) {
mirror::Class* klass = it->second;
- ClassHelper kh(klass);
- if ((klass->GetClassLoader() == class_loader) &&
- (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
+ if (klass->GetClassLoader() == class_loader && descriptor == klass->GetDescriptor()) {
if (kIsDebugBuild) {
// Check for duplicates in the table.
for (++it; it != end && it->first == hash; ++it) {
mirror::Class* klass2 = it->second;
- ClassHelper kh(klass2);
CHECK(!((klass2->GetClassLoader() == class_loader) &&
- (strcmp(descriptor, kh.GetDescriptor()) == 0)))
+ descriptor == klass2->GetDescriptor()))
<< PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " "
<< PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader();
}
@@ -2486,11 +2483,10 @@
for (int32_t j = 0; j < types->GetLength(); j++) {
mirror::Class* klass = types->Get(j);
if (klass != NULL) {
- ClassHelper kh(klass);
DCHECK(klass->GetClassLoader() == NULL);
- const char* descriptor = kh.GetDescriptor();
- size_t hash = Hash(descriptor);
- mirror::Class* existing = LookupClassFromTableLocked(descriptor, NULL, hash);
+ std::string descriptor = klass->GetDescriptor();
+ size_t hash = Hash(descriptor.c_str());
+ mirror::Class* existing = LookupClassFromTableLocked(descriptor.c_str(), NULL, hash);
if (existing != NULL) {
CHECK(existing == klass) << PrettyClassAndClassLoader(existing) << " != "
<< PrettyClassAndClassLoader(klass);
@@ -2544,8 +2540,7 @@
for (auto it = class_table_.lower_bound(hash), end = class_table_.end();
it != end && it->first == hash; ++it) {
mirror::Class* klass = it->second;
- ClassHelper kh(klass);
- if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
+ if (descriptor == klass->GetDescriptor()) {
result.push_back(klass);
}
}
@@ -2554,7 +2549,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 +2584,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);
@@ -2757,7 +2752,7 @@
}
LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
<< " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
- << ClassHelper(klass).GetDescriptor();
+ << klass->GetDescriptor();
return false;
}
@@ -2903,7 +2898,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)));
@@ -3077,8 +3072,7 @@
}
// Check if there are encoded static values needing initialization.
if (klass->NumStaticFields() != 0) {
- ClassHelper kh(klass);
- const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
+ const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
DCHECK(dex_class_def != NULL);
if (dex_class_def->static_values_off_ != 0) {
return false;
@@ -3121,7 +3115,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 +3192,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;
@@ -3207,13 +3201,12 @@
}
if (klass->NumStaticFields() > 0) {
- ClassHelper kh(klass.Get());
- const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
+ const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != NULL);
- const DexFile& dex_file = kh.GetDexFile();
+ const DexFile& dex_file = klass->GetDexFile();
StackHandleScope<2> hs(self);
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(kh.GetDexCache()));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
EncodedStaticFieldValueIterator it(dex_file, &dex_cache, &class_loader,
this, *dex_class_def);
if (it.HasNext()) {
@@ -3242,7 +3235,7 @@
bool success = true;
{
- ObjectLock<mirror::Class> lock(self, &klass);
+ ObjectLock<mirror::Class> lock(self, klass);
if (self->IsExceptionPending()) {
WrapExceptionInInitializer();
@@ -3258,8 +3251,8 @@
// Set the class as initialized except if failed to initialize static fields.
klass->SetStatus(mirror::Class::kStatusInitialized, self);
if (VLOG_IS_ON(class_linker)) {
- ClassHelper kh(klass.Get());
- LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
+ LOG(INFO) << "Initialized class " << klass->GetDescriptor() << " from " <<
+ klass->GetLocation();
}
// Opportunistically set static method trampolines to their destination.
FixupStaticTrampolines(klass.Get());
@@ -3613,6 +3606,7 @@
bool ClassLinker::LinkInterfaceMethods(const Handle<mirror::Class>& klass,
const Handle<mirror::ObjectArray<mirror::Class> >& interfaces) {
+ Thread* const self = Thread::Current();
// Set the imt table to be all conflicts by default.
klass->SetImTable(Runtime::Current()->GetDefaultImt());
size_t super_ifcount;
@@ -3621,18 +3615,14 @@
} else {
super_ifcount = 0;
}
- size_t ifcount = super_ifcount;
- uint32_t num_interfaces;
- {
- ClassHelper kh(klass.Get());
- num_interfaces =
- interfaces.Get() == nullptr ? kh.NumDirectInterfaces() : interfaces->GetLength();
- ifcount += num_interfaces;
- for (size_t i = 0; i < num_interfaces; i++) {
- mirror::Class* interface =
- interfaces.Get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
- ifcount += interface->GetIfTableCount();
- }
+ uint32_t num_interfaces =
+ interfaces.Get() == nullptr ? klass->NumDirectInterfaces() : interfaces->GetLength();
+ size_t ifcount = super_ifcount + num_interfaces;
+ for (size_t i = 0; i < num_interfaces; i++) {
+ mirror::Class* interface =
+ interfaces.Get() == nullptr ? mirror::Class::GetDirectInterface(self, klass, i) :
+ interfaces->Get(i);
+ ifcount += interface->GetIfTableCount();
}
if (ifcount == 0) {
// Class implements no interfaces.
@@ -3656,7 +3646,6 @@
return true;
}
}
- Thread* self = Thread::Current();
StackHandleScope<2> hs(self);
Handle<mirror::IfTable> iftable(hs.NewHandle(AllocIfTable(self, ifcount)));
if (UNLIKELY(iftable.Get() == NULL)) {
@@ -3673,15 +3662,14 @@
// Flatten the interface inheritance hierarchy.
size_t idx = super_ifcount;
for (size_t i = 0; i < num_interfaces; i++) {
- ClassHelper kh(klass.Get());
mirror::Class* interface =
- interfaces.Get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
+ interfaces.Get() == nullptr ? mirror::Class::GetDirectInterface(self, klass, i) :
+ interfaces->Get(i);
DCHECK(interface != NULL);
if (!interface->IsInterface()) {
- ClassHelper ih(interface);
ThrowIncompatibleClassChangeError(klass.Get(), "Class %s implements non-interface class %s",
PrettyDescriptor(klass.Get()).c_str(),
- PrettyDescriptor(ih.GetDescriptor()).c_str());
+ PrettyDescriptor(interface->GetDescriptor()).c_str());
return false;
}
// Check if interface is already in iftable
@@ -4007,8 +3995,7 @@
}
// We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
- if (!is_static &&
- (strcmp("Ljava/lang/ref/Reference;", ClassHelper(klass.Get()).GetDescriptor()) == 0)) {
+ if (!is_static && "Ljava/lang/ref/Reference;" == klass->GetDescriptor()) {
// We know there are no non-reference fields in the Reference classes, and we know
// that 'referent' is alphabetically last, so this is easy...
CHECK_EQ(num_reference_fields, num_fields);
@@ -4033,8 +4020,8 @@
FieldHelper fh(field);
Primitive::Type type = fh.GetTypeAsPrimitiveType();
bool is_primitive = type != Primitive::kPrimNot;
- if ((strcmp("Ljava/lang/ref/Reference;", ClassHelper(klass.Get()).GetDescriptor()) == 0)
- && (strcmp("referent", fh.GetName()) == 0)) {
+ if ("Ljava/lang/ref/Reference;" == klass->GetDescriptor() &&
+ strcmp("referent", fh.GetName()) == 0) {
is_primitive = true; // We lied above, so we have to expect a lie here.
}
if (is_primitive) {
@@ -4058,7 +4045,7 @@
} else {
klass->SetNumReferenceInstanceFields(num_reference_fields);
if (!klass->IsVariableSize()) {
- DCHECK_GE(size, sizeof(mirror::Object)) << ClassHelper(klass.Get()).GetDescriptor();
+ DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor();
size_t previous_size = klass->GetObjectSize();
if (previous_size != 0) {
// Make sure that we didn't originally have an incorrect size.
@@ -4334,14 +4321,17 @@
return resolved;
}
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- mirror::Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader);
- if (klass == NULL) {
+ Thread* const self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass(
+ hs.NewHandle(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader)));
+ if (klass.Get() == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
if (is_static) {
- resolved = klass->FindStaticField(dex_cache.Get(), field_idx);
+ resolved = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx);
} else {
resolved = klass->FindInstanceField(dex_cache.Get(), field_idx);
}
@@ -4350,12 +4340,12 @@
const char* name = dex_file.GetFieldName(field_id);
const char* type = dex_file.GetFieldTypeDescriptor(field_id);
if (is_static) {
- resolved = klass->FindStaticField(name, type);
+ resolved = mirror::Class::FindStaticField(self, klass, name, type);
} else {
resolved = klass->FindInstanceField(name, type);
}
if (resolved == NULL) {
- ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass, type, name);
+ ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass.Get(), type, name);
return NULL;
}
}
@@ -4373,8 +4363,11 @@
return resolved;
}
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- mirror::Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader);
- if (klass == NULL) {
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass(
+ hs.NewHandle(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader)));
+ if (klass.Get() == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
@@ -4382,11 +4375,11 @@
StringPiece name(dex_file.StringDataByIdx(field_id.name_idx_));
StringPiece type(dex_file.StringDataByIdx(
dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_));
- resolved = klass->FindField(name, type);
+ resolved = mirror::Class::FindField(self, klass, name, type);
if (resolved != NULL) {
dex_cache->SetResolvedField(field_idx, resolved);
} else {
- ThrowNoSuchFieldError("", klass, type, name);
+ ThrowNoSuchFieldError("", klass.Get(), type, name);
}
return resolved;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 3dac6e5..db780d9 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -355,8 +355,8 @@
}
const void* GetQuickGenericJniTrampoline() const {
- return quick_generic_jni_trampoline_;
- }
+ return quick_generic_jni_trampoline_;
+ }
const void* GetQuickResolutionTrampoline() const {
return quick_resolution_trampoline_;
@@ -511,6 +511,9 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool LinkFields(const Handle<mirror::Class>& klass, bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void LinkCode(const Handle<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
+ const DexFile& dex_file, uint32_t dex_method_index, uint32_t method_index)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CreateReferenceInstanceOffsets(const Handle<mirror::Class>& klass)
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 9970dd5..ff90f41 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -60,12 +60,11 @@
void AssertPrimitiveClass(const std::string& descriptor, mirror::Class* primitive)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper primitive_ch(primitive);
ASSERT_TRUE(primitive != NULL);
ASSERT_TRUE(primitive->GetClass() != NULL);
ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass());
EXPECT_TRUE(primitive->GetClass()->GetSuperClass() != NULL);
- ASSERT_STREQ(descriptor.c_str(), primitive_ch.GetDescriptor());
+ ASSERT_STREQ(descriptor.c_str(), primitive->GetDescriptor().c_str());
EXPECT_TRUE(primitive->GetSuperClass() == NULL);
EXPECT_FALSE(primitive->HasSuperClass());
EXPECT_TRUE(primitive->GetClassLoader() == NULL);
@@ -87,7 +86,7 @@
EXPECT_EQ(0U, primitive->NumVirtualMethods());
EXPECT_EQ(0U, primitive->NumInstanceFields());
EXPECT_EQ(0U, primitive->NumStaticFields());
- EXPECT_EQ(0U, primitive_ch.NumDirectInterfaces());
+ EXPECT_EQ(0U, primitive->NumDirectInterfaces());
EXPECT_TRUE(primitive->GetVTable() == NULL);
EXPECT_EQ(0, primitive->GetIfTableCount());
EXPECT_TRUE(primitive->GetIfTable() == NULL);
@@ -103,8 +102,7 @@
Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
Handle<mirror::Class> array(
hs.NewHandle(class_linker_->FindClass(self, array_descriptor.c_str(), loader)));
- ClassHelper array_component_ch(array->GetComponentType());
- EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor());
+ EXPECT_STREQ(component_type.c_str(), array->GetComponentType()->GetDescriptor().c_str());
EXPECT_EQ(class_loader, array->GetClassLoader());
EXPECT_EQ(kAccFinal | kAccAbstract, (array->GetAccessFlags() & (kAccFinal | kAccAbstract)));
AssertArrayClass(array_descriptor, array);
@@ -112,19 +110,17 @@
void AssertArrayClass(const std::string& array_descriptor, const Handle<mirror::Class>& array)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper kh(array.Get());
ASSERT_TRUE(array.Get() != NULL);
ASSERT_TRUE(array->GetClass() != NULL);
ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
- ASSERT_STREQ(array_descriptor.c_str(), kh.GetDescriptor());
+ ASSERT_STREQ(array_descriptor.c_str(), array->GetDescriptor().c_str());
EXPECT_TRUE(array->GetSuperClass() != NULL);
Thread* self = Thread::Current();
EXPECT_EQ(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"), array->GetSuperClass());
EXPECT_TRUE(array->HasSuperClass());
ASSERT_TRUE(array->GetComponentType() != NULL);
- kh.ChangeClass(array->GetComponentType());
- ASSERT_TRUE(kh.GetDescriptor() != NULL);
+ ASSERT_TRUE(!array->GetComponentType()->GetDescriptor().empty());
EXPECT_EQ(mirror::Class::kStatusInitialized, array->GetStatus());
EXPECT_FALSE(array->IsErroneous());
EXPECT_TRUE(array->IsLoaded());
@@ -142,16 +138,15 @@
EXPECT_EQ(0U, array->NumVirtualMethods());
EXPECT_EQ(0U, array->NumInstanceFields());
EXPECT_EQ(0U, array->NumStaticFields());
- kh.ChangeClass(array.Get());
- EXPECT_EQ(2U, kh.NumDirectInterfaces());
+ EXPECT_EQ(2U, array->NumDirectInterfaces());
EXPECT_TRUE(array->GetVTable() != NULL);
EXPECT_EQ(2, array->GetIfTableCount());
ASSERT_TRUE(array->GetIfTable() != NULL);
- kh.ChangeClass(kh.GetDirectInterface(0));
- EXPECT_STREQ(kh.GetDescriptor(), "Ljava/lang/Cloneable;");
- kh.ChangeClass(array.Get());
- kh.ChangeClass(kh.GetDirectInterface(1));
- EXPECT_STREQ(kh.GetDescriptor(), "Ljava/io/Serializable;");
+ mirror::Class* direct_interface0 = mirror::Class::GetDirectInterface(self, array, 0);
+ EXPECT_TRUE(direct_interface0 != nullptr);
+ EXPECT_STREQ(direct_interface0->GetDescriptor().c_str(), "Ljava/lang/Cloneable;");
+ mirror::Class* direct_interface1 = mirror::Class::GetDirectInterface(self, array, 1);
+ EXPECT_STREQ(direct_interface1->GetDescriptor().c_str(), "Ljava/io/Serializable;");
EXPECT_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.Get());
}
@@ -185,8 +180,7 @@
void AssertClass(const std::string& descriptor, const Handle<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper kh(klass.Get());
- EXPECT_STREQ(descriptor.c_str(), kh.GetDescriptor());
+ EXPECT_STREQ(descriptor.c_str(), klass->GetDescriptor().c_str());
if (descriptor == "Ljava/lang/Object;") {
EXPECT_FALSE(klass->HasSuperClass());
} else {
@@ -202,7 +196,8 @@
EXPECT_FALSE(klass->IsArrayClass());
EXPECT_TRUE(klass->GetComponentType() == NULL);
EXPECT_TRUE(klass->IsInSamePackage(klass.Get()));
- EXPECT_TRUE(mirror::Class::IsInSamePackage(kh.GetDescriptor(), kh.GetDescriptor()));
+ EXPECT_TRUE(mirror::Class::IsInSamePackage(klass->GetDescriptor().c_str(),
+ klass->GetDescriptor().c_str()));
if (klass->IsInterface()) {
EXPECT_TRUE(klass->IsAbstract());
if (klass->NumDirectMethods() == 1) {
@@ -311,7 +306,7 @@
Handle<mirror::Class> klass(
hs.NewHandle(class_linker_->FindSystemClass(self, descriptor.c_str())));
ASSERT_TRUE(klass.Get() != nullptr);
- EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass.Get()).GetDescriptor());
+ EXPECT_STREQ(descriptor.c_str(), klass.Get()->GetDescriptor().c_str());
EXPECT_EQ(class_loader, klass->GetClassLoader());
if (klass->IsPrimitive()) {
AssertPrimitiveClass(descriptor, klass.Get());
@@ -706,12 +701,11 @@
TEST_F(ClassLinkerTest, FindClass) {
ScopedObjectAccess soa(Thread::Current());
mirror::Class* JavaLangObject = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
- ClassHelper kh(JavaLangObject);
ASSERT_TRUE(JavaLangObject != NULL);
ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
- ASSERT_STREQ(kh.GetDescriptor(), "Ljava/lang/Object;");
+ ASSERT_STREQ(JavaLangObject->GetDescriptor().c_str(), "Ljava/lang/Object;");
EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
EXPECT_FALSE(JavaLangObject->HasSuperClass());
EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
@@ -748,19 +742,18 @@
}
EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
- EXPECT_EQ(0U, kh.NumDirectInterfaces());
+ EXPECT_EQ(0U, JavaLangObject->NumDirectInterfaces());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass"))));
AssertNonExistentClass("LMyClass;");
mirror::Class* MyClass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader);
- kh.ChangeClass(MyClass);
ASSERT_TRUE(MyClass != NULL);
ASSERT_TRUE(MyClass->GetClass() != NULL);
ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
- ASSERT_STREQ(kh.GetDescriptor(), "LMyClass;");
+ ASSERT_STREQ(MyClass->GetDescriptor().c_str(), "LMyClass;");
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
EXPECT_EQ(class_loader.Get(), MyClass->GetClassLoader());
@@ -782,7 +775,7 @@
EXPECT_EQ(0U, MyClass->NumVirtualMethods());
EXPECT_EQ(0U, MyClass->NumInstanceFields());
EXPECT_EQ(0U, MyClass->NumStaticFields());
- EXPECT_EQ(0U, kh.NumDirectInterfaces());
+ EXPECT_EQ(0U, MyClass->NumDirectInterfaces());
EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
@@ -913,56 +906,57 @@
EXPECT_EQ(9U, statics->NumStaticFields());
- mirror::ArtField* s0 = statics->FindStaticField("s0", "Z");
+ mirror::ArtField* s0 = mirror::Class::FindStaticField(soa.Self(), statics, "s0", "Z");
FieldHelper fh(s0);
- EXPECT_STREQ(ClassHelper(s0->GetClass()).GetDescriptor(), "Ljava/lang/reflect/ArtField;");
+ EXPECT_STREQ(s0->GetClass()->GetDescriptor().c_str(), "Ljava/lang/reflect/ArtField;");
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimBoolean);
EXPECT_EQ(true, s0->GetBoolean(statics.Get()));
s0->SetBoolean<false>(statics.Get(), false);
- mirror::ArtField* s1 = statics->FindStaticField("s1", "B");
+ mirror::ArtField* s1 = mirror::Class::FindStaticField(soa.Self(), statics, "s1", "B");
fh.ChangeField(s1);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimByte);
EXPECT_EQ(5, s1->GetByte(statics.Get()));
s1->SetByte<false>(statics.Get(), 6);
- mirror::ArtField* s2 = statics->FindStaticField("s2", "C");
+ mirror::ArtField* s2 = mirror::Class::FindStaticField(soa.Self(), statics, "s2", "C");
fh.ChangeField(s2);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimChar);
EXPECT_EQ('a', s2->GetChar(statics.Get()));
s2->SetChar<false>(statics.Get(), 'b');
- mirror::ArtField* s3 = statics->FindStaticField("s3", "S");
+ mirror::ArtField* s3 = mirror::Class::FindStaticField(soa.Self(), statics, "s3", "S");
fh.ChangeField(s3);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimShort);
EXPECT_EQ(-536, s3->GetShort(statics.Get()));
s3->SetShort<false>(statics.Get(), -535);
- mirror::ArtField* s4 = statics->FindStaticField("s4", "I");
+ mirror::ArtField* s4 = mirror::Class::FindStaticField(soa.Self(), statics, "s4", "I");
fh.ChangeField(s4);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimInt);
EXPECT_EQ(2000000000, s4->GetInt(statics.Get()));
s4->SetInt<false>(statics.Get(), 2000000001);
- mirror::ArtField* s5 = statics->FindStaticField("s5", "J");
+ mirror::ArtField* s5 = mirror::Class::FindStaticField(soa.Self(), statics, "s5", "J");
fh.ChangeField(s5);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimLong);
EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics.Get()));
s5->SetLong<false>(statics.Get(), INT64_C(0x34567890abcdef12));
- mirror::ArtField* s6 = statics->FindStaticField("s6", "F");
+ mirror::ArtField* s6 = mirror::Class::FindStaticField(soa.Self(), statics, "s6", "F");
fh.ChangeField(s6);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimFloat);
EXPECT_EQ(0.5, s6->GetFloat(statics.Get()));
s6->SetFloat<false>(statics.Get(), 0.75);
- mirror::ArtField* s7 = statics->FindStaticField("s7", "D");
+ mirror::ArtField* s7 = mirror::Class::FindStaticField(soa.Self(), statics, "s7", "D");
fh.ChangeField(s7);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimDouble);
EXPECT_EQ(16777217, s7->GetDouble(statics.Get()));
s7->SetDouble<false>(statics.Get(), 16777219);
- mirror::ArtField* s8 = statics->FindStaticField("s8", "Ljava/lang/String;");
+ mirror::ArtField* s8 = mirror::Class::FindStaticField(soa.Self(), statics, "s8",
+ "Ljava/lang/String;");
fh.ChangeField(s8);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimNot);
EXPECT_TRUE(s8->GetObject(statics.Get())->AsString()->Equals("android"));
@@ -984,19 +978,24 @@
TEST_F(ClassLinkerTest, Interfaces) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<6> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Interfaces"))));
- mirror::Class* I = class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader);
- mirror::Class* J = class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader);
- mirror::Class* K = class_linker_->FindClass(soa.Self(), "LInterfaces$K;", class_loader);
- mirror::Class* A = class_linker_->FindClass(soa.Self(), "LInterfaces$A;", class_loader);
- mirror::Class* B = class_linker_->FindClass(soa.Self(), "LInterfaces$B;", class_loader);
- EXPECT_TRUE(I->IsAssignableFrom(A));
- EXPECT_TRUE(J->IsAssignableFrom(A));
- EXPECT_TRUE(J->IsAssignableFrom(K));
- EXPECT_TRUE(K->IsAssignableFrom(B));
- EXPECT_TRUE(J->IsAssignableFrom(B));
+ Handle<mirror::Class> I(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader)));
+ Handle<mirror::Class> J(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader)));
+ Handle<mirror::Class> K(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$K;", class_loader)));
+ Handle<mirror::Class> A(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$A;", class_loader)));
+ Handle<mirror::Class> B(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$B;", class_loader)));
+ EXPECT_TRUE(I->IsAssignableFrom(A.Get()));
+ EXPECT_TRUE(J->IsAssignableFrom(A.Get()));
+ EXPECT_TRUE(J->IsAssignableFrom(K.Get()));
+ EXPECT_TRUE(K->IsAssignableFrom(B.Get()));
+ EXPECT_TRUE(J->IsAssignableFrom(B.Get()));
const Signature void_sig = I->GetDexCache()->GetDexFile()->CreateSignature("()V");
mirror::ArtMethod* Ii = I->FindVirtualMethod("i", void_sig);
@@ -1029,10 +1028,14 @@
EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1));
EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
- mirror::ArtField* Afoo = A->FindStaticField("foo", "Ljava/lang/String;");
- mirror::ArtField* Bfoo = B->FindStaticField("foo", "Ljava/lang/String;");
- mirror::ArtField* Jfoo = J->FindStaticField("foo", "Ljava/lang/String;");
- mirror::ArtField* Kfoo = K->FindStaticField("foo", "Ljava/lang/String;");
+ mirror::ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo",
+ "Ljava/lang/String;");
+ mirror::ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo",
+ "Ljava/lang/String;");
+ mirror::ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo",
+ "Ljava/lang/String;");
+ mirror::ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo",
+ "Ljava/lang/String;");
ASSERT_TRUE(Afoo != NULL);
EXPECT_EQ(Afoo, Bfoo);
EXPECT_EQ(Afoo, Jfoo);
@@ -1106,9 +1109,8 @@
ScopedObjectAccess soa(Thread::Current());
for (int i = 0; i < ClassLinker::kClassRootsMax; i++) {
mirror::Class* klass = class_linker_->GetClassRoot(ClassLinker::ClassRoot(i));
- ClassHelper kh(klass);
- EXPECT_TRUE(kh.GetDescriptor() != NULL);
- EXPECT_STREQ(kh.GetDescriptor(),
+ EXPECT_TRUE(!klass->GetDescriptor().empty());
+ EXPECT_STREQ(klass->GetDescriptor().c_str(),
class_linker_->GetClassRootDescriptor(ClassLinker::ClassRoot(i))) << " i = " << i;
}
}
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 315f274..a3e3cfa 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -36,8 +36,7 @@
static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (referrer != NULL) {
- ClassHelper kh(referrer);
- std::string location(kh.GetLocation());
+ std::string location(referrer->GetLocation());
if (!location.empty()) {
os << " (declaration of '" << PrettyDescriptor(referrer)
<< "' appears in " << location << ")";
@@ -297,10 +296,9 @@
void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
const StringPiece& type, const StringPiece& name)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper kh(c);
std::ostringstream msg;
msg << "No " << scope << "field " << name << " of type " << type
- << " in class " << kh.GetDescriptor() << " or its superclasses";
+ << " in class " << c->GetDescriptor() << " or its superclasses";
ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
}
@@ -309,9 +307,8 @@
void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
const Signature& signature) {
std::ostringstream msg;
- ClassHelper kh(c);
msg << "No " << type << " method " << name << signature
- << " in class " << kh.GetDescriptor() << " or its super classes";
+ << " in class " << c->GetDescriptor() << " or its super classes";
ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
}
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index f6b4891..2cbff79 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -756,7 +756,7 @@
if (!o->IsClass()) {
return StringPrintf("non-class %p", o); // This is only used for debugging output anyway.
}
- return DescriptorToName(ClassHelper(o->AsClass()).GetDescriptor());
+ return DescriptorToName(o->AsClass()->GetDescriptor().c_str());
}
JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id) {
@@ -1088,7 +1088,7 @@
}
if (pDescriptor != NULL) {
- *pDescriptor = ClassHelper(c).GetDescriptor();
+ *pDescriptor = c->GetDescriptor();
}
return JDWP::ERR_NONE;
}
@@ -1124,7 +1124,7 @@
if (c == NULL) {
return status;
}
- *signature = ClassHelper(c).GetDescriptor();
+ *signature = c->GetDescriptor();
return JDWP::ERR_NONE;
}
@@ -1137,7 +1137,7 @@
if (c->IsProxyClass()) {
return JDWP::ERR_ABSENT_INFORMATION;
}
- result = ClassHelper(c).GetSourceFile();
+ result = c->GetSourceFile();
return JDWP::ERR_NONE;
}
@@ -1202,7 +1202,7 @@
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return JDWP::ERR_INVALID_LENGTH;
}
- std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
+ std::string descriptor(a->GetClass()->GetDescriptor());
JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
expandBufAdd1(pReply, tag);
@@ -1264,9 +1264,8 @@
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return JDWP::ERR_INVALID_LENGTH;
}
- ClassHelper ch(dst->GetClass());
- const char* descriptor = ch.GetDescriptor();
- JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor + 1);
+ std::string descriptor = dst->GetClass()->GetDescriptor();
+ JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
if (IsPrimitiveTag(tag)) {
size_t width = GetTagWidth(tag);
@@ -1497,16 +1496,17 @@
JDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
JDWP::JdwpError status;
- mirror::Class* c = DecodeClass(class_id, status);
- if (c == NULL) {
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> c(hs.NewHandle(DecodeClass(class_id, status)));
+ if (c.Get() == nullptr) {
return status;
}
-
- ClassHelper kh(c);
- size_t interface_count = kh.NumDirectInterfaces();
+ size_t interface_count = c->NumDirectInterfaces();
expandBufAdd4BE(pReply, interface_count);
for (size_t i = 0; i < interface_count; ++i) {
- expandBufAddRefTypeId(pReply, gRegistry->AddRefType(kh.GetDirectInterface(i)));
+ expandBufAddRefTypeId(pReply,
+ gRegistry->AddRefType(mirror::Class::GetDirectInterface(self, c, i)));
}
return JDWP::ERR_NONE;
}
@@ -2592,8 +2592,7 @@
// since the class may not yet be verified.
int state = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
JDWP::JdwpTypeTag tag = GetTypeTag(c);
- gJdwpState->PostClassPrepare(tag, gRegistry->Add(c),
- ClassHelper(c).GetDescriptor(), state);
+ gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), c->GetDescriptor(), state);
}
void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
@@ -4357,7 +4356,7 @@
while (count--) {
AllocRecord* record = &recent_allocation_records_[idx];
- class_names.Add(ClassHelper(record->type).GetDescriptor());
+ class_names.Add(record->type->GetDescriptor().c_str());
MethodHelper mh;
for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
@@ -4411,8 +4410,8 @@
// (1b) stack depth
AllocRecord* record = &recent_allocation_records_[idx];
size_t stack_depth = record->GetDepth();
- ClassHelper kh(record->type);
- size_t allocated_object_class_name_index = class_names.IndexOf(kh.GetDescriptor());
+ size_t allocated_object_class_name_index =
+ class_names.IndexOf(record->type->GetDescriptor().c_str());
JDWP::Append4BE(bytes, record->byte_count);
JDWP::Append2BE(bytes, record->thin_lock_id);
JDWP::Append2BE(bytes, allocated_object_class_name_index);
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 6998e21..bfcb58f 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -737,11 +737,6 @@
return reinterpret_cast<void*>(art_quick_to_interpreter_bridge);
}
-extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
-static inline const void* GetQuickGenericJniTrampoline() {
- return reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
-}
-
static inline const void* GetQuickToPortableBridge() {
// TODO: quick to portable bridge. Bug: 8196384
return GetQuickToInterpreterBridge();
@@ -763,10 +758,6 @@
return class_linker->GetQuickImtConflictTrampoline();
}
-static inline const void* GetQuickGenericJniTrampoline(ClassLinker* class_linker) {
- return class_linker->GetQuickGenericJniTrampoline();
-}
-
static inline const void* GetQuickToInterpreterBridgeTrampoline(ClassLinker* class_linker) {
return class_linker->GetQuickToInterpreterBridgeTrampoline();
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b4c2d14..ef31be3 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2765,7 +2765,7 @@
void Heap::CheckPreconditionsForAllocObject(mirror::Class* c, size_t byte_count) {
CHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) ||
(c->IsVariableSize() || c->GetObjectSize() == byte_count) ||
- strlen(ClassHelper(c).GetDescriptor()) == 0);
+ c->GetDescriptor().empty());
CHECK_GE(byte_count, sizeof(mirror::Object));
}
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/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 20e2b8d..478c74c 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -49,7 +49,8 @@
value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
result->SetD(log(value.GetD()));
} else if (name == "java.lang.String java.lang.Class.getNameNative()") {
- result->SetL(receiver->AsClass()->ComputeName());
+ StackHandleScope<1> hs(self);
+ result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
} else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
result->SetI(args[0]);
} else if (name == "float java.lang.Float.intBitsToFloat(int)") {
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index c5fb0d8..418aff5 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -117,8 +117,8 @@
"Ljava/lang/VirtualMachineError;",
"Invoking %s with bad arg %d, type '%s' not instance of '%s'",
mh.GetName(), shorty_pos,
- ClassHelper(o->GetClass()).GetDescriptor(),
- ClassHelper(arg_type).GetDescriptor());
+ o->GetClass()->GetDescriptor().c_str(),
+ arg_type->GetDescriptor().c_str());
return false;
}
}
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 9b03334..0c7c8a9 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -345,9 +345,9 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Put '%s' that is not instance of field '%s' in '%s'",
- ClassHelper(reg->GetClass()).GetDescriptor(),
- ClassHelper(field_class).GetDescriptor(),
- ClassHelper(f->GetDeclaringClass()).GetDescriptor());
+ reg->GetClass()->GetDescriptor().c_str(),
+ field_class->GetDescriptor().c_str(),
+ f->GetDeclaringClass()->GetDescriptor().c_str());
return false;
}
}
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 5b7dee1d..e0f9e5f 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -342,8 +342,8 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Returning '%s' that is not instance of return type '%s'",
- ClassHelper(obj_result->GetClass()).GetDescriptor(),
- ClassHelper(return_type).GetDescriptor());
+ obj_result->GetClass()->GetDescriptor().c_str(),
+ return_type->GetDescriptor().c_str());
HANDLE_PENDING_EXCEPTION();
}
}
@@ -614,7 +614,7 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Throwing '%s' that is not instance of Throwable",
- ClassHelper(exception->GetClass()).GetDescriptor());
+ exception->GetClass()->GetDescriptor().c_str());
} else {
self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
}
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 859cfc4..c1d24f5 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -258,8 +258,8 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Returning '%s' that is not instance of return type '%s'",
- ClassHelper(obj_result->GetClass()).GetDescriptor(),
- ClassHelper(return_type).GetDescriptor());
+ obj_result->GetClass()->GetDescriptor().c_str(),
+ return_type->GetDescriptor().c_str());
HANDLE_PENDING_EXCEPTION();
}
}
@@ -528,7 +528,7 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Throwing '%s' that is not instance of Throwable",
- ClassHelper(exception->GetClass()).GetDescriptor());
+ exception->GetClass()->GetDescriptor().c_str());
} else {
self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
}
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 3afb149..17a3de4 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -109,7 +109,7 @@
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchMethodError;",
"no %s method \"%s.%s%s\"",
- kind, ClassHelper(c).GetDescriptor(), name, sig);
+ kind, c->GetDescriptor().c_str(), name, sig);
}
static mirror::Class* EnsureInitialized(Thread* self, mirror::Class* klass)
@@ -206,20 +206,21 @@
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
"no type \"%s\" found and so no field \"%s\" "
"could be found in class \"%s\" or its superclasses", sig, name,
- ClassHelper(c.Get()).GetDescriptor());
+ c->GetDescriptor().c_str());
soa.Self()->GetException(nullptr)->SetCause(cause.Get());
return nullptr;
}
if (is_static) {
- field = c->FindStaticField(name, ClassHelper(field_type).GetDescriptor());
+ field = mirror::Class::FindStaticField(soa.Self(), c, name,
+ field_type->GetDescriptor().c_str());
} else {
- field = c->FindInstanceField(name, ClassHelper(field_type).GetDescriptor());
+ field = c->FindInstanceField(name, field_type->GetDescriptor().c_str());
}
if (field == nullptr) {
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
"no \"%s\" field \"%s\" in class \"%s\" or its superclasses",
- sig, name, ClassHelper(c.Get()).GetDescriptor());
+ sig, name, c->GetDescriptor().c_str());
return nullptr;
}
return soa.EncodeField(field);
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 5225919..ffafc85 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -47,8 +47,8 @@
}
#if defined(__LP64__) && !defined(__x86_64__)
-// Where to start with low memory allocation.
-static constexpr uintptr_t LOW_MEM_START = kPageSize * 2;
+// Where to start with low memory allocation. The first 64KB is protected by SELinux.
+static constexpr uintptr_t LOW_MEM_START = 64 * KB;
uintptr_t MemMap::next_mem_pos_ = LOW_MEM_START; // first page to check for low-mem extent
#endif
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index c3e2d22..cde977b 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -222,7 +222,7 @@
DCHECK(entry_point != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker()));
CHECK(entry_point != GetQuickToInterpreterBridge());
- if (UNLIKELY(entry_point == GetQuickGenericJniTrampoline())) {
+ if (UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) {
// Generic JNI frame.
DCHECK(IsNative());
uint32_t handle_refs = MethodHelper(this).GetNumberOfReferenceArgsWithoutReceiver() + 1;
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index d454ae8..b2d8288 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -21,9 +21,11 @@
#include "art_field.h"
#include "art_method.h"
+#include "class_linker-inl.h"
#include "class_loader.h"
#include "common_throws.h"
#include "dex_cache.h"
+#include "dex_file.h"
#include "gc/heap-inl.h"
#include "iftable.h"
#include "object_array-inl.h"
@@ -508,7 +510,7 @@
}
template<ReadBarrierOption kReadBarrierOption>
-bool Class::IsArtFieldClass() {
+inline bool Class::IsArtFieldClass() {
Class* java_lang_Class = GetClass<kVerifyNone, kReadBarrierOption>();
Class* java_lang_reflect_ArtField =
java_lang_Class->GetInstanceField(0)->GetClass<kVerifyNone, kReadBarrierOption>();
@@ -516,7 +518,7 @@
}
template<ReadBarrierOption kReadBarrierOption>
-bool Class::IsArtMethodClass() {
+inline bool Class::IsArtMethodClass() {
return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>();
}
@@ -527,6 +529,24 @@
return this == java_lang_Class;
}
+inline const DexFile& Class::GetDexFile() {
+ return *GetDexCache()->GetDexFile();
+}
+
+inline bool Class::DescriptorEquals(const char* match) {
+ if (UNLIKELY(IsArrayClass())) {
+ return match[0] == '[' && GetComponentType()->DescriptorEquals(match + 1);
+ } else if (UNLIKELY(IsPrimitive())) {
+ return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0;
+ } else if (UNLIKELY(IsProxyClass())) {
+ return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
+ } else {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
+ return strcmp(dex_file.GetTypeDescriptor(type_id), match) == 0;
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 15b69f3..4869b45 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -136,15 +136,13 @@
// Class.getName: keywords for primitive types, regular "[I" form for primitive arrays (so "int"
// but "[I"), and arrays of reference types written between "L" and ";" but with dots rather than
// slashes (so "java.lang.String" but "[Ljava.lang.String;"). Madness.
-String* Class::ComputeName() {
- String* name = GetName();
+String* Class::ComputeName(Handle<Class> h_this) {
+ String* name = h_this->GetName();
if (name != nullptr) {
return name;
}
+ std::string descriptor(h_this->GetDescriptor());
Thread* self = Thread::Current();
- StackHandleScope<1> hs(self);
- Handle<mirror::Class> handle_c(hs.NewHandle(this));
- std::string descriptor(ClassHelper(this).GetDescriptor());
if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
// The descriptor indicates that this is the class for
// a primitive type; special-case the return value.
@@ -173,7 +171,7 @@
std::replace(descriptor.begin(), descriptor.end(), '/', '.');
name = String::AllocFromModifiedUtf8(self, descriptor.c_str());
}
- handle_c->SetName(name);
+ h_this->SetName(name);
return name;
}
@@ -190,52 +188,59 @@
return;
}
- Class* super = GetSuperClass();
- ClassHelper kh(this);
+ Thread* self = Thread::Current();
+ StackHandleScope<2> hs(self);
+ Handle<mirror::Class> h_this(hs.NewHandle(this));
+ Handle<mirror::Class> h_super(hs.NewHandle(GetSuperClass()));
+
os << "----- " << (IsInterface() ? "interface" : "class") << " "
- << "'" << kh.GetDescriptor() << "' cl=" << GetClassLoader() << " -----\n",
+ << "'" << GetDescriptor() << "' cl=" << GetClassLoader() << " -----\n",
os << " objectSize=" << SizeOf() << " "
- << "(" << (super != NULL ? super->SizeOf() : -1) << " from super)\n",
+ << "(" << (h_super.Get() != NULL ? h_super->SizeOf() : -1) << " from super)\n",
os << StringPrintf(" access=0x%04x.%04x\n",
GetAccessFlags() >> 16, GetAccessFlags() & kAccJavaFlagsMask);
- if (super != NULL) {
- os << " super='" << PrettyClass(super) << "' (cl=" << super->GetClassLoader() << ")\n";
+ if (h_super.Get() != NULL) {
+ os << " super='" << PrettyClass(h_super.Get()) << "' (cl=" << h_super->GetClassLoader()
+ << ")\n";
}
if (IsArrayClass()) {
os << " componentType=" << PrettyClass(GetComponentType()) << "\n";
}
- if (kh.NumDirectInterfaces() > 0) {
- os << " interfaces (" << kh.NumDirectInterfaces() << "):\n";
- for (size_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- Class* interface = kh.GetDirectInterface(i);
+ const size_t num_direct_interfaces = NumDirectInterfaces();
+ if (num_direct_interfaces > 0) {
+ os << " interfaces (" << num_direct_interfaces << "):\n";
+ for (size_t i = 0; i < num_direct_interfaces; ++i) {
+ Class* interface = GetDirectInterface(self, h_this, i);
const ClassLoader* cl = interface->GetClassLoader();
os << StringPrintf(" %2zd: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl);
}
}
- os << " vtable (" << NumVirtualMethods() << " entries, "
- << (super != NULL ? super->NumVirtualMethods() : 0) << " in super):\n";
+ // After this point, this may have moved due to GetDirectInterface.
+ os << " vtable (" << h_this->NumVirtualMethods() << " entries, "
+ << (h_super.Get() != NULL ? h_super->NumVirtualMethods() : 0) << " in super):\n";
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(GetVirtualMethodDuringLinking(i)).c_str());
+ os << StringPrintf(" %2zd: %s\n", i,
+ PrettyMethod(h_this->GetVirtualMethodDuringLinking(i)).c_str());
}
- os << " direct methods (" << NumDirectMethods() << " entries):\n";
- for (size_t i = 0; i < NumDirectMethods(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(GetDirectMethod(i)).c_str());
+ os << " direct methods (" << h_this->NumDirectMethods() << " entries):\n";
+ for (size_t i = 0; i < h_this->NumDirectMethods(); ++i) {
+ os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(h_this->GetDirectMethod(i)).c_str());
}
- if (NumStaticFields() > 0) {
- os << " static fields (" << NumStaticFields() << " entries):\n";
- if (IsResolved() || IsErroneous()) {
- for (size_t i = 0; i < NumStaticFields(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyField(GetStaticField(i)).c_str());
+ if (h_this->NumStaticFields() > 0) {
+ os << " static fields (" << h_this->NumStaticFields() << " entries):\n";
+ if (h_this->IsResolved() || h_this->IsErroneous()) {
+ for (size_t i = 0; i < h_this->NumStaticFields(); ++i) {
+ os << StringPrintf(" %2zd: %s\n", i, PrettyField(h_this->GetStaticField(i)).c_str());
}
} else {
os << " <not yet available>";
}
}
- if (NumInstanceFields() > 0) {
- os << " instance fields (" << NumInstanceFields() << " entries):\n";
- if (IsResolved() || IsErroneous()) {
- for (size_t i = 0; i < NumInstanceFields(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyField(GetInstanceField(i)).c_str());
+ if (h_this->NumInstanceFields() > 0) {
+ os << " instance fields (" << h_this->NumInstanceFields() << " entries):\n";
+ if (h_this->IsResolved() || h_this->IsErroneous()) {
+ for (size_t i = 0; i < h_this->NumInstanceFields(); ++i) {
+ os << StringPrintf(" %2zd: %s\n", i, PrettyField(h_this->GetInstanceField(i)).c_str());
}
} else {
os << " <not yet available>";
@@ -305,8 +310,7 @@
return true;
}
// Compare the package part of the descriptor string.
- return IsInSamePackage(ClassHelper(klass1).GetDescriptor(),
- ClassHelper(klass2).GetDescriptor());
+ return IsInSamePackage(klass1->GetDescriptor().c_str(), klass2->GetDescriptor().c_str());
}
bool Class::IsStringClass() const {
@@ -585,71 +589,82 @@
return NULL;
}
-ArtField* Class::FindStaticField(const StringPiece& name, const StringPiece& type) {
+ArtField* Class::FindStaticField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ const StringPiece& type) {
// Is the field in this class (or its interfaces), or any of its
// superclasses (or their interfaces)?
- for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
+ for (Class* k = klass.Get(); k != nullptr; k = k->GetSuperClass()) {
// Is the field in this class?
ArtField* f = k->FindDeclaredStaticField(name, type);
- if (f != NULL) {
+ if (f != nullptr) {
return f;
}
+ // Wrap k incase it moves during GetDirectInterface.
+ StackHandleScope<1> hs(self);
+ HandleWrapper<mirror::Class> h_k(hs.NewHandleWrapper(&k));
// Is this field in any of this class' interfaces?
- ClassHelper kh(k);
- for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- Class* interface = kh.GetDirectInterface(i);
- f = interface->FindStaticField(name, type);
- if (f != NULL) {
+ for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> interface(hs.NewHandle(GetDirectInterface(self, h_k, i)));
+ f = FindStaticField(self, interface, name, type);
+ if (f != nullptr) {
return f;
}
}
}
- return NULL;
+ return nullptr;
}
-ArtField* Class::FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) {
- for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
+ArtField* Class::FindStaticField(Thread* self, Handle<Class> klass, const DexCache* dex_cache,
+ uint32_t dex_field_idx) {
+ for (Class* k = klass.Get(); k != nullptr; k = k->GetSuperClass()) {
// Is the field in this class?
ArtField* f = k->FindDeclaredStaticField(dex_cache, dex_field_idx);
if (f != NULL) {
return f;
}
+ // Wrap k incase it moves during GetDirectInterface.
+ StackHandleScope<1> hs(self);
+ HandleWrapper<mirror::Class> h_k(hs.NewHandleWrapper(&k));
// Is this field in any of this class' interfaces?
- ClassHelper kh(k);
- for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- Class* interface = kh.GetDirectInterface(i);
- f = interface->FindStaticField(dex_cache, dex_field_idx);
- if (f != NULL) {
+ for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> interface(hs.NewHandle(GetDirectInterface(self, h_k, i)));
+ f = FindStaticField(self, interface, dex_cache, dex_field_idx);
+ if (f != nullptr) {
return f;
}
}
}
- return NULL;
+ return nullptr;
}
-ArtField* Class::FindField(const StringPiece& name, const StringPiece& type) {
+ArtField* Class::FindField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ const StringPiece& type) {
// Find a field using the JLS field resolution order
- for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
+ for (Class* k = klass.Get(); k != NULL; k = k->GetSuperClass()) {
// Is the field in this class?
ArtField* f = k->FindDeclaredInstanceField(name, type);
- if (f != NULL) {
+ if (f != nullptr) {
return f;
}
f = k->FindDeclaredStaticField(name, type);
- if (f != NULL) {
+ if (f != nullptr) {
return f;
}
// Is this field in any of this class' interfaces?
- ClassHelper kh(k);
- for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- Class* interface = kh.GetDirectInterface(i);
- f = interface->FindStaticField(name, type);
- if (f != NULL) {
+ StackHandleScope<1> hs(self);
+ HandleWrapper<mirror::Class> h_k(hs.NewHandleWrapper(&k));
+ for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> interface(hs.NewHandle(GetDirectInterface(self, h_k, i)));
+ f = interface->FindStaticField(self, interface, name, type);
+ if (f != nullptr) {
return f;
}
}
}
- return NULL;
+ return nullptr;
}
static void SetPreverifiedFlagOnMethods(mirror::ObjectArray<mirror::ArtMethod>* methods)
@@ -671,5 +686,111 @@
SetPreverifiedFlagOnMethods(GetVirtualMethods());
}
+std::string Class::GetDescriptor() {
+ if (UNLIKELY(IsArrayClass())) {
+ return GetArrayDescriptor();
+ } else if (UNLIKELY(IsPrimitive())) {
+ return Primitive::Descriptor(GetPrimitiveType());
+ } else if (UNLIKELY(IsProxyClass())) {
+ return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this);
+ } else {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
+ return dex_file.GetTypeDescriptor(type_id);
+ }
+}
+
+std::string Class::GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return "[" + GetComponentType()->GetDescriptor();
+}
+
+const DexFile::ClassDef* Class::GetClassDef() {
+ uint16_t class_def_idx = GetDexClassDefIndex();
+ if (class_def_idx == DexFile::kDexNoIndex16) {
+ return nullptr;
+ }
+ return &GetDexFile().GetClassDef(class_def_idx);
+}
+
+uint32_t Class::NumDirectInterfaces() {
+ if (IsPrimitive()) {
+ return 0;
+ } else if (IsArrayClass()) {
+ return 2;
+ } else if (IsProxyClass()) {
+ mirror::SynthesizedProxyClass* proxy_class=
+ reinterpret_cast<mirror::SynthesizedProxyClass*>(this);
+ mirror::ObjectArray<mirror::Class>* interfaces = proxy_class->GetInterfaces();
+ return interfaces != nullptr ? interfaces->GetLength() : 0;
+ } else {
+ const DexFile::TypeList* interfaces = GetInterfaceTypeList();
+ if (interfaces == nullptr) {
+ return 0;
+ } else {
+ return interfaces->Size();
+ }
+ }
+}
+
+uint16_t Class::GetDirectInterfaceTypeIdx(uint32_t idx) {
+ DCHECK(!IsPrimitive());
+ DCHECK(!IsArrayClass());
+ return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
+}
+
+mirror::Class* Class::GetDirectInterface(Thread* self, Handle<mirror::Class> klass, uint32_t idx) {
+ DCHECK(klass.Get() != nullptr);
+ DCHECK(!klass->IsPrimitive());
+ if (klass->IsArrayClass()) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ if (idx == 0) {
+ return class_linker->FindSystemClass(self, "Ljava/lang/Cloneable;");
+ } else {
+ DCHECK_EQ(1U, idx);
+ return class_linker->FindSystemClass(self, "Ljava/io/Serializable;");
+ }
+ } else if (klass->IsProxyClass()) {
+ mirror::SynthesizedProxyClass* proxy_class =
+ reinterpret_cast<mirror::SynthesizedProxyClass*>(klass.Get());
+ mirror::ObjectArray<mirror::Class>* interfaces = proxy_class->GetInterfaces();
+ DCHECK(interfaces != nullptr);
+ return interfaces->Get(idx);
+ } else {
+ uint16_t type_idx = klass->GetDirectInterfaceTypeIdx(idx);
+ mirror::Class* interface = klass->GetDexCache()->GetResolvedType(type_idx);
+ if (interface == nullptr) {
+ interface = Runtime::Current()->GetClassLinker()->ResolveType(klass->GetDexFile(), type_idx,
+ klass.Get());
+ CHECK(interface != nullptr || self->IsExceptionPending());
+ }
+ return interface;
+ }
+}
+
+const char* Class::GetSourceFile() {
+ std::string descriptor(GetDescriptor());
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::ClassDef* dex_class_def = GetClassDef();
+ CHECK(dex_class_def != nullptr) << "No class def for class " << PrettyClass(this);
+ return dex_file.GetSourceFile(*dex_class_def);
+}
+
+std::string Class::GetLocation() {
+ mirror::DexCache* dex_cache = GetDexCache();
+ if (dex_cache != nullptr && !IsProxyClass()) {
+ return dex_cache->GetLocation()->ToModifiedUtf8();
+ }
+ // Arrays and proxies are generated and have no corresponding dex file location.
+ return "generated class";
+}
+
+const DexFile::TypeList* Class::GetInterfaceTypeList() {
+ const DexFile::ClassDef* class_def = GetClassDef();
+ if (class_def == nullptr) {
+ return nullptr;
+ }
+ return GetDexFile().GetInterfacesList(*class_def);
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 92b999e..a283f60 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_MIRROR_CLASS_H_
#define ART_RUNTIME_MIRROR_CLASS_H_
+#include "dex_file.h"
#include "gc/allocator_type.h"
#include "invoke_type.h"
#include "modifiers.h"
@@ -274,7 +275,7 @@
String* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns the cached name.
void SetName(String* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Sets the cached name.
// Computes the name, then sets the cached value.
- String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static String* ComputeName(Handle<Class> h_this) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsProxyClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -776,7 +777,8 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find a static or instance field using the JLS resolution order
- ArtField* FindField(const StringPiece& name, const StringPiece& type)
+ static ArtField* FindField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ const StringPiece& type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Finds the given instance field in this class or a superclass.
@@ -795,12 +797,14 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Finds the given static field in this class or a superclass.
- ArtField* FindStaticField(const StringPiece& name, const StringPiece& type)
+ static ArtField* FindStaticField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ const StringPiece& type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Finds the given static field in this class or superclass, only searches classes that
// have the same dex cache.
- ArtField* FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx)
+ static ArtField* FindStaticField(Thread* self, Handle<Class> klass, const DexCache* dex_cache,
+ uint32_t dex_field_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ArtField* FindDeclaredStaticField(const StringPiece& name, const StringPiece& type)
@@ -857,6 +861,19 @@
void VisitReferences(mirror::Class* klass, const Visitor& visitor)
NO_THREAD_SAFETY_ANALYSIS;
+ std::string GetDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool DescriptorEquals(const char* match) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const DexFile::ClassDef* GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint16_t GetDirectInterfaceTypeIdx(uint32_t idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static mirror::Class* GetDirectInterface(Thread* self, Handle<mirror::Class> klass, uint32_t idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const DexFile::TypeList* GetInterfaceTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
void SetVerifyErrorClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index e0fd6a2..e24602a 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -104,7 +104,7 @@
TEST_F(ObjectTest, Clone) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<2> hs(soa.Self());
Handle<ObjectArray<Object>> a1(
hs.NewHandle(class_linker_->AllocObjectArray<Object>(soa.Self(), 256)));
size_t s1 = a1->SizeOf();
@@ -115,7 +115,7 @@
TEST_F(ObjectTest, AllocObjectArray) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<2> hs(soa.Self());
Handle<ObjectArray<Object> > oa(
hs.NewHandle(class_linker_->AllocObjectArray<Object>(soa.Self(), 2)));
EXPECT_EQ(2, oa->GetLength());
@@ -142,12 +142,12 @@
soa.Self()->ClearException();
ASSERT_TRUE(oa->GetClass() != NULL);
- ClassHelper oa_ch(oa->GetClass());
- ASSERT_EQ(2U, oa_ch.NumDirectInterfaces());
+ Handle<mirror::Class> klass(hs.NewHandle(oa->GetClass()));
+ ASSERT_EQ(2U, klass->NumDirectInterfaces());
EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;"),
- oa_ch.GetDirectInterface(0));
+ mirror::Class::GetDirectInterface(soa.Self(), klass, 0));
EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;"),
- oa_ch.GetDirectInterface(1));
+ mirror::Class::GetDirectInterface(soa.Self(), klass, 1));
}
TEST_F(ObjectTest, AllocArray) {
@@ -682,26 +682,31 @@
TEST_F(ObjectTest, FindStaticField) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<4> hs(soa.Self());
Handle<String> s(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
ASSERT_TRUE(s.Get() != NULL);
- Class* c = s->GetClass();
- ASSERT_TRUE(c != NULL);
+ Handle<Class> c(hs.NewHandle(s->GetClass()));
+ ASSERT_TRUE(c.Get() != NULL);
// Wrong type.
EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
- EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
+ EXPECT_TRUE(mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER", "I") == NULL);
// Wrong name.
EXPECT_TRUE(c->FindDeclaredStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
- EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
+ EXPECT_TRUE(
+ mirror::Class::FindStaticField(soa.Self(), c, "cASE_INSENSITIVE_ORDER",
+ "Ljava/util/Comparator;") == NULL);
// Right name and type.
- ArtField* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- ArtField* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- EXPECT_TRUE(f1 != NULL);
- EXPECT_TRUE(f2 != NULL);
- EXPECT_EQ(f1, f2);
+ Handle<ArtField> f1(hs.NewHandle(
+ c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;")));
+ Handle<ArtField> f2(hs.NewHandle(
+ mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER",
+ "Ljava/util/Comparator;")));
+ EXPECT_TRUE(f1.Get() != NULL);
+ EXPECT_TRUE(f2.Get() != NULL);
+ EXPECT_EQ(f1.Get(), f2.Get());
// TODO: test static fields via superclasses.
// TODO: test static fields via interfaces.
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/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 8d183da..69b05f4 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -262,12 +262,14 @@
}
const DexFile* dex_file = dex_cache->GetDexFile();
const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
- mirror::Class* klass = dex_cache->GetResolvedType(field_id.class_idx_);
- if (klass == NULL) {
+ Thread* const self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass(hs.NewHandle(dex_cache->GetResolvedType(field_id.class_idx_)));
+ if (klass.Get() == NULL) {
return;
}
if (is_static) {
- field = klass->FindStaticField(dex_cache.Get(), field_idx);
+ field = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx);
} else {
field = klass->FindInstanceField(dex_cache.Get(), field_idx);
}
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index b6cf7d8..e619dda 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -84,8 +84,9 @@
static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Class* c = DecodeClass(soa, javaThis);
- return soa.AddLocalReference<jstring>(c->ComputeName());
+ StackHandleScope<1> hs(soa.Self());
+ mirror::Class* const c = DecodeClass(soa, javaThis);
+ return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c)));
}
static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index 7c6f2f3..db77437 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -35,7 +35,7 @@
DCHECK(javaDimArray != NULL);
mirror::Object* dimensions_obj = soa.Decode<mirror::Object*>(javaDimArray);
DCHECK(dimensions_obj->IsArrayInstance());
- DCHECK_STREQ(ClassHelper(dimensions_obj->GetClass()).GetDescriptor(), "[I");
+ DCHECK_STREQ(dimensions_obj->GetClass()->GetDescriptor().c_str(), "[I");
Handle<mirror::IntArray> dimensions_array(
hs.NewHandle(down_cast<mirror::IntArray*>(dimensions_obj)));
mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(), element_class,
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 0dd6ca1..664ac89 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -38,201 +38,34 @@
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);
};
-class ClassHelper {
- public:
- explicit ClassHelper(mirror::Class* c )
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : interface_type_list_(nullptr), klass_(nullptr) {
- if (c != nullptr) {
- ChangeClass(c);
- }
- }
-
- void ChangeClass(mirror::Class* new_c)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(new_c != nullptr) << "klass_=" << klass_; // Log what we were changing from if any
- if (!new_c->IsClass()) {
- LOG(FATAL) << "new_c=" << new_c << " cc " << new_c->GetClass() << " ccc "
- << ((new_c->GetClass() != nullptr) ? new_c->GetClass()->GetClass() : nullptr);
- }
- klass_ = new_c;
- interface_type_list_ = nullptr;
- }
-
- // The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
- // If you need it longer, copy it into a std::string.
- const char* GetDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(klass_ != nullptr);
- if (UNLIKELY(klass_->IsArrayClass())) {
- return GetArrayDescriptor();
- } else if (UNLIKELY(klass_->IsPrimitive())) {
- return Primitive::Descriptor(klass_->GetPrimitiveType());
- } else if (UNLIKELY(klass_->IsProxyClass())) {
- descriptor_ = GetClassLinker()->GetDescriptorForProxy(klass_);
- return descriptor_.c_str();
- } else {
- const DexFile& dex_file = GetDexFile();
- const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
- return dex_file.GetTypeDescriptor(type_id);
- }
- }
-
- const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string result("[");
- mirror::Class* saved_klass = klass_;
- CHECK(saved_klass != nullptr);
- ChangeClass(klass_->GetComponentType());
- result += GetDescriptor();
- ChangeClass(saved_klass);
- descriptor_ = result;
- return descriptor_.c_str();
- }
-
- const DexFile::ClassDef* GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != nullptr);
- uint16_t class_def_idx = klass_->GetDexClassDefIndex();
- if (class_def_idx == DexFile::kDexNoIndex16) {
- return nullptr;
- }
- return &GetDexFile().GetClassDef(class_def_idx);
- }
-
- uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != nullptr);
- if (klass_->IsPrimitive()) {
- return 0;
- } else if (klass_->IsArrayClass()) {
- return 2;
- } else if (klass_->IsProxyClass()) {
- mirror::SynthesizedProxyClass* proxyClass = reinterpret_cast<mirror::SynthesizedProxyClass*>(klass_);
- mirror::ObjectArray<mirror::Class>* interfaces = proxyClass->GetInterfaces();
- return interfaces != nullptr ? interfaces->GetLength() : 0;
- } else {
- const DexFile::TypeList* interfaces = GetInterfaceTypeList();
- if (interfaces == nullptr) {
- return 0;
- } else {
- return interfaces->Size();
- }
- }
- }
-
- uint16_t GetDirectInterfaceTypeIdx(uint32_t idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != nullptr);
- DCHECK(!klass_->IsPrimitive());
- DCHECK(!klass_->IsArrayClass());
- return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
- }
-
- mirror::Class* GetDirectInterface(uint32_t idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != nullptr);
- DCHECK(!klass_->IsPrimitive());
- if (klass_->IsArrayClass()) {
- if (idx == 0) {
- return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/lang/Cloneable;");
- } else {
- DCHECK_EQ(1U, idx);
- return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/io/Serializable;");
- }
- } else if (klass_->IsProxyClass()) {
- mirror::SynthesizedProxyClass* proxyClass = reinterpret_cast<mirror::SynthesizedProxyClass*>(klass_);
- mirror::ObjectArray<mirror::Class>* interfaces = proxyClass->GetInterfaces();
- DCHECK(interfaces != nullptr);
- return interfaces->Get(idx);
- } else {
- uint16_t type_idx = GetDirectInterfaceTypeIdx(idx);
- mirror::Class* interface = GetDexCache()->GetResolvedType(type_idx);
- if (interface == nullptr) {
- interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
- CHECK(interface != nullptr || Thread::Current()->IsExceptionPending());
- }
- return interface;
- }
- }
-
- const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string descriptor(GetDescriptor());
- const DexFile& dex_file = GetDexFile();
- const DexFile::ClassDef* dex_class_def = GetClassDef();
- CHECK(dex_class_def != nullptr) << "No class def for class " << PrettyClass(klass_);
- return dex_file.GetSourceFile(*dex_class_def);
- }
-
- std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::DexCache* dex_cache = GetDexCache();
- if (dex_cache != nullptr && !klass_->IsProxyClass()) {
- return dex_cache->GetLocation()->ToModifiedUtf8();
- } else {
- // Arrays and proxies are generated and have no corresponding dex file location.
- return "generated class";
- }
- }
-
- const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return *GetDexCache()->GetDexFile();
- }
-
- mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return klass_->GetDexCache();
- }
-
- private:
- const DexFile::TypeList* GetInterfaceTypeList()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const DexFile::TypeList* result = interface_type_list_;
- if (result == nullptr) {
- const DexFile::ClassDef* class_def = GetClassDef();
- if (class_def != nullptr) {
- result = GetDexFile().GetInterfacesList(*class_def);
- interface_type_list_ = result;
- }
- }
- return result;
- }
-
- ClassLinker* GetClassLinker() ALWAYS_INLINE {
- return Runtime::Current()->GetClassLinker();
- }
-
- const DexFile::TypeList* interface_type_list_;
- mirror::Class* klass_;
- std::string descriptor_;
-
- DISALLOW_COPY_AND_ASSIGN(ClassHelper);
-};
-
class FieldHelper {
public:
FieldHelper() : field_(nullptr) {}
@@ -306,8 +139,7 @@
DCHECK(field_->IsStatic());
DCHECK_LT(field_index, 2U);
// 0 == Class[] interfaces; 1 == Class[][] throws;
- ClassHelper kh(field_->GetDeclaringClass());
- declaring_class_descriptor_ = kh.GetDescriptor();
+ declaring_class_descriptor_ = field_->GetDeclaringClass()->GetDescriptor();
return declaring_class_descriptor_.c_str();
}
const DexFile& dex_file = GetDexFile();
@@ -470,7 +302,7 @@
}
const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return ClassHelper(method_->GetDeclaringClass()).GetSourceFile();
+ return method_->GetDeclaringClass()->GetSourceFile();
}
uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 8517e34..f38fb21 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -107,30 +107,33 @@
TEST_F(ProxyTest, ProxyClassHelper) {
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("Interfaces");
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<4> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
- mirror::Class* I = class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader);
- mirror::Class* J = class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader);
- ASSERT_TRUE(I != nullptr);
- ASSERT_TRUE(J != nullptr);
- std::vector<mirror::Class*> interfaces;
- interfaces.push_back(I);
- interfaces.push_back(J);
+ Handle<mirror::Class> I(hs.NewHandle(
+ class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader)));
+ Handle<mirror::Class> J(hs.NewHandle(
+ class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader)));
+ ASSERT_TRUE(I.Get() != nullptr);
+ ASSERT_TRUE(J.Get() != nullptr);
- mirror::Class* proxyClass = GenerateProxyClass(soa, jclass_loader, "$Proxy1234", interfaces);
- ASSERT_TRUE(proxyClass != nullptr);
- ASSERT_TRUE(proxyClass->IsProxyClass());
- ASSERT_TRUE(proxyClass->IsInitialized());
+ std::vector<mirror::Class*> interfaces;
+ interfaces.push_back(I.Get());
+ interfaces.push_back(J.Get());
+ Handle<mirror::Class> proxy_class(hs.NewHandle(
+ GenerateProxyClass(soa, jclass_loader, "$Proxy1234", interfaces)));
+ interfaces.clear(); // Don't least possibly stale objects in the array as good practice.
+ ASSERT_TRUE(proxy_class.Get() != nullptr);
+ ASSERT_TRUE(proxy_class->IsProxyClass());
+ ASSERT_TRUE(proxy_class->IsInitialized());
// Check ClassHelper for proxy.
- ClassHelper kh(proxyClass);
- EXPECT_EQ(kh.NumDirectInterfaces(), 2U); // Interfaces$I and Interfaces$J.
- EXPECT_EQ(I, kh.GetDirectInterface(0));
- EXPECT_EQ(J, kh.GetDirectInterface(1));
- std::string proxyClassDescriptor(kh.GetDescriptor());
- EXPECT_EQ("L$Proxy1234;", proxyClassDescriptor);
+ EXPECT_EQ(proxy_class->NumDirectInterfaces(), 2U); // Interfaces$I and Interfaces$J.
+ EXPECT_EQ(I.Get(), mirror::Class::GetDirectInterface(soa.Self(), proxy_class, 0));
+ EXPECT_EQ(J.Get(), mirror::Class::GetDirectInterface(soa.Self(), proxy_class, 1));
+ std::string proxy_class_descriptor(proxy_class->GetDescriptor());
+ EXPECT_STREQ("L$Proxy1234;", proxy_class_descriptor.c_str());
}
// Creates a proxy class and check FieldHelper works correctly.
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 98310e6..cbd66a6 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -242,22 +242,21 @@
}
#define DO_FIRST_ARG(match_descriptor, get_fn, append) { \
- const StringPiece src_descriptor(arg != nullptr \
- ? ClassHelper(arg->GetClass<>()).GetDescriptor() \
- : "null"); \
- if (LIKELY(src_descriptor == match_descriptor)) { \
+ if (LIKELY(arg != nullptr && arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
mirror::ArtField* primitive_field = arg->GetClass()->GetIFields()->Get(0); \
append(primitive_field-> get_fn(arg));
#define DO_ARG(match_descriptor, get_fn, append) \
- } else if (LIKELY(src_descriptor == match_descriptor)) { \
+ } else if (LIKELY(arg != nullptr && \
+ arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
mirror::ArtField* primitive_field = arg->GetClass()->GetIFields()->Get(0); \
append(primitive_field-> get_fn(arg));
#define DO_FAIL(expected) \
} else { \
if (arg->GetClass<>()->IsPrimitive()) { \
- ThrowIllegalPrimitiveArgumentException(expected, src_descriptor); \
+ ThrowIllegalPrimitiveArgumentException(expected, \
+ arg->GetClass<>()->GetDescriptor().c_str()); \
} else { \
ThrowIllegalArgumentException(nullptr, \
StringPrintf("method %s argument %zd has type %s, got %s", \
@@ -742,32 +741,32 @@
}
JValue boxed_value;
- const StringPiece src_descriptor(ClassHelper(o->GetClass()).GetDescriptor());
+ mirror::Class* klass = o->GetClass();
mirror::Class* src_class = nullptr;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0);
- if (src_descriptor == "Ljava/lang/Boolean;") {
+ if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
src_class = class_linker->FindPrimitiveClass('Z');
boxed_value.SetZ(primitive_field->GetBoolean(o));
- } else if (src_descriptor == "Ljava/lang/Byte;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) {
src_class = class_linker->FindPrimitiveClass('B');
boxed_value.SetB(primitive_field->GetByte(o));
- } else if (src_descriptor == "Ljava/lang/Character;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Character;")) {
src_class = class_linker->FindPrimitiveClass('C');
boxed_value.SetC(primitive_field->GetChar(o));
- } else if (src_descriptor == "Ljava/lang/Float;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Float;")) {
src_class = class_linker->FindPrimitiveClass('F');
boxed_value.SetF(primitive_field->GetFloat(o));
- } else if (src_descriptor == "Ljava/lang/Double;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Double;")) {
src_class = class_linker->FindPrimitiveClass('D');
boxed_value.SetD(primitive_field->GetDouble(o));
- } else if (src_descriptor == "Ljava/lang/Integer;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) {
src_class = class_linker->FindPrimitiveClass('I');
boxed_value.SetI(primitive_field->GetInt(o));
- } else if (src_descriptor == "Ljava/lang/Long;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Long;")) {
src_class = class_linker->FindPrimitiveClass('J');
boxed_value.SetJ(primitive_field->GetLong(o));
- } else if (src_descriptor == "Ljava/lang/Short;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Short;")) {
src_class = class_linker->FindPrimitiveClass('S');
boxed_value.SetS(primitive_field->GetShort(o));
} else {
@@ -775,7 +774,7 @@
StringPrintf("%s has type %s, got %s",
UnboxingFailureKind(f).c_str(),
PrettyDescriptor(dst_class).c_str(),
- PrettyDescriptor(src_descriptor.data()).c_str()).c_str());
+ PrettyDescriptor(o->GetClass()->GetDescriptor()).c_str()).c_str());
return false;
}
diff --git a/runtime/stack.h b/runtime/stack.h
index 963983a..2e32f51 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -306,6 +306,11 @@
return method_;
}
+ mirror::ArtMethod** GetMethodAddress() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(method_ != nullptr);
+ return &method_;
+ }
+
mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -389,12 +394,7 @@
#endif
// Link to previous shadow frame or NULL.
ShadowFrame* link_;
-#if defined(ART_USE_PORTABLE_COMPILER)
- // TODO: make const in the portable case.
mirror::ArtMethod* method_;
-#else
- mirror::ArtMethod* const method_;
-#endif
uint32_t dex_pc_;
uint32_t vregs_[0];
@@ -518,6 +518,16 @@
}
}
+ mirror::ArtMethod** GetMethodAddress() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (cur_shadow_frame_ != nullptr) {
+ return cur_shadow_frame_->GetMethodAddress();
+ } else if (cur_quick_frame_ != nullptr) {
+ return cur_quick_frame_;
+ } else {
+ return nullptr;
+ }
+ }
+
bool IsShadowFrame() const {
return cur_shadow_frame_ != nullptr;
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index d535118..488961e 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();
}
}
@@ -1962,7 +1962,10 @@
}
void VisitShadowFrame(ShadowFrame* shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = shadow_frame->GetMethod();
+ mirror::ArtMethod** method_addr = shadow_frame->GetMethodAddress();
+ visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
+ mirror::ArtMethod* m = *method_addr;
+ DCHECK(m != nullptr);
size_t num_regs = shadow_frame->NumberOfVRegs();
if (m->IsNative() || shadow_frame->HasReferenceArray()) {
// handle scope for JNI or References for interpreter.
@@ -2003,7 +2006,9 @@
private:
void VisitQuickFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = GetMethod();
+ mirror::ArtMethod** method_addr = GetMethodAddress();
+ visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
+ mirror::ArtMethod* m = *method_addr;
// Process register map (which native and runtime methods don't have)
if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) {
const uint8_t* native_gc_map = m->GetNativeGcMap();
diff --git a/runtime/utils.cc b/runtime/utils.cc
index f26b598..ad0175a 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -230,7 +230,7 @@
if (klass == NULL) {
return "null";
}
- return PrettyDescriptor(ClassHelper(klass).GetDescriptor());
+ return PrettyDescriptor(klass->GetDescriptor());
}
std::string PrettyDescriptor(const std::string& descriptor) {
@@ -412,11 +412,9 @@
if (obj->GetClass() == NULL) {
return "(raw)";
}
- ClassHelper kh(obj->GetClass());
- std::string result(PrettyDescriptor(kh.GetDescriptor()));
+ std::string result(PrettyDescriptor(obj->GetClass()->GetDescriptor()));
if (obj->IsClass()) {
- kh.ChangeClass(obj->AsClass());
- result += "<" + PrettyDescriptor(kh.GetDescriptor()) + ">";
+ result += "<" + PrettyDescriptor(obj->AsClass()->GetDescriptor()) + ">";
}
return result;
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9dd366d..0a31f63 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -93,11 +93,10 @@
}
bool early_failure = false;
std::string failure_message;
- ClassHelper kh(klass);
- const DexFile& dex_file = kh.GetDexFile();
- const DexFile::ClassDef* class_def = kh.GetClassDef();
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::ClassDef* class_def = klass->GetClassDef();
mirror::Class* super = klass->GetSuperClass();
- if (super == NULL && strcmp("Ljava/lang/Object;", kh.GetDescriptor()) != 0) {
+ if (super == NULL && "Ljava/lang/Object;" != klass->GetDescriptor()) {
early_failure = true;
failure_message = " that has no super class";
} else if (super != NULL && super->IsFinal()) {
@@ -116,7 +115,7 @@
return kHardFailure;
}
StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(kh.GetDexCache()));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
return VerifyClass(&dex_file, dex_cache, class_loader, class_def, allow_soft_failures, error);
}
@@ -3057,7 +3056,7 @@
if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
mirror::Class* klass = res_method->GetDeclaringClass();
const RegType& res_method_class =
- reg_types_.FromClass(ClassHelper(klass).GetDescriptor(), klass,
+ reg_types_.FromClass(klass->GetDescriptor().c_str(), klass,
klass->CannotBeAssignedFromOtherTypes());
if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS:
@@ -3182,7 +3181,7 @@
if (!actual_arg_type.IsZero()) {
mirror::Class* klass = res_method->GetDeclaringClass();
const RegType& res_method_class =
- reg_types_.FromClass(ClassHelper(klass).GetDescriptor(), klass,
+ reg_types_.FromClass(klass->GetDescriptor().c_str(), klass,
klass->CannotBeAssignedFromOtherTypes());
if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index c6f3e5c..8df1e5d 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -621,7 +621,7 @@
if (super_klass != NULL) {
// A super class of a precise type isn't precise as a precise type indicates the register
// holds exactly that type.
- return cache->FromClass(ClassHelper(super_klass).GetDescriptor(), super_klass, false);
+ return cache->FromClass(super_klass->GetDescriptor().c_str(), super_klass, false);
} else {
return cache->Zero();
}
@@ -899,7 +899,7 @@
} else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
return incoming_type;
} else {
- return reg_types->FromClass(ClassHelper(join_class).GetDescriptor(), join_class, false);
+ return reg_types->FromClass(join_class->GetDescriptor().c_str(), join_class, false);
}
}
} else {
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 689a33e..ff9edbb 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -567,7 +567,7 @@
return FromDescriptor(loader, component.c_str(), false);
} else {
mirror::Class* klass = array.GetClass()->GetComponentType();
- return FromClass(ClassHelper(klass).GetDescriptor(), klass,
+ return FromClass(klass->GetDescriptor().c_str(), klass,
klass->CannotBeAssignedFromOtherTypes());
}
}