Version 3.11.4

Some cleanup to common.gypi. This fixes some host/target combinations that weren't working in the Make build on Mac.

Handle EINTR in socket functions and continue incomplete sends. (issue 2098)

Fixed python deprecations.  (issue 1391)

Made socket send and receive more robust and return 0 on failure. (Chromium issue 15719)

Fixed GCC 4.7 (C++11) compilation.  (issue 2136)

Set '-m32' option for host and target platforms

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@11619 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 979c9c0..97dac40 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2012-05-22: Version 3.11.4
+
+        Some cleanup to common.gypi. This fixes some host/target combinations
+        that weren't working in the Make build on Mac.
+
+        Handle EINTR in socket functions and continue incomplete sends.
+        (issue 2098)
+
+        Fixed python deprecations.  (issue 1391)
+
+        Made socket send and receive more robust and return 0 on failure.
+        (Chromium issue 15719)
+
+        Fixed GCC 4.7 (C++11) compilation.  (issue 2136)
+
+        Set '-m32' option for host and target platforms
+
+        Performance and stability improvements on all platforms.
+
+
 2012-05-18: Version 3.11.3
 
         Disable optimization for functions that have scopes that cannot be
diff --git a/Makefile b/Makefile
index fbca566..0d825c0 100644
--- a/Makefile
+++ b/Makefile
@@ -228,6 +228,7 @@
                             must-set-ANDROID_NDK_ROOT
 	GYP_GENERATORS=make \
 	CC="${ANDROID_TOOL_PREFIX}-gcc" \
+	CXX="${ANDROID_TOOL_PREFIX}-g++" \
 	build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
 	              -Ibuild/standalone.gypi --depth=. -Ibuild/android.gypi \
 	              -S.android $(GYPFLAGS)
diff --git a/build/common.gypi b/build/common.gypi
index 4a9d45d..1726d2a 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -110,151 +110,117 @@
       ['v8_enable_gdbjit==1', {
         'defines': ['ENABLE_GDB_JIT_INTERFACE',],
       }],
-      ['OS!="mac"', {
-        # TODO(mark): The OS!="mac" conditional is temporary. It can be
-        # removed once the Mac Chromium build stops setting target_arch to
-        # ia32 and instead sets it to mac. Other checks in this file for
-        # OS=="mac" can be removed at that time as well. This can be cleaned
-        # up once http://crbug.com/44205 is fixed.
+      ['v8_target_arch=="arm"', {
+        'defines': [
+          'V8_TARGET_ARCH_ARM',
+        ],
         'conditions': [
-          ['v8_target_arch=="arm"', {
+          [ 'v8_can_use_unaligned_accesses=="true"', {
             'defines': [
-              'V8_TARGET_ARCH_ARM',
-            ],
-            'conditions': [
-              [ 'v8_can_use_unaligned_accesses=="true"', {
-                'defines': [
-                  'CAN_USE_UNALIGNED_ACCESSES=1',
-                ],
-              }],
-              [ 'v8_can_use_unaligned_accesses=="false"', {
-                'defines': [
-                  'CAN_USE_UNALIGNED_ACCESSES=0',
-                ],
-              }],
-              [ 'v8_can_use_vfp_instructions=="true"', {
-                'defines': [
-                  'CAN_USE_VFP_INSTRUCTIONS',
-                ],
-              }],
-              [ 'v8_use_arm_eabi_hardfloat=="true"', {
-                'defines': [
-                  'USE_EABI_HARDFLOAT=1',
-                  'CAN_USE_VFP_INSTRUCTIONS',
-                ],
-                'target_conditions': [
-                  ['_toolset=="target"', {
-                    'cflags': ['-mfloat-abi=hard',],
-                  }],
-                ],
-              }, {
-                'defines': [
-                  'USE_EABI_HARDFLOAT=0',
-                ],
-              }],
-              # The ARM assembler assumes the host is 32 bits,
-              # so force building 32-bit host tools.
-              ['host_arch=="x64" or OS=="android"', {
-                'target_conditions': [
-                  ['_toolset=="host"', {
-                    'cflags': ['-m32'],
-                    'ldflags': ['-m32'],
-                  }],
-                ],
-              }],
+              'CAN_USE_UNALIGNED_ACCESSES=1',
             ],
           }],
-          ['v8_target_arch=="ia32"', {
+          [ 'v8_can_use_unaligned_accesses=="false"', {
             'defines': [
-              'V8_TARGET_ARCH_IA32',
+              'CAN_USE_UNALIGNED_ACCESSES=0',
             ],
           }],
-          ['v8_target_arch=="mips"', {
+          [ 'v8_can_use_vfp_instructions=="true"', {
             'defines': [
-              'V8_TARGET_ARCH_MIPS',
-            ],
-            'variables': {
-              'mipscompiler': '<!($(echo ${CXX:-$(which g++)}) -v 2>&1 | grep -q "^Target: mips-" && echo "yes" || echo "no")',
-            },
-            'conditions': [
-              ['mipscompiler=="yes"', {
-                'target_conditions': [
-                  ['_toolset=="target"', {
-                    'cflags': ['-EL'],
-                    'ldflags': ['-EL'],
-                    'conditions': [
-                      [ 'v8_use_mips_abi_hardfloat=="true"', {
-                        'cflags': ['-mhard-float'],
-                        'ldflags': ['-mhard-float'],
-                      }, {
-                        'cflags': ['-msoft-float'],
-                        'ldflags': ['-msoft-float'],
-                      }],
-                      ['mips_arch_variant=="mips32r2"', {
-                        'cflags': ['-mips32r2', '-Wa,-mips32r2'],
-                      }],
-                      ['mips_arch_variant=="loongson"', {
-                        'cflags': ['-mips3', '-Wa,-mips3'],
-                      }, {
-                        'cflags': ['-mips32', '-Wa,-mips32'],
-                      }],
-                    ],
-                  }],
-                ],
-              }],
-              [ 'v8_can_use_fpu_instructions=="true"', {
-                'defines': [
-                  'CAN_USE_FPU_INSTRUCTIONS',
-                ],
-              }],
-              [ 'v8_use_mips_abi_hardfloat=="true"', {
-                'defines': [
-                  '__mips_hard_float=1',
-                  'CAN_USE_FPU_INSTRUCTIONS',
-                ],
-              }, {
-                'defines': [
-                  '__mips_soft_float=1'
-                ],
-              }],
-              ['mips_arch_variant=="mips32r2"', {
-                'defines': ['_MIPS_ARCH_MIPS32R2',],
-              }],
-              ['mips_arch_variant=="loongson"', {
-                'defines': ['_MIPS_ARCH_LOONGSON',],
-              }],
-              # The MIPS assembler assumes the host is 32 bits,
-              # so force building 32-bit host tools.
-              ['host_arch=="x64"', {
-                'target_conditions': [
-                  ['_toolset=="host"', {
-                    'cflags': ['-m32'],
-                    'ldflags': ['-m32'],
-                  }],
-                ],
-              }],
+              'CAN_USE_VFP_INSTRUCTIONS',
             ],
           }],
-          ['v8_target_arch=="x64"', {
+          [ 'v8_use_arm_eabi_hardfloat=="true"', {
             'defines': [
-              'V8_TARGET_ARCH_X64',
+              'USE_EABI_HARDFLOAT=1',
+              'CAN_USE_VFP_INSTRUCTIONS',
+            ],
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': ['-mfloat-abi=hard',],
+              }],
+            ],
+          }, {
+            'defines': [
+              'USE_EABI_HARDFLOAT=0',
             ],
           }],
         ],
-      }, {  # Section for OS=="mac".
+      }],  # v8_target_arch=="arm"
+      ['v8_target_arch=="ia32"', {
+        'defines': [
+          'V8_TARGET_ARCH_IA32',
+        ],
+      }],  # v8_target_arch=="ia32"
+      ['v8_target_arch=="mips"', {
+        'defines': [
+          'V8_TARGET_ARCH_MIPS',
+        ],
+        'variables': {
+          'mipscompiler': '<!($(echo ${CXX:-$(which g++)}) -v 2>&1 | grep -q "^Target: mips-" && echo "yes" || echo "no")',
+        },
         'conditions': [
-          ['target_arch=="ia32"', {
-            'xcode_settings': {
-              'ARCHS': ['i386'],
-            }
+          ['mipscompiler=="yes"', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': ['-EL'],
+                'ldflags': ['-EL'],
+                'conditions': [
+                  [ 'v8_use_mips_abi_hardfloat=="true"', {
+                    'cflags': ['-mhard-float'],
+                    'ldflags': ['-mhard-float'],
+                  }, {
+                    'cflags': ['-msoft-float'],
+                    'ldflags': ['-msoft-float'],
+                  }],
+                  ['mips_arch_variant=="mips32r2"', {
+                    'cflags': ['-mips32r2', '-Wa,-mips32r2'],
+                  }],
+                  ['mips_arch_variant=="loongson"', {
+                    'cflags': ['-mips3', '-Wa,-mips3'],
+                  }, {
+                    'cflags': ['-mips32', '-Wa,-mips32'],
+                  }],
+                ],
+              }],
+            ],
           }],
-          ['target_arch=="x64"', {
-            'xcode_settings': {
-              'ARCHS': ['x86_64'],
-            }
+          [ 'v8_can_use_fpu_instructions=="true"', {
+            'defines': [
+              'CAN_USE_FPU_INSTRUCTIONS',
+            ],
+          }],
+          [ 'v8_use_mips_abi_hardfloat=="true"', {
+            'defines': [
+              '__mips_hard_float=1',
+              'CAN_USE_FPU_INSTRUCTIONS',
+            ],
+          }, {
+            'defines': [
+              '__mips_soft_float=1'
+            ],
+          }],
+          ['mips_arch_variant=="mips32r2"', {
+            'defines': ['_MIPS_ARCH_MIPS32R2',],
+          }],
+          ['mips_arch_variant=="loongson"', {
+            'defines': ['_MIPS_ARCH_LOONGSON',],
           }],
         ],
-      }],
+      }],  # v8_target_arch=="mips"
+      ['v8_target_arch=="x64"', {
+        'defines': [
+          'V8_TARGET_ARCH_X64',
+        ],
+        'xcode_settings': {
+          'ARCHS': [ 'x86_64' ],
+        },
+        'msvs_settings': {
+          'VCLinkerTool': {
+            'StackReserveSize': '2097152',
+          },
+        },
+      }],  # v8_target_arch=="x64"
       ['v8_use_liveobjectlist=="true"', {
         'defines': [
           'ENABLE_DEBUGGER_SUPPORT',
@@ -280,24 +246,9 @@
           },
         },
       }],
-      ['OS=="win" and v8_target_arch=="x64"', {
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'StackReserveSize': '2097152',
-          },
-        },
-      }],
       ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
          or OS=="netbsd"', {
         'conditions': [
-          [ 'v8_target_arch!="x64"', {
-            # Pass -m32 to the compiler iff it understands the flag.
-            'variables': {
-              'm32flag': '<!((echo | $(echo ${CXX:-$(which g++)}) -m32 -E - > /dev/null 2>&1) && echo -n "-m32" || true)',
-            },
-            'cflags': [ '<(m32flag)' ],
-            'ldflags': [ '<(m32flag)' ],
-          }],
           [ 'v8_no_strict_aliasing==1', {
             'cflags': [ '-fno-strict-aliasing' ],
           }],
@@ -306,6 +257,41 @@
       ['OS=="solaris"', {
         'defines': [ '__C99FEATURES__=1' ],  # isinf() etc.
       }],
+      ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
+         or OS=="netbsd" or OS=="mac" or OS=="android") and \
+        (v8_target_arch=="arm" or v8_target_arch=="ia32" or \
+         v8_target_arch=="mips")', {
+        # Check whether the host compiler and target compiler support the
+        # '-m32' option and set it if so.
+        'target_conditions': [
+          ['_toolset=="host"', {
+            'variables': {
+              'm32flag': '<!((echo | $(echo ${CXX_host:-${CXX:-$(which g++)}}) -m32 -E - > /dev/null 2>&1) && echo -n "-m32" || true)',
+            },
+            'cflags': [ '<(m32flag)' ],
+            'ldflags': [ '<(m32flag)' ],
+            'xcode_settings': {
+              'ARCHS': [ 'i386' ],
+            },
+          }],
+          ['_toolset=="target"', {
+            'variables': {
+              'm32flag': '<!((echo | $(echo ${CXX_target:-${CXX:-$(which g++)}}) -m32 -E - > /dev/null 2>&1) && echo -n "-m32" || true)',
+            },
+            'cflags': [ '<(m32flag)' ],
+            'ldflags': [ '<(m32flag)' ],
+            'xcode_settings': {
+              'ARCHS': [ 'i386' ],
+            },
+          }],
+        ],
+      }],
+      ['OS=="freebsd" or OS=="openbsd"', {
+        'cflags': [ '-I/usr/local/include' ],
+      }],
+      ['OS=="netbsd"', {
+        'cflags': [ '-I/usr/pkg/include' ],
+      }],
     ],  # conditions
     'configurations': {
       'Debug': {
@@ -332,12 +318,6 @@
           },
         },
         'conditions': [
-          ['OS=="freebsd" or OS=="openbsd"', {
-            'cflags': [ '-I/usr/local/include' ],
-          }],
-          ['OS=="netbsd"', {
-            'cflags': [ '-I/usr/pkg/include' ],
-          }],
           ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', {
             'cflags': [ '-Wall', '<(werror)', '-W', '-Wno-unused-parameter',
                         '-Wnon-virtual-dtor', '-Woverloaded-virtual' ],
@@ -367,12 +347,6 @@
               }],
             ],
           }],
-          ['OS=="freebsd" or OS=="openbsd"', {
-            'cflags': [ '-I/usr/local/include' ],
-          }],
-          ['OS=="netbsd"', {
-            'cflags': [ '-I/usr/pkg/include' ],
-          }],
           ['OS=="mac"', {
             'xcode_settings': {
               'GCC_OPTIMIZATION_LEVEL': '3',  # -O3
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index ec8aac8..dbae813 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -1236,6 +1236,7 @@
 
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1252,13 +1253,13 @@
 
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
 class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
-                                    LOperand* key) {
+  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand* key) {
     inputs_[0] = external_pointer;
     inputs_[1] = key;
   }
@@ -1272,6 +1273,7 @@
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1740,6 +1742,7 @@
   LOperand* object() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1762,6 +1765,7 @@
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 
   bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
 };
@@ -1806,6 +1810,7 @@
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index bf11ab9..d224d24 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2744,7 +2744,9 @@
 
   // Load the result.
   __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
-  __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize));
+  uint32_t offset = FixedArray::kHeaderSize +
+                    (instr->additional_index() << kPointerSizeLog2);
+  __ ldr(result, FieldMemOperand(scratch, offset));
 
   // Check for the hole value.
   if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -2776,13 +2778,14 @@
   }
 
   Operand operand = key_is_constant
-      ? Operand(constant_key * (1 << shift_size) +
+      ? Operand(((constant_key + instr->additional_index()) << shift_size) +
                 FixedDoubleArray::kHeaderSize - kHeapObjectTag)
       : Operand(key, LSL, shift_size);
   __ add(elements, elements, operand);
   if (!key_is_constant) {
     __ add(elements, elements,
-           Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+           Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
+                   (instr->additional_index() << shift_size)));
   }
 
   __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
@@ -2809,26 +2812,33 @@
     key = ToRegister(instr->key());
   }
   int shift_size = ElementsKindToShiftSize(elements_kind);
+  int additional_offset = instr->additional_index() << shift_size;
 
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
       elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
     CpuFeatures::Scope scope(VFP3);
     DwVfpRegister result = ToDoubleRegister(instr->result());
     Operand operand = key_is_constant
-        ? Operand(constant_key * (1 << shift_size))
+        ? Operand(constant_key << shift_size)
         : Operand(key, LSL, shift_size);
     __ add(scratch0(), external_pointer, operand);
     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
-      __ vldr(result.low(), scratch0(), 0);
+      __ vldr(result.low(), scratch0(), additional_offset);
       __ vcvt_f64_f32(result, result.low());
     } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
-      __ vldr(result, scratch0(), 0);
+      __ vldr(result, scratch0(), additional_offset);
     }
   } else {
     Register result = ToRegister(instr->result());
+    if (instr->additional_index() != 0 && !key_is_constant) {
+      __ add(scratch0(), key, Operand(instr->additional_index()));
+    }
     MemOperand mem_operand(key_is_constant
-        ? MemOperand(external_pointer, constant_key * (1 << shift_size))
-        : MemOperand(external_pointer, key, LSL, shift_size));
+        ? MemOperand(external_pointer,
+                     (constant_key << shift_size) + additional_offset)
+        : (instr->additional_index() == 0
+           ? MemOperand(external_pointer, key, LSL, shift_size)
+           : MemOperand(external_pointer, scratch0(), LSL, shift_size)));
     switch (elements_kind) {
       case EXTERNAL_BYTE_ELEMENTS:
         __ ldrsb(result, mem_operand);
@@ -3726,10 +3736,16 @@
     ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
     LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
     int offset =
-        ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
+        (ToInteger32(const_operand) + instr->additional_index()) * kPointerSize
+        + FixedArray::kHeaderSize;
     __ str(value, FieldMemOperand(elements, offset));
   } else {
     __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
+    if (instr->additional_index() != 0) {
+      __ add(scratch,
+             scratch,
+             Operand(instr->additional_index() << kPointerSizeLog2));
+    }
     __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize));
   }
 
@@ -3771,7 +3787,7 @@
   }
   int shift_size = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
   Operand operand = key_is_constant
-      ? Operand(constant_key * (1 << shift_size) +
+      ? Operand((constant_key << shift_size) +
                 FixedDoubleArray::kHeaderSize - kHeapObjectTag)
       : Operand(key, LSL, shift_size);
   __ add(scratch, elements, operand);
@@ -3789,7 +3805,7 @@
             vs);
   }
 
-  __ vstr(value, scratch, 0);
+  __ vstr(value, scratch, instr->additional_index() << shift_size);
 }
 
 
@@ -3810,25 +3826,33 @@
     key = ToRegister(instr->key());
   }
   int shift_size = ElementsKindToShiftSize(elements_kind);
+  int additional_offset = instr->additional_index() << shift_size;
 
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
       elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
     CpuFeatures::Scope scope(VFP3);
     DwVfpRegister value(ToDoubleRegister(instr->value()));
-    Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
+    Operand operand(key_is_constant ? Operand(constant_key << shift_size)
                                     : Operand(key, LSL, shift_size));
     __ add(scratch0(), external_pointer, operand);
     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
       __ vcvt_f32_f64(double_scratch0().low(), value);
-      __ vstr(double_scratch0().low(), scratch0(), 0);
+      __ vstr(double_scratch0().low(), scratch0(), additional_offset);
     } else {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
-      __ vstr(value, scratch0(), 0);
+      __ vstr(value, scratch0(), additional_offset);
     }
   } else {
     Register value(ToRegister(instr->value()));
+    if (instr->additional_index() != 0 && !key_is_constant) {
+      __ add(scratch0(), key, Operand(instr->additional_index()));
+    }
     MemOperand mem_operand(key_is_constant
-        ? MemOperand(external_pointer, constant_key * (1 << shift_size))
-        : MemOperand(external_pointer, key, LSL, shift_size));
+        ? MemOperand(external_pointer,
+                     ((constant_key + instr->additional_index())
+                         << shift_size))
+        : (instr->additional_index() == 0
+            ? MemOperand(external_pointer, key, LSL, shift_size)
+            : MemOperand(external_pointer, scratch0(), LSL, shift_size)));
     switch (elements_kind) {
       case EXTERNAL_PIXEL_ELEMENTS:
       case EXTERNAL_BYTE_ELEMENTS:
diff --git a/src/debug-agent.cc b/src/debug-agent.cc
index 511663d..10c0053 100644
--- a/src/debug-agent.cc
+++ b/src/debug-agent.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// 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:
@@ -247,7 +247,7 @@
     while (!(c == '\n' && prev_c == '\r')) {
       prev_c = c;
       received = conn->Receive(&c, 1);
-      if (received <= 0) {
+      if (received == 0) {
         PrintF("Error %d\n", Socket::LastError());
         return SmartArrayPointer<char>();
       }
@@ -454,7 +454,7 @@
   int total_received = 0;
   while (total_received < len) {
     int received = conn->Receive(data + total_received, len - total_received);
-    if (received <= 0) {
+    if (received == 0) {
       return total_received;
     }
     total_received += received;
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 62a9782..ccba511 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -197,6 +197,8 @@
 DEFINE_bool(use_osr, true, "use on-stack replacement")
 DEFINE_bool(array_bounds_checks_elimination, true,
             "perform array bounds checks elimination")
+DEFINE_bool(array_index_dehoisting, false,
+            "perform array index dehoisting")
 
 DEFINE_bool(trace_osr, false, "trace on-stack replacement")
 DEFINE_int(stress_runs, 0, "number of stress runs")
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 9d262fc..4f21db7 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -3946,15 +3946,27 @@
   virtual bool DataEquals(HValue* other) { return true; }
 };
 
+class ArrayInstructionInterface {
+ public:
+  virtual HValue* GetKey() = 0;
+  virtual void SetKey(HValue* key) = 0;
+  virtual void SetIndexOffset(uint32_t index_offset) = 0;
+  virtual bool IsDehoisted() = 0;
+  virtual void SetDehoisted(bool is_dehoisted) = 0;
+  virtual ~ArrayInstructionInterface() { };
+};
 
-class HLoadKeyedFastElement: public HTemplateInstruction<2> {
+class HLoadKeyedFastElement
+    : public HTemplateInstruction<2>, public ArrayInstructionInterface {
  public:
   enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK };
 
   HLoadKeyedFastElement(HValue* obj,
                         HValue* key,
                         HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
-      : hole_check_mode_(hole_check_mode) {
+      : hole_check_mode_(hole_check_mode),
+        index_offset_(0),
+        is_dehoisted_(false) {
     SetOperandAt(0, obj);
     SetOperandAt(1, key);
     set_representation(Representation::Tagged());
@@ -3964,6 +3976,12 @@
 
   HValue* object() { return OperandAt(0); }
   HValue* key() { return OperandAt(1); }
+  uint32_t index_offset() { return index_offset_; }
+  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
+  HValue* GetKey() { return key(); }
+  void SetKey(HValue* key) { SetOperandAt(1, key); }
+  bool IsDehoisted() { return is_dehoisted_; }
+  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
 
   virtual Representation RequiredInputRepresentation(int index) {
     // The key is supposed to be Integer32.
@@ -3982,17 +4000,23 @@
   virtual bool DataEquals(HValue* other) {
     if (!other->IsLoadKeyedFastElement()) return false;
     HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other);
+    if (is_dehoisted_ && index_offset_ != other_load->index_offset_)
+      return false;
     return hole_check_mode_ == other_load->hole_check_mode_;
   }
 
  private:
   HoleCheckMode hole_check_mode_;
+  uint32_t index_offset_;
+  bool is_dehoisted_;
 };
 
 
-class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
+class HLoadKeyedFastDoubleElement
+    : public HTemplateInstruction<2>, public ArrayInstructionInterface {
  public:
-  HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) {
+  HLoadKeyedFastDoubleElement(HValue* elements, HValue* key)
+      : index_offset_(0), is_dehoisted_(false) {
     SetOperandAt(0, elements);
     SetOperandAt(1, key);
     set_representation(Representation::Double());
@@ -4002,6 +4026,12 @@
 
   HValue* elements() { return OperandAt(0); }
   HValue* key() { return OperandAt(1); }
+  uint32_t index_offset() { return index_offset_; }
+  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
+  HValue* GetKey() { return key(); }
+  void SetKey(HValue* key) { SetOperandAt(1, key); }
+  bool IsDehoisted() { return is_dehoisted_; }
+  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
 
   virtual Representation RequiredInputRepresentation(int index) {
     // The key is supposed to be Integer32.
@@ -4016,15 +4046,22 @@
 
  protected:
   virtual bool DataEquals(HValue* other) { return true; }
+
+ private:
+  uint32_t index_offset_;
+  bool is_dehoisted_;
 };
 
 
-class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
+class HLoadKeyedSpecializedArrayElement
+    : public HTemplateInstruction<2>, public ArrayInstructionInterface {
  public:
   HLoadKeyedSpecializedArrayElement(HValue* external_elements,
                                     HValue* key,
                                     ElementsKind elements_kind)
-      :  elements_kind_(elements_kind) {
+      :  elements_kind_(elements_kind),
+         index_offset_(0),
+         is_dehoisted_(false) {
     SetOperandAt(0, external_elements);
     SetOperandAt(1, key);
     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
@@ -4052,6 +4089,12 @@
   HValue* external_pointer() { return OperandAt(0); }
   HValue* key() { return OperandAt(1); }
   ElementsKind elements_kind() const { return elements_kind_; }
+  uint32_t index_offset() { return index_offset_; }
+  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
+  HValue* GetKey() { return key(); }
+  void SetKey(HValue* key) { SetOperandAt(1, key); }
+  bool IsDehoisted() { return is_dehoisted_; }
+  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
 
   virtual Range* InferRange(Zone* zone);
 
@@ -4067,6 +4110,8 @@
 
  private:
   ElementsKind elements_kind_;
+  uint32_t index_offset_;
+  bool is_dehoisted_;
 };
 
 
@@ -4188,11 +4233,12 @@
 };
 
 
-class HStoreKeyedFastElement: public HTemplateInstruction<3> {
+class HStoreKeyedFastElement
+    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
  public:
   HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val,
                          ElementsKind elements_kind = FAST_ELEMENTS)
-      : elements_kind_(elements_kind) {
+      : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) {
     SetOperandAt(0, obj);
     SetOperandAt(1, key);
     SetOperandAt(2, val);
@@ -4212,6 +4258,12 @@
   bool value_is_smi() {
     return elements_kind_ == FAST_SMI_ONLY_ELEMENTS;
   }
+  uint32_t index_offset() { return index_offset_; }
+  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
+  HValue* GetKey() { return key(); }
+  void SetKey(HValue* key) { SetOperandAt(1, key); }
+  bool IsDehoisted() { return is_dehoisted_; }
+  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
 
   bool NeedsWriteBarrier() {
     if (value_is_smi()) {
@@ -4227,14 +4279,18 @@
 
  private:
   ElementsKind elements_kind_;
+  uint32_t index_offset_;
+  bool is_dehoisted_;
 };
 
 
-class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
+class HStoreKeyedFastDoubleElement
+    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
  public:
   HStoreKeyedFastDoubleElement(HValue* elements,
                                HValue* key,
-                               HValue* val) {
+                               HValue* val)
+      : index_offset_(0), is_dehoisted_(false) {
     SetOperandAt(0, elements);
     SetOperandAt(1, key);
     SetOperandAt(2, val);
@@ -4254,6 +4310,12 @@
   HValue* elements() { return OperandAt(0); }
   HValue* key() { return OperandAt(1); }
   HValue* value() { return OperandAt(2); }
+  uint32_t index_offset() { return index_offset_; }
+  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
+  HValue* GetKey() { return key(); }
+  void SetKey(HValue* key) { SetOperandAt(1, key); }
+  bool IsDehoisted() { return is_dehoisted_; }
+  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
 
   bool NeedsWriteBarrier() {
     return StoringValueNeedsWriteBarrier(value());
@@ -4264,16 +4326,21 @@
   virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
+
+ private:
+  uint32_t index_offset_;
+  bool is_dehoisted_;
 };
 
 
-class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
+class HStoreKeyedSpecializedArrayElement
+    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
  public:
   HStoreKeyedSpecializedArrayElement(HValue* external_elements,
                                      HValue* key,
                                      HValue* val,
                                      ElementsKind elements_kind)
-      : elements_kind_(elements_kind) {
+      : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) {
     SetGVNFlag(kChangesSpecializedArrayElements);
     SetOperandAt(0, external_elements);
     SetOperandAt(1, key);
@@ -4301,11 +4368,19 @@
   HValue* key() { return OperandAt(1); }
   HValue* value() { return OperandAt(2); }
   ElementsKind elements_kind() const { return elements_kind_; }
+  uint32_t index_offset() { return index_offset_; }
+  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
+  HValue* GetKey() { return key(); }
+  void SetKey(HValue* key) { SetOperandAt(1, key); }
+  bool IsDehoisted() { return is_dehoisted_; }
+  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement)
 
  private:
   ElementsKind elements_kind_;
+  uint32_t index_offset_;
+  bool is_dehoisted_;
 };
 
 
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 4e9afc6..99beda0 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -2758,6 +2758,7 @@
   sce.Process();
 
   graph()->EliminateRedundantBoundsChecks();
+  graph()->DehoistSimpleArrayIndexComputations();
 
   return graph();
 }
@@ -3016,7 +3017,6 @@
     HBoundsCheck* check = HBoundsCheck::cast(i);
     check->ReplaceAllUsesWith(check->index());
 
-    isolate()->counters()->array_bounds_checks_seen()->Increment();
     if (!FLAG_array_bounds_checks_elimination) continue;
 
     int32_t offset;
@@ -3035,10 +3035,8 @@
       *data_p = bb_data_list;
     } else if (data->OffsetIsCovered(offset)) {
       check->DeleteAndReplaceWith(NULL);
-      isolate()->counters()->array_bounds_checks_removed()->Increment();
     } else if (data->BasicBlock() == bb) {
       data->CoverCheck(check, offset);
-      isolate()->counters()->array_bounds_checks_removed()->Increment();
     } else {
       int32_t new_lower_offset = offset < data->LowerOffset()
           ? offset
@@ -3082,6 +3080,93 @@
 }
 
 
+static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
+  HValue* index = array_operation->GetKey();
+
+  HConstant* constant;
+  HValue* subexpression;
+  int32_t sign;
+  if (index->IsAdd()) {
+    sign = 1;
+    HAdd* add = HAdd::cast(index);
+    if (add->left()->IsConstant()) {
+      subexpression = add->right();
+      constant = HConstant::cast(add->left());
+    } else if (add->right()->IsConstant()) {
+      subexpression = add->left();
+      constant = HConstant::cast(add->right());
+    } else {
+      return;
+    }
+  } else if (index->IsSub()) {
+    sign = -1;
+    HSub* sub = HSub::cast(index);
+    if (sub->left()->IsConstant()) {
+      subexpression = sub->right();
+      constant = HConstant::cast(sub->left());
+    } else if (sub->right()->IsConstant()) {
+      subexpression = sub->left();
+      constant = HConstant::cast(sub->right());
+    } return;
+  } else {
+    return;
+  }
+
+  if (!constant->HasInteger32Value()) return;
+  int32_t value = constant->Integer32Value() * sign;
+  // We limit offset values to 30 bits because we want to avoid the risk of
+  // overflows when the offset is added to the object header size.
+  if (value >= 1 << 30 || value < 0) return;
+  array_operation->SetKey(subexpression);
+  if (index->HasNoUses()) {
+    index->DeleteAndReplaceWith(NULL);
+  }
+  ASSERT(value >= 0);
+  array_operation->SetIndexOffset(static_cast<uint32_t>(value));
+  array_operation->SetDehoisted(true);
+}
+
+
+void HGraph::DehoistSimpleArrayIndexComputations() {
+  if (!FLAG_array_index_dehoisting) return;
+
+  HPhase phase("H_Dehoist index computations", this);
+  for (int i = 0; i < blocks()->length(); ++i) {
+    for (HInstruction* instr = blocks()->at(i)->first();
+        instr != NULL;
+        instr = instr->next()) {
+      ArrayInstructionInterface* array_instruction = NULL;
+      if (instr->IsLoadKeyedFastElement()) {
+        HLoadKeyedFastElement* op = HLoadKeyedFastElement::cast(instr);
+        array_instruction = static_cast<ArrayInstructionInterface*>(op);
+      } else if (instr->IsLoadKeyedFastDoubleElement()) {
+        HLoadKeyedFastDoubleElement* op =
+            HLoadKeyedFastDoubleElement::cast(instr);
+        array_instruction = static_cast<ArrayInstructionInterface*>(op);
+      } else if (instr->IsLoadKeyedSpecializedArrayElement()) {
+        HLoadKeyedSpecializedArrayElement* op =
+            HLoadKeyedSpecializedArrayElement::cast(instr);
+        array_instruction = static_cast<ArrayInstructionInterface*>(op);
+      } else if (instr->IsStoreKeyedFastElement()) {
+        HStoreKeyedFastElement* op = HStoreKeyedFastElement::cast(instr);
+        array_instruction = static_cast<ArrayInstructionInterface*>(op);
+      } else if (instr->IsStoreKeyedFastDoubleElement()) {
+        HStoreKeyedFastDoubleElement* op =
+            HStoreKeyedFastDoubleElement::cast(instr);
+        array_instruction = static_cast<ArrayInstructionInterface*>(op);
+      } else if (instr->IsStoreKeyedSpecializedArrayElement()) {
+        HStoreKeyedSpecializedArrayElement* op =
+            HStoreKeyedSpecializedArrayElement::cast(instr);
+        array_instruction = static_cast<ArrayInstructionInterface*>(op);
+      } else {
+        continue;
+      }
+      DehoistArrayIndex(array_instruction);
+    }
+  }
+}
+
+
 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
   ASSERT(current_block() != NULL);
   current_block()->AddInstruction(instr);
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 909d07b..b56a5af 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -267,6 +267,7 @@
   void AssignDominators();
   void ReplaceCheckedValues();
   void EliminateRedundantBoundsChecks();
+  void DehoistSimpleArrayIndexComputations();
   void PropagateDeoptimizingMark();
 
   // Returns false if there are phi-uses of the arguments-object
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 455c502..fa58146 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2421,9 +2421,11 @@
 
   // Load the result.
   __ mov(result,
-         BuildFastArrayOperand(instr->elements(), instr->key(),
+         BuildFastArrayOperand(instr->elements(),
+                               instr->key(),
                                FAST_ELEMENTS,
-                               FixedArray::kHeaderSize - kHeapObjectTag));
+                               FixedArray::kHeaderSize - kHeapObjectTag,
+                               instr->additional_index()));
 
   // Check for the hole value.
   if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -2442,13 +2444,17 @@
   Operand hole_check_operand = BuildFastArrayOperand(
       instr->elements(), instr->key(),
       FAST_DOUBLE_ELEMENTS,
-      offset);
+      offset,
+      instr->additional_index());
   __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
   DeoptimizeIf(equal, instr->environment());
 
   Operand double_load_operand = BuildFastArrayOperand(
-      instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS,
-      FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+      instr->elements(),
+      instr->key(),
+      FAST_DOUBLE_ELEMENTS,
+      FixedDoubleArray::kHeaderSize - kHeapObjectTag,
+      instr->additional_index());
   __ movdbl(result, double_load_operand);
 }
 
@@ -2457,7 +2463,8 @@
     LOperand* elements_pointer,
     LOperand* key,
     ElementsKind elements_kind,
-    uint32_t offset) {
+    uint32_t offset,
+    uint32_t additional_index) {
   Register elements_pointer_reg = ToRegister(elements_pointer);
   int shift_size = ElementsKindToShiftSize(elements_kind);
   if (key->IsConstantOperand()) {
@@ -2466,10 +2473,14 @@
       Abort("array index constant value too big");
     }
     return Operand(elements_pointer_reg,
-                   constant_value * (1 << shift_size) + offset);
+                   ((constant_value + additional_index) << shift_size)
+                       + offset);
   } else {
     ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
-    return Operand(elements_pointer_reg, ToRegister(key), scale_factor, offset);
+    return Operand(elements_pointer_reg,
+                   ToRegister(key),
+                   scale_factor,
+                   offset + (additional_index << shift_size));
   }
 }
 
@@ -2478,7 +2489,10 @@
     LLoadKeyedSpecializedArrayElement* instr) {
   ElementsKind elements_kind = instr->elements_kind();
   Operand operand(BuildFastArrayOperand(instr->external_pointer(),
-                                        instr->key(), elements_kind, 0));
+                                        instr->key(),
+                                        elements_kind,
+                                        0,
+                                        instr->additional_index()));
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
     XMMRegister result(ToDoubleRegister(instr->result()));
     __ movss(result, operand);
@@ -3415,7 +3429,10 @@
     LStoreKeyedSpecializedArrayElement* instr) {
   ElementsKind elements_kind = instr->elements_kind();
   Operand operand(BuildFastArrayOperand(instr->external_pointer(),
-                                        instr->key(), elements_kind, 0));
+                                        instr->key(),
+                                        elements_kind,
+                                        0,
+                                        instr->additional_index()));
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
     __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
     __ movss(operand, xmm0);
@@ -3456,31 +3473,21 @@
   Register elements = ToRegister(instr->object());
   Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
 
-  // Do the store.
-  if (instr->key()->IsConstantOperand()) {
-    ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
-    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
-    int offset =
-        ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
-    __ mov(FieldOperand(elements, offset), value);
-  } else {
-    __ mov(FieldOperand(elements,
-                        key,
-                        times_pointer_size,
-                        FixedArray::kHeaderSize),
-           value);
-  }
+  Operand operand = BuildFastArrayOperand(
+      instr->object(),
+      instr->key(),
+      FAST_ELEMENTS,
+      FixedArray::kHeaderSize - kHeapObjectTag,
+      instr->additional_index());
+  __ mov(operand, value);
 
   if (instr->hydrogen()->NeedsWriteBarrier()) {
+    ASSERT(!instr->key()->IsConstantOperand());
     HType type = instr->hydrogen()->value()->type();
     SmiCheck check_needed =
         type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
     // Compute address of modified element and store it into key register.
-    __ lea(key,
-           FieldOperand(elements,
-                        key,
-                        times_pointer_size,
-                        FixedArray::kHeaderSize));
+    __ lea(key, operand);
     __ RecordWrite(elements,
                    key,
                    value,
@@ -3508,8 +3515,11 @@
   }
 
   Operand double_store_operand = BuildFastArrayOperand(
-      instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS,
-      FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+      instr->elements(),
+      instr->key(),
+      FAST_DOUBLE_ELEMENTS,
+      FixedDoubleArray::kHeaderSize - kHeapObjectTag,
+      instr->additional_index());
   __ movdbl(double_store_operand, value);
 }
 
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index a2810f0..392bca2 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -242,7 +242,8 @@
   Operand BuildFastArrayOperand(LOperand* elements_pointer,
                                 LOperand* key,
                                 ElementsKind elements_kind,
-                                uint32_t offset);
+                                uint32_t offset,
+                                uint32_t additional_index = 0);
 
   // Specific math operations - used from DoUnaryMathOperation.
   void EmitIntegerMathAbs(LUnaryMathOperation* instr);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 5adaf43..d0cb230 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1990,8 +1990,7 @@
   LOperand* external_pointer = UseRegister(instr->external_pointer());
   LOperand* key = UseRegisterOrConstant(instr->key());
   LLoadKeyedSpecializedArrayElement* result =
-      new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer,
-                                            key);
+      new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
   LInstruction* load_instr = DefineAsRegister(result);
   // An unsigned int array load might overflow and cause a deopt, make sure it
   // has an environment.
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 09f0b0d..be64b2f 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -1238,13 +1238,13 @@
 
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
 class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadKeyedFastDoubleElement(LOperand* elements,
-                              LOperand* key) {
+  LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
     inputs_[0] = elements;
     inputs_[1] = key;
   }
@@ -1255,13 +1255,13 @@
 
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
 class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
-                                    LOperand* key) {
+  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand* key) {
     inputs_[0] = external_pointer;
     inputs_[1] = key;
   }
@@ -1275,6 +1275,7 @@
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1775,6 +1776,7 @@
   LOperand* object() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1797,6 +1799,7 @@
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 
   bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
 };
@@ -1822,6 +1825,7 @@
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index 6631659..d942d78 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -421,7 +421,11 @@
     return NULL;
   }
 
-  int socket = accept(socket_, NULL, NULL);
+  int socket;
+  do {
+    socket = accept(socket_, NULL, NULL);
+  } while (socket == -1 && errno == EINTR);
+
   if (socket == -1) {
     return NULL;
   } else {
@@ -448,7 +452,9 @@
   }
 
   // Connect.
-  status = connect(socket_, result->ai_addr, result->ai_addrlen);
+  do {
+    status = connect(socket_, result->ai_addr, result->ai_addrlen);
+  } while (status == -1 && errno == EINTR);
   freeaddrinfo(result);
   return status == 0;
 }
@@ -467,14 +473,29 @@
 
 
 int POSIXSocket::Send(const char* data, int len) const {
-  int status = send(socket_, data, len, 0);
-  return status;
+  if (len <= 0) return 0;
+  int written = 0;
+  while (written < len) {
+    int status = send(socket_, data + written, len - written, 0);
+    if (status == 0) {
+      break;
+    } else if (status > 0) {
+      written += status;
+    } else if (errno != EINTR) {
+      return 0;
+    }
+  }
+  return written;
 }
 
 
 int POSIXSocket::Receive(char* data, int len) const {
-  int status = recv(socket_, data, len, 0);
-  return status;
+  if (len <= 0) return 0;
+  int status;
+  do {
+    status = recv(socket_, data, len, 0);
+  } while (status == -1 && errno == EINTR);
+  return (status < 0) ? 0 : status;
 }
 
 
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 9e377a1..2473949 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -1848,14 +1848,26 @@
 
 
 int Win32Socket::Send(const char* data, int len) const {
-  int status = send(socket_, data, len, 0);
-  return status;
+  if (len <= 0) return 0;
+  int written = 0;
+  while (written < len) {
+    int status = send(socket_, data + written, len - written, 0);
+    if (status == 0) {
+      break;
+    } else if (status > 0) {
+      written += status;
+    } else {
+      return 0;
+    }
+  }
+  return written;
 }
 
 
 int Win32Socket::Receive(char* data, int len) const {
+  if (len <= 0) return 0;
   int status = recv(socket_, data, len, 0);
-  return status;
+  return (status == SOCKET_ERROR) ? 0 : status;
 }
 
 
diff --git a/src/platform.h b/src/platform.h
index 168791a..a2ddf7a 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -653,6 +653,7 @@
   virtual bool Shutdown() = 0;
 
   // Data Transimission
+  // Return 0 on failure.
   virtual int Send(const char* data, int len) const = 0;
   virtual int Receive(char* data, int len) const = 0;
 
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index c03e526..da2a969 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -3606,9 +3606,9 @@
   writer_->AddString(",\"meta\":");
   // The object describing node serialization layout.
   // We use a set of macros to improve readability.
-#define JSON_A(s) "["s"]"
-#define JSON_O(s) "{"s"}"
-#define JSON_S(s) "\""s"\""
+#define JSON_A(s) "[" s "]"
+#define JSON_O(s) "{" s "}"
+#define JSON_S(s) "\"" s "\""
   writer_->AddString(JSON_O(
     JSON_S("node_fields") ":" JSON_A(
         JSON_S("type") ","
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 94a5264..6db9c77 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -236,8 +236,6 @@
   SC(math_sin, V8.MathSin)                                            \
   SC(math_sqrt, V8.MathSqrt)                                          \
   SC(math_tan, V8.MathTan)                                            \
-  SC(array_bounds_checks_seen, V8.ArrayBoundsChecksSeen)              \
-  SC(array_bounds_checks_removed, V8.ArrayBoundsChecksRemoved)        \
   SC(transcendental_cache_hit, V8.TranscendentalCacheHit)             \
   SC(transcendental_cache_miss, V8.TranscendentalCacheMiss)           \
   SC(stack_interrupts, V8.StackInterrupts)                            \
diff --git a/src/version.cc b/src/version.cc
index 7c33df1..79b6ebd 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     11
-#define BUILD_NUMBER      3
+#define BUILD_NUMBER      4
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index 7ed81b4..0738153 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -1684,7 +1684,7 @@
           default:
             UNREACHABLE();
         }
-        AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"x",
+        AppendToBuffer("test%c rax,0x%" V8_PTR_PREFIX "x",
                        operand_size_code(),
                        value);
         break;
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 5f5c2af..d1cf338 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -2369,11 +2369,20 @@
 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
   Register result = ToRegister(instr->result());
 
+  if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
+    // Sign extend key because it could be a 32 bit negative value
+    // and the dehoisted address computation happens in 64 bits.
+    Register key_reg = ToRegister(instr->key());
+    __ movsxlq(key_reg, key_reg);
+  }
+
   // Load the result.
   __ movq(result,
-          BuildFastArrayOperand(instr->elements(), instr->key(),
+          BuildFastArrayOperand(instr->elements(),
+                                instr->key(),
                                 FAST_ELEMENTS,
-                                FixedArray::kHeaderSize - kHeapObjectTag));
+                                FixedArray::kHeaderSize - kHeapObjectTag,
+                                instr->additional_index()));
 
   // Check for the hole value.
   if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -2387,19 +2396,30 @@
     LLoadKeyedFastDoubleElement* instr) {
   XMMRegister result(ToDoubleRegister(instr->result()));
 
+  if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
+    // Sign extend key because it could be a 32 bit negative value
+    // and the dehoisted address computation happens in 64 bits
+    Register key_reg = ToRegister(instr->key());
+    __ movsxlq(key_reg, key_reg);
+  }
+
   int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
       sizeof(kHoleNanLower32);
   Operand hole_check_operand = BuildFastArrayOperand(
       instr->elements(),
       instr->key(),
       FAST_DOUBLE_ELEMENTS,
-      offset);
+      offset,
+      instr->additional_index());
   __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
   DeoptimizeIf(equal, instr->environment());
 
   Operand double_load_operand = BuildFastArrayOperand(
-      instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS,
-      FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+      instr->elements(),
+      instr->key(),
+      FAST_DOUBLE_ELEMENTS,
+      FixedDoubleArray::kHeaderSize - kHeapObjectTag,
+      instr->additional_index());
   __ movsd(result, double_load_operand);
 }
 
@@ -2408,7 +2428,8 @@
     LOperand* elements_pointer,
     LOperand* key,
     ElementsKind elements_kind,
-    uint32_t offset) {
+    uint32_t offset,
+    uint32_t additional_index) {
   Register elements_pointer_reg = ToRegister(elements_pointer);
   int shift_size = ElementsKindToShiftSize(elements_kind);
   if (key->IsConstantOperand()) {
@@ -2417,11 +2438,14 @@
       Abort("array index constant value too big");
     }
     return Operand(elements_pointer_reg,
-                   constant_value * (1 << shift_size) + offset);
+                   ((constant_value + additional_index) << shift_size)
+                       + offset);
   } else {
     ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
-    return Operand(elements_pointer_reg, ToRegister(key),
-                   scale_factor, offset);
+    return Operand(elements_pointer_reg,
+                   ToRegister(key),
+                   scale_factor,
+                   offset + (additional_index << shift_size));
   }
 }
 
@@ -2430,7 +2454,17 @@
     LLoadKeyedSpecializedArrayElement* instr) {
   ElementsKind elements_kind = instr->elements_kind();
   Operand operand(BuildFastArrayOperand(instr->external_pointer(),
-                                        instr->key(), elements_kind, 0));
+                                        instr->key(),
+                                        elements_kind,
+                                        0,
+                                        instr->additional_index()));
+  if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
+    // Sign extend key because it could be a 32 bit negative value
+    // and the dehoisted address computation happens in 64 bits
+    Register key_reg = ToRegister(instr->key());
+    __ movsxlq(key_reg, key_reg);
+  }
+
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
     XMMRegister result(ToDoubleRegister(instr->result()));
     __ movss(result, operand);
@@ -3332,7 +3366,18 @@
     LStoreKeyedSpecializedArrayElement* instr) {
   ElementsKind elements_kind = instr->elements_kind();
   Operand operand(BuildFastArrayOperand(instr->external_pointer(),
-                                        instr->key(), elements_kind, 0));
+                                        instr->key(),
+                                        elements_kind,
+                                        0,
+                                        instr->additional_index()));
+
+  if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
+    // Sign extend key because it could be a 32 bit negative value
+    // and the dehoisted address computation happens in 64 bits
+    Register key_reg = ToRegister(instr->key());
+    __ movsxlq(key_reg, key_reg);
+  }
+
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
     XMMRegister value(ToDoubleRegister(instr->value()));
     __ cvtsd2ss(value, value);
@@ -3402,30 +3447,29 @@
   Register elements = ToRegister(instr->object());
   Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
 
-  // Do the store.
-  if (instr->key()->IsConstantOperand()) {
-    ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
-    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
-    int offset =
-        ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
-    __ movq(FieldOperand(elements, offset), value);
-  } else {
-    __ movq(FieldOperand(elements,
-                         key,
-                         times_pointer_size,
-                         FixedArray::kHeaderSize),
-            value);
+  Operand operand =
+      BuildFastArrayOperand(instr->object(),
+                            instr->key(),
+                            FAST_ELEMENTS,
+                            FixedArray::kHeaderSize - kHeapObjectTag,
+                            instr->additional_index());
+
+  if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
+    // Sign extend key because it could be a 32 bit negative value
+    // and the dehoisted address computation happens in 64 bits
+    Register key_reg = ToRegister(instr->key());
+    __ movsxlq(key_reg, key_reg);
   }
 
+  __ movq(operand, value);
+
   if (instr->hydrogen()->NeedsWriteBarrier()) {
+    ASSERT(!instr->key()->IsConstantOperand());
     HType type = instr->hydrogen()->value()->type();
     SmiCheck check_needed =
         type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
     // Compute address of modified element and store it into key register.
-    __ lea(key, FieldOperand(elements,
-                             key,
-                             times_pointer_size,
-                             FixedArray::kHeaderSize));
+    __ lea(key, operand);
     __ RecordWrite(elements,
                    key,
                    value,
@@ -3454,8 +3498,19 @@
   }
 
   Operand double_store_operand = BuildFastArrayOperand(
-      instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS,
-      FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+      instr->elements(),
+      instr->key(),
+      FAST_DOUBLE_ELEMENTS,
+      FixedDoubleArray::kHeaderSize - kHeapObjectTag,
+      instr->additional_index());
+
+  if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
+    // Sign extend key because it could be a 32 bit negative value
+    // and the dehoisted address computation happens in 64 bits
+    Register key_reg = ToRegister(instr->key());
+    __ movsxlq(key_reg, key_reg);
+  }
+
   __ movsd(double_store_operand, value);
 }
 
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 1331fba..73e1a9b 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -231,7 +231,8 @@
       LOperand* elements_pointer,
       LOperand* key,
       ElementsKind elements_kind,
-      uint32_t offset);
+      uint32_t offset,
+      uint32_t additional_index = 0);
 
   // Specific math operations - used from DoUnaryMathOperation.
   void EmitIntegerMathAbs(LUnaryMathOperation* instr);
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 9083c1f..642a0a0 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -1199,6 +1199,7 @@
 
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1215,13 +1216,13 @@
 
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
 class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
-                                    LOperand* key) {
+  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand* key) {
     inputs_[0] = external_pointer;
     inputs_[1] = key;
   }
@@ -1235,6 +1236,7 @@
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1692,6 +1694,7 @@
   LOperand* object() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1716,6 +1719,7 @@
   LOperand* value() { return inputs_[2]; }
 
   bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
@@ -1739,6 +1743,7 @@
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
 
 
diff --git a/tools/js2c.py b/tools/js2c.py
index fa559f3..d06cbe4 100644
--- a/tools/js2c.py
+++ b/tools/js2c.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright 2006-2008 the V8 project authors. All rights reserved.
+# 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:
@@ -195,14 +195,14 @@
       macro_match = MACRO_PATTERN.match(line)
       if macro_match:
         name = macro_match.group(1)
-        args = map(string.strip, macro_match.group(2).split(','))
+        args = [match.strip() for match in macro_match.group(2).split(',')]
         body = macro_match.group(3).strip()
         macros.append((re.compile("\\b%s\\(" % name), TextMacro(args, body)))
       else:
         python_match = PYTHON_MACRO_PATTERN.match(line)
         if python_match:
           name = python_match.group(1)
-          args = map(string.strip, python_match.group(2).split(','))
+          args = [match.strip() for match in python_match.group(2).split(',')]
           body = python_match.group(3).strip()
           fun = eval("lambda " + ",".join(args) + ': ' + body)
           macros.append((re.compile("\\b%s\\(" % name), PythonMacro(args, fun)))
diff --git a/tools/jsmin.py b/tools/jsmin.py
index e82f3d0..250dea9 100644
--- a/tools/jsmin.py
+++ b/tools/jsmin.py
@@ -1,6 +1,6 @@
 #!/usr/bin/python2.4
 
-# Copyright 2009 the V8 project authors. All rights reserved.
+# 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:
@@ -154,7 +154,7 @@
       return var_name
     while True:
       identifier_first_char = self.identifier_counter % 52
-      identifier_second_char = self.identifier_counter / 52
+      identifier_second_char = self.identifier_counter // 52
       new_identifier = self.CharFromNumber(identifier_first_char)
       if identifier_second_char != 0:
         new_identifier = (