2010-04-26: Version 2.2.5
Various performance improvements (especially for ARM and x64)
Fixed bug in CPU profiling (http://crbug.com/42137)
Fixed a bug with the natives cache.
Fixed two bugs in the ARM code generator that can cause wrong calculations.
Fixed a bug that may cause a wrong result for shift operations.
git-svn-id: http://v8.googlecode.com/svn/trunk@4498 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 23d5e00..a6d81bf 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -306,6 +306,7 @@
reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
num_prinfo_ = 0;
next_buffer_check_ = 0;
+ const_pool_blocked_nesting_ = 0;
no_const_pool_before_ = 0;
last_const_pool_end_ = 0;
last_bound_pos_ = 0;
@@ -317,6 +318,7 @@
Assembler::~Assembler() {
+ ASSERT(const_pool_blocked_nesting_ == 0);
if (own_buffer_) {
if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
spare_buffer_ = buffer_;
@@ -348,6 +350,51 @@
}
+bool Assembler::IsNop(Instr instr, int type) {
+ // Check for mov rx, rx.
+ ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop.
+ return instr == (al | 13*B21 | type*B12 | type);
+}
+
+
+bool Assembler::IsBranch(Instr instr) {
+ return (instr & (B27 | B25)) == (B27 | B25);
+}
+
+
+int Assembler::GetBranchOffset(Instr instr) {
+ ASSERT(IsBranch(instr));
+ // Take the jump offset in the lower 24 bits, sign extend it and multiply it
+ // with 4 to get the offset in bytes.
+ return ((instr & Imm24Mask) << 8) >> 6;
+}
+
+
+bool Assembler::IsLdrRegisterImmediate(Instr instr) {
+ return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
+}
+
+
+int Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
+ ASSERT(IsLdrRegisterImmediate(instr));
+ bool positive = (instr & B23) == B23;
+ int offset = instr & Off12Mask; // Zero extended offset.
+ return positive ? offset : -offset;
+}
+
+
+Instr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
+ ASSERT(IsLdrRegisterImmediate(instr));
+ bool positive = offset >= 0;
+ if (!positive) offset = -offset;
+ ASSERT(is_uint12(offset));
+ // Set bit indicating whether the offset should be added.
+ instr = (instr & ~B23) | (positive ? B23 : 0);
+ // Set the actual offset.
+ return (instr & ~Off12Mask) | offset;
+}
+
+
// Labels refer to positions in the (to be) generated code.
// There are bound, linked, and unused labels.
//
@@ -371,10 +418,10 @@
}
ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
int imm26 = ((instr & Imm24Mask) << 8) >> 6;
- if ((instr & CondMask) == nv && (instr & B24) != 0)
+ if ((instr & CondMask) == nv && (instr & B24) != 0) {
// blx uses bit 24 to encode bit 2 of imm26
imm26 += 2;
-
+ }
return pos + kPcLoadDelta + imm26;
}
@@ -902,6 +949,10 @@
if (dst.is(pc)) {
WriteRecordedPositions();
}
+ // Don't allow nop instructions in the form mov rn, rn to be generated using
+ // the mov instruction. They must be generated using nop(int)
+ // pseudo instructions.
+ ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
addrmod1(cond | 13*B21 | s, r0, dst, src);
}
@@ -1691,6 +1742,13 @@
// Pseudo instructions.
+void Assembler::nop(int type) {
+ // This is mov rx, rx.
+ ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop.
+ emit(al | 13*B21 | type*B12 | type);
+}
+
+
void Assembler::lea(Register dst,
const MemOperand& x,
SBit s,
@@ -1726,11 +1784,6 @@
}
-void Assembler::BlockConstPoolFor(int instructions) {
- BlockConstPoolBefore(pc_offset() + instructions * kInstrSize);
-}
-
-
// Debugging.
void Assembler::RecordJSReturn() {
WriteRecordedPositions();
@@ -1894,12 +1947,17 @@
// However, some small sequences of instructions must not be broken up by the
// insertion of a constant pool; such sequences are protected by setting
- // no_const_pool_before_, which is checked here. Also, recursive calls to
- // CheckConstPool are blocked by no_const_pool_before_.
- if (pc_offset() < no_const_pool_before_) {
+ // either const_pool_blocked_nesting_ or no_const_pool_before_, which are
+ // both checked here. Also, recursive calls to CheckConstPool are blocked by
+ // no_const_pool_before_.
+ if (const_pool_blocked_nesting_ > 0 || pc_offset() < no_const_pool_before_) {
// Emission is currently blocked; make sure we try again as soon as
// possible.
- next_buffer_check_ = no_const_pool_before_;
+ if (const_pool_blocked_nesting_ > 0) {
+ next_buffer_check_ = pc_offset() + kInstrSize;
+ } else {
+ next_buffer_check_ = no_const_pool_before_;
+ }
// Something is wrong if emission is forced and blocked at the same time.
ASSERT(!force_emit);