Update V8 to version 4.1.0.21

This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.

Original commit message:

Version 4.1.0.21 (cherry-pick)

Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412

Unlink pages from the space page list after evacuation.

BUG=430201
LOG=N
R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/953813002

Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}

---

FPIIM-449

Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 22c2a55..bf88f69 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -246,6 +246,9 @@
   DisassemblerIA32(const NameConverter& converter,
                    bool abort_on_unimplemented = true)
       : converter_(converter),
+        vex_byte0_(0),
+        vex_byte1_(0),
+        vex_byte2_(0),
         instruction_table_(InstructionTable::get_instance()),
         tmp_buffer_pos_(0),
         abort_on_unimplemented_(abort_on_unimplemented) {
@@ -260,6 +263,9 @@
 
  private:
   const NameConverter& converter_;
+  byte vex_byte0_;  // 0xc4 or 0xc5
+  byte vex_byte1_;
+  byte vex_byte2_;  // only for 3 bytes vex prefix
   InstructionTable* instruction_table_;
   v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
   unsigned int tmp_buffer_pos_;
@@ -287,6 +293,57 @@
     kSAR = 7
   };
 
+  bool vex_128() {
+    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
+    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
+    return (checked & 4) != 1;
+  }
+
+  bool vex_66() {
+    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
+    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
+    return (checked & 3) == 1;
+  }
+
+  bool vex_f3() {
+    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
+    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
+    return (checked & 3) == 2;
+  }
+
+  bool vex_f2() {
+    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
+    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
+    return (checked & 3) == 3;
+  }
+
+  bool vex_w() {
+    if (vex_byte0_ == 0xc5) return false;
+    return (vex_byte2_ & 0x80) != 0;
+  }
+
+  bool vex_0f() {
+    if (vex_byte0_ == 0xc5) return true;
+    return (vex_byte1_ & 3) == 1;
+  }
+
+  bool vex_0f38() {
+    if (vex_byte0_ == 0xc5) return false;
+    return (vex_byte1_ & 3) == 2;
+  }
+
+  bool vex_0f3a() {
+    if (vex_byte0_ == 0xc5) return false;
+    return (vex_byte1_ & 3) == 3;
+  }
+
+  int vex_vreg() {
+    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
+    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
+    return ~(checked >> 3) & 0xf;
+  }
+
+  char float_size_code() { return "sd"[vex_w()]; }
 
   const char* NameOfCPURegister(int reg) const {
     return converter_.NameOfCPURegister(reg);
@@ -340,6 +397,7 @@
   int FPUInstruction(byte* data);
   int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
   int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
+  int AVXInstruction(byte* data);
   void AppendToBuffer(const char* format, ...);
 
 
@@ -679,6 +737,111 @@
 }
 
 
+int DisassemblerIA32::AVXInstruction(byte* data) {
+  byte opcode = *data;
+  byte* current = data + 1;
+  if (vex_66() && vex_0f38()) {
+    int mod, regop, rm, vvvv = vex_vreg();
+    get_modrm(*current, &mod, &regop, &rm);
+    switch (opcode) {
+      case 0x99:
+        AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0xa9:
+        AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0xb9:
+        AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0x9b:
+        AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0xab:
+        AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0xbb:
+        AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0x9d:
+        AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0xad:
+        AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0xbd:
+        AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0x9f:
+        AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0xaf:
+        AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0xbf:
+        AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(),
+                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      default:
+        UnimplementedInstruction();
+    }
+  } else if (vex_f2() && vex_0f()) {
+    int mod, regop, rm, vvvv = vex_vreg();
+    get_modrm(*current, &mod, &regop, &rm);
+    switch (opcode) {
+      case 0x58:
+        AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
+                       NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0x59:
+        AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop),
+                       NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0x5c:
+        AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop),
+                       NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      case 0x5e:
+        AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop),
+                       NameOfXMMRegister(vvvv));
+        current += PrintRightXMMOperand(current);
+        break;
+      default:
+        UnimplementedInstruction();
+    }
+  } else {
+    UnimplementedInstruction();
+  }
+
+  return static_cast<int>(current - data);
+}
+
+
 // Returns number of bytes used, including *data.
 int DisassemblerIA32::FPUInstruction(byte* data) {
   byte escape_opcode = *data;
@@ -903,65 +1066,81 @@
   } else if (*data == 0x2E /*cs*/) {
     branch_hint = "predicted not taken";
     data++;
+  } else if (*data == 0xC4 && *(data + 1) >= 0xc0) {
+    vex_byte0_ = *data;
+    vex_byte1_ = *(data + 1);
+    vex_byte2_ = *(data + 2);
+    data += 3;
+  } else if (*data == 0xC5 && *(data + 1) >= 0xc0) {
+    vex_byte0_ = *data;
+    vex_byte1_ = *(data + 1);
+    data += 2;
   }
+
   bool processed = true;  // Will be set to false if the current instruction
                           // is not in 'instructions' table.
-  const InstructionDesc& idesc = instruction_table_->Get(*data);
-  switch (idesc.type) {
-    case ZERO_OPERANDS_INSTR:
-      AppendToBuffer(idesc.mnem);
-      data++;
-      break;
+  // Decode AVX instructions.
+  if (vex_byte0_ != 0) {
+    data += AVXInstruction(data);
+  } else {
+    const InstructionDesc& idesc = instruction_table_->Get(*data);
+    switch (idesc.type) {
+      case ZERO_OPERANDS_INSTR:
+        AppendToBuffer(idesc.mnem);
+        data++;
+        break;
 
-    case TWO_OPERANDS_INSTR:
-      data++;
-      data += PrintOperands(idesc.mnem, idesc.op_order_, data);
-      break;
+      case TWO_OPERANDS_INSTR:
+        data++;
+        data += PrintOperands(idesc.mnem, idesc.op_order_, data);
+        break;
 
-    case JUMP_CONDITIONAL_SHORT_INSTR:
-      data += JumpConditionalShort(data, branch_hint);
-      break;
+      case JUMP_CONDITIONAL_SHORT_INSTR:
+        data += JumpConditionalShort(data, branch_hint);
+        break;
 
-    case REGISTER_INSTR:
-      AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
-      data++;
-      break;
+      case REGISTER_INSTR:
+        AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
+        data++;
+        break;
 
-    case MOVE_REG_INSTR: {
-      byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
-      AppendToBuffer("mov %s,%s",
-                     NameOfCPURegister(*data & 0x07),
-                     NameOfAddress(addr));
-      data += 5;
-      break;
+      case MOVE_REG_INSTR: {
+        byte* addr =
+            reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
+        AppendToBuffer("mov %s,%s", NameOfCPURegister(*data & 0x07),
+                       NameOfAddress(addr));
+        data += 5;
+        break;
+      }
+
+      case CALL_JUMP_INSTR: {
+        byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
+        AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
+        data += 5;
+        break;
+      }
+
+      case SHORT_IMMEDIATE_INSTR: {
+        byte* addr =
+            reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
+        AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
+        data += 5;
+        break;
+      }
+
+      case BYTE_IMMEDIATE_INSTR: {
+        AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
+        data += 2;
+        break;
+      }
+
+      case NO_INSTR:
+        processed = false;
+        break;
+
+      default:
+        UNIMPLEMENTED();  // This type is not implemented.
     }
-
-    case CALL_JUMP_INSTR: {
-      byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5;
-      AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
-      data += 5;
-      break;
-    }
-
-    case SHORT_IMMEDIATE_INSTR: {
-      byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
-      AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
-      data += 5;
-      break;
-    }
-
-    case BYTE_IMMEDIATE_INSTR: {
-      AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
-      data += 2;
-      break;
-    }
-
-    case NO_INSTR:
-      processed = false;
-      break;
-
-    default:
-      UNIMPLEMENTED();  // This type is not implemented.
   }
   //----------------------------
   if (!processed) {
@@ -1047,6 +1226,12 @@
                            NameOfXMMRegister(regop),
                            NameOfXMMRegister(rm));
             data++;
+          } else if (f0byte == 0x2e) {
+            data += 2;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
+            data += PrintRightXMMOperand(data);
           } else if (f0byte >= 0x53 && f0byte <= 0x5F) {
             const char* const pseudo_op[] = {
               "rcpps",
@@ -1386,6 +1571,15 @@
                            NameOfXMMRegister(regop),
                            NameOfXMMRegister(rm));
             data++;
+          } else if (*data == 0x72) {
+            data++;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            int8_t imm8 = static_cast<int8_t>(data[1]);
+            DCHECK(regop == esi || regop == edx);
+            AppendToBuffer("%s %s,%d", (regop == esi) ? "pslld" : "psrld",
+                           NameOfXMMRegister(rm), static_cast<int>(imm8));
+            data += 2;
           } else if (*data == 0x73) {
             data++;
             int mod, regop, rm;
@@ -1608,12 +1802,36 @@
             get_modrm(*data, &mod, &regop, &rm);
             AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop));
             data += PrintRightXMMOperand(data);
+          } else if (b2 == 0x58) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("addss %s,", NameOfXMMRegister(regop));
+            data += PrintRightXMMOperand(data);
+          } else if (b2 == 0x59) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("mulss %s,", NameOfXMMRegister(regop));
+            data += PrintRightXMMOperand(data);
           } else if (b2 == 0x5A) {
             data += 3;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
             AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
             data += PrintRightXMMOperand(data);
+          } else if (b2 == 0x5c) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("subss %s,", NameOfXMMRegister(regop));
+            data += PrintRightXMMOperand(data);
+          } else if (b2 == 0x5e) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("divss %s,", NameOfXMMRegister(regop));
+            data += PrintRightXMMOperand(data);
           } else if (b2 == 0x6F) {
             data += 3;
             int mod, regop, rm;
@@ -1681,17 +1899,17 @@
 //------------------------------------------------------------------------------
 
 
-static const char* cpu_regs[8] = {
+static const char* const cpu_regs[8] = {
   "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
 };
 
 
-static const char* byte_cpu_regs[8] = {
+static const char* const byte_cpu_regs[8] = {
   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
 };
 
 
-static const char* xmm_regs[8] = {
+static const char* const xmm_regs[8] = {
   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
 };