Reviewers: Jakob,
Message:
PTAL.
Description:
Ensure using byte registers for byte instructions on ia32 and x64.
BUG=v8:1945
TEST=regress-1945.js
Please review this at http://codereview.chromium.org/9418005/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/ia32/assembler-ia32.cc
M src/ia32/lithium-codegen-ia32.cc
M src/x64/assembler-x64.h
M src/x64/assembler-x64.cc
M src/x64/lithium-codegen-x64.cc
A test/mjsunit/regress/regress-1945.js
Index: src/ia32/assembler-ia32.cc
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index
bb050b63f91b2820bb9702a3255e54f295d43437..b706892ea859b1d9fdbb0d3a5070529a521cf59c
100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -575,7 +575,7 @@ void Assembler::leave() {
void Assembler::mov_b(Register dst, const Operand& src) {
- ASSERT(dst.code() < 4);
+ CHECK(dst.is_byte_register());
EnsureSpace ensure_space(this);
EMIT(0x8A);
emit_operand(dst, src);
@@ -591,7 +591,7 @@ void Assembler::mov_b(const Operand& dst, int8_t imm8) {
void Assembler::mov_b(const Operand& dst, Register src) {
- ASSERT(src.code() < 4);
+ CHECK(src.is_byte_register());
EnsureSpace ensure_space(this);
EMIT(0x88);
emit_operand(src, dst);
@@ -829,7 +829,7 @@ void Assembler::cmpb(const Operand& op, int8_t imm8) {
void Assembler::cmpb(const Operand& op, Register reg) {
- ASSERT(reg.is_byte_register());
+ CHECK(reg.is_byte_register());
EnsureSpace ensure_space(this);
EMIT(0x38);
emit_operand(reg, op);
@@ -837,7 +837,7 @@ void Assembler::cmpb(const Operand& op, Register reg) {
void Assembler::cmpb(Register reg, const Operand& op) {
- ASSERT(reg.is_byte_register());
+ CHECK(reg.is_byte_register());
EnsureSpace ensure_space(this);
EMIT(0x3A);
emit_operand(reg, op);
@@ -901,6 +901,7 @@ void Assembler::cmpw_ax(const Operand& op) {
void Assembler::dec_b(Register dst) {
+ CHECK(dst.is_byte_register());
EnsureSpace ensure_space(this);
EMIT(0xFE);
EMIT(0xC8 | dst.code());
@@ -1204,6 +1205,7 @@ void Assembler::test(Register reg, const Operand& op)
{
void Assembler::test_b(Register reg, const Operand& op) {
+ CHECK(reg.is_byte_register());
EnsureSpace ensure_space(this);
EMIT(0x84);
emit_operand(reg, op);
@@ -1219,7 +1221,7 @@ void Assembler::test(const Operand& op, const
Immediate& imm) {
void Assembler::test_b(const Operand& op, uint8_t imm8) {
- if (op.is_reg_only() && op.reg().code() >= 4) {
+ if (op.is_reg_only() && !op.reg().is_byte_register()) {
test(op, Immediate(imm8));
return;
}
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc
b/src/ia32/lithium-codegen-ia32.cc
index
225584a83d536ce7c4207de712b2eadbc5ddae12..538645a712bca51d83245cd83de39b2244b7ca95
100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -1868,11 +1868,10 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Faster code path to avoid two compares: subtract lower bound from
the
// actual type and do a signed compare with the width of the type
range.
__ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
- __ mov(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
+ __ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
__ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- __ cmpb(Operand(temp2),
- static_cast<int8_t>(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
- FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+ __ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
+ FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ j(above, is_false);
}
@@ -4079,7 +4078,7 @@ void
LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
} else {
__ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
__ and_(temp, mask);
- __ cmpb(Operand(temp), tag);
+ __ cmp(temp, tag);
DeoptimizeIf(not_equal, instr->environment());
}
}
Index: src/x64/assembler-x64.cc
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index
eb8d7d4d998048f79bd20c77eb05760fe93094ec..2773c11b084e2e2a11031ad71242c0244c057681
100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -1059,7 +1059,7 @@ void Assembler::decl(const Operand& dst) {
void Assembler::decb(Register dst) {
EnsureSpace ensure_space(this);
- if (dst.code() > 3) {
+ if (!dst.is_byte_register()) {
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_32(dst);
}
@@ -1387,7 +1387,7 @@ void Assembler::leave() {
void Assembler::movb(Register dst, const Operand& src) {
EnsureSpace ensure_space(this);
- if (dst.code() > 3) {
+ if (!dst.is_byte_register()) {
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_32(dst, src);
} else {
@@ -1400,7 +1400,7 @@ void Assembler::movb(Register dst, const Operand&
src) {
void Assembler::movb(Register dst, Immediate imm) {
EnsureSpace ensure_space(this);
- if (dst.code() > 3) {
+ if (!dst.is_byte_register()) {
emit_rex_32(dst);
}
emit(0xB0 + dst.low_bits());
@@ -1410,7 +1410,7 @@ void Assembler::movb(Register dst, Immediate imm) {
void Assembler::movb(const Operand& dst, Register src) {
EnsureSpace ensure_space(this);
- if (src.code() > 3) {
+ if (!src.is_byte_register()) {
emit_rex_32(src, dst);
} else {
emit_optional_rex_32(src, dst);
@@ -1996,7 +1996,7 @@ void Assembler::testb(Register dst, Register src) {
emit(0x84);
emit_modrm(src, dst);
} else {
- if (dst.code() > 3 || src.code() > 3) {
+ if (!dst.is_byte_register() || !src.is_byte_register()) {
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_32(dst, src);
}
@@ -2013,7 +2013,7 @@ void Assembler::testb(Register reg, Immediate mask) {
emit(0xA8);
emit(mask.value_); // Low byte emitted.
} else {
- if (reg.code() > 3) {
+ if (!reg.is_byte_register()) {
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_32(reg);
}
@@ -2036,7 +2036,7 @@ void Assembler::testb(const Operand& op, Immediate
mask) {
void Assembler::testb(const Operand& op, Register reg) {
EnsureSpace ensure_space(this);
- if (reg.code() > 3) {
+ if (!reg.is_byte_register()) {
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_32(reg, op);
} else {
Index: src/x64/assembler-x64.h
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index
745850d822e68a003a338f689b5755c5545fb252..8e1dc79847bda94e2524a9bc3bdcee5d8ae41388
100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -131,6 +131,8 @@ struct Register {
}
bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
bool is(Register reg) const { return code_ == reg.code_; }
+ // rax, rbx, rcx and rdx are byte registers, the rest are not.
+ bool is_byte_register() const { return code_ <= 3; }
int code() const {
ASSERT(is_valid());
return code_;
Index: src/x64/lithium-codegen-x64.cc
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index
ff8aeefe2c73d4ed19bb5cc1417232ee3c14db2a..4129db69db5c5e405b3fee5741b7c9d207bd4657
100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -1793,11 +1793,10 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Faster code path to avoid two compares: subtract lower bound from
the
// actual type and do a signed compare with the width of the type
range.
__ movq(temp, FieldOperand(input, HeapObject::kMapOffset));
- __ movq(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
- __ subb(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- __ cmpb(temp2,
-
Immediate(static_cast<int8_t>(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
-
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)));
+ __ movzxbl(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
+ __ subq(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+ __ cmpq(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
+ FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ j(above, is_false);
}
Index: test/mjsunit/regress/regress-1945.js
diff --git a/test/mjsunit/regress/regress-1945.js
b/test/mjsunit/regress/regress-1945.js
new file mode 100644
index
0000000000000000000000000000000000000000..9de83c8c2368fa78a311f70c5ed38a5d98541624
--- /dev/null
+++ b/test/mjsunit/regress/regress-1945.js
@@ -0,0 +1,35 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+var _d = new Date();
+_d.setHours(0,0,0,0);
+_d.setHours(0,0,0,0);
+%OptimizeFunctionOnNextCall(_d.setHours);
+_d.setHours(0,0,0,0);
+
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev