Merge "ART: Fix Trace types, check minimum buf size"
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 7d76795..5a3236d 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -244,6 +244,7 @@
COMPILER_GTEST_HOST_SRC_FILES := \
$(COMPILER_GTEST_COMMON_SRC_FILES) \
+ compiler/dex/quick/x86/quick_assemble_x86_test.cc \
compiler/utils/arm/assembler_arm32_test.cc \
compiler/utils/arm/assembler_thumb2_test.cc \
compiler/utils/assembler_thumb_test.cc \
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 7f9698b..7bfbb34 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -1451,6 +1451,7 @@
friend class TopologicalSortOrderTest;
friend class TypeInferenceTest;
friend class QuickCFITest;
+ friend class QuickAssembleX86TestBase;
};
} // namespace art
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index eb33357..934fa35 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -409,7 +409,7 @@
EXT_0F_ENCODING_MAP(Paddq, 0x66, 0xD4, REG_DEF0_USE0),
EXT_0F_ENCODING_MAP(Psadbw, 0x66, 0xF6, REG_DEF0_USE0),
EXT_0F_ENCODING_MAP(Addps, 0x00, 0x58, REG_DEF0_USE0),
- EXT_0F_ENCODING_MAP(Addpd, 0xF2, 0x58, REG_DEF0_USE0),
+ EXT_0F_ENCODING_MAP(Addpd, 0x66, 0x58, REG_DEF0_USE0),
EXT_0F_ENCODING_MAP(Psubb, 0x66, 0xF8, REG_DEF0_USE0),
EXT_0F_ENCODING_MAP(Psubw, 0x66, 0xF9, REG_DEF0_USE0),
EXT_0F_ENCODING_MAP(Psubd, 0x66, 0xFA, REG_DEF0_USE0),
@@ -1627,13 +1627,13 @@
* instruction. In those cases we will try to substitute a new code
* sequence or request that the trace be shortened and retried.
*/
-AssemblerStatus X86Mir2Lir::AssembleInstructions(CodeOffset start_addr) {
+AssemblerStatus X86Mir2Lir::AssembleInstructions(LIR* first_lir_insn, CodeOffset start_addr) {
UNUSED(start_addr);
LIR *lir;
AssemblerStatus res = kSuccess; // Assume success
const bool kVerbosePcFixup = false;
- for (lir = first_lir_insn_; lir != nullptr; lir = NEXT_LIR(lir)) {
+ for (lir = first_lir_insn; lir != nullptr; lir = NEXT_LIR(lir)) {
if (IsPseudoLirOp(lir->opcode)) {
continue;
}
@@ -2034,7 +2034,7 @@
*/
while (true) {
- AssemblerStatus res = AssembleInstructions(0);
+ AssemblerStatus res = AssembleInstructions(first_lir_insn_, 0);
if (res == kSuccess) {
break;
} else {
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 72580a3..5a46520 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -432,7 +432,7 @@
int AssignInsnOffsets();
void AssignOffsets();
- AssemblerStatus AssembleInstructions(CodeOffset start_addr);
+ AssemblerStatus AssembleInstructions(LIR* first_lir_insn, CodeOffset start_addr);
size_t ComputeSize(const X86EncodingMap* entry, int32_t raw_reg, int32_t raw_index,
int32_t raw_base, int32_t displacement);
@@ -972,6 +972,9 @@
static const X86EncodingMap EncodingMap[kX86Last];
friend std::ostream& operator<<(std::ostream& os, const X86OpCode& rhs);
+ friend class QuickAssembleX86Test;
+ friend class QuickAssembleX86MacroTest;
+ friend class QuickAssembleX86LowLevelTest;
DISALLOW_COPY_AND_ASSIGN(X86Mir2Lir);
};
diff --git a/compiler/dex/quick/x86/quick_assemble_x86_test.cc b/compiler/dex/quick/x86/quick_assemble_x86_test.cc
new file mode 100644
index 0000000..36339f7
--- /dev/null
+++ b/compiler/dex/quick/x86/quick_assemble_x86_test.cc
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dex/quick/quick_compiler.h"
+#include "dex/pass_manager.h"
+#include "dex/verification_results.h"
+#include "dex/quick/dex_file_to_method_inliner_map.h"
+#include "runtime/dex_file.h"
+#include "driver/compiler_options.h"
+#include "driver/compiler_driver.h"
+#include "codegen_x86.h"
+#include "gtest/gtest.h"
+#include "utils/assembler_test_base.h"
+
+namespace art {
+
+class QuickAssembleX86TestBase : public testing::Test {
+ protected:
+ X86Mir2Lir* Prepare(InstructionSet target) {
+ isa_ = target;
+ pool_.reset(new ArenaPool());
+ compiler_options_.reset(new CompilerOptions(
+ CompilerOptions::kDefaultCompilerFilter,
+ CompilerOptions::kDefaultHugeMethodThreshold,
+ CompilerOptions::kDefaultLargeMethodThreshold,
+ CompilerOptions::kDefaultSmallMethodThreshold,
+ CompilerOptions::kDefaultTinyMethodThreshold,
+ CompilerOptions::kDefaultNumDexMethodsThreshold,
+ false,
+ CompilerOptions::kDefaultTopKProfileThreshold,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ nullptr,
+ new PassManagerOptions(),
+ nullptr,
+ false));
+ verification_results_.reset(new VerificationResults(compiler_options_.get()));
+ method_inliner_map_.reset(new DexFileToMethodInlinerMap());
+ compiler_driver_.reset(new CompilerDriver(
+ compiler_options_.get(),
+ verification_results_.get(),
+ method_inliner_map_.get(),
+ Compiler::kQuick,
+ isa_,
+ nullptr,
+ false,
+ nullptr,
+ nullptr,
+ nullptr,
+ 0,
+ false,
+ false,
+ "",
+ 0,
+ -1,
+ ""));
+ cu_.reset(new CompilationUnit(pool_.get(), isa_, compiler_driver_.get(), nullptr));
+ DexFile::CodeItem* code_item = static_cast<DexFile::CodeItem*>(
+ cu_->arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc));
+ memset(code_item, 0, sizeof(DexFile::CodeItem));
+ cu_->mir_graph.reset(new MIRGraph(cu_.get(), &cu_->arena));
+ cu_->mir_graph->current_code_item_ = code_item;
+ cu_->cg.reset(QuickCompiler::GetCodeGenerator(cu_.get(), nullptr));
+
+ test_helper_.reset(new AssemblerTestInfrastructure(
+ isa_ == kX86 ? "x86" : "x86_64",
+ "as",
+ isa_ == kX86 ? " --32" : "",
+ "objdump",
+ " -h",
+ "objdump",
+ isa_ == kX86 ?
+ " -D -bbinary -mi386 --no-show-raw-insn" :
+ " -D -bbinary -mi386:x86-64 -Mx86-64,addr64,data32 --no-show-raw-insn",
+ nullptr));
+
+ X86Mir2Lir* m2l = static_cast<X86Mir2Lir*>(cu_->cg.get());
+ m2l->CompilerInitializeRegAlloc();
+ return m2l;
+ }
+
+ void Release() {
+ cu_.reset();
+ compiler_driver_.reset();
+ method_inliner_map_.reset();
+ verification_results_.reset();
+ compiler_options_.reset();
+ pool_.reset();
+
+ test_helper_.reset();
+ }
+
+ void TearDown() OVERRIDE {
+ Release();
+ }
+
+ bool CheckTools(InstructionSet target) {
+ Prepare(target);
+ bool result = test_helper_->CheckTools();
+ Release();
+ return result;
+ }
+
+ std::unique_ptr<CompilationUnit> cu_;
+ std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
+
+ private:
+ InstructionSet isa_;
+ std::unique_ptr<ArenaPool> pool_;
+ std::unique_ptr<CompilerOptions> compiler_options_;
+ std::unique_ptr<VerificationResults> verification_results_;
+ std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
+ std::unique_ptr<CompilerDriver> compiler_driver_;
+};
+
+class QuickAssembleX86LowLevelTest : public QuickAssembleX86TestBase {
+ protected:
+ void Test(InstructionSet target, std::string test_name, std::string gcc_asm,
+ int opcode, int op0 = 0, int op1 = 0, int op2 = 0, int op3 = 0, int op4 = 0) {
+ X86Mir2Lir* m2l = Prepare(target);
+
+ LIR lir;
+ memset(&lir, 0, sizeof(LIR));
+ lir.opcode = opcode;
+ lir.operands[0] = op0;
+ lir.operands[1] = op1;
+ lir.operands[2] = op2;
+ lir.operands[3] = op3;
+ lir.operands[4] = op4;
+ lir.flags.size = m2l->GetInsnSize(&lir);
+
+ AssemblerStatus status = m2l->AssembleInstructions(&lir, 0);
+ // We don't expect a retry.
+ ASSERT_EQ(status, AssemblerStatus::kSuccess);
+
+ // Need a "base" std::vector.
+ std::vector<uint8_t> buffer(m2l->code_buffer_.begin(), m2l->code_buffer_.end());
+ test_helper_->Driver(buffer, gcc_asm, test_name);
+
+ Release();
+ }
+};
+
+TEST_F(QuickAssembleX86LowLevelTest, Addpd) {
+ Test(kX86, "Addpd", "addpd %xmm1, %xmm0\n", kX86AddpdRR,
+ RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
+ Test(kX86_64, "Addpd", "addpd %xmm1, %xmm0\n", kX86AddpdRR,
+ RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
+}
+
+TEST_F(QuickAssembleX86LowLevelTest, Subpd) {
+ Test(kX86, "Subpd", "subpd %xmm1, %xmm0\n", kX86SubpdRR,
+ RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
+ Test(kX86_64, "Subpd", "subpd %xmm1, %xmm0\n", kX86SubpdRR,
+ RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
+}
+
+TEST_F(QuickAssembleX86LowLevelTest, Mulpd) {
+ Test(kX86, "Mulpd", "mulpd %xmm1, %xmm0\n", kX86MulpdRR,
+ RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
+ Test(kX86_64, "Mulpd", "mulpd %xmm1, %xmm0\n", kX86MulpdRR,
+ RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
+}
+
+class QuickAssembleX86MacroTest : public QuickAssembleX86TestBase {
+ protected:
+ typedef void (X86Mir2Lir::*AsmFn)(MIR*);
+
+ void TestVectorFn(InstructionSet target,
+ Instruction::Code opcode,
+ AsmFn f,
+ std::string inst_string) {
+ X86Mir2Lir *m2l = Prepare(target);
+
+ // Create a vector MIR.
+ MIR* mir = cu_->mir_graph->NewMIR();
+ mir->dalvikInsn.opcode = opcode;
+ mir->dalvikInsn.vA = 0; // Destination and source.
+ mir->dalvikInsn.vB = 1; // Source.
+ int vector_size = 128;
+ int vector_type = kDouble;
+ mir->dalvikInsn.vC = (vector_type << 16) | vector_size; // Type size.
+ (m2l->*f)(mir);
+ m2l->AssembleLIR();
+
+ std::string gcc_asm = inst_string + " %xmm1, %xmm0\n";
+ // Need a "base" std::vector.
+ std::vector<uint8_t> buffer(m2l->code_buffer_.begin(), m2l->code_buffer_.end());
+ test_helper_->Driver(buffer, gcc_asm, inst_string);
+
+ Release();
+ }
+
+ // Tests are member functions as many of the assembler functions are protected or private,
+ // and it would be inelegant to define ART_FRIEND_TEST for all the tests.
+
+ void TestAddpd() {
+ TestVectorFn(kX86,
+ static_cast<Instruction::Code>(kMirOpPackedAddition),
+ &X86Mir2Lir::GenAddVector,
+ "addpd");
+ TestVectorFn(kX86_64,
+ static_cast<Instruction::Code>(kMirOpPackedAddition),
+ &X86Mir2Lir::GenAddVector,
+ "addpd");
+ }
+
+ void TestSubpd() {
+ TestVectorFn(kX86,
+ static_cast<Instruction::Code>(kMirOpPackedSubtract),
+ &X86Mir2Lir::GenSubtractVector,
+ "subpd");
+ TestVectorFn(kX86_64,
+ static_cast<Instruction::Code>(kMirOpPackedSubtract),
+ &X86Mir2Lir::GenSubtractVector,
+ "subpd");
+ }
+
+ void TestMulpd() {
+ TestVectorFn(kX86,
+ static_cast<Instruction::Code>(kMirOpPackedMultiply),
+ &X86Mir2Lir::GenMultiplyVector,
+ "mulpd");
+ TestVectorFn(kX86_64,
+ static_cast<Instruction::Code>(kMirOpPackedMultiply),
+ &X86Mir2Lir::GenMultiplyVector,
+ "mulpd");
+ }
+};
+
+TEST_F(QuickAssembleX86MacroTest, CheckTools) {
+ ASSERT_TRUE(CheckTools(kX86)) << "x86 tools not found.";
+ ASSERT_TRUE(CheckTools(kX86_64)) << "x86_64 tools not found.";
+}
+
+#define DECLARE_TEST(name) \
+ TEST_F(QuickAssembleX86MacroTest, name) { \
+ Test ## name(); \
+ }
+
+DECLARE_TEST(Addpd)
+DECLARE_TEST(Subpd)
+DECLARE_TEST(Mulpd)
+
+} // namespace art