summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/code_generator_x86.cc30
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc60
-rw-r--r--compiler/optimizing/intrinsics.cc2
-rw-r--r--compiler/utils/x86/assembler_x86.cc37
-rw-r--r--compiler/utils/x86/assembler_x86.h4
-rw-r--r--compiler/utils/x86/assembler_x86_test.cc16
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.cc35
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.h5
-rw-r--r--compiler/utils/x86_64/assembler_x86_64_test.cc46
-rw-r--r--runtime/Android.mk11
-rw-r--r--runtime/arch/arm64/quick_entrypoints_arm64.S33
-rw-r--r--runtime/verifier/method_verifier.cc7
-rw-r--r--test/401-optimizing-compiler/src/Main.java2
-rw-r--r--test/402-optimizing-control-flow/src/Main.java2
-rw-r--r--test/403-optimizing-long/src/Main.java2
-rw-r--r--test/404-optimizing-allocator/src/Main.java2
-rw-r--r--test/405-optimizing-long-allocator/src/Main.java2
-rw-r--r--test/411-optimizing-arith-mul/src/Main.java2
-rw-r--r--test/412-new-array/src/Main.java2
-rw-r--r--test/414-optimizing-arith-sub/src/Main.java2
-rw-r--r--test/415-optimizing-arith-neg/src/Main.java2
-rw-r--r--test/417-optimizing-arith-div/src/Main.java2
-rw-r--r--test/421-large-frame/src/Main.java2
-rw-r--r--test/422-type-conversion/src/Main.java2
-rw-r--r--test/427-bitwise/src/Main.java2
-rw-r--r--test/477-long-to-float-conversion-precision/src/Main.java2
-rw-r--r--test/705-register-conflict/src/Main.java2
27 files changed, 246 insertions, 70 deletions
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index e15eff9056..0569565bdd 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -2348,7 +2348,12 @@ void LocationsBuilderX86::VisitMul(HMul* mul) {
case Primitive::kPrimInt:
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
- locations->SetOut(Location::SameAsFirstInput());
+ if (mul->InputAt(1)->IsIntConstant()) {
+ // Can use 3 operand multiply.
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+ } else {
+ locations->SetOut(Location::SameAsFirstInput());
+ }
break;
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -2376,21 +2381,24 @@ void InstructionCodeGeneratorX86::VisitMul(HMul* mul) {
LocationSummary* locations = mul->GetLocations();
Location first = locations->InAt(0);
Location second = locations->InAt(1);
- DCHECK(first.Equals(locations->Out()));
+ Location out = locations->Out();
switch (mul->GetResultType()) {
- case Primitive::kPrimInt: {
- if (second.IsRegister()) {
+ case Primitive::kPrimInt:
+ // The constant may have ended up in a register, so test explicitly to avoid
+ // problems where the output may not be the same as the first operand.
+ if (mul->InputAt(1)->IsIntConstant()) {
+ Immediate imm(mul->InputAt(1)->AsIntConstant()->GetValue());
+ __ imull(out.AsRegister<Register>(), first.AsRegister<Register>(), imm);
+ } else if (second.IsRegister()) {
+ DCHECK(first.Equals(out));
__ imull(first.AsRegister<Register>(), second.AsRegister<Register>());
- } else if (second.IsConstant()) {
- Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
- __ imull(first.AsRegister<Register>(), imm);
} else {
DCHECK(second.IsStackSlot());
+ DCHECK(first.Equals(out));
__ imull(first.AsRegister<Register>(), Address(ESP, second.GetStackIndex()));
}
break;
- }
case Primitive::kPrimLong: {
Register in1_hi = first.AsRegisterPairHigh<Register>();
@@ -4535,7 +4543,11 @@ void ParallelMoveResolverX86::EmitSwap(size_t index) {
Location destination = move->GetDestination();
if (source.IsRegister() && destination.IsRegister()) {
- __ xchgl(destination.AsRegister<Register>(), source.AsRegister<Register>());
+ // Use XOR swap algorithm to avoid serializing XCHG instruction or using a temporary.
+ DCHECK_NE(destination.AsRegister<Register>(), source.AsRegister<Register>());
+ __ xorl(destination.AsRegister<Register>(), source.AsRegister<Register>());
+ __ xorl(source.AsRegister<Register>(), destination.AsRegister<Register>());
+ __ xorl(destination.AsRegister<Register>(), source.AsRegister<Register>());
} else if (source.IsRegister() && destination.IsStackSlot()) {
Exchange(source.AsRegister<Register>(), destination.GetStackIndex());
} else if (source.IsStackSlot() && destination.IsRegister()) {
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index a95ce68657..287737b4c8 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -2535,13 +2535,19 @@ void LocationsBuilderX86_64::VisitMul(HMul* mul) {
case Primitive::kPrimInt: {
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
- locations->SetOut(Location::SameAsFirstInput());
+ if (mul->InputAt(1)->IsIntConstant()) {
+ // Can use 3 operand multiply.
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+ } else {
+ locations->SetOut(Location::SameAsFirstInput());
+ }
break;
}
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrInt32LongConstant(mul->InputAt(1)));
- if (locations->InAt(1).IsConstant()) {
+ locations->SetInAt(1, Location::Any());
+ if (mul->InputAt(1)->IsLongConstant() &&
+ IsInt<32>(mul->InputAt(1)->AsLongConstant()->GetValue())) {
// Can use 3 operand multiply.
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
} else {
@@ -2566,37 +2572,51 @@ void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) {
LocationSummary* locations = mul->GetLocations();
Location first = locations->InAt(0);
Location second = locations->InAt(1);
+ Location out = locations->Out();
switch (mul->GetResultType()) {
- case Primitive::kPrimInt: {
- DCHECK(first.Equals(locations->Out()));
- if (second.IsRegister()) {
+ case Primitive::kPrimInt:
+ // The constant may have ended up in a register, so test explicitly to avoid
+ // problems where the output may not be the same as the first operand.
+ if (mul->InputAt(1)->IsIntConstant()) {
+ Immediate imm(mul->InputAt(1)->AsIntConstant()->GetValue());
+ __ imull(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>(), imm);
+ } else if (second.IsRegister()) {
+ DCHECK(first.Equals(out));
__ imull(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
- } else if (second.IsConstant()) {
- Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
- __ imull(first.AsRegister<CpuRegister>(), imm);
} else {
+ DCHECK(first.Equals(out));
DCHECK(second.IsStackSlot());
__ imull(first.AsRegister<CpuRegister>(),
Address(CpuRegister(RSP), second.GetStackIndex()));
}
break;
- }
case Primitive::kPrimLong: {
- if (second.IsConstant()) {
- int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
- DCHECK(IsInt<32>(value));
- __ imulq(locations->Out().AsRegister<CpuRegister>(),
- first.AsRegister<CpuRegister>(),
- Immediate(static_cast<int32_t>(value)));
- } else {
- DCHECK(first.Equals(locations->Out()));
+ // The constant may have ended up in a register, so test explicitly to avoid
+ // problems where the output may not be the same as the first operand.
+ if (mul->InputAt(1)->IsLongConstant()) {
+ int64_t value = mul->InputAt(1)->AsLongConstant()->GetValue();
+ if (IsInt<32>(value)) {
+ __ imulq(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>(),
+ Immediate(static_cast<int32_t>(value)));
+ } else {
+ // Have to use the constant area.
+ DCHECK(first.Equals(out));
+ __ imulq(first.AsRegister<CpuRegister>(), codegen_->LiteralInt64Address(value));
+ }
+ } else if (second.IsRegister()) {
+ DCHECK(first.Equals(out));
__ imulq(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+ } else {
+ DCHECK(second.IsDoubleStackSlot());
+ DCHECK(first.Equals(out));
+ __ imulq(first.AsRegister<CpuRegister>(),
+ Address(CpuRegister(RSP), second.GetStackIndex()));
}
break;
}
case Primitive::kPrimFloat: {
- DCHECK(first.Equals(locations->Out()));
+ DCHECK(first.Equals(out));
if (second.IsFpuRegister()) {
__ mulss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
} else if (second.IsConstant()) {
@@ -2611,7 +2631,7 @@ void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) {
}
case Primitive::kPrimDouble: {
- DCHECK(first.Equals(locations->Out()));
+ DCHECK(first.Equals(out));
if (second.IsFpuRegister()) {
__ mulsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
} else if (second.IsConstant()) {
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 8ef13e125e..bc7da802b1 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -359,7 +359,7 @@ void IntrinsicsRecognizer::Run() {
std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic) {
switch (intrinsic) {
case Intrinsics::kNone:
- os << "No intrinsic.";
+ os << "None";
break;
#define OPTIMIZING_INTRINSICS(Name, IsStatic) \
case Intrinsics::k ## Name: \
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 44efc65e3f..8c2a3ed637 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -145,6 +145,13 @@ void X86Assembler::movl(const Address& dst, Label* lbl) {
EmitLabel(lbl, dst.length_ + 5);
}
+void X86Assembler::movntl(const Address& dst, Register src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0x0F);
+ EmitUint8(0xC3);
+ EmitOperand(src, dst);
+}
+
void X86Assembler::bswapl(Register dst) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x0F);
@@ -1194,11 +1201,26 @@ void X86Assembler::imull(Register dst, Register src) {
}
-void X86Assembler::imull(Register reg, const Immediate& imm) {
+void X86Assembler::imull(Register dst, Register src, const Immediate& imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0x69);
- EmitOperand(reg, Operand(reg));
- EmitImmediate(imm);
+ // See whether imm can be represented as a sign-extended 8bit value.
+ int32_t v32 = static_cast<int32_t>(imm.value());
+ if (IsInt<8>(v32)) {
+ // Sign-extension works.
+ EmitUint8(0x6B);
+ EmitOperand(dst, Operand(src));
+ EmitUint8(static_cast<uint8_t>(v32 & 0xFF));
+ } else {
+ // Not representable, use full immediate.
+ EmitUint8(0x69);
+ EmitOperand(dst, Operand(src));
+ EmitImmediate(imm);
+ }
+}
+
+
+void X86Assembler::imull(Register reg, const Immediate& imm) {
+ imull(reg, reg, imm);
}
@@ -1523,6 +1545,13 @@ void X86Assembler::repe_cmpsw() {
}
+void X86Assembler::repe_cmpsl() {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0xF3);
+ EmitUint8(0xA7);
+}
+
+
X86Assembler* X86Assembler::lock() {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF0);
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index e2abcde624..d9c1b404c9 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -231,6 +231,8 @@ class X86Assembler FINAL : public Assembler {
void movl(const Address& dst, const Immediate& imm);
void movl(const Address& dst, Label* lbl);
+ void movntl(const Address& dst, Register src);
+
void bswapl(Register dst);
void movzxb(Register dst, ByteRegister src);
@@ -409,6 +411,7 @@ class X86Assembler FINAL : public Assembler {
void imull(Register dst, Register src);
void imull(Register reg, const Immediate& imm);
+ void imull(Register dst, Register src, const Immediate& imm);
void imull(Register reg, const Address& address);
void imull(Register reg);
@@ -466,6 +469,7 @@ class X86Assembler FINAL : public Assembler {
void repne_scasw();
void repe_cmpsw();
+ void repe_cmpsl();
X86Assembler* lock();
void cmpxchgl(const Address& address, Register reg);
diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc
index 0e8c4aee0c..b664d2342f 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -105,6 +105,16 @@ TEST_F(AssemblerX86Test, Movl) {
DriverStr(expected, "movl");
}
+TEST_F(AssemblerX86Test, Movntl) {
+ GetAssembler()->movntl(x86::Address(x86::EDI, x86::EBX, x86::TIMES_4, 12), x86::EAX);
+ GetAssembler()->movntl(x86::Address(x86::EDI, 0), x86::EAX);
+ const char* expected =
+ "movntil %EAX, 0xc(%EDI,%EBX,4)\n"
+ "movntil %EAX, (%EDI)\n";
+
+ DriverStr(expected, "movntl");
+}
+
TEST_F(AssemblerX86Test, psrlq) {
GetAssembler()->psrlq(x86::XMM0, CreateImmediate(32));
const char* expected = "psrlq $0x20, %xmm0\n";
@@ -202,4 +212,10 @@ TEST_F(AssemblerX86Test, Repecmpsw) {
DriverStr(expected, "Repecmpsw");
}
+TEST_F(AssemblerX86Test, Repecmpsl) {
+ GetAssembler()->repe_cmpsl();
+ const char* expected = "repe cmpsl\n";
+ DriverStr(expected, "Repecmpsl");
+}
+
} // namespace art
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 93c90db5d3..327c3e9bef 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -194,6 +194,21 @@ void X86_64Assembler::movl(const Address& dst, const Immediate& imm) {
EmitImmediate(imm);
}
+void X86_64Assembler::movntl(const Address& dst, CpuRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitOptionalRex32(src, dst);
+ EmitUint8(0x0F);
+ EmitUint8(0xC3);
+ EmitOperand(src.LowBits(), dst);
+}
+
+void X86_64Assembler::movntq(const Address& dst, CpuRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitRex64(src, dst);
+ EmitUint8(0x0F);
+ EmitUint8(0xC3);
+ EmitOperand(src.LowBits(), dst);
+}
void X86_64Assembler::cmov(Condition c, CpuRegister dst, CpuRegister src) {
cmov(c, dst, src, true);
@@ -1672,28 +1687,33 @@ void X86_64Assembler::imull(CpuRegister dst, CpuRegister src) {
EmitOperand(dst.LowBits(), Operand(src));
}
-void X86_64Assembler::imull(CpuRegister reg, const Immediate& imm) {
+void X86_64Assembler::imull(CpuRegister dst, CpuRegister src, const Immediate& imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
CHECK(imm.is_int32()); // imull only supports 32b immediate.
- EmitOptionalRex32(reg, reg);
+ EmitOptionalRex32(dst, src);
// See whether imm can be represented as a sign-extended 8bit value.
int32_t v32 = static_cast<int32_t>(imm.value());
if (IsInt<8>(v32)) {
// Sign-extension works.
EmitUint8(0x6B);
- EmitOperand(reg.LowBits(), Operand(reg));
+ EmitOperand(dst.LowBits(), Operand(src));
EmitUint8(static_cast<uint8_t>(v32 & 0xFF));
} else {
// Not representable, use full immediate.
EmitUint8(0x69);
- EmitOperand(reg.LowBits(), Operand(reg));
+ EmitOperand(dst.LowBits(), Operand(src));
EmitImmediate(imm);
}
}
+void X86_64Assembler::imull(CpuRegister reg, const Immediate& imm) {
+ imull(reg, reg, imm);
+}
+
+
void X86_64Assembler::imull(CpuRegister reg, const Address& address) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitOptionalRex32(reg, address);
@@ -2081,6 +2101,13 @@ void X86_64Assembler::repe_cmpsw() {
}
+void X86_64Assembler::repe_cmpsl() {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0xF3);
+ EmitUint8(0xA7);
+}
+
+
void X86_64Assembler::LoadDoubleConstant(XmmRegister dst, double value) {
// TODO: Need to have a code constants table.
int64_t constant = bit_cast<int64_t, double>(value);
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 0cd31971b4..dbc0c08f2d 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -326,6 +326,9 @@ class X86_64Assembler FINAL : public Assembler {
void movq(CpuRegister dst, CpuRegister src);
void movl(CpuRegister dst, CpuRegister src);
+ void movntl(const Address& dst, CpuRegister src);
+ void movntq(const Address& dst, CpuRegister src);
+
void movq(CpuRegister dst, const Address& src);
void movl(CpuRegister dst, const Address& src);
void movq(const Address& dst, CpuRegister src);
@@ -539,6 +542,7 @@ class X86_64Assembler FINAL : public Assembler {
void imull(CpuRegister dst, CpuRegister src);
void imull(CpuRegister reg, const Immediate& imm);
+ void imull(CpuRegister dst, CpuRegister src, const Immediate& imm);
void imull(CpuRegister reg, const Address& address);
void imulq(CpuRegister src);
@@ -604,6 +608,7 @@ class X86_64Assembler FINAL : public Assembler {
void repne_scasw();
void repe_cmpsw();
+ void repe_cmpsl();
//
// Macros for High-level operations.
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 2c1a6a1f3c..74f47fff3b 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -674,6 +674,46 @@ TEST_F(AssemblerX86_64Test, MovqAddrImm) {
DriverStr(expected, "movq");
}
+TEST_F(AssemblerX86_64Test, Movntl) {
+ GetAssembler()->movntl(x86_64::Address(
+ x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
+ GetAssembler()->movntl(x86_64::Address(
+ x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
+ GetAssembler()->movntl(x86_64::Address(
+ x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
+ GetAssembler()->movntl(x86_64::Address(x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RAX));
+ GetAssembler()->movntl(x86_64::Address(
+ x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0), x86_64::CpuRegister(x86_64::R9));
+ const char* expected =
+ "movntil %EAX, 0xc(%RDI,%RBX,4)\n"
+ "movntil %EAX, 0xc(%RDI,%R9,4)\n"
+ "movntil %EAX, 0xc(%RDI,%R9,4)\n"
+ "movntil %EAX, (%R13)\n"
+ "movntil %R9d, (%R13,%R9,1)\n";
+
+ DriverStr(expected, "movntl");
+}
+
+TEST_F(AssemblerX86_64Test, Movntq) {
+ GetAssembler()->movntq(x86_64::Address(
+ x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
+ GetAssembler()->movntq(x86_64::Address(
+ x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
+ GetAssembler()->movntq(x86_64::Address(
+ x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
+ GetAssembler()->movntq(x86_64::Address(x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RAX));
+ GetAssembler()->movntq(x86_64::Address(
+ x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0), x86_64::CpuRegister(x86_64::R9));
+ const char* expected =
+ "movntiq %RAX, 0xc(%RDI,%RBX,4)\n"
+ "movntiq %RAX, 0xc(%RDI,%R9,4)\n"
+ "movntiq %RAX, 0xc(%RDI,%R9,4)\n"
+ "movntiq %RAX, (%R13)\n"
+ "movntiq %R9, (%R13,%R9,1)\n";
+
+ DriverStr(expected, "movntq");
+}
+
TEST_F(AssemblerX86_64Test, Cvtsi2ssAddr) {
GetAssembler()->cvtsi2ss(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
@@ -1269,4 +1309,10 @@ TEST_F(AssemblerX86_64Test, Repecmpsw) {
DriverStr(expected, "Repecmpsw");
}
+TEST_F(AssemblerX86_64Test, Repecmpsl) {
+ GetAssembler()->repe_cmpsl();
+ const char* expected = "repe cmpsl\n";
+ DriverStr(expected, "Repecmpsl");
+}
+
} // namespace art
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 4a944963a2..ce3e6d1f37 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -341,10 +341,13 @@ LIBART_ENUM_OPERATOR_OUT_HEADER_FILES := \
LIBART_CFLAGS := -DBUILDING_LIBART=1
+LIBART_TARGET_CFLAGS :=
+LIBART_HOST_CFLAGS :=
+
ifeq ($(MALLOC_IMPL),dlmalloc)
- LIBART_CFLAGS += -DUSE_DLMALLOC
+ LIBART_TARGET_CFLAGS += -DUSE_DLMALLOC
else
- LIBART_CFLAGS += -DUSE_JEMALLOC
+ LIBART_TARGET_CFLAGS += -DUSE_JEMALLOC
endif
# Default dex2oat instruction set features.
@@ -440,8 +443,10 @@ $$(ENUM_OPERATOR_OUT_GEN): $$(GENERATED_SRC_DIR)/%_operator_out.cc : $(LOCAL_PAT
LOCAL_CFLAGS := $$(LIBART_CFLAGS)
LOCAL_LDFLAGS := $$(LIBART_LDFLAGS)
ifeq ($$(art_target_or_host),target)
+ LOCAL_CFLAGS += $$(LIBART_TARGET_CFLAGS)
LOCAL_LDFLAGS += $$(LIBART_TARGET_LDFLAGS)
else #host
+ LOCAL_CFLAGS += $$(LIBART_HOST_CFLAGS)
LOCAL_LDFLAGS += $$(LIBART_HOST_LDFLAGS)
ifeq ($$(art_static_or_shared),static)
LOCAL_LDFLAGS += -static
@@ -581,4 +586,6 @@ LIBART_HOST_SRC_FILES_32 :=
LIBART_HOST_SRC_FILES_64 :=
LIBART_ENUM_OPERATOR_OUT_HEADER_FILES :=
LIBART_CFLAGS :=
+LIBART_TARGET_CFLAGS :=
+LIBART_HOST_CFLAGS :=
build-libart :=
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 548ab47f82..8ba3d4392d 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -537,18 +537,18 @@ SAVE_SIZE_AND_METHOD=SAVE_SIZE+8
// W10 - temporary
add x9, sp, #8 // Destination address is bottom of stack + null.
- // Use \@ to differentiate between macro invocations.
-.LcopyParams\@:
+ // Copy parameters into the stack. Use numeric label as this is a macro and Clang's assembler
+ // does not have unique-id variables.
+1:
cmp w2, #0
- beq .LendCopyParams\@
+ beq 2f
sub w2, w2, #4 // Need 65536 bytes of range.
ldr w10, [x1, x2]
str w10, [x9, x2]
- b .LcopyParams\@
-
-.LendCopyParams\@:
+ b 1b
+2:
// Store null into ArtMethod* at bottom of frame.
str xzr, [sp]
.endm
@@ -587,26 +587,29 @@ SAVE_SIZE_AND_METHOD=SAVE_SIZE+8
// Store result (w0/x0/s0/d0) appropriately, depending on resultType.
ldrb w10, [x5]
+ // Check the return type and store the correct register into the jvalue in memory.
+ // Use numeric label as this is a macro and Clang's assembler does not have unique-id variables.
+
// Don't set anything for a void type.
cmp w10, #'V'
- beq .Lexit_art_quick_invoke_stub\@
+ beq 3f
+ // Is it a double?
cmp w10, #'D'
- bne .Lreturn_is_float\@
+ bne 1f
str d0, [x4]
- b .Lexit_art_quick_invoke_stub\@
+ b 3f
-.Lreturn_is_float\@:
+1: // Is it a float?
cmp w10, #'F'
- bne .Lreturn_is_int\@
+ bne 2f
str s0, [x4]
- b .Lexit_art_quick_invoke_stub\@
+ b 3f
- // Just store x0. Doesn't matter if it is 64 or 32 bits.
-.Lreturn_is_int\@:
+2: // Just store x0. Doesn't matter if it is 64 or 32 bits.
str x0, [x4]
-.Lexit_art_quick_invoke_stub\@:
+3: // Finish up.
ldp x2, x19, [xFP, #32] // Restore stack pointer and x19.
.cfi_restore x19
mov sp, x2
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index d63b455668..0181e5b7cc 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2874,6 +2874,13 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
}
}
}
+ // Handle this like a RETURN_VOID now. Code is duplicated to separate standard from
+ // quickened opcodes (otherwise this could be a fall-through).
+ if (!IsConstructor()) {
+ if (!GetMethodReturnType().IsConflict()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void not expected";
+ }
+ }
break;
// Note: the following instructions encode offsets derived from class linking.
// As such they use Class*/Field*/AbstractMethod* as these offsets only have
diff --git a/test/401-optimizing-compiler/src/Main.java b/test/401-optimizing-compiler/src/Main.java
index a1e62b3b39..f2e451854b 100644
--- a/test/401-optimizing-compiler/src/Main.java
+++ b/test/401-optimizing-compiler/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/402-optimizing-control-flow/src/Main.java b/test/402-optimizing-control-flow/src/Main.java
index c9c24dd568..4c93d266e8 100644
--- a/test/402-optimizing-control-flow/src/Main.java
+++ b/test/402-optimizing-control-flow/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/403-optimizing-long/src/Main.java b/test/403-optimizing-long/src/Main.java
index 21af4e14aa..5927d1c325 100644
--- a/test/403-optimizing-long/src/Main.java
+++ b/test/403-optimizing-long/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/404-optimizing-allocator/src/Main.java b/test/404-optimizing-allocator/src/Main.java
index 7b31820470..1ff5475e45 100644
--- a/test/404-optimizing-allocator/src/Main.java
+++ b/test/404-optimizing-allocator/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$reg$ is a marker for the optimizing compiler to ensure
+// Note that $opt$reg$ is a marker for the optimizing compiler to test
// it does use its register allocator.
public class Main {
diff --git a/test/405-optimizing-long-allocator/src/Main.java b/test/405-optimizing-long-allocator/src/Main.java
index 9fd840b543..a0e0bb5355 100644
--- a/test/405-optimizing-long-allocator/src/Main.java
+++ b/test/405-optimizing-long-allocator/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it compiles these methods.
public class Main {
diff --git a/test/411-optimizing-arith-mul/src/Main.java b/test/411-optimizing-arith-mul/src/Main.java
index 3a5d7c05c9..60e418e1e5 100644
--- a/test/411-optimizing-arith-mul/src/Main.java
+++ b/test/411-optimizing-arith-mul/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/412-new-array/src/Main.java b/test/412-new-array/src/Main.java
index e4669b8a96..b9c2a053e0 100644
--- a/test/412-new-array/src/Main.java
+++ b/test/412-new-array/src/Main.java
@@ -17,7 +17,7 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main extends TestCase {
diff --git a/test/414-optimizing-arith-sub/src/Main.java b/test/414-optimizing-arith-sub/src/Main.java
index 30e84368d0..b4531cdfd4 100644
--- a/test/414-optimizing-arith-sub/src/Main.java
+++ b/test/414-optimizing-arith-sub/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/415-optimizing-arith-neg/src/Main.java b/test/415-optimizing-arith-neg/src/Main.java
index bd8a1583d5..cabf635554 100644
--- a/test/415-optimizing-arith-neg/src/Main.java
+++ b/test/415-optimizing-arith-neg/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/417-optimizing-arith-div/src/Main.java b/test/417-optimizing-arith-div/src/Main.java
index 909ceb43d6..68e89b3eb2 100644
--- a/test/417-optimizing-arith-div/src/Main.java
+++ b/test/417-optimizing-arith-div/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/421-large-frame/src/Main.java b/test/421-large-frame/src/Main.java
index 81896abbd8..6717ba0661 100644
--- a/test/421-large-frame/src/Main.java
+++ b/test/421-large-frame/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java
index 9f8f417cff..146f309c81 100644
--- a/test/422-type-conversion/src/Main.java
+++ b/test/422-type-conversion/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/427-bitwise/src/Main.java b/test/427-bitwise/src/Main.java
index e9840669dd..aa69554a4f 100644
--- a/test/427-bitwise/src/Main.java
+++ b/test/427-bitwise/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/477-long-to-float-conversion-precision/src/Main.java b/test/477-long-to-float-conversion-precision/src/Main.java
index cd9703943d..568bc04d6c 100644
--- a/test/477-long-to-float-conversion-precision/src/Main.java
+++ b/test/477-long-to-float-conversion-precision/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {
diff --git a/test/705-register-conflict/src/Main.java b/test/705-register-conflict/src/Main.java
index 42c79fb275..9ae10ecba6 100644
--- a/test/705-register-conflict/src/Main.java
+++ b/test/705-register-conflict/src/Main.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// Note that $opt$ is a marker for the optimizing compiler to ensure
+// Note that $opt$ is a marker for the optimizing compiler to test
// it does compile the method.
public class Main {