Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion r12839 committed - Consolidated all the key store/load classes in the Hydrogen and Lithiu...

Received: by 10.66.86.130 with SMTP id p2mr451155paz.22.1351848017981;
        Fri, 02 Nov 2012 02:20:17 -0700 (PDT)
X-BeenThere: v8-dev@googlegroups.com
Received: by 10.68.190.100 with SMTP id gp4ls14128087pbc.9.gmail; Fri, 02 Nov
 2012 02:20:17 -0700 (PDT)
Received: by 10.66.87.73 with SMTP id v9mr467511paz.46.1351848017033;
        Fri, 02 Nov 2012 02:20:17 -0700 (PDT)
Received: by 10.66.87.73 with SMTP id v9mr467509paz.46.1351848016980;
        Fri, 02 Nov 2012 02:20:16 -0700 (PDT)
Return-Path: <3UJCTUBAKBkknzop3t4p-yz2p0w9rzzrwp.nzx6J-op6rzzrwpr2z503....@codesite.bounces.google.com>
Received: from mail-da0-f75.google.com (mail-da0-f75.google.com [209.85.210.75])
        by gmr-mx.google.com with ESMTPS id js4si2180548pbb.2.2012.11.02.02.20.16
        (version=TLSv1/SSLv3 cipher=OTHER);
        Fri, 02 Nov 2012 02:20:16 -0700 (PDT)
Received-SPF: pass (google.com: domain of 3UJCTUBAKBkknzop3t4p-yz2p0w9rzzrwp.nzx6J-op6rzzrwpr2z503....@codesite.bounces.google.com designates 209.85.210.75 as permitted sender) client-ip=209.85.210.75;
Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of 3UJCTUBAKBkknzop3t4p-yz2p0w9rzzrwp.nzx6J-op6rzzrwpr2z503....@codesite.bounces.google.com designates 209.85.210.75 as permitted sender) smtp.mail=3UJCTUBAKBkknzop3t4p-yz2p0w9rzzrwp.nzx6J-op6rzzrwpr2z503....@codesite.bounces.google.com; dkim=pass header...@google.com
Received: by mail-da0-f75.google.com with SMTP id n34so918599dal.2
        for <v8-dev@googlegroups.com>; Fri, 02 Nov 2012 02:20:16 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=google.com; s=20120113;
        h=mime-version:x-generated-by:message-id:date:subject:from:to
         :content-type;
        bh=LdCXeAb+xnlUWC9j70mRNAK/yd9CHWu167QyeG0WKIM=;
        b=DXY6IdV0OYVg6z3UOrzxJZNZa5YFRXVM9u2g4wK1Wi85V4o2CisjCWEn5M6o9FR1oL
         roujVw4fS16xFVSGOZSFkqKdcOZ4sV3MWxKNonjcafxHuH4ZIzxEsd8oSDY9uxgkW/Fl
         lf8I5VnzTe45TMLH3jsUPwnqTucsUBZyJvmYrV5dFxZH7n5TfItny0RTVtWVmjE9/erb
         BrJeRj/+a+xqiWjXj+KAMB3Udi/SYrDXsHu0h/1GGzNHRyzfPaLP1UkaAf8WD2H7VFnb
         ZXolNM6vJSnMZJNrIrB++DmQLd+NGYk7Zj5f7OXIk93tEvfvf7SZ565l2k4C7GCyS+6Q
         yhFg==
MIME-Version: 1.0
Received: by 10.66.78.40 with SMTP id y8mr515580paw.9.1351848016775; Fri, 02
 Nov 2012 02:20:16 -0700 (PDT)
X-Generated-By: Google Code
Message-ID: <f46d042e008bd4d31604cd7fa...@google.com>
Date: Fri, 02 Nov 2012 09:20:16 +0000
Subject: [v8] r12839 committed - Consolidated all the key store/load classes
 in the Hydrogen and Lithiu...
From: codesite-nore...@google.com
To: v8-dev@googlegroups.com
Content-Type: text/plain; charset=ISO-8859-1; format=flowed; delsp=yes

Revision: 12839
Author:   mvstan...@chromium.org
Date:     Fri Nov  2 02:18:53 2012
Log:      Consolidated all the key store/load classes in the Hydrogen and  
Lithium
space into just two:
HLoadKeyed/HLoadKeyedGeneric and HStoreKeyed/HStoreKeyedGeneric
LLoadKeyed/LLoadKeyedGeneric and LStoreKeyed/LStoreKeyedGeneric
BUG=

Review URL: https://codereview.chromium.org/11238016
http://code.google.com/p/v8/source/detail?r=12839

Modified:
  /branches/bleeding_edge/src/arm/lithium-arm.cc
  /branches/bleeding_edge/src/arm/lithium-arm.h
  /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
  /branches/bleeding_edge/src/arm/lithium-codegen-arm.h
  /branches/bleeding_edge/src/elements-kind.cc
  /branches/bleeding_edge/src/elements-kind.h
  /branches/bleeding_edge/src/hydrogen-instructions.cc
  /branches/bleeding_edge/src/hydrogen-instructions.h
  /branches/bleeding_edge/src/hydrogen.cc
  /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
  /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h
  /branches/bleeding_edge/src/ia32/lithium-ia32.cc
  /branches/bleeding_edge/src/ia32/lithium-ia32.h
  /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
  /branches/bleeding_edge/src/x64/lithium-codegen-x64.h
  /branches/bleeding_edge/src/x64/lithium-x64.cc
  /branches/bleeding_edge/src/x64/lithium-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc	Fri Oct 19 05:39:59 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc	Fri Nov  2 02:18:53 2012
@@ -372,16 +372,7 @@
  }


-void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
-  object()->PrintTo(stream);
-  stream->Add("[");
-  key()->PrintTo(stream);
-  stream->Add("] <- ");
-  value()->PrintTo(stream);
-}
-
-
-void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+void LStoreKeyed::PrintDataTo(StringStream* stream) {
    elements()->PrintTo(stream);
    stream->Add("[");
    key()->PrintTo(stream);
@@ -1860,53 +1851,40 @@
  }


-LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
-    HLoadKeyedFastElement* instr) {
-  ASSERT(instr->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-  LOperand* obj = UseRegisterAtStart(instr->object());
-  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
-  LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj,  
key);
-  if (instr->RequiresHoleCheck()) AssignEnvironment(result);
-  return DefineAsRegister(result);
-}
-
-
-LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
-    HLoadKeyedFastDoubleElement* instr) {
-  ASSERT(instr->representation().IsDouble());
+LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
    ASSERT(instr->key()->representation().IsInteger32() ||
           instr->key()->representation().IsTagged());
-  LOperand* elements = UseTempRegister(instr->elements());
+  ElementsKind elements_kind = instr->elements_kind();
    LOperand* key = UseRegisterOrConstantAtStart(instr->key());
-  LLoadKeyedFastDoubleElement* result =
-      new(zone()) LLoadKeyedFastDoubleElement(elements, key);
-  return AssignEnvironment(DefineAsRegister(result));
-}
+  LLoadKeyed* result = NULL;

+  if (!instr->is_external()) {
+    LOperand* obj = NULL;
+    if (instr->representation().IsDouble()) {
+      obj = UseTempRegister(instr->elements());
+    } else {
+      ASSERT(instr->representation().IsTagged());
+      obj = UseRegisterAtStart(instr->elements());
+    }
+    result = new(zone()) LLoadKeyed(obj, key);
+  } else {
+    ASSERT(
+        (instr->representation().IsInteger32() &&
+         (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
+         (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+        (instr->representation().IsDouble() &&
+         ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
+          (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+    LOperand* external_pointer = UseRegister(instr->elements());
+    result = new(zone()) LLoadKeyed(external_pointer, key);
+  }

-LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
-    HLoadKeyedSpecializedArrayElement* instr) {
-  ElementsKind elements_kind = instr->elements_kind();
-  ASSERT(
-      (instr->representation().IsInteger32() &&
-       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
-       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
-      (instr->representation().IsDouble() &&
-       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
-       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-  LOperand* external_pointer = UseRegister(instr->external_pointer());
-  LOperand* key = UseRegisterOrConstant(instr->key());
-  LLoadKeyedSpecializedArrayElement* result =
-      new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
-  LInstruction* load_instr = DefineAsRegister(result);
+  DefineAsRegister(result);
    // An unsigned int array load might overflow and cause a deopt, make  
sure it
    // has an environment.
-  return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
-      AssignEnvironment(load_instr) : load_instr;
+  bool can_deoptimize = instr->RequiresHoleCheck() ||
+      (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
+  return can_deoptimize ? AssignEnvironment(result) : result;
  }


@@ -1920,66 +1898,48 @@
  }


-LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
-    HStoreKeyedFastElement* instr) {
+LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
+  ElementsKind elements_kind = instr->elements_kind();
    bool needs_write_barrier = instr->NeedsWriteBarrier();
-  ASSERT(instr->value()->representation().IsTagged());
-  ASSERT(instr->object()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-
-  LOperand* obj = UseTempRegister(instr->object());
-  LOperand* val = needs_write_barrier
-      ? UseTempRegister(instr->value())
-      : UseRegisterAtStart(instr->value());
    LOperand* key = needs_write_barrier
        ? UseTempRegister(instr->key())
        : UseRegisterOrConstantAtStart(instr->key());
-  return new(zone()) LStoreKeyedFastElement(obj, key, val);
-}
-
-
-LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
-    HStoreKeyedFastDoubleElement* instr) {
-  ASSERT(instr->value()->representation().IsDouble());
-  ASSERT(instr->elements()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-
-  LOperand* elements = UseRegisterAtStart(instr->elements());
-  LOperand* val = UseTempRegister(instr->value());
-  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
-
-  return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
-}
-
-
-LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
-    HStoreKeyedSpecializedArrayElement* instr) {
-  ElementsKind elements_kind = instr->elements_kind();
-  ASSERT(
-      (instr->value()->representation().IsInteger32() &&
-       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
-       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
-      (instr->value()->representation().IsDouble() &&
-       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
-       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->external_pointer()->representation().IsExternal());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-
-  LOperand* external_pointer = UseRegister(instr->external_pointer());
    bool val_is_temp_register =
        elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
        elements_kind == EXTERNAL_FLOAT_ELEMENTS;
-  LOperand* val = val_is_temp_register
+  LOperand* val = val_is_temp_register || needs_write_barrier
        ? UseTempRegister(instr->value())
        : UseRegister(instr->value());
-  LOperand* key = UseRegisterOrConstant(instr->key());
+
+  LStoreKeyed* result = NULL;
+  if (!instr->is_external()) {
+    ASSERT(instr->elements()->representation().IsTagged());
+
+    LOperand* object = NULL;
+    if (instr->value()->representation().IsDouble()) {
+      object = UseRegisterAtStart(instr->elements());
+    } else {
+      ASSERT(instr->value()->representation().IsTagged());
+      object = UseTempRegister(instr->elements());
+    }
+
+    result = new(zone()) LStoreKeyed(object, key, val);
+  } else {
+    ASSERT(
+        (instr->value()->representation().IsInteger32() &&
+         (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
+         (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+        (instr->value()->representation().IsDouble() &&
+         ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
+          (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+    ASSERT(instr->elements()->representation().IsExternal());
+
+    LOperand* external_pointer = UseRegister(instr->elements());
+    result = new(zone()) LStoreKeyed(external_pointer, key, val);
+  }

-  return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
-                                                        key,
-                                                        val);
+  ASSERT(result != NULL);
+  return result;
  }


=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h	Fri Oct 19 05:39:59 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.h	Fri Nov  2 02:18:53 2012
@@ -125,10 +125,8 @@
    V(LoadFunctionPrototype)                      \
    V(LoadGlobalCell)                             \
    V(LoadGlobalGeneric)                          \
-  V(LoadKeyedFastDoubleElement)                 \
-  V(LoadKeyedFastElement)                       \
+  V(LoadKeyed)                                  \
    V(LoadKeyedGeneric)                           \
-  V(LoadKeyedSpecializedArrayElement)           \
    V(LoadNamedField)                             \
    V(LoadNamedFieldPolymorphic)                  \
    V(LoadNamedGeneric)                           \
@@ -157,10 +155,8 @@
    V(StoreContextSlot)                           \
    V(StoreGlobalCell)                            \
    V(StoreGlobalGeneric)                         \
-  V(StoreKeyedFastDoubleElement)                \
-  V(StoreKeyedFastElement)                      \
+  V(StoreKeyed)                                 \
    V(StoreKeyedGeneric)                          \
-  V(StoreKeyedSpecializedArrayElement)          \
    V(StoreNamedField)                            \
    V(StoreNamedGeneric)                          \
    V(StringAdd)                                  \
@@ -1357,58 +1353,25 @@
  };


-class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
+class LLoadKeyed: public LTemplateInstruction<1, 2, 0> {
   public:
-  LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
+  LLoadKeyed(LOperand* elements, LOperand* key) {
      inputs_[0] = elements;
      inputs_[1] = key;
    }

    LOperand* elements() { return inputs_[0]; }
    LOperand* key() { return inputs_[1]; }
-
-   
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
-
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
-class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
- public:
-  LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
-    inputs_[0] = elements;
-    inputs_[1] = key;
+  ElementsKind elements_kind() const {
+    return hydrogen()->elements_kind();
    }
-
-  LOperand* elements() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
-                               "load-keyed-fast-double-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
-
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
-class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2,  
0> {
- public:
-  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand*  
key) {
-    inputs_[0] = external_pointer;
-    inputs_[1] = key;
+  bool is_external() const {
+    return hydrogen()->is_external();
    }

-  LOperand* external_pointer() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
-                               "load-keyed-specialized-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)

-  ElementsKind elements_kind() const {
-    return hydrogen()->elements_kind();
-  }
    uint32_t additional_index() const { return hydrogen()->index_offset(); }
  };

@@ -1922,51 +1885,28 @@
  };


-class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
+class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
   public:
-  LStoreKeyedFastElement(LOperand* object, LOperand* key, LOperand* value)  
{
+  LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
      inputs_[0] = object;
      inputs_[1] = key;
      inputs_[2] = value;
    }

-  LOperand* object() { return inputs_[0]; }
+  bool is_external() const { return hydrogen()->is_external(); }
+  LOperand* elements() { return inputs_[0]; }
    LOperand* key() { return inputs_[1]; }
    LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
-                               "store-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
-
-  virtual void PrintDataTo(StringStream* stream);
-
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
-class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
- public:
-  LStoreKeyedFastDoubleElement(LOperand* elements,
-                               LOperand* key,
-                               LOperand* value) {
-    inputs_[0] = elements;
-    inputs_[1] = key;
-    inputs_[2] = value;
+  ElementsKind elements_kind() const {
+    return hydrogen()->elements_kind();
    }

-  LOperand* elements() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
-                               "store-keyed-fast-double-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)

    virtual void PrintDataTo(StringStream* stream);
-
+  bool NeedsCanonicalization() { return  
hydrogen()->NeedsCanonicalization(); }
    uint32_t additional_index() const { return hydrogen()->index_offset(); }
-
-  bool NeedsCanonicalization() { return  
hydrogen()->NeedsCanonicalization(); }
  };


@@ -1990,28 +1930,6 @@
    StrictModeFlag strict_mode_flag() { return  
hydrogen()->strict_mode_flag(); }
  };

-class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0,  
3, 0> {
- public:
-  LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
-                                     LOperand* key,
-                                     LOperand* value) {
-    inputs_[0] = external_pointer;
-    inputs_[1] = key;
-    inputs_[2] = value;
-  }
-
-  LOperand* external_pointer() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
-                               "store-keyed-specialized-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
-
-  ElementsKind elements_kind() const { return hydrogen()->elements_kind();  
}
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-

  class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
   public:
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc	Mon Oct 29  
04:45:40 2012
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc	Fri Nov  2  
02:18:53 2012
@@ -2918,50 +2918,87 @@
  }


-void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
-  Register elements = ToRegister(instr->elements());
-  Register result = ToRegister(instr->result());
-  Register scratch = scratch0();
-  Register store_base = scratch;
-  int offset = 0;
-
-  if (instr->key()->IsConstantOperand()) {
-    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
-    offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
-                                           instr->additional_index());
-    store_base = elements;
+void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
+  Register external_pointer = ToRegister(instr->elements());
+  Register key = no_reg;
+  ElementsKind elements_kind = instr->elements_kind();
+  bool key_is_constant = instr->key()->IsConstantOperand();
+  int constant_key = 0;
+  if (key_is_constant) {
+    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
+    if (constant_key & 0xF0000000) {
+      Abort("array index constant value too big.");
+    }
    } else {
-    Register key = EmitLoadRegister(instr->key(), scratch0());
-    // Even though the HLoadKeyedFastElement instruction forces the input
-    // representation for the key to be an integer, the input gets replaced
-    // during bound check elimination with the index argument to the bounds
-    // check, which can be tagged, so that case must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
-      __ add(scratch, elements,
-             Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize));
-    } else {
-      __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
-    }
-    offset = FixedArray::OffsetOfElementAt(instr->additional_index());
+    key = ToRegister(instr->key());
    }
-  __ ldr(result, FieldMemOperand(store_base, offset));
+  int element_size_shift = ElementsKindToShiftSize(elements_kind);
+  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+      ? (element_size_shift - kSmiTagSize) : element_size_shift;
+  int additional_offset = instr->additional_index() << element_size_shift;

-  // Check for the hole value.
-  if (instr->hydrogen()->RequiresHoleCheck()) {
-    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
-      __ tst(result, Operand(kSmiTagMask));
-      DeoptimizeIf(ne, instr->environment());
-    } else {
-      __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
-      __ cmp(result, scratch);
-      DeoptimizeIf(eq, instr->environment());
+  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 << element_size_shift)
+        : Operand(key, LSL, shift_size);
+    __ add(scratch0(), external_pointer, operand);
+    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+      __ vldr(result.low(), scratch0(), additional_offset);
+      __ vcvt_f64_f32(result, result.low());
+    } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
+      __ vldr(result, scratch0(), additional_offset);
+    }
+  } else {
+    Register result = ToRegister(instr->result());
+    MemOperand mem_operand = PrepareKeyedOperand(
+        key, external_pointer, key_is_constant, constant_key,
+        element_size_shift, shift_size,
+        instr->additional_index(), additional_offset);
+    switch (elements_kind) {
+      case EXTERNAL_BYTE_ELEMENTS:
+        __ ldrsb(result, mem_operand);
+        break;
+      case EXTERNAL_PIXEL_ELEMENTS:
+      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+        __ ldrb(result, mem_operand);
+        break;
+      case EXTERNAL_SHORT_ELEMENTS:
+        __ ldrsh(result, mem_operand);
+        break;
+      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+        __ ldrh(result, mem_operand);
+        break;
+      case EXTERNAL_INT_ELEMENTS:
+        __ ldr(result, mem_operand);
+        break;
+      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+        __ ldr(result, mem_operand);
+        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
+          __ cmp(result, Operand(0x80000000));
+          DeoptimizeIf(cs, instr->environment());
+        }
+        break;
+      case EXTERNAL_FLOAT_ELEMENTS:
+      case EXTERNAL_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_ELEMENTS:
+      case FAST_HOLEY_SMI_ELEMENTS:
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_ELEMENTS:
+      case FAST_SMI_ELEMENTS:
+      case DICTIONARY_ELEMENTS:
+      case NON_STRICT_ARGUMENTS_ELEMENTS:
+        UNREACHABLE();
+        break;
      }
    }
  }


-void LCodeGen::DoLoadKeyedFastDoubleElement(
-    LLoadKeyedFastDoubleElement* instr) {
+void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
    Register elements = ToRegister(instr->elements());
    bool key_is_constant = instr->key()->IsConstantOperand();
    Register key = no_reg;
@@ -3001,6 +3038,59 @@

    __ vldr(result, elements, 0);
  }
+
+
+void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
+  Register elements = ToRegister(instr->elements());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+  Register store_base = scratch;
+  int offset = 0;
+
+  if (instr->key()->IsConstantOperand()) {
+    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
+    offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
+                                           instr->additional_index());
+    store_base = elements;
+  } else {
+    Register key = EmitLoadRegister(instr->key(), scratch0());
+    // Even though the HLoadKeyed instruction forces the input
+    // representation for the key to be an integer, the input gets replaced
+    // during bound check elimination with the index argument to the bounds
+    // check, which can be tagged, so that case must be handled here, too.
+    if (instr->hydrogen()->key()->representation().IsTagged()) {
+      __ add(scratch, elements,
+             Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize));
+    } else {
+      __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
+    }
+    offset = FixedArray::OffsetOfElementAt(instr->additional_index());
+  }
+  __ ldr(result, FieldMemOperand(store_base, offset));
+
+  // Check for the hole value.
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
+      __ tst(result, Operand(kSmiTagMask));
+      DeoptimizeIf(ne, instr->environment());
+    } else {
+      __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
+      __ cmp(result, scratch);
+      DeoptimizeIf(eq, instr->environment());
+    }
+  }
+}
+
+
+void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
+  if (instr->is_external()) {
+    DoLoadKeyedExternalArray(instr);
+  } else if (instr->hydrogen()->representation().IsDouble()) {
+    DoLoadKeyedFixedDoubleArray(instr);
+  } else {
+    DoLoadKeyedFixedArray(instr);
+  }
+}


  MemOperand LCodeGen::PrepareKeyedOperand(Register key,
@@ -3038,87 +3128,6 @@
    }
  }

-
-void LCodeGen::DoLoadKeyedSpecializedArrayElement(
-    LLoadKeyedSpecializedArrayElement* instr) {
-  Register external_pointer = ToRegister(instr->external_pointer());
-  Register key = no_reg;
-  ElementsKind elements_kind = instr->elements_kind();
-  bool key_is_constant = instr->key()->IsConstantOperand();
-  int constant_key = 0;
-  if (key_is_constant) {
-    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
-    if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
-    }
-  } else {
-    key = ToRegister(instr->key());
-  }
-  int element_size_shift = ElementsKindToShiftSize(elements_kind);
-  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
-      ? (element_size_shift - kSmiTagSize) : element_size_shift;
-  int additional_offset = instr->additional_index() << element_size_shift;
-
-  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 << element_size_shift)
-        : Operand(key, LSL, shift_size);
-    __ add(scratch0(), external_pointer, operand);
-    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
-      __ vldr(result.low(), scratch0(), additional_offset);
-      __ vcvt_f64_f32(result, result.low());
-    } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
-      __ vldr(result, scratch0(), additional_offset);
-    }
-  } else {
-    Register result = ToRegister(instr->result());
-    MemOperand mem_operand = PrepareKeyedOperand(
-        key, external_pointer, key_is_constant, constant_key,
-        element_size_shift, shift_size,
-        instr->additional_index(), additional_offset);
-    switch (elements_kind) {
-      case EXTERNAL_BYTE_ELEMENTS:
-        __ ldrsb(result, mem_operand);
-        break;
-      case EXTERNAL_PIXEL_ELEMENTS:
-      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-        __ ldrb(result, mem_operand);
-        break;
-      case EXTERNAL_SHORT_ELEMENTS:
-        __ ldrsh(result, mem_operand);
-        break;
-      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-        __ ldrh(result, mem_operand);
-        break;
-      case EXTERNAL_INT_ELEMENTS:
-        __ ldr(result, mem_operand);
-        break;
-      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-        __ ldr(result, mem_operand);
-        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
-          __ cmp(result, Operand(0x80000000));
-          DeoptimizeIf(cs, instr->environment());
-        }
-        break;
-      case EXTERNAL_FLOAT_ELEMENTS:
-      case EXTERNAL_DOUBLE_ELEMENTS:
-      case FAST_HOLEY_DOUBLE_ELEMENTS:
-      case FAST_HOLEY_ELEMENTS:
-      case FAST_HOLEY_SMI_ELEMENTS:
-      case FAST_DOUBLE_ELEMENTS:
-      case FAST_ELEMENTS:
-      case FAST_SMI_ELEMENTS:
-      case DICTIONARY_ELEMENTS:
-      case NON_STRICT_ARGUMENTS_ELEMENTS:
-        UNREACHABLE();
-        break;
-    }
-  }
-}
-

  void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
    ASSERT(ToRegister(instr->object()).is(r1));
@@ -3999,103 +4008,9 @@
    DeoptimizeIf(hs, instr->environment());
  }

-
-void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
-  Register value = ToRegister(instr->value());
-  Register elements = ToRegister(instr->object());
-  Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) :  
no_reg;
-  Register scratch = scratch0();
-  Register store_base = scratch;
-  int offset = 0;
-
-  // Do the store.
-  if (instr->key()->IsConstantOperand()) {
-    ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
-    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
-    offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
-                                           instr->additional_index());
-    store_base = elements;
-  } else {
-    // Even though the HLoadKeyedFastElement instruction forces the input
-    // representation for the key to be an integer, the input gets replaced
-    // during bound check elimination with the index argument to the bounds
-    // check, which can be tagged, so that case must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
-      __ add(scratch, elements,
-             Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize));
-    } else {
-      __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
-    }
-    offset = FixedArray::OffsetOfElementAt(instr->additional_index());
-  }
-  __ str(value, FieldMemOperand(store_base, offset));
-
-  if (instr->hydrogen()->NeedsWriteBarrier()) {
-    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.
-    __ add(key, store_base, Operand(offset - kHeapObjectTag));
-    __ RecordWrite(elements,
-                   key,
-                   value,
-                   kLRHasBeenSaved,
-                   kSaveFPRegs,
-                   EMIT_REMEMBERED_SET,
-                   check_needed);
-  }
-}
-
-
-void LCodeGen::DoStoreKeyedFastDoubleElement(
-    LStoreKeyedFastDoubleElement* instr) {
-  DwVfpRegister value = ToDoubleRegister(instr->value());
-  Register elements = ToRegister(instr->elements());
-  Register key = no_reg;
-  Register scratch = scratch0();
-  bool key_is_constant = instr->key()->IsConstantOperand();
-  int constant_key = 0;
-
-  // Calculate the effective address of the slot in the array to store the
-  // double value.
-  if (key_is_constant) {
-    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
-    if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
-    }
-  } else {
-    key = ToRegister(instr->key());
-  }
-  int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
-  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
-      ? (element_size_shift - kSmiTagSize) : element_size_shift;
-  Operand operand = key_is_constant
-      ? Operand((constant_key << element_size_shift) +
-                FixedDoubleArray::kHeaderSize - kHeapObjectTag)
-      : Operand(key, LSL, shift_size);
-  __ add(scratch, elements, operand);
-  if (!key_is_constant) {
-    __ add(scratch, scratch,
-           Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
-  }
-
-  if (instr->NeedsCanonicalization()) {
-    // Check for NaN. All NaNs must be canonicalized.
-    __ VFPCompareAndSetFlags(value, value);
-    // Only load canonical NaN if the comparison above set the overflow.
-    __ Vmov(value,
-            FixedDoubleArray::canonical_not_the_hole_nan_as_double(),
-            no_reg, vs);
-  }
-
-  __ vstr(value, scratch, instr->additional_index() << element_size_shift);
-}

-
-void LCodeGen::DoStoreKeyedSpecializedArrayElement(
-    LStoreKeyedSpecializedArrayElement* instr) {
-
-  Register external_pointer = ToRegister(instr->external_pointer());
+void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
+  Register external_pointer = ToRegister(instr->elements());
    Register key = no_reg;
    ElementsKind elements_kind = instr->elements_kind();
    bool key_is_constant = instr->key()->IsConstantOperand();
@@ -4162,6 +4077,110 @@
      }
    }
  }
+
+
+void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
+  DwVfpRegister value = ToDoubleRegister(instr->value());
+  Register elements = ToRegister(instr->elements());
+  Register key = no_reg;
+  Register scratch = scratch0();
+  bool key_is_constant = instr->key()->IsConstantOperand();
+  int constant_key = 0;
+
+  // Calculate the effective address of the slot in the array to store the
+  // double value.
+  if (key_is_constant) {
+    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
+    if (constant_key & 0xF0000000) {
+      Abort("array index constant value too big.");
+    }
+  } else {
+    key = ToRegister(instr->key());
+  }
+  int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
+  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+      ? (element_size_shift - kSmiTagSize) : element_size_shift;
+  Operand operand = key_is_constant
+      ? Operand((constant_key << element_size_shift) +
+                FixedDoubleArray::kHeaderSize - kHeapObjectTag)
+      : Operand(key, LSL, shift_size);
+  __ add(scratch, elements, operand);
+  if (!key_is_constant) {
+    __ add(scratch, scratch,
+           Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+  }
+
+  if (instr->NeedsCanonicalization()) {
+    // Check for NaN. All NaNs must be canonicalized.
+    __ VFPCompareAndSetFlags(value, value);
+    // Only load canonical NaN if the comparison above set the overflow.
+    __ Vmov(value,
+            FixedDoubleArray::canonical_not_the_hole_nan_as_double(),
+            no_reg, vs);
+  }
+
+  __ vstr(value, scratch, instr->additional_index() << element_size_shift);
+}
+
+
+void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
+  Register value = ToRegister(instr->value());
+  Register elements = ToRegister(instr->elements());
+  Register key = instr->key()->IsRegister() ? ToRegister(instr->key())
+      : no_reg;
+  Register scratch = scratch0();
+  Register store_base = scratch;
+  int offset = 0;
+
+  // Do the store.
+  if (instr->key()->IsConstantOperand()) {
+    ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
+    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
+    offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
+                                           instr->additional_index());
+    store_base = elements;
+  } else {
+    // Even though the HLoadKeyed instruction forces the input
+    // representation for the key to be an integer, the input gets replaced
+    // during bound check elimination with the index argument to the bounds
+    // check, which can be tagged, so that case must be handled here, too.
+    if (instr->hydrogen()->key()->representation().IsTagged()) {
+      __ add(scratch, elements,
+             Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize));
+    } else {
+      __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
+    }
+    offset = FixedArray::OffsetOfElementAt(instr->additional_index());
+  }
+  __ str(value, FieldMemOperand(store_base, offset));
+
+  if (instr->hydrogen()->NeedsWriteBarrier()) {
+    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.
+    __ add(key, store_base, Operand(offset - kHeapObjectTag));
+    __ RecordWrite(elements,
+                   key,
+                   value,
+                   kLRHasBeenSaved,
+                   kSaveFPRegs,
+                   EMIT_REMEMBERED_SET,
+                   check_needed);
+  }
+}
+
+
+void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
+  // By cases: external, fast double
+  if (instr->is_external()) {
+    DoStoreKeyedExternalArray(instr);
+  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
+    DoStoreKeyedFixedDoubleArray(instr);
+  } else {
+    DoStoreKeyedFixedArray(instr);
+  }
+}


  void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.h	Thu Oct 18  
05:21:42 2012
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.h	Fri Nov  2  
02:18:53 2012
@@ -377,6 +377,12 @@
    };

    void EnsureSpaceForLazyDeopt();
+  void DoLoadKeyedExternalArray(LLoadKeyed* instr);
+  void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
+  void DoLoadKeyedFixedArray(LLoadKeyed* instr);
+  void DoStoreKeyedExternalArray(LStoreKeyed* instr);
+  void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
+  void DoStoreKeyedFixedArray(LStoreKeyed* instr);

    Zone* zone_;
    LPlatformChunk* const chunk_;
=======================================
--- /branches/bleeding_edge/src/elements-kind.cc	Wed May 23 07:24:29 2012
+++ /branches/bleeding_edge/src/elements-kind.cc	Fri Nov  2 02:18:53 2012
@@ -35,9 +35,14 @@
  namespace internal {


+const char* ElementsKindToString(ElementsKind kind) {
+  ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
+  return accessor->name();
+}
+
+
  void PrintElementsKind(FILE* out, ElementsKind kind) {
-  ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
-  PrintF(out, "%s", accessor->name());
+  PrintF(out, "%s", ElementsKindToString(kind));
  }


=======================================
--- /branches/bleeding_edge/src/elements-kind.h	Fri Jun  8 06:06:24 2012
+++ /branches/bleeding_edge/src/elements-kind.h	Fri Nov  2 02:18:53 2012
@@ -77,6 +77,7 @@
  const int kFastElementsKindCount = LAST_FAST_ELEMENTS_KIND -
      FIRST_FAST_ELEMENTS_KIND + 1;

+const char* ElementsKindToString(ElementsKind kind);
  void PrintElementsKind(FILE* out, ElementsKind kind);

  ElementsKind GetInitialFastElementsKind();
@@ -107,6 +108,13 @@
    return kind == FAST_DOUBLE_ELEMENTS ||
        kind == FAST_HOLEY_DOUBLE_ELEMENTS;
  }
+
+
+inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
+  return IsFastDoubleElementsKind(kind) ||
+      kind == EXTERNAL_DOUBLE_ELEMENTS ||
+      kind == EXTERNAL_FLOAT_ELEMENTS;
+}


  inline bool IsFastSmiOrObjectElementsKind(ElementsKind kind) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc	Tue Oct 16  
04:41:07 2012
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc	Fri Nov  2  
02:18:53 2012
@@ -1622,7 +1622,7 @@
  }


-Range* HLoadKeyedSpecializedArrayElement::InferRange(Zone* zone) {
+Range* HLoadKeyed::InferRange(Zone* zone) {
    switch (elements_kind()) {
      case EXTERNAL_PIXEL_ELEMENTS:
        return new(zone) Range(0, 255);
@@ -1849,8 +1849,17 @@
  }


-void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
-  object()->PrintNameTo(stream);
+void HLoadKeyed::PrintDataTo(StringStream* stream) {
+  if (!is_external()) {
+    elements()->PrintNameTo(stream);
+  } else {
+    ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
+           elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
+    elements()->PrintNameTo(stream);
+    stream->Add(".");
+    stream->Add(ElementsKindToString(elements_kind()));
+  }
+
    stream->Add("[");
    key()->PrintNameTo(stream);
    stream->Add("] ");
@@ -1861,27 +1870,24 @@
  }


-bool HLoadKeyedFastElement::RequiresHoleCheck() const {
+bool HLoadKeyed::RequiresHoleCheck() const {
    if (IsFastPackedElementsKind(elements_kind())) {
      return false;
    }
+
+  if (IsFastDoubleElementsKind(elements_kind())) {
+    return true;
+  }

    for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
      HValue* use = it.value();
-    if (!use->IsChange()) return true;
+    if (!use->IsChange()) {
+      return true;
+    }
    }

    return false;
  }
-
-
-void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
-  elements()->PrintNameTo(stream);
-  stream->Add("[");
-  key()->PrintNameTo(stream);
-  stream->Add("] ");
-  dependency()->PrintNameTo(stream);
-}


  void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
@@ -1896,21 +1902,22 @@
    // Recognize generic keyed loads that use property name generated
    // by for-in statement as a key and rewrite them into fast property load
    // by index.
-  if (key()->IsLoadKeyedFastElement()) {
-    HLoadKeyedFastElement* key_load = HLoadKeyedFastElement::cast(key());
-    if (key_load->object()->IsForInCacheArray()) {
+  if (key()->IsLoadKeyed()) {
+    HLoadKeyed* key_load = HLoadKeyed::cast(key());
+    if (key_load->elements()->IsForInCacheArray()) {
        HForInCacheArray* names_cache =
-          HForInCacheArray::cast(key_load->object());
+          HForInCacheArray::cast(key_load->elements());

        if (names_cache->enumerable() == object()) {
          HForInCacheArray* index_cache =
              names_cache->index_cache();
          HCheckMapValue* map_check =
              new(block()->zone()) HCheckMapValue(object(),  
names_cache->map());
-        HInstruction* index = new(block()->zone()) HLoadKeyedFastElement(
+        HInstruction* index = new(block()->zone()) HLoadKeyed(
              index_cache,
              key_load->key(),
-            key_load->key());
+            key_load->key(),
+            key_load->elements_kind());
          map_check->InsertBefore(this);
          index->InsertBefore(this);
          HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
@@ -1923,56 +1930,6 @@

    return this;
  }
-
-
-void HLoadKeyedSpecializedArrayElement::PrintDataTo(
-    StringStream* stream) {
-  external_pointer()->PrintNameTo(stream);
-  stream->Add(".");
-  switch (elements_kind()) {
-    case EXTERNAL_BYTE_ELEMENTS:
-      stream->Add("byte");
-      break;
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-      stream->Add("u_byte");
-      break;
-    case EXTERNAL_SHORT_ELEMENTS:
-      stream->Add("short");
-      break;
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-      stream->Add("u_short");
-      break;
-    case EXTERNAL_INT_ELEMENTS:
-      stream->Add("int");
-      break;
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-      stream->Add("u_int");
-      break;
-    case EXTERNAL_FLOAT_ELEMENTS:
-      stream->Add("float");
-      break;
-    case EXTERNAL_DOUBLE_ELEMENTS:
-      stream->Add("double");
-      break;
-    case EXTERNAL_PIXEL_ELEMENTS:
-      stream->Add("pixel");
-      break;
-    case FAST_ELEMENTS:
-    case FAST_SMI_ELEMENTS:
-    case FAST_DOUBLE_ELEMENTS:
-    case FAST_HOLEY_ELEMENTS:
-    case FAST_HOLEY_SMI_ELEMENTS:
-    case FAST_HOLEY_DOUBLE_ELEMENTS:
-    case DICTIONARY_ELEMENTS:
-    case NON_STRICT_ARGUMENTS_ELEMENTS:
-      UNREACHABLE();
-      break;
-  }
-  stream->Add("[");
-  key()->PrintNameTo(stream);
-  stream->Add("] ");
-  dependency()->PrintNameTo(stream);
-}


  void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
@@ -2001,17 +1958,17 @@
  }


-void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
-  object()->PrintNameTo(stream);
-  stream->Add("[");
-  key()->PrintNameTo(stream);
-  stream->Add("] = ");
-  value()->PrintNameTo(stream);
-}
+void HStoreKeyed::PrintDataTo(StringStream* stream) {
+  if (!is_external()) {
+    elements()->PrintNameTo(stream);
+  } else {
+    elements()->PrintNameTo(stream);
+    stream->Add(".");
+    stream->Add(ElementsKindToString(elements_kind()));
+    ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
+           elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
+  }

-
-void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
-  elements()->PrintNameTo(stream);
    stream->Add("[");
    key()->PrintNameTo(stream);
    stream->Add("] = ");
@@ -2026,56 +1983,6 @@
    stream->Add("] = ");
    value()->PrintNameTo(stream);
  }
-
-
-void HStoreKeyedSpecializedArrayElement::PrintDataTo(
-    StringStream* stream) {
-  external_pointer()->PrintNameTo(stream);
-  stream->Add(".");
-  switch (elements_kind()) {
-    case EXTERNAL_BYTE_ELEMENTS:
-      stream->Add("byte");
-      break;
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-      stream->Add("u_byte");
-      break;
-    case EXTERNAL_SHORT_ELEMENTS:
-      stream->Add("short");
-      break;
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-      stream->Add("u_short");
-      break;
-    case EXTERNAL_INT_ELEMENTS:
-      stream->Add("int");
-      break;
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-      stream->Add("u_int");
-      break;
-    case EXTERNAL_FLOAT_ELEMENTS:
-      stream->Add("float");
-      break;
-    case EXTERNAL_DOUBLE_ELEMENTS:
-      stream->Add("double");
-      break;
-    case EXTERNAL_PIXEL_ELEMENTS:
-      stream->Add("pixel");
-      break;
-    case FAST_SMI_ELEMENTS:
-    case FAST_ELEMENTS:
-    case FAST_DOUBLE_ELEMENTS:
-    case FAST_HOLEY_SMI_ELEMENTS:
-    case FAST_HOLEY_ELEMENTS:
-    case FAST_HOLEY_DOUBLE_ELEMENTS:
-    case DICTIONARY_ELEMENTS:
-    case NON_STRICT_ARGUMENTS_ELEMENTS:
-      UNREACHABLE();
-      break;
-  }
-  stream->Add("[");
-  key()->PrintNameTo(stream);
-  stream->Add("] = ");
-  value()->PrintNameTo(stream);
-}


  void HTransitionElementsKind::PrintDataTo(StringStream* stream) {
@@ -2368,10 +2275,10 @@
  }


-bool HStoreKeyedFastDoubleElement::NeedsCanonicalization() {
-  // If value was loaded from unboxed double backing store or
-  // converted from an integer then we don't have to canonicalize it.
-  if (value()->IsLoadKeyedFastDoubleElement() ||
+bool HStoreKeyed::NeedsCanonicalization() {
+  // If value is an integer or comes from the result of a keyed load
+  // then it will be a non-hole value: no need for canonicalization.
+  if (value()->IsLoadKeyed() ||
        (value()->IsChange() &&  
HChange::cast(value())->from().IsInteger32())) {
      return false;
    }
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h	Thu Oct 25 08:45:24  
2012
+++ /branches/bleeding_edge/src/hydrogen-instructions.h	Fri Nov  2 02:18:53  
2012
@@ -133,10 +133,8 @@
    V(LoadFunctionPrototype)                     \
    V(LoadGlobalCell)                            \
    V(LoadGlobalGeneric)                         \
-  V(LoadKeyedFastDoubleElement)                \
-  V(LoadKeyedFastElement)                      \
+  V(LoadKeyed)                                 \
    V(LoadKeyedGeneric)                          \
-  V(LoadKeyedSpecializedArrayElement)          \
    V(LoadNamedField)                            \
    V(LoadNamedFieldPolymorphic)                 \
    V(LoadNamedGeneric)                          \
@@ -163,10 +161,8 @@
    V(StoreContextSlot)                          \
    V(StoreGlobalCell)                           \
    V(StoreGlobalGeneric)                        \
-  V(StoreKeyedFastDoubleElement)               \
-  V(StoreKeyedFastElement)                     \
+  V(StoreKeyed)                                \
    V(StoreKeyedGeneric)                         \
-  V(StoreKeyedSpecializedArrayElement)         \
    V(StoreNamedField)                           \
    V(StoreNamedGeneric)                         \
    V(StringAdd)                                 \
@@ -4244,29 +4240,59 @@
    virtual ~ArrayInstructionInterface() { };
  };

-class HLoadKeyedFastElement
+
+class HLoadKeyed
      : public HTemplateInstruction<3>, public ArrayInstructionInterface {
   public:
-  HLoadKeyedFastElement(HValue* obj,
-                        HValue* key,
-                        HValue* dependency,
-                        ElementsKind elements_kind = FAST_ELEMENTS)
+  HLoadKeyed(HValue* obj,
+             HValue* key,
+             HValue* dependency,
+             ElementsKind elements_kind)
        : bit_field_(0) {
-    ASSERT(IsFastSmiOrObjectElementsKind(elements_kind));
      bit_field_ = ElementsKindField::encode(elements_kind);
-    if (IsFastSmiElementsKind(elements_kind) &&
-        IsFastPackedElementsKind(elements_kind)) {
-      set_type(HType::Smi());
-    }
+
      SetOperandAt(0, obj);
      SetOperandAt(1, key);
      SetOperandAt(2, dependency);
-    set_representation(Representation::Tagged());
-    SetGVNFlag(kDependsOnArrayElements);
+
+    if (!is_external()) {
+      // I can detect the case between storing double (holey and fast) and
+      // smi/object by looking at elements_kind_.
+      ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
+             IsFastDoubleElementsKind(elements_kind));
+
+      if (IsFastSmiOrObjectElementsKind(elements_kind)) {
+        if (IsFastSmiElementsKind(elements_kind) &&
+            IsFastPackedElementsKind(elements_kind)) {
+          set_type(HType::Smi());
+        }
+
+        set_representation(Representation::Tagged());
+        SetGVNFlag(kDependsOnArrayElements);
+      } else {
+        set_representation(Representation::Double());
+        SetGVNFlag(kDependsOnDoubleArrayElements);
+      }
+    } else {
+      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+          elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+        set_representation(Representation::Double());
+      } else {
+        set_representation(Representation::Integer32());
+      }
+
+      SetGVNFlag(kDependsOnSpecializedArrayElements);
+      // Native code could change the specialized array.
+      SetGVNFlag(kDependsOnCalls);
+    }
+
      SetFlag(kUseGVN);
    }

-  HValue* object() { return OperandAt(0); }
+  bool is_external() const {
+    return IsExternalArrayElementsKind(elements_kind());
+  }
+  HValue* elements() { return OperandAt(0); }
    HValue* key() { return OperandAt(1); }
    HValue* dependency() { return OperandAt(2); }
    uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
@@ -4284,8 +4310,13 @@
    }

    virtual Representation RequiredInputRepresentation(int index) {
-    // The key is supposed to be Integer32.
-    if (index == 0) return Representation::Tagged();
+    // kind_fast:       tagged[int32] (none)
+    // kind_double:     tagged[int32] (none)
+    // kind_external: external[int32] (none)
+    if (index == 0) {
+      return is_external() ? Representation::External()
+          : Representation::Tagged();
+    }
      if (index == 1) return Representation::Integer32();
      return Representation::None();
    }
@@ -4294,154 +4325,49 @@

    bool RequiresHoleCheck() const;

-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement)
+  virtual Range* InferRange(Zone* zone);
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)

   protected:
    virtual bool DataEquals(HValue* other) {
-    if (!other->IsLoadKeyedFastElement()) return false;
-    HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other);
+    if (!other->IsLoadKeyed()) return false;
+    HLoadKeyed* other_load = HLoadKeyed::cast(other);
+
      if (IsDehoisted() && index_offset() != other_load->index_offset())
        return false;
      return elements_kind() == other_load->elements_kind();
    }

   private:
-  virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
-
-  class ElementsKindField:  public BitField<ElementsKind, 0, 4> {};
-  class IndexOffsetField:   public BitField<uint32_t, 4, 27> {};
-  class IsDehoistedField:   public BitField<bool, 31, 1> {};
-  uint32_t bit_field_;
-};
-
-
-enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK };
-
-
-class HLoadKeyedFastDoubleElement
-    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
- public:
-  HLoadKeyedFastDoubleElement(
-    HValue* elements,
-    HValue* key,
-    HValue* dependency,
-    HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
-      : index_offset_(0),
-        is_dehoisted_(false),
-        hole_check_mode_(hole_check_mode) {
-    SetOperandAt(0, elements);
-    SetOperandAt(1, key);
-    SetOperandAt(2, dependency);
-    set_representation(Representation::Double());
-    SetGVNFlag(kDependsOnDoubleArrayElements);
-    SetFlag(kUseGVN);
+  virtual bool IsDeletable() const {
+    return !RequiresHoleCheck();
    }

-  HValue* elements() { return OperandAt(0); }
-  HValue* key() { return OperandAt(1); }
-  HValue* dependency() { 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; }
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    // The key is supposed to be Integer32.
-    if (index == 0) return Representation::Tagged();
-    if (index == 1) return Representation::Integer32();
-    return Representation::None();
-  }
-
-  bool RequiresHoleCheck() const {
-    return hole_check_mode_ == PERFORM_HOLE_CHECK;
-  }
-
-  virtual void PrintDataTo(StringStream* stream);
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
-
- protected:
-  virtual bool DataEquals(HValue* other) {
-    if (!other->IsLoadKeyedFastDoubleElement()) return false;
-    HLoadKeyedFastDoubleElement* other_load =
-        HLoadKeyedFastDoubleElement::cast(other);
-    return hole_check_mode_ == other_load->hole_check_mode_;
-  }
-
- private:
-  virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
-
-  uint32_t index_offset_;
-  bool is_dehoisted_;
-  HoleCheckMode hole_check_mode_;
-};
-
-
-class HLoadKeyedSpecializedArrayElement
-    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
- public:
-  HLoadKeyedSpecializedArrayElement(HValue* external_elements,
-                                    HValue* key,
-                                    HValue* dependency,
-                                    ElementsKind elements_kind)
-      :  elements_kind_(elements_kind),
-         index_offset_(0),
-         is_dehoisted_(false) {
-    SetOperandAt(0, external_elements);
-    SetOperandAt(1, key);
-    SetOperandAt(2, dependency);
-    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
-        elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
-      set_representation(Representation::Double());
-    } else {
-      set_representation(Representation::Integer32());
-    }
-    SetGVNFlag(kDependsOnSpecializedArrayElements);
-    // Native code could change the specialized array.
-    SetGVNFlag(kDependsOnCalls);
-    SetFlag(kUseGVN);
-  }
-
-  virtual void PrintDataTo(StringStream* stream);
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    // The key is supposed to be Integer32.
-    if (index == 0) return Representation::External();
-    if (index == 1) return Representation::Integer32();
-    return Representation::None();
-  }
-
-  HValue* external_pointer() { return OperandAt(0); }
-  HValue* key() { return OperandAt(1); }
-  HValue* dependency() { 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; }
+  // Establish some checks around our packed fields
+  enum LoadKeyedBits {
+    kBitsForElementsKind = 5,
+    kBitsForIndexOffset = 26,
+    kBitsForIsDehoisted = 1,

-  virtual Range* InferRange(Zone* zone);
+    kStartElementsKind = 0,
+    kStartIndexOffset = kStartElementsKind + kBitsForElementsKind,
+    kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
+  };

-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
-
- protected:
-  virtual bool DataEquals(HValue* other) {
-    if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
-    HLoadKeyedSpecializedArrayElement* cast_other =
-        HLoadKeyedSpecializedArrayElement::cast(other);
-    return elements_kind_ == cast_other->elements_kind();
-  }
-
- private:
-  virtual bool IsDeletable() const { return true; }
-
-  ElementsKind elements_kind_;
-  uint32_t index_offset_;
-  bool is_dehoisted_;
+  STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset +
+                 kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
+  STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
+  class ElementsKindField:
+    public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
+    {};  // NOLINT
+  class IndexOffsetField:
+    public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
+    {};  // NOLINT
+  class IsDehoistedField:
+    public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
+    {};  // NOLINT
+  uint32_t bit_field_;
  };


@@ -4462,6 +4388,7 @@
    virtual void PrintDataTo(StringStream* stream);

    virtual Representation RequiredInputRepresentation(int index) {
+    // tagged[tagged]
      return Representation::Tagged();
    }

@@ -4567,31 +4494,56 @@
  };


-class HStoreKeyedFastElement
+class HStoreKeyed
      : public HTemplateInstruction<3>, public ArrayInstructionInterface {
   public:
-  HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val,
-                         ElementsKind elements_kind = FAST_ELEMENTS)
+  HStoreKeyed(HValue* obj, HValue* key, HValue* val,
+              ElementsKind elements_kind)
        : elements_kind_(elements_kind), index_offset_(0),  
is_dehoisted_(false) {
      SetOperandAt(0, obj);
      SetOperandAt(1, key);
      SetOperandAt(2, val);
-    SetGVNFlag(kChangesArrayElements);
+
+    if (is_external()) {
+      SetGVNFlag(kChangesSpecializedArrayElements);
+    } else if (IsFastDoubleElementsKind(elements_kind)) {
+      SetGVNFlag(kChangesDoubleArrayElements);
+      SetFlag(kDeoptimizeOnUndefined);
+    } else {
+      SetGVNFlag(kChangesArrayElements);
+    }
    }

    virtual Representation RequiredInputRepresentation(int index) {
-    // The key is supposed to be Integer32.
-    return index == 1
-        ? Representation::Integer32()
-        : Representation::Tagged();
+    // kind_fast:       tagged[int32] = tagged
+    // kind_double:     tagged[int32] = double
+    // kind_external: external[int32] = (double | int32)
+    if (index == 0) {
+      return is_external() ? Representation::External()
+                           : Representation::Tagged();
+    } else if (index == 1) {
+      return Representation::Integer32();
+    }
+
+    ASSERT_EQ(index, 2);
+    if (IsDoubleOrFloatElementsKind(elements_kind())) {
+      return Representation::Double();
+    }
+
+    return is_external() ? Representation::Integer32()
+                         : Representation::Tagged();
    }

-  HValue* object() { return OperandAt(0); }
+  bool is_external() const {
+    return IsExternalArrayElementsKind(elements_kind());
+  }
+  HValue* elements() { return OperandAt(0); }
    HValue* key() { return OperandAt(1); }
    HValue* value() { return OperandAt(2); }
-  bool value_is_smi() {
+  bool value_is_smi() const {
      return IsFastSmiElementsKind(elements_kind_);
    }
+  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(); }
@@ -4606,111 +4558,12 @@
        return StoringValueNeedsWriteBarrier(value());
      }
    }
-
-  virtual void PrintDataTo(StringStream* stream);
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement)
-
- private:
-  ElementsKind elements_kind_;
-  uint32_t index_offset_;
-  bool is_dehoisted_;
-};
-
-
-class HStoreKeyedFastDoubleElement
-    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
- public:
-  HStoreKeyedFastDoubleElement(HValue* elements,
-                               HValue* key,
-                               HValue* val)
-      : index_offset_(0), is_dehoisted_(false) {
-    SetOperandAt(0, elements);
-    SetOperandAt(1, key);
-    SetOperandAt(2, val);
-    SetFlag(kDeoptimizeOnUndefined);
-    SetGVNFlag(kChangesDoubleArrayElements);
-  }
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    if (index == 1) {
-      return Representation::Integer32();
-    } else if (index == 2) {
-      return Representation::Double();
-    } else {
-      return Representation::Tagged();
-    }
-  }
-
-  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());
-  }

    bool NeedsCanonicalization();

    virtual void PrintDataTo(StringStream* stream);
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
-
- private:
-  uint32_t index_offset_;
-  bool is_dehoisted_;
-};
-
-
-class HStoreKeyedSpecializedArrayElement
-    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
- public:
-  HStoreKeyedSpecializedArrayElement(HValue* external_elements,
-                                     HValue* key,
-                                     HValue* val,
-                                     ElementsKind elements_kind)
-      : elements_kind_(elements_kind), index_offset_(0),  
is_dehoisted_(false) {
-    SetGVNFlag(kChangesSpecializedArrayElements);
-    SetOperandAt(0, external_elements);
-    SetOperandAt(1, key);
-    SetOperandAt(2, val);
-  }
-
-  virtual void PrintDataTo(StringStream* stream);

-  virtual Representation RequiredInputRepresentation(int index) {
-    if (index == 0) {
-      return Representation::External();
-    } else {
-      bool float_or_double_elements =
-          elements_kind() == EXTERNAL_FLOAT_ELEMENTS ||
-          elements_kind() == EXTERNAL_DOUBLE_ELEMENTS;
-      if (index == 2 && float_or_double_elements) {
-        return Representation::Double();
-      } else {
-        return Representation::Integer32();
-      }
-    }
-  }
-
-  HValue* external_pointer() { return OperandAt(0); }
-  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)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)

   private:
    ElementsKind elements_kind_;
@@ -4741,6 +4594,7 @@
    StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }

    virtual Representation RequiredInputRepresentation(int index) {
+    // tagged[tagged] = tagged
      return Representation::Tagged();
    }

=======================================
--- /branches/bleeding_edge/src/hydrogen.cc	Mon Oct 15 00:25:20 2012
+++ /branches/bleeding_edge/src/hydrogen.cc	Fri Nov  2 02:18:53 2012
@@ -2715,17 +2715,18 @@
    } else if (use->IsChange() || use->IsSimulate()) {
      // Conversions and deoptimization have special support for unt32.
      return true;
-  } else if (use->IsStoreKeyedSpecializedArrayElement()) {
-    // Storing a value into an external integer array is a bit level  
operation.
-    HStoreKeyedSpecializedArrayElement* store =
-        HStoreKeyedSpecializedArrayElement::cast(use);
-
-    if (store->value() == val) {
-      // Clamping or a conversion to double should have beed inserted.
-      ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
-      ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
-      ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
-      return true;
+  } else if (use->IsStoreKeyed()) {
+    HStoreKeyed* store = HStoreKeyed::cast(use);
+    if (store->is_external()) {
+      // Storing a value into an external integer array is a bit level
+      // operation.
+      if (store->value() == val) {
+        // Clamping or a conversion to double should have beed inserted.
+        ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
+        ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
+        ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
+        return true;
+      }
      }
    }

@@ -3757,27 +3758,11 @@
          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);
+      if (instr->IsLoadKeyed()) {
+        HLoadKeyed* op = HLoadKeyed::cast(instr);
          array_instruction = static_cast<ArrayInstructionInterface*>(op);
-      } else if (instr->IsStoreKeyedSpecializedArrayElement()) {
-        HStoreKeyedSpecializedArrayElement* op =
-            HStoreKeyedSpecializedArrayElement::cast(instr);
+      } else if (instr->IsStoreKeyed()) {
+        HStoreKeyed* op = HStoreKeyed::cast(instr);
          array_instruction = static_cast<ArrayInstructionInterface*>(op);
        } else {
          continue;
@@ -4617,10 +4602,11 @@
    set_current_block(loop_body);

    HValue* key = AddInstruction(
-      new(zone()) HLoadKeyedFastElement(
+      new(zone()) HLoadKeyed(
            environment()->ExpressionStackAt(2),  // Enum cache.
            environment()->ExpressionStackAt(0),  // Iteration index.
-          environment()->ExpressionStackAt(0)));
+          environment()->ExpressionStackAt(0),
+          FAST_ELEMENTS));

    // Check if the expected map still matches that of the enumerable.
    // If not just deoptimize.
@@ -5225,18 +5211,14 @@
          // Fall through.
        case FAST_ELEMENTS:
        case FAST_HOLEY_ELEMENTS:
-        AddInstruction(new(zone()) HStoreKeyedFastElement(
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+        AddInstruction(new(zone()) HStoreKeyed(
              elements,
              key,
              value,
              boilerplate_elements_kind));
          break;
-      case FAST_DOUBLE_ELEMENTS:
-      case FAST_HOLEY_DOUBLE_ELEMENTS:
-        AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements,
-                                                                key,
-                                                                value));
-        break;
        default:
          UNREACHABLE();
          break;
@@ -6085,13 +6067,15 @@
          UNREACHABLE();
          break;
      }
-    return new(zone()) HStoreKeyedSpecializedArrayElement(
-        external_elements, checked_key, val, elements_kind);
+    return new(zone()) HStoreKeyed(external_elements,
+                                   checked_key,
+                                   val,
+                                   elements_kind);
    } else {
      ASSERT(val == NULL);
-    HLoadKeyedSpecializedArrayElement* load =
-       new(zone()) HLoadKeyedSpecializedArrayElement(
-          external_elements, checked_key, dependency, elements_kind);
+    HLoadKeyed* load =
+       new(zone()) HLoadKeyed(
+           external_elements, checked_key, dependency, elements_kind);
      if (FLAG_opt_safe_uint32_operations &&
          elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
        graph()->RecordUint32Instruction(load);
@@ -6110,10 +6094,6 @@
    if (is_store) {
      ASSERT(val != NULL);
      switch (elements_kind) {
-      case FAST_DOUBLE_ELEMENTS:
-      case FAST_HOLEY_DOUBLE_ELEMENTS:
-        return new(zone()) HStoreKeyedFastDoubleElement(
-            elements, checked_key, val);
        case FAST_SMI_ELEMENTS:
        case FAST_HOLEY_SMI_ELEMENTS:
          // Smi-only arrays need a smi check.
@@ -6121,7 +6101,9 @@
          // Fall through.
        case FAST_ELEMENTS:
        case FAST_HOLEY_ELEMENTS:
-        return new(zone()) HStoreKeyedFastElement(
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+        return new(zone()) HStoreKeyed(
              elements, checked_key, val, elements_kind);
        default:
          UNREACHABLE();
@@ -6129,16 +6111,10 @@
      }
    }
    // It's an element load (!is_store).
-  HoleCheckMode mode = IsFastPackedElementsKind(elements_kind) ?
-      OMIT_HOLE_CHECK :
-      PERFORM_HOLE_CHECK;
-  if (IsFastDoubleElementsKind(elements_kind)) {
-    return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key,
-                                                   load_dependency, mode);
-  } else {  // Smi or Object elements.
-    return new(zone()) HLoadKeyedFastElement(elements, checked_key,
-                                             load_dependency,  
elements_kind);
-  }
+  return new(zone()) HLoadKeyed(elements,
+                                checked_key,
+                                load_dependency,
+                                elements_kind);
  }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc	Mon Oct 15  
00:25:20 2012
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc	Fri Nov  2  
02:18:53 2012
@@ -2749,33 +2749,71 @@
  }


-void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
-  Register result = ToRegister(instr->result());
-
-  // Load the result.
-  __ mov(result,
-         BuildFastArrayOperand(instr->elements(),
-                               instr->key(),
-                               instr->hydrogen()->key()->representation(),
-                               FAST_ELEMENTS,
-                               FixedArray::kHeaderSize - kHeapObjectTag,
-                               instr->additional_index()));
-
-  // Check for the hole value.
-  if (instr->hydrogen()->RequiresHoleCheck()) {
-    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
-      __ test(result, Immediate(kSmiTagMask));
-      DeoptimizeIf(not_equal, instr->environment());
-    } else {
-      __ cmp(result, factory()->the_hole_value());
-      DeoptimizeIf(equal, instr->environment());
+void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
+  ElementsKind elements_kind = instr->elements_kind();
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand() &&
+       
ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
+                                  elements_kind)) {
+    __ SmiUntag(ToRegister(key));
+  }
+  Operand operand(BuildFastArrayOperand(
+      instr->elements(),
+      key,
+      instr->hydrogen()->key()->representation(),
+      elements_kind,
+      0,
+      instr->additional_index()));
+  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+    XMMRegister result(ToDoubleRegister(instr->result()));
+    __ movss(result, operand);
+    __ cvtss2sd(result, result);
+  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+    __ movdbl(ToDoubleRegister(instr->result()), operand);
+  } else {
+    Register result(ToRegister(instr->result()));
+    switch (elements_kind) {
+      case EXTERNAL_BYTE_ELEMENTS:
+        __ movsx_b(result, operand);
+        break;
+      case EXTERNAL_PIXEL_ELEMENTS:
+      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+        __ movzx_b(result, operand);
+        break;
+      case EXTERNAL_SHORT_ELEMENTS:
+        __ movsx_w(result, operand);
+        break;
+      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+        __ movzx_w(result, operand);
+        break;
+      case EXTERNAL_INT_ELEMENTS:
+        __ mov(result, operand);
+        break;
+      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+        __ mov(result, operand);
+        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
+          __ test(result, Operand(result));
+          DeoptimizeIf(negative, instr->environment());
+        }
+        break;
+      case EXTERNAL_FLOAT_ELEMENTS:
+      case EXTERNAL_DOUBLE_ELEMENTS:
+      case FAST_SMI_ELEMENTS:
+      case FAST_ELEMENTS:
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_SMI_ELEMENTS:
+      case FAST_HOLEY_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+      case DICTIONARY_ELEMENTS:
+      case NON_STRICT_ARGUMENTS_ELEMENTS:
+        UNREACHABLE();
+        break;
      }
    }
  }


-void LCodeGen::DoLoadKeyedFastDoubleElement(
-    LLoadKeyedFastDoubleElement* instr) {
+void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
    XMMRegister result = ToDoubleRegister(instr->result());

    if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -2800,6 +2838,42 @@
        instr->additional_index());
    __ movdbl(result, double_load_operand);
  }
+
+
+void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
+  Register result = ToRegister(instr->result());
+
+  // Load the result.
+  __ mov(result,
+         BuildFastArrayOperand(instr->elements(),
+                               instr->key(),
+                               instr->hydrogen()->key()->representation(),
+                               FAST_ELEMENTS,
+                               FixedArray::kHeaderSize - kHeapObjectTag,
+                               instr->additional_index()));
+
+  // Check for the hole value.
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
+      __ test(result, Immediate(kSmiTagMask));
+      DeoptimizeIf(not_equal, instr->environment());
+    } else {
+      __ cmp(result, factory()->the_hole_value());
+      DeoptimizeIf(equal, instr->environment());
+    }
+  }
+}
+
+
+void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
+  if (instr->is_external()) {
+    DoLoadKeyedExternalArray(instr);
+  } else if (instr->hydrogen()->representation().IsDouble()) {
+    DoLoadKeyedFixedDoubleArray(instr);
+  } else {
+    DoLoadKeyedFixedArray(instr);
+  }
+}


  Operand LCodeGen::BuildFastArrayOperand(
@@ -2811,7 +2885,7 @@
      uint32_t additional_index) {
    Register elements_pointer_reg = ToRegister(elements_pointer);
    int shift_size = ElementsKindToShiftSize(elements_kind);
-  // Even though the HLoad/StoreKeyedFastElement instructions force the  
input
+  // Even though the HLoad/StoreKeyed instructions force the input
    // representation for the key to be an integer, the input gets replaced  
during
    // bound check elimination with the index argument to the bounds check,  
which
    // can be tagged, so that case must be handled here, too.
@@ -2834,71 +2908,6 @@
                     offset + (additional_index << shift_size));
    }
  }
-
-
-void LCodeGen::DoLoadKeyedSpecializedArrayElement(
-    LLoadKeyedSpecializedArrayElement* instr) {
-  ElementsKind elements_kind = instr->elements_kind();
-  LOperand* key = instr->key();
-  if (!key->IsConstantOperand() &&
-       
ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
-                                  elements_kind)) {
-    __ SmiUntag(ToRegister(key));
-  }
-  Operand operand(BuildFastArrayOperand(
-      instr->external_pointer(),
-      key,
-      instr->hydrogen()->key()->representation(),
-      elements_kind,
-      0,
-      instr->additional_index()));
-  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
-    XMMRegister result(ToDoubleRegister(instr->result()));
-    __ movss(result, operand);
-    __ cvtss2sd(result, result);
-  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
-    __ movdbl(ToDoubleRegister(instr->result()), operand);
-  } else {
-    Register result(ToRegister(instr->result()));
-    switch (elements_kind) {
-      case EXTERNAL_BYTE_ELEMENTS:
-        __ movsx_b(result, operand);
-        break;
-      case EXTERNAL_PIXEL_ELEMENTS:
-      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-        __ movzx_b(result, operand);
-        break;
-      case EXTERNAL_SHORT_ELEMENTS:
-        __ movsx_w(result, operand);
-        break;
-      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-        __ movzx_w(result, operand);
-        break;
-      case EXTERNAL_INT_ELEMENTS:
-        __ mov(result, operand);
-        break;
-      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-        __ mov(result, operand);
-        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
-          __ test(result, Operand(result));
-          DeoptimizeIf(negative, instr->environment());
-        }
-        break;
-      case EXTERNAL_FLOAT_ELEMENTS:
-      case EXTERNAL_DOUBLE_ELEMENTS:
-      case FAST_SMI_ELEMENTS:
-      case FAST_ELEMENTS:
-      case FAST_DOUBLE_ELEMENTS:
-      case FAST_HOLEY_SMI_ELEMENTS:
-      case FAST_HOLEY_ELEMENTS:
-      case FAST_HOLEY_DOUBLE_ELEMENTS:
-      case DICTIONARY_ELEMENTS:
-      case NON_STRICT_ARGUMENTS_ELEMENTS:
-        UNREACHABLE();
-        break;
-    }
-  }
-}


  void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
@@ -3818,8 +3827,7 @@
  }


-void LCodeGen::DoStoreKeyedSpecializedArrayElement(
-    LStoreKeyedSpecializedArrayElement* instr) {
+void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
    ElementsKind elements_kind = instr->elements_kind();
    LOperand* key = instr->key();
    if (!key->IsConstantOperand() &&
@@ -3828,7 +3836,7 @@
      __ SmiUntag(ToRegister(key));
    }
    Operand operand(BuildFastArrayOperand(
-      instr->external_pointer(),
+      instr->elements(),
        key,
        instr->hydrogen()->key()->representation(),
        elements_kind,
@@ -3872,13 +3880,39 @@
  }


-void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
+void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
+  XMMRegister value = ToDoubleRegister(instr->value());
+
+  if (instr->NeedsCanonicalization()) {
+    Label have_value;
+
+    __ ucomisd(value, value);
+    __ j(parity_odd, &have_value);  // NaN.
+
+    ExternalReference canonical_nan_reference =
+        ExternalReference::address_of_canonical_non_hole_nan();
+    __ movdbl(value, Operand::StaticVariable(canonical_nan_reference));
+    __ bind(&have_value);
+  }
+
+  Operand double_store_operand = BuildFastArrayOperand(
+      instr->elements(),
+      instr->key(),
+      instr->hydrogen()->key()->representation(),
+      FAST_DOUBLE_ELEMENTS,
+      FixedDoubleArray::kHeaderSize - kHeapObjectTag,
+      instr->additional_index());
+  __ movdbl(double_store_operand, value);
+}
+
+
+void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
    Register value = ToRegister(instr->value());
-  Register elements = ToRegister(instr->object());
+  Register elements = ToRegister(instr->elements());
    Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) :  
no_reg;

    Operand operand = BuildFastArrayOperand(
-      instr->object(),
+      instr->elements(),
        instr->key(),
        instr->hydrogen()->key()->representation(),
        FAST_ELEMENTS,
@@ -3903,30 +3937,15 @@
  }


-void LCodeGen::DoStoreKeyedFastDoubleElement(
-    LStoreKeyedFastDoubleElement* instr) {
-  XMMRegister value = ToDoubleRegister(instr->value());
-
-  if (instr->NeedsCanonicalization()) {
-    Label have_value;
-
-    __ ucomisd(value, value);
-    __ j(parity_odd, &have_value);  // NaN.
-
-    ExternalReference canonical_nan_reference =
-        ExternalReference::address_of_canonical_non_hole_nan();
-    __ movdbl(value, Operand::StaticVariable(canonical_nan_reference));
-    __ bind(&have_value);
+void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
+  // By cases...external, fast-double, fast
+  if (instr->is_external()) {
+    DoStoreKeyedExternalArray(instr);
+  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
+    DoStoreKeyedFixedDoubleArray(instr);
+  } else {
+    DoStoreKeyedFixedArray(instr);
    }
-
-  Operand double_store_operand = BuildFastArrayOperand(
-      instr->elements(),
-      instr->key(),
-      instr->hydrogen()->key()->representation(),
-      FAST_DOUBLE_ELEMENTS,
-      FixedDoubleArray::kHeaderSize - kHeapObjectTag,
-      instr->additional_index());
-  __ movdbl(double_store_operand, value);
  }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h	Wed Sep 12  
05:28:42 2012
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h	Fri Nov  2  
02:18:53 2012
@@ -340,6 +340,12 @@
                      int* offset);

    void EnsureSpaceForLazyDeopt();
+  void DoLoadKeyedExternalArray(LLoadKeyed* instr);
+  void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
+  void DoLoadKeyedFixedArray(LLoadKeyed* instr);
+  void DoStoreKeyedExternalArray(LStoreKeyed* instr);
+  void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
+  void DoStoreKeyedFixedArray(LStoreKeyed* instr);

    // Emits code for pushing either a tagged constant, a (non-double)
    // register, or a stack slot operand.
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc	Fri Oct 19 06:20:22  
2012
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc	Fri Nov  2 02:18:53  
2012
@@ -407,16 +407,7 @@
  }


-void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
-  object()->PrintTo(stream);
-  stream->Add("[");
-  key()->PrintTo(stream);
-  stream->Add("] <- ");
-  value()->PrintTo(stream);
-}
-
-
-void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+void LStoreKeyed::PrintDataTo(StringStream* stream) {
    elements()->PrintTo(stream);
    stream->Add("[");
    key()->PrintTo(stream);
@@ -1932,59 +1923,38 @@
  }


-LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
-    HLoadKeyedFastElement* instr) {
-  ASSERT(instr->representation().IsTagged());
+LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
    ASSERT(instr->key()->representation().IsInteger32() ||
           instr->key()->representation().IsTagged());
-  LOperand* obj = UseRegisterAtStart(instr->object());
-  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
-  LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj,  
key);
-  if (instr->RequiresHoleCheck()) AssignEnvironment(result);
-  return DefineAsRegister(result);
-}
-
-
-LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
-    HLoadKeyedFastDoubleElement* instr) {
-  ASSERT(instr->representation().IsDouble());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-  LOperand* elements = UseRegisterAtStart(instr->elements());
-  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
-  LLoadKeyedFastDoubleElement* result =
-      new(zone()) LLoadKeyedFastDoubleElement(elements, key);
-  return AssignEnvironment(DefineAsRegister(result));
-}
-
-
-LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
-    HLoadKeyedSpecializedArrayElement* instr) {
    ElementsKind elements_kind = instr->elements_kind();
-  ASSERT(
-      (instr->representation().IsInteger32() &&
-       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
-       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
-      (instr->representation().IsDouble() &&
-       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
-       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-  LOperand* external_pointer = UseRegister(instr->external_pointer());
    bool clobbers_key = ExternalArrayOpRequiresTemp(
        instr->key()->representation(), elements_kind);
    LOperand* key = clobbers_key
        ? UseTempRegister(instr->key())
-      : UseRegisterOrConstant(instr->key());
+      : UseRegisterOrConstantAtStart(instr->key());
+  LLoadKeyed* result = NULL;

-  LLoadKeyedSpecializedArrayElement* result =
-    new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
-  LInstruction* load_instr = DefineAsRegister(result);
+  if (!instr->is_external()) {
+    LOperand* obj = UseRegisterAtStart(instr->elements());
+    result = new(zone()) LLoadKeyed(obj, key);
+  } else {
+    ASSERT(
+        (instr->representation().IsInteger32() &&
+         (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
+         (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+        (instr->representation().IsDouble() &&
+         ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
+          (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+    LOperand* external_pointer = UseRegister(instr->elements());
+    result = new(zone()) LLoadKeyed(external_pointer, key);
+  }
+
+  DefineAsRegister(result);
+  bool can_deoptimize = instr->RequiresHoleCheck() ||
+      (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
    // An unsigned int array load might overflow and cause a deopt, make  
sure it
    // has an environment.
-  return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS)
-      ? AssignEnvironment(load_instr)
-      : load_instr;
+  return can_deoptimize ? AssignEnvironment(result) : result;
  }


@@ -1998,73 +1968,67 @@
    return MarkAsCall(DefineFixed(result, eax), instr);
  }

-
-LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
-    HStoreKeyedFastElement* instr) {
-  bool needs_write_barrier = instr->NeedsWriteBarrier();
-  ASSERT(instr->value()->representation().IsTagged());
-  ASSERT(instr->object()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-
-  LOperand* obj = UseRegister(instr->object());
-  LOperand* val = needs_write_barrier
-      ? UseTempRegister(instr->value())
-      : UseRegisterAtStart(instr->value());
-  LOperand* key = needs_write_barrier
-      ? UseTempRegister(instr->key())
-      : UseRegisterOrConstantAtStart(instr->key());
-  return new(zone()) LStoreKeyedFastElement(obj, key, val);
-}

+LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
+  LStoreKeyed* result = NULL;

-LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
-    HStoreKeyedFastDoubleElement* instr) {
-  ASSERT(instr->value()->representation().IsDouble());
-  ASSERT(instr->elements()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
+  if (!instr->is_external()) {
+    ASSERT(instr->elements()->representation().IsTagged());
+    ASSERT(instr->key()->representation().IsInteger32() ||
+           instr->key()->representation().IsTagged());

-  LOperand* elements = UseRegisterAtStart(instr->elements());
-  LOperand* val = UseTempRegister(instr->value());
-  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+    if (instr->value()->representation().IsDouble()) {
+      LOperand* object = UseRegisterAtStart(instr->elements());
+      LOperand* val = UseTempRegister(instr->value());
+      LOperand* key = UseRegisterOrConstantAtStart(instr->key());

-  return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
-}
+      result = new(zone()) LStoreKeyed(object, key, val);
+    } else {
+      ASSERT(instr->value()->representation().IsTagged());
+      bool needs_write_barrier = instr->NeedsWriteBarrier();

-
-LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
-    HStoreKeyedSpecializedArrayElement* instr) {
-  ElementsKind elements_kind = instr->elements_kind();
+      LOperand* obj = UseRegister(instr->elements());
+      LOperand* val = needs_write_barrier
+          ? UseTempRegister(instr->value())
+          : UseRegisterAtStart(instr->value());
+      LOperand* key = needs_write_barrier
+          ? UseTempRegister(instr->key())
+          : UseRegisterOrConstantAtStart(instr->key());
+      result = new(zone()) LStoreKeyed(obj, key, val);
+    }
+  } else {
+    ElementsKind elements_kind = instr->elements_kind();
      ASSERT(
-      (instr->value()->representation().IsInteger32() &&
-       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
-       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
-      (instr->value()->representation().IsDouble() &&
-       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
-       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->external_pointer()->representation().IsExternal());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
+        (instr->value()->representation().IsInteger32() &&
+         (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
+         (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+        (instr->value()->representation().IsDouble() &&
+         ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
+          (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+    ASSERT(instr->elements()->representation().IsExternal());

-  LOperand* external_pointer = UseRegister(instr->external_pointer());
-  LOperand* val = NULL;
-  if (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
-      elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
-      elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
-    // We need a byte register in this case for the value.
-    val = UseFixed(instr->value(), eax);
-  } else {
-    val = UseRegister(instr->value());
+    LOperand* external_pointer = UseRegister(instr->elements());
+    // Determine if we need a byte register in this case for the value.
+    bool val_is_fixed_register =
+        elements_kind == EXTERNAL_BYTE_ELEMENTS ||
+        elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
+        elements_kind == EXTERNAL_PIXEL_ELEMENTS;
+
+    LOperand* val = val_is_fixed_register
+        ? UseFixed(instr->value(), eax)
+        : UseRegister(instr->value());
+    bool clobbers_key = ExternalArrayOpRequiresTemp(
+        instr->key()->representation(), elements_kind);
+    LOperand* key = clobbers_key
+        ? UseTempRegister(instr->key())
+        : UseRegisterOrConstantAtStart(instr->key());
+    result = new(zone()) LStoreKeyed(external_pointer,
+                                     key,
+                                     val);
    }
-  bool clobbers_key = ExternalArrayOpRequiresTemp(
-      instr->key()->representation(), elements_kind);
-  LOperand* key = clobbers_key
-      ? UseTempRegister(instr->key())
-      : UseRegisterOrConstant(instr->key());
-  return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
-                                                        key,
-                                                        val);
+
+  ASSERT(result != NULL);
+  return result;
  }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h	Fri Sep 14 04:55:49 2012
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h	Fri Nov  2 02:18:53 2012
@@ -119,10 +119,8 @@
    V(LoadFunctionPrototype)                      \
    V(LoadGlobalCell)                             \
    V(LoadGlobalGeneric)                          \
-  V(LoadKeyedFastElement)                       \
-  V(LoadKeyedFastDoubleElement)                 \
+  V(LoadKeyed)                                  \
    V(LoadKeyedGeneric)                           \
-  V(LoadKeyedSpecializedArrayElement)           \
    V(LoadNamedField)                             \
    V(LoadNamedFieldPolymorphic)                  \
    V(LoadNamedGeneric)                           \
@@ -152,10 +150,8 @@
    V(StoreContextSlot)                           \
    V(StoreGlobalCell)                            \
    V(StoreGlobalGeneric)                         \
-  V(StoreKeyedFastDoubleElement)                \
-  V(StoreKeyedFastElement)                      \
+  V(StoreKeyed)                                 \
    V(StoreKeyedGeneric)                          \
-  V(StoreKeyedSpecializedArrayElement)          \
    V(StoreNamedField)                            \
    V(StoreNamedGeneric)                          \
    V(StringAdd)                                  \
@@ -1389,36 +1385,24 @@
  };


-class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
+class LLoadKeyed: public LTemplateInstruction<1, 2, 0> {
   public:
-  LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
+  LLoadKeyed(LOperand* elements, LOperand* key) {
      inputs_[0] = elements;
      inputs_[1] = key;
    }

    LOperand* elements() { return inputs_[0]; }
    LOperand* key() { return inputs_[1]; }
-
-   
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
-
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
-class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
- public:
-  LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
-    inputs_[0] = elements;
-    inputs_[1] = key;
+  ElementsKind elements_kind() const {
+    return hydrogen()->elements_kind();
+  }
+  bool is_external() const {
+    return hydrogen()->is_external();
    }

-  LOperand* elements() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
-                               "load-keyed-fast-double-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)

    uint32_t additional_index() const { return hydrogen()->index_offset(); }
  };
@@ -1437,27 +1421,6 @@
  }


-class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2,  
0> {
- public:
-  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand*  
key) {
-    inputs_[0] = external_pointer;
-    inputs_[1] = key;
-  }
-
-  LOperand* external_pointer() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
-                               "load-keyed-specialized-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
-
-  ElementsKind elements_kind() const {
-    return hydrogen()->elements_kind();
-  }
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
  class LLoadKeyedGeneric: public LTemplateInstruction<1, 3, 0> {
   public:
    LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) {
@@ -2006,78 +1969,31 @@
  };


-class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
+class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
   public:
-  LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val) {
+  LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
      inputs_[0] = obj;
      inputs_[1] = key;
      inputs_[2] = val;
    }

-  LOperand* object() { return inputs_[0]; }
+  bool is_external() const { return hydrogen()->is_external(); }
+  LOperand* elements() { return inputs_[0]; }
    LOperand* key() { return inputs_[1]; }
    LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
-                               "store-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
-
-  virtual void PrintDataTo(StringStream* stream);
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
-class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
- public:
-  LStoreKeyedFastDoubleElement(LOperand* elements,
-                               LOperand* key,
-                               LOperand* val) {
-    inputs_[0] = elements;
-    inputs_[1] = key;
-    inputs_[2] = val;
+  ElementsKind elements_kind() const {
+    return hydrogen()->elements_kind();
    }

-  LOperand* elements() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
-                               "store-keyed-fast-double-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)

    virtual void PrintDataTo(StringStream* stream);
-
    uint32_t additional_index() const { return hydrogen()->index_offset(); }
-
    bool NeedsCanonicalization() { return  
hydrogen()->NeedsCanonicalization(); }
  };


-class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0,  
3, 0> {
- public:
-  LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
-                                     LOperand* key,
-                                     LOperand* val) {
-    inputs_[0] = external_pointer;
-    inputs_[1] = key;
-    inputs_[2] = val;
-  }
-
-  LOperand* external_pointer() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
-                               "store-keyed-specialized-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
-
-  ElementsKind elements_kind() const {
-    return hydrogen()->elements_kind();
-  }
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
  class LStoreKeyedGeneric: public LTemplateInstruction<0, 4, 0> {
   public:
    LStoreKeyedGeneric(LOperand* context,
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc	Fri Oct 19  
06:20:22 2012
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc	Fri Nov  2  
02:18:53 2012
@@ -2612,15 +2612,16 @@
  }


-void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
-  Register result = ToRegister(instr->result());
+void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
+  ElementsKind elements_kind = instr->elements_kind();
    LOperand* key = instr->key();
    if (!key->IsConstantOperand()) {
      Register key_reg = ToRegister(key);
-    // Even though the HLoad/StoreKeyedFastElement instructions force the  
input
-    // representation for the key to be an integer, the input gets replaced
-    // during bound check elimination with the index argument to the bounds
-    // check, which can be tagged, so that case must be handled here, too.
+    // Even though the HLoad/StoreKeyed (in this case) instructions force
+    // the input representation for the key to be an integer, the input
+    // gets replaced during bound check elimination with the index argument
+    // to the bounds check, which can be tagged, so that case must be
+    // handled here, too.
      if (instr->hydrogen()->key()->representation().IsTagged()) {
        __ SmiToInteger64(key_reg, key_reg);
      } else if (instr->hydrogen()->IsDehoisted()) {
@@ -2629,35 +2630,68 @@
        __ movsxlq(key_reg, key_reg);
      }
    }
+  Operand operand(BuildFastArrayOperand(
+      instr->elements(),
+      key,
+      elements_kind,
+      0,
+      instr->additional_index()));

-  // Load the result.
-  __ movq(result,
-          BuildFastArrayOperand(instr->elements(),
-                                key,
-                                FAST_ELEMENTS,
-                                FixedArray::kHeaderSize - kHeapObjectTag,
-                                instr->additional_index()));
-
-  // Check for the hole value.
-  if (instr->hydrogen()->RequiresHoleCheck()) {
-    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
-      Condition smi = __ CheckSmi(result);
-      DeoptimizeIf(NegateCondition(smi), instr->environment());
-    } else {
-      __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
-      DeoptimizeIf(equal, instr->environment());
+  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+    XMMRegister result(ToDoubleRegister(instr->result()));
+    __ movss(result, operand);
+    __ cvtss2sd(result, result);
+  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+    __ movsd(ToDoubleRegister(instr->result()), operand);
+  } else {
+    Register result(ToRegister(instr->result()));
+    switch (elements_kind) {
+      case EXTERNAL_BYTE_ELEMENTS:
+        __ movsxbq(result, operand);
+        break;
+      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+      case EXTERNAL_PIXEL_ELEMENTS:
+        __ movzxbq(result, operand);
+        break;
+      case EXTERNAL_SHORT_ELEMENTS:
+        __ movsxwq(result, operand);
+        break;
+      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+        __ movzxwq(result, operand);
+        break;
+      case EXTERNAL_INT_ELEMENTS:
+        __ movsxlq(result, operand);
+        break;
+      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+        __ movl(result, operand);
+        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
+          __ testl(result, result);
+          DeoptimizeIf(negative, instr->environment());
+        }
+        break;
+      case EXTERNAL_FLOAT_ELEMENTS:
+      case EXTERNAL_DOUBLE_ELEMENTS:
+      case FAST_ELEMENTS:
+      case FAST_SMI_ELEMENTS:
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_ELEMENTS:
+      case FAST_HOLEY_SMI_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+      case DICTIONARY_ELEMENTS:
+      case NON_STRICT_ARGUMENTS_ELEMENTS:
+        UNREACHABLE();
+        break;
      }
    }
  }


-void LCodeGen::DoLoadKeyedFastDoubleElement(
-    LLoadKeyedFastDoubleElement* instr) {
+void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
    XMMRegister result(ToDoubleRegister(instr->result()));
    LOperand* key = instr->key();
    if (!key->IsConstantOperand()) {
      Register key_reg = ToRegister(key);
-    // Even though the HLoad/StoreKeyedFastElement instructions force the  
input
+    // Even though the HLoad/StoreKeyed instructions force the input
      // representation for the key to be an integer, the input gets replaced
      // during bound check elimination with the index argument to the bounds
      // check, which can be tagged, so that case must be handled here, too.
@@ -2691,6 +2725,57 @@
        instr->additional_index());
    __ movsd(result, double_load_operand);
  }
+
+
+void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
+  Register result = ToRegister(instr->result());
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand()) {
+    Register key_reg = ToRegister(key);
+    // Even though the HLoad/StoreKeyedFastElement instructions force
+    // the input representation for the key to be an integer, the input
+    // gets replaced during bound check elimination with the index
+    // argument to the bounds check, which can be tagged, so that
+    // case must be handled here, too.
+    if (instr->hydrogen()->key()->representation().IsTagged()) {
+      __ SmiToInteger64(key_reg, key_reg);
+    } else if (instr->hydrogen()->IsDehoisted()) {
+      // Sign extend key because it could be a 32 bit negative value
+      // and the dehoisted address computation happens in 64 bits
+      __ movsxlq(key_reg, key_reg);
+    }
+  }
+
+  // Load the result.
+  __ movq(result,
+          BuildFastArrayOperand(instr->elements(),
+                                key,
+                                FAST_ELEMENTS,
+                                FixedArray::kHeaderSize - kHeapObjectTag,
+                                instr->additional_index()));
+
+  // Check for the hole value.
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
+      Condition smi = __ CheckSmi(result);
+      DeoptimizeIf(NegateCondition(smi), instr->environment());
+    } else {
+      __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
+      DeoptimizeIf(equal, instr->environment());
+    }
+  }
+}
+
+
+void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
+  if (instr->is_external()) {
+    DoLoadKeyedExternalArray(instr);
+  } else if (instr->hydrogen()->representation().IsDouble()) {
+    DoLoadKeyedFixedDoubleArray(instr);
+  } else {
+    DoLoadKeyedFixedArray(instr);
+  }
+}


  Operand LCodeGen::BuildFastArrayOperand(
@@ -2717,80 +2802,6 @@
                     offset + (additional_index << shift_size));
    }
  }
-
-
-void LCodeGen::DoLoadKeyedSpecializedArrayElement(
-    LLoadKeyedSpecializedArrayElement* instr) {
-  ElementsKind elements_kind = instr->elements_kind();
-  LOperand* key = instr->key();
-  if (!key->IsConstantOperand()) {
-    Register key_reg = ToRegister(key);
-    // Even though the HLoad/StoreKeyedFastElement instructions force the  
input
-    // representation for the key to be an integer, the input gets replaced
-    // during bound check elimination with the index argument to the bounds
-    // check, which can be tagged, so that case must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
-      __ SmiToInteger64(key_reg, key_reg);
-    } else if (instr->hydrogen()->IsDehoisted()) {
-      // Sign extend key because it could be a 32 bit negative value
-      // and the dehoisted address computation happens in 64 bits
-      __ movsxlq(key_reg, key_reg);
-    }
-  }
-  Operand operand(BuildFastArrayOperand(
-      instr->external_pointer(),
-      key,
-      elements_kind,
-      0,
-      instr->additional_index()));
-
-  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
-    XMMRegister result(ToDoubleRegister(instr->result()));
-    __ movss(result, operand);
-    __ cvtss2sd(result, result);
-  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
-    __ movsd(ToDoubleRegister(instr->result()), operand);
-  } else {
-    Register result(ToRegister(instr->result()));
-    switch (elements_kind) {
-      case EXTERNAL_BYTE_ELEMENTS:
-        __ movsxbq(result, operand);
-        break;
-      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-      case EXTERNAL_PIXEL_ELEMENTS:
-        __ movzxbq(result, operand);
-        break;
-      case EXTERNAL_SHORT_ELEMENTS:
-        __ movsxwq(result, operand);
-        break;
-      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-        __ movzxwq(result, operand);
-        break;
-      case EXTERNAL_INT_ELEMENTS:
-        __ movsxlq(result, operand);
-        break;
-      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-        __ movl(result, operand);
-        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
-          __ testl(result, result);
-          DeoptimizeIf(negative, instr->environment());
-        }
-        break;
-      case EXTERNAL_FLOAT_ELEMENTS:
-      case EXTERNAL_DOUBLE_ELEMENTS:
-      case FAST_ELEMENTS:
-      case FAST_SMI_ELEMENTS:
-      case FAST_DOUBLE_ELEMENTS:
-      case FAST_HOLEY_ELEMENTS:
-      case FAST_HOLEY_SMI_ELEMENTS:
-      case FAST_HOLEY_DOUBLE_ELEMENTS:
-      case DICTIONARY_ELEMENTS:
-      case NON_STRICT_ARGUMENTS_ELEMENTS:
-        UNREACHABLE();
-        break;
-    }
-  }
-}


  void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
@@ -3663,70 +3674,6 @@
        : isolate()->builtins()->StoreIC_Initialize();
    CallCode(ic, RelocInfo::CODE_TARGET, instr);
  }
-
-
-void LCodeGen::DoStoreKeyedSpecializedArrayElement(
-    LStoreKeyedSpecializedArrayElement* instr) {
-  ElementsKind elements_kind = instr->elements_kind();
-  LOperand* key = instr->key();
-  if (!key->IsConstantOperand()) {
-    Register key_reg = ToRegister(key);
-    // Even though the HLoad/StoreKeyedFastElement instructions force the  
input
-    // representation for the key to be an integer, the input gets replaced
-    // during bound check elimination with the index argument to the bounds
-    // check, which can be tagged, so that case must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
-      __ SmiToInteger64(key_reg, key_reg);
-    } else if (instr->hydrogen()->IsDehoisted()) {
-      // Sign extend key because it could be a 32 bit negative value
-      // and the dehoisted address computation happens in 64 bits
-      __ movsxlq(key_reg, key_reg);
-    }
-  }
-  Operand operand(BuildFastArrayOperand(
-      instr->external_pointer(),
-      key,
-      elements_kind,
-      0,
-      instr->additional_index()));
-
-  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
-    XMMRegister value(ToDoubleRegister(instr->value()));
-    __ cvtsd2ss(value, value);
-    __ movss(operand, value);
-  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
-    __ movsd(operand, ToDoubleRegister(instr->value()));
-  } else {
-    Register value(ToRegister(instr->value()));
-    switch (elements_kind) {
-      case EXTERNAL_PIXEL_ELEMENTS:
-      case EXTERNAL_BYTE_ELEMENTS:
-      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-        __ movb(operand, value);
-        break;
-      case EXTERNAL_SHORT_ELEMENTS:
-      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-        __ movw(operand, value);
-        break;
-      case EXTERNAL_INT_ELEMENTS:
-      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-        __ movl(operand, value);
-        break;
-      case EXTERNAL_FLOAT_ELEMENTS:
-      case EXTERNAL_DOUBLE_ELEMENTS:
-      case FAST_ELEMENTS:
-      case FAST_SMI_ELEMENTS:
-      case FAST_DOUBLE_ELEMENTS:
-      case FAST_HOLEY_ELEMENTS:
-      case FAST_HOLEY_SMI_ELEMENTS:
-      case FAST_HOLEY_DOUBLE_ELEMENTS:
-      case DICTIONARY_ELEMENTS:
-      case NON_STRICT_ARGUMENTS_ELEMENTS:
-        UNREACHABLE();
-        break;
-    }
-  }
-}


  void LCodeGen::DeoptIfTaggedButNotSmi(LEnvironment* environment,
@@ -3789,16 +3736,16 @@
  }


-void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
-  Register value = ToRegister(instr->value());
-  Register elements = ToRegister(instr->object());
+void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
+  ElementsKind elements_kind = instr->elements_kind();
    LOperand* key = instr->key();
    if (!key->IsConstantOperand()) {
      Register key_reg = ToRegister(key);
-    // Even though the HLoad/StoreKeyedFastElement instructions force the  
input
-    // representation for the key to be an integer, the input gets replaced
-    // during bound check elimination with the index argument to the bounds
-    // check, which can be tagged, so that case must be handled here, too.
+    // Even though the HLoad/StoreKeyedFastElement instructions force
+    // the input representation for the key to be an integer, the input
+    // gets replaced during bound check elimination with the index
+    // argument to the bounds check, which can be tagged, so that case
+    // must be handled here, too.
      if (instr->hydrogen()->key()->representation().IsTagged()) {
        __ SmiToInteger64(key_reg, key_reg);
      } else if (instr->hydrogen()->IsDehoisted()) {
@@ -3807,45 +3754,62 @@
        __ movsxlq(key_reg, key_reg);
      }
    }
+  Operand operand(BuildFastArrayOperand(
+      instr->elements(),
+      key,
+      elements_kind,
+      0,
+      instr->additional_index()));

-  Operand operand =
-      BuildFastArrayOperand(instr->object(),
-                            key,
-                            FAST_ELEMENTS,
-                            FixedArray::kHeaderSize - kHeapObjectTag,
-                            instr->additional_index());
-
-  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.
-    Register key_reg(ToRegister(key));
-    __ lea(key_reg, operand);
-    __ movq(Operand(key_reg, 0), value);
-    __ RecordWrite(elements,
-                   key_reg,
-                   value,
-                   kSaveFPRegs,
-                   EMIT_REMEMBERED_SET,
-                   check_needed);
+  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+    XMMRegister value(ToDoubleRegister(instr->value()));
+    __ cvtsd2ss(value, value);
+    __ movss(operand, value);
+  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+    __ movsd(operand, ToDoubleRegister(instr->value()));
    } else {
-    __ movq(operand, value);
+    Register value(ToRegister(instr->value()));
+    switch (elements_kind) {
+      case EXTERNAL_PIXEL_ELEMENTS:
+      case EXTERNAL_BYTE_ELEMENTS:
+      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+        __ movb(operand, value);
+        break;
+      case EXTERNAL_SHORT_ELEMENTS:
+      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+        __ movw(operand, value);
+        break;
+      case EXTERNAL_INT_ELEMENTS:
+      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+        __ movl(operand, value);
+        break;
+      case EXTERNAL_FLOAT_ELEMENTS:
+      case EXTERNAL_DOUBLE_ELEMENTS:
+      case FAST_ELEMENTS:
+      case FAST_SMI_ELEMENTS:
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_ELEMENTS:
+      case FAST_HOLEY_SMI_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+      case DICTIONARY_ELEMENTS:
+      case NON_STRICT_ARGUMENTS_ELEMENTS:
+        UNREACHABLE();
+        break;
+    }
    }
  }


-void LCodeGen::DoStoreKeyedFastDoubleElement(
-    LStoreKeyedFastDoubleElement* instr) {
+void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
    XMMRegister value = ToDoubleRegister(instr->value());
    LOperand* key = instr->key();
    if (!key->IsConstantOperand()) {
      Register key_reg = ToRegister(key);
-    // Even though the HLoad/StoreKeyedFastElement instructions force the  
input
-    // representation for the key to be an integer, the input gets replaced
-    // during bound check elimination with the index argument to the bounds
-    // check, which can be tagged, so that case must be handled here, too.
+    // Even though the HLoad/StoreKeyedFastElement instructions force
+    // the input representation for the key to be an integer, the
+    // input gets replaced during bound check elimination with the index
+    // argument to the bounds check, which can be tagged, so that case
+    // must be handled here, too.
      if (instr->hydrogen()->key()->representation().IsTagged()) {
        __ SmiToInteger64(key_reg, key_reg);
      } else if (instr->hydrogen()->IsDehoisted()) {
@@ -3877,6 +3841,66 @@

    __ movsd(double_store_operand, value);
  }
+
+
+void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
+  Register value = ToRegister(instr->value());
+  Register elements = ToRegister(instr->elements());
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand()) {
+    Register key_reg = ToRegister(key);
+    // Even though the HLoad/StoreKeyedFastElement instructions force
+    // the input representation for the key to be an integer, the
+    // input gets replaced during bound check elimination with the index
+    // argument to the bounds check, which can be tagged, so that case
+    // must be handled here, too.
+    if (instr->hydrogen()->key()->representation().IsTagged()) {
+      __ SmiToInteger64(key_reg, key_reg);
+    } else if (instr->hydrogen()->IsDehoisted()) {
+      // Sign extend key because it could be a 32 bit negative value
+      // and the dehoisted address computation happens in 64 bits
+      __ movsxlq(key_reg, key_reg);
+    }
+  }
+
+  Operand operand =
+      BuildFastArrayOperand(instr->elements(),
+                            key,
+                            FAST_ELEMENTS,
+                            FixedArray::kHeaderSize - kHeapObjectTag,
+                            instr->additional_index());
+
+  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.
+    Register key_reg(ToRegister(key));
+    __ lea(key_reg, operand);
+    __ movq(Operand(key_reg, 0), value);
+    __ RecordWrite(elements,
+                   key_reg,
+                   value,
+                   kSaveFPRegs,
+                   EMIT_REMEMBERED_SET,
+                   check_needed);
+  } else {
+    __ movq(operand, value);
+  }
+}
+
+
+void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
+  if (instr->is_external()) {
+    DoStoreKeyedExternalArray(instr);
+  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
+    DoStoreKeyedFixedDoubleArray(instr);
+  } else {
+    DoStoreKeyedFixedArray(instr);
+  }
+}
+

  void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
    ASSERT(ToRegister(instr->object()).is(rdx));
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.h	Wed Sep 12  
05:28:42 2012
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.h	Fri Nov  2  
02:18:53 2012
@@ -335,6 +335,12 @@
    };

    void EnsureSpaceForLazyDeopt(int space_needed);
+  void DoLoadKeyedExternalArray(LLoadKeyed* instr);
+  void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
+  void DoLoadKeyedFixedArray(LLoadKeyed* instr);
+  void DoStoreKeyedExternalArray(LStoreKeyed* instr);
+  void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
+  void DoStoreKeyedFixedArray(LStoreKeyed* instr);

    Zone* zone_;
    LPlatformChunk* const chunk_;
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc	Fri Oct 19 06:20:22 2012
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc	Fri Nov  2 02:18:53 2012
@@ -394,16 +394,7 @@
  }


-void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
-  object()->PrintTo(stream);
-  stream->Add("[");
-  key()->PrintTo(stream);
-  stream->Add("] <- ");
-  value()->PrintTo(stream);
-}
-
-
-void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+void LStoreKeyed::PrintDataTo(StringStream* stream) {
    elements()->PrintTo(stream);
    stream->Add("[");
    key()->PrintTo(stream);
@@ -1843,63 +1834,37 @@
  }


-LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
-    HLoadKeyedFastElement* instr) {
-  ASSERT(instr->representation().IsTagged());
+LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
    ASSERT(instr->key()->representation().IsInteger32() ||
           instr->key()->representation().IsTagged());
-  LOperand* obj = UseRegisterAtStart(instr->object());
+  ElementsKind elements_kind = instr->elements_kind();
    bool clobbers_key = instr->key()->representation().IsTagged();
    LOperand* key = clobbers_key
        ? UseTempRegister(instr->key())
        : UseRegisterOrConstantAtStart(instr->key());
-  LLoadKeyedFastElement* result =
-      new(zone()) LLoadKeyedFastElement(obj, key);
-  if (instr->RequiresHoleCheck()) AssignEnvironment(result);
-  return DefineAsRegister(result);
-}
+  LLoadKeyed* result = NULL;

-
-LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
-    HLoadKeyedFastDoubleElement* instr) {
-  ASSERT(instr->representation().IsDouble());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-  LOperand* elements = UseRegisterAtStart(instr->elements());
-  bool clobbers_key = instr->key()->representation().IsTagged();
-  LOperand* key = clobbers_key
-      ? UseTempRegister(instr->key())
-      : UseRegisterOrConstantAtStart(instr->key());
-  LLoadKeyedFastDoubleElement* result =
-      new(zone()) LLoadKeyedFastDoubleElement(elements, key);
-  return AssignEnvironment(DefineAsRegister(result));
-}
-
+  if (!instr->is_external()) {
+    LOperand* obj = UseRegisterAtStart(instr->elements());
+    result = new(zone()) LLoadKeyed(obj, key);
+  } else {
+    ASSERT(
+        (instr->representation().IsInteger32() &&
+         (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
+         (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+        (instr->representation().IsDouble() &&
+         ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
+          (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+    LOperand* external_pointer = UseRegister(instr->elements());
+    result = new(zone()) LLoadKeyed(external_pointer, key);
+  }

-LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
-    HLoadKeyedSpecializedArrayElement* instr) {
-  ElementsKind elements_kind = instr->elements_kind();
-  ASSERT(
-      (instr->representation().IsInteger32() &&
-       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
-       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
-      (instr->representation().IsDouble() &&
-       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
-       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-  LOperand* external_pointer = UseRegister(instr->external_pointer());
-  bool clobbers_key = instr->key()->representation().IsTagged();
-  LOperand* key = clobbers_key
-      ? UseTempRegister(instr->key())
-      : UseRegisterOrConstantAtStart(instr->key());
-  LLoadKeyedSpecializedArrayElement* result =
-      new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
-  LInstruction* load_instr = DefineAsRegister(result);
+  DefineAsRegister(result);
+  bool can_deoptimize = instr->RequiresHoleCheck() ||
+      (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
    // An unsigned int array load might overflow and cause a deopt, make  
sure it
    // has an environment.
-  return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
-      AssignEnvironment(load_instr) : load_instr;
+  return can_deoptimize ? AssignEnvironment(result) : result;
  }


@@ -1912,71 +1877,49 @@
  }


-LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
-    HStoreKeyedFastElement* instr) {
+LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
+  ElementsKind elements_kind = instr->elements_kind();
    bool needs_write_barrier = instr->NeedsWriteBarrier();
-  ASSERT(instr->value()->representation().IsTagged());
-  ASSERT(instr->object()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-
-  LOperand* obj = UseTempRegister(instr->object());
-  LOperand* val = needs_write_barrier
+  bool clobbers_key = instr->key()->representation().IsTagged();
+  LOperand* key = (clobbers_key || needs_write_barrier)
+      ? UseTempRegister(instr->key())
+      : UseRegisterOrConstantAtStart(instr->key());
+  bool val_is_temp_register =
+      elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT_ELEMENTS;
+  LOperand* val = (needs_write_barrier || val_is_temp_register)
        ? UseTempRegister(instr->value())
        : UseRegisterAtStart(instr->value());
-  bool clobbers_key = needs_write_barrier ||
-      instr->key()->representation().IsTagged();
-  LOperand* key = clobbers_key
-      ? UseTempRegister(instr->key())
-      : UseRegisterOrConstantAtStart(instr->key());
-  return new(zone()) LStoreKeyedFastElement(obj, key, val);
-}
+  LStoreKeyed* result = NULL;

+  if (!instr->is_external()) {
+    ASSERT(instr->elements()->representation().IsTagged());

-LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
-    HStoreKeyedFastDoubleElement* instr) {
-  ASSERT(instr->value()->representation().IsDouble());
-  ASSERT(instr->elements()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
+    LOperand* object = NULL;
+    if (instr->value()->representation().IsDouble()) {
+      object = UseRegisterAtStart(instr->elements());
+    } else {
+      ASSERT(instr->value()->representation().IsTagged());
+      object = UseTempRegister(instr->elements());
+    }

-  LOperand* elements = UseRegisterAtStart(instr->elements());
-  LOperand* val = UseTempRegister(instr->value());
-  bool clobbers_key = instr->key()->representation().IsTagged();
-  LOperand* key = clobbers_key
-      ? UseTempRegister(instr->key())
-      : UseRegisterOrConstantAtStart(instr->key());
-  return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
-}
+    result = new(zone()) LStoreKeyed(object, key, val);
+  } else {
+    ASSERT(
+        (instr->value()->representation().IsInteger32() &&
+         (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
+         (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+        (instr->value()->representation().IsDouble() &&
+         ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
+          (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+    ASSERT(instr->elements()->representation().IsExternal());

+    LOperand* external_pointer = UseRegister(instr->elements());
+    result = new(zone()) LStoreKeyed(external_pointer, key, val);
+  }

-LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
-    HStoreKeyedSpecializedArrayElement* instr) {
-  ElementsKind elements_kind = instr->elements_kind();
-  ASSERT(
-      (instr->value()->representation().IsInteger32() &&
-       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
-       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
-      (instr->value()->representation().IsDouble() &&
-       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
-       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->external_pointer()->representation().IsExternal());
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
-
-  LOperand* external_pointer = UseRegister(instr->external_pointer());
-  bool val_is_temp_register =
-      elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
-      elements_kind == EXTERNAL_FLOAT_ELEMENTS;
-  LOperand* val = val_is_temp_register
-      ? UseTempRegister(instr->value())
-      : UseRegister(instr->value());
-  bool clobbers_key = instr->key()->representation().IsTagged();
-  LOperand* key = clobbers_key
-      ? UseTempRegister(instr->key())
-      : UseRegisterOrConstantAtStart(instr->key());
-  return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
-                                                        key, val);
+  ASSERT(result != NULL);
+  return result;
  }


=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h	Fri Oct 19 06:20:22 2012
+++ /branches/bleeding_edge/src/x64/lithium-x64.h	Fri Nov  2 02:18:53 2012
@@ -126,10 +126,8 @@
    V(LoadFunctionPrototype)                      \
    V(LoadGlobalCell)                             \
    V(LoadGlobalGeneric)                          \
-  V(LoadKeyedFastDoubleElement)                 \
-  V(LoadKeyedFastElement)                       \
+  V(LoadKeyed)                                  \
    V(LoadKeyedGeneric)                           \
-  V(LoadKeyedSpecializedArrayElement)           \
    V(LoadNamedField)                             \
    V(LoadNamedFieldPolymorphic)                  \
    V(LoadNamedGeneric)                           \
@@ -157,10 +155,8 @@
    V(StoreContextSlot)                           \
    V(StoreGlobalCell)                            \
    V(StoreGlobalGeneric)                         \
-  V(StoreKeyedFastDoubleElement)                \
-  V(StoreKeyedFastElement)                      \
+  V(StoreKeyed)                                 \
    V(StoreKeyedGeneric)                          \
-  V(StoreKeyedSpecializedArrayElement)          \
    V(StoreNamedField)                            \
    V(StoreNamedGeneric)                          \
    V(StringAdd)                                  \
@@ -1353,56 +1349,25 @@
  };


-class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
+class LLoadKeyed: public LTemplateInstruction<1, 2, 0> {
   public:
-  LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
+  LLoadKeyed(LOperand* elements, LOperand* key) {
      inputs_[0] = elements;
      inputs_[1] = key;
    }

-   
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
-
-  LOperand* elements() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)

-class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
- public:
-  LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
-    inputs_[0] = elements;
-    inputs_[1] = key;
+  bool is_external() const {
+    return hydrogen()->is_external();
    }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
-                               "load-keyed-fast-double-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
-
    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) {
-    inputs_[0] = external_pointer;
-    inputs_[1] = key;
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
-                               "load-keyed-specialized-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
-
-  LOperand* external_pointer() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
    ElementsKind elements_kind() const {
      return hydrogen()->elements_kind();
    }
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
  };


@@ -1899,76 +1864,29 @@
  };


-class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
+class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
   public:
-  LStoreKeyedFastElement(LOperand* object, LOperand* key, LOperand* value)  
{
+  LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
      inputs_[0] = object;
      inputs_[1] = key;
      inputs_[2] = value;
    }

-  LOperand* object() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
-                               "store-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
-
-  virtual void PrintDataTo(StringStream* stream);
-
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
-class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
- public:
-  LStoreKeyedFastDoubleElement(LOperand* elements,
-                               LOperand* key,
-                               LOperand* value) {
-    inputs_[0] = elements;
-    inputs_[1] = key;
-    inputs_[2] = value;
-  }
-
+  bool is_external() const { return hydrogen()->is_external(); }
    LOperand* elements() { return inputs_[0]; }
    LOperand* key() { return inputs_[1]; }
    LOperand* value() { return inputs_[2]; }
+  ElementsKind elements_kind() const { return hydrogen()->elements_kind();  
}

-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
-                               "store-keyed-fast-double-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)

    virtual void PrintDataTo(StringStream* stream);
-
    bool NeedsCanonicalization() { return  
hydrogen()->NeedsCanonicalization(); }
    uint32_t additional_index() const { return hydrogen()->index_offset(); }
  };


-class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0,  
3, 0> {
- public:
-  LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
-                                     LOperand* key,
-                                     LOperand* value) {
-    inputs_[0] = external_pointer;
-    inputs_[1] = key;
-    inputs_[2] = value;
-  }
-
-  LOperand* external_pointer() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
-                               "store-keyed-specialized-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
-
-  ElementsKind elements_kind() const { return hydrogen()->elements_kind();  
}
-  uint32_t additional_index() const { return hydrogen()->index_offset(); }
-};
-
-
  class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
   public:
    LStoreKeyedGeneric(LOperand* object, LOperand* key, LOperand* value) {