Revision: 12156
Author:   [email protected]
Date:     Fri Jul 20 04:00:33 2012
Log:      Optimize Smi keys for KeyedLoads

Allows KeyeLoad/KeyedStore operations where the key is a Smi to fold the untagging of the key into the element offset calculation.

Review URL: https://chromiumcodereview.appspot.com/10735020
http://code.google.com/p/v8/source/detail?r=12156

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/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-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.h
 /branches/bleeding_edge/test/mjsunit/external-array.js

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Thu Jul 12 08:29:14 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Fri Jul 20 04:00:33 2012
@@ -1835,7 +1835,8 @@
 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
     HLoadKeyedFastElement* instr) {
   ASSERT(instr->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
   LOperand* obj = UseRegisterAtStart(instr->object());
   LOperand* key = UseRegisterAtStart(instr->key());
LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
@@ -1847,7 +1848,8 @@
 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
     HLoadKeyedFastDoubleElement* instr) {
   ASSERT(instr->representation().IsDouble());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
   LOperand* elements = UseTempRegister(instr->elements());
   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   LLoadKeyedFastDoubleElement* result =
@@ -1866,7 +1868,8 @@
       (instr->representation().IsDouble() &&
        ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
   LOperand* external_pointer = UseRegister(instr->external_pointer());
   LOperand* key = UseRegisterOrConstant(instr->key());
   LLoadKeyedSpecializedArrayElement* result =
@@ -1894,7 +1897,8 @@
   bool needs_write_barrier = instr->NeedsWriteBarrier();
   ASSERT(instr->value()->representation().IsTagged());
   ASSERT(instr->object()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());

   LOperand* obj = UseTempRegister(instr->object());
   LOperand* val = needs_write_barrier
@@ -1911,7 +1915,8 @@
     HStoreKeyedFastDoubleElement* instr) {
   ASSERT(instr->value()->representation().IsDouble());
   ASSERT(instr->elements()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());

   LOperand* elements = UseRegisterAtStart(instr->elements());
   LOperand* val = UseTempRegister(instr->value());
@@ -1932,7 +1937,8 @@
        ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
   ASSERT(instr->external_pointer()->representation().IsExternal());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());

   LOperand* external_pointer = UseRegister(instr->external_pointer());
   bool val_is_temp_register =
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h       Thu Jul 12 08:29:14 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.h       Fri Jul 20 04:00:33 2012
@@ -859,6 +859,7 @@
   LOperand* length() { return inputs_[1]; }

   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
+  DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
 };


=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Jul 19 07:45:19 2012 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Jul 20 04:00:33 2012
@@ -2784,7 +2784,12 @@
   Register scratch = scratch0();

   // Load the result.
-  __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
+  if (instr->hydrogen()->key()->representation().IsTagged()) {
+    __ add(scratch, elements,
+           Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize));
+  } else {
+    __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
+  }
   uint32_t offset = FixedArray::kHeaderSize +
                     (instr->additional_index() << kPointerSizeLog2);
   __ ldr(result, FieldMemOperand(scratch, offset));
@@ -2811,8 +2816,9 @@
   DwVfpRegister result = ToDoubleRegister(instr->result());
   Register scratch = scratch0();

-  int shift_size =
-      ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
+  int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
+  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+      ? (element_size_shift - kSmiTagSize) : element_size_shift;
   int constant_key = 0;
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
@@ -2824,14 +2830,15 @@
   }

   Operand operand = key_is_constant
- ? Operand(((constant_key + instr->additional_index()) << shift_size) +
+      ? Operand(((constant_key + instr->additional_index()) <<
+                 element_size_shift) +
                 FixedDoubleArray::kHeaderSize - kHeapObjectTag)
       : Operand(key, LSL, shift_size);
   __ add(elements, elements, operand);
   if (!key_is_constant) {
     __ add(elements, elements,
            Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
-                   (instr->additional_index() << shift_size)));
+                   (instr->additional_index() << element_size_shift)));
   }

   if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -2842,6 +2849,42 @@

   __ vldr(result, elements, 0);
 }
+
+
+MemOperand LCodeGen::PrepareKeyedOperand(Register key,
+                                         Register base,
+                                         bool key_is_constant,
+                                         int constant_key,
+                                         int element_size,
+                                         int shift_size,
+                                         int additional_index,
+                                         int additional_offset) {
+  if (additional_index != 0 && !key_is_constant) {
+    additional_index *= 1 << (element_size - shift_size);
+    __ add(scratch0(), key, Operand(additional_index));
+  }
+
+  if (key_is_constant) {
+    return MemOperand(base,
+                      (constant_key << element_size) + additional_offset);
+  }
+
+  if (additional_index == 0) {
+    if (shift_size >= 0) {
+      return MemOperand(base, key, LSL, shift_size);
+    } else {
+      ASSERT_EQ(-1, shift_size);
+      return MemOperand(base, key, LSR, 1);
+    }
+  }
+
+  if (shift_size >= 0) {
+    return MemOperand(base, scratch0(), LSL, shift_size);
+  } else {
+    ASSERT_EQ(-1, shift_size);
+    return MemOperand(base, scratch0(), LSR, 1);
+  }
+}


 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
@@ -2859,15 +2902,17 @@
   } else {
     key = ToRegister(instr->key());
   }
-  int shift_size = ElementsKindToShiftSize(elements_kind);
-  int additional_offset = instr->additional_index() << shift_size;
+  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 << shift_size)
+        ? Operand(constant_key << element_size_shift)
         : Operand(key, LSL, shift_size);
     __ add(scratch0(), external_pointer, operand);
     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
@@ -2878,15 +2923,10 @@
     }
   } else {
     Register result = ToRegister(instr->result());
-    if (instr->additional_index() != 0 && !key_is_constant) {
-      __ add(scratch0(), key, Operand(instr->additional_index()));
-    }
-    MemOperand mem_operand(key_is_constant
-        ? MemOperand(external_pointer,
-                     (constant_key << shift_size) + additional_offset)
-        : (instr->additional_index() == 0
-           ? MemOperand(external_pointer, key, LSL, shift_size)
-           : MemOperand(external_pointer, scratch0(), LSL, shift_size)));
+    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);
@@ -3803,7 +3843,12 @@
         + FixedArray::kHeaderSize;
     __ str(value, FieldMemOperand(elements, offset));
   } else {
-    __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
+    if (instr->hydrogen()->key()->representation().IsTagged()) {
+      __ add(scratch, elements,
+             Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize));
+    } else {
+      __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
+    }
     if (instr->additional_index() != 0) {
       __ add(scratch,
              scratch,
@@ -3848,9 +3893,11 @@
   } else {
     key = ToRegister(instr->key());
   }
-  int shift_size = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
+  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 << shift_size) +
+      ? Operand((constant_key << element_size_shift) +
                 FixedDoubleArray::kHeaderSize - kHeapObjectTag)
       : Operand(key, LSL, shift_size);
   __ add(scratch, elements, operand);
@@ -3868,7 +3915,7 @@
             vs);
   }

-  __ vstr(value, scratch, instr->additional_index() << shift_size);
+  __ vstr(value, scratch, instr->additional_index() << element_size_shift);
 }


@@ -3888,15 +3935,18 @@
   } else {
     key = ToRegister(instr->key());
   }
-  int shift_size = ElementsKindToShiftSize(elements_kind);
-  int additional_offset = instr->additional_index() << shift_size;
+  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 value(ToDoubleRegister(instr->value()));
-    Operand operand(key_is_constant ? Operand(constant_key << shift_size)
-                                    : Operand(key, LSL, shift_size));
+    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) {
       __ vcvt_f32_f64(double_scratch0().low(), value);
@@ -3906,16 +3956,10 @@
     }
   } else {
     Register value(ToRegister(instr->value()));
-    if (instr->additional_index() != 0 && !key_is_constant) {
-      __ add(scratch0(), key, Operand(instr->additional_index()));
-    }
-    MemOperand mem_operand(key_is_constant
-        ? MemOperand(external_pointer,
-                     ((constant_key + instr->additional_index())
-                         << shift_size))
-        : (instr->additional_index() == 0
-            ? MemOperand(external_pointer, key, LSL, shift_size)
-            : MemOperand(external_pointer, scratch0(), LSL, shift_size)));
+    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_PIXEL_ELEMENTS:
       case EXTERNAL_BYTE_ELEMENTS:
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Thu Jul 12 08:29:14 2012 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Fri Jul 20 04:00:33 2012
@@ -132,6 +132,15 @@
   void DoParallelMove(LParallelMove* move);
   void DoGap(LGap* instr);

+  MemOperand PrepareKeyedOperand(Register key,
+                                 Register base,
+                                 bool key_is_constant,
+                                 int constant_key,
+                                 int element_size,
+                                 int shift_size,
+                                 int additional_index,
+                                 int additional_offset);
+
   // Emit frame translation commands for an environment.
void WriteTranslation(LEnvironment* environment, Translation* translation);

=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Thu Jul 19 11:58:23 2012 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Fri Jul 20 04:00:33 2012
@@ -1888,6 +1888,7 @@
 class HFixedArrayBaseLength: public HUnaryOperation {
  public:
   explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
+    set_type(HType::Smi());
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
     SetGVNFlag(kDependsOnArrayLengths);
@@ -2757,17 +2758,31 @@
 };


+enum BoundsCheckKeyMode {
+  DONT_ALLOW_SMI_KEY,
+  ALLOW_SMI_KEY
+};
+
+
 class HBoundsCheck: public HTemplateInstruction<2> {
  public:
-  HBoundsCheck(HValue* index, HValue* length) {
+  HBoundsCheck(HValue* index, HValue* length,
+               BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY)
+      : key_mode_(key_mode) {
     SetOperandAt(0, index);
     SetOperandAt(1, length);
     set_representation(Representation::Integer32());
     SetFlag(kUseGVN);
   }

-  virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::Integer32();
+  virtual Representation RequiredInputRepresentation(int arg_index) {
+    if (index()->representation().IsTagged() &&
+        !index()->IsConstant() &&
+        key_mode_ == ALLOW_SMI_KEY) {
+      return Representation::Tagged();
+    } else {
+      return Representation::Integer32();
+    }
   }

   virtual void PrintDataTo(StringStream* stream);
@@ -2779,6 +2794,7 @@

  protected:
   virtual bool DataEquals(HValue* other) { return true; }
+  BoundsCheckKeyMode key_mode_;
 };


=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Thu Jul 19 11:58:23 2012
+++ /branches/bleeding_edge/src/hydrogen.cc     Fri Jul 20 04:00:33 2012
@@ -5842,7 +5842,8 @@
   HInstruction* checked_key = NULL;
   if (map->has_external_array_elements()) {
     length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
-    checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
+    checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
+                                                          ALLOW_SMI_KEY));
     HLoadExternalArrayPointer* external_elements =
         new(zone()) HLoadExternalArrayPointer(elements);
     AddInstruction(external_elements);
@@ -6077,7 +6078,8 @@
         HInstruction* length;
length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
                                                            HType::Smi()));
- checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
+        checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
+ ALLOW_SMI_KEY));
         access = AddInstruction(BuildFastElementAccess(
             elements, checked_key, val, elements_kind, is_store));
         if (!is_store) {
@@ -6092,7 +6094,8 @@

         set_current_block(if_fastobject);
length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); - checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
+        checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
+ ALLOW_SMI_KEY));
         access = AddInstruction(BuildFastElementAccess(
             elements, checked_key, val, elements_kind, is_store));
       } else if (elements_kind == DICTIONARY_ELEMENTS) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Jul 19 07:45:19 2012 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Jul 20 04:00:33 2012
@@ -2650,6 +2650,7 @@
   __ mov(result,
          BuildFastArrayOperand(instr->elements(),
                                instr->key(),
+                               instr->hydrogen()->key()->representation(),
                                FAST_ELEMENTS,
                                FixedArray::kHeaderSize - kHeapObjectTag,
                                instr->additional_index()));
@@ -2676,6 +2677,7 @@
         sizeof(kHoleNanLower32);
     Operand hole_check_operand = BuildFastArrayOperand(
         instr->elements(), instr->key(),
+        instr->hydrogen()->key()->representation(),
         FAST_DOUBLE_ELEMENTS,
         offset,
         instr->additional_index());
@@ -2686,6 +2688,7 @@
   Operand double_load_operand = BuildFastArrayOperand(
       instr->elements(),
       instr->key(),
+      instr->hydrogen()->key()->representation(),
       FAST_DOUBLE_ELEMENTS,
       FixedDoubleArray::kHeaderSize - kHeapObjectTag,
       instr->additional_index());
@@ -2696,11 +2699,15 @@
 Operand LCodeGen::BuildFastArrayOperand(
     LOperand* elements_pointer,
     LOperand* key,
+    Representation key_representation,
     ElementsKind elements_kind,
     uint32_t offset,
     uint32_t additional_index) {
   Register elements_pointer_reg = ToRegister(elements_pointer);
   int shift_size = ElementsKindToShiftSize(elements_kind);
+  if (key_representation.IsTagged() && (shift_size >= 1)) {
+    shift_size -= kSmiTagSize;
+  }
   if (key->IsConstantOperand()) {
     int constant_value = ToInteger32(LConstantOperand::cast(key));
     if (constant_value & 0xF0000000) {
@@ -2722,11 +2729,19 @@
 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
     LLoadKeyedSpecializedArrayElement* instr) {
   ElementsKind elements_kind = instr->elements_kind();
-  Operand operand(BuildFastArrayOperand(instr->external_pointer(),
-                                        instr->key(),
-                                        elements_kind,
-                                        0,
-                                        instr->additional_index()));
+  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);
@@ -3679,11 +3694,19 @@
 void LCodeGen::DoStoreKeyedSpecializedArrayElement(
     LStoreKeyedSpecializedArrayElement* instr) {
   ElementsKind elements_kind = instr->elements_kind();
-  Operand operand(BuildFastArrayOperand(instr->external_pointer(),
-                                        instr->key(),
-                                        elements_kind,
-                                        0,
-                                        instr->additional_index()));
+  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) {
     __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
     __ movss(operand, xmm0);
@@ -3730,6 +3753,7 @@
   Operand operand = BuildFastArrayOperand(
       instr->object(),
       instr->key(),
+      instr->hydrogen()->key()->representation(),
       FAST_ELEMENTS,
       FixedArray::kHeaderSize - kHeapObjectTag,
       instr->additional_index());
@@ -3771,6 +3795,7 @@
   Operand double_store_operand = BuildFastArrayOperand(
       instr->elements(),
       instr->key(),
+      instr->hydrogen()->key()->representation(),
       FAST_DOUBLE_ELEMENTS,
       FixedDoubleArray::kHeaderSize - kHeapObjectTag,
       instr->additional_index());
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Thu Jul 12 08:29:14 2012 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Fri Jul 20 04:00:33 2012
@@ -246,6 +246,7 @@
   double ToDouble(LConstantOperand* op) const;
   Operand BuildFastArrayOperand(LOperand* elements_pointer,
                                 LOperand* key,
+                                Representation key_representation,
                                 ElementsKind elements_kind,
                                 uint32_t offset,
                                 uint32_t additional_index = 0);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Thu Jul 12 08:29:14 2012 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Fri Jul 20 04:00:33 2012
@@ -1900,7 +1900,8 @@
 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
     HLoadKeyedFastElement* instr) {
   ASSERT(instr->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  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);
@@ -1912,7 +1913,8 @@
 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
     HLoadKeyedFastDoubleElement* instr) {
   ASSERT(instr->representation().IsDouble());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
   LOperand* elements = UseRegisterAtStart(instr->elements());
   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   LLoadKeyedFastDoubleElement* result =
@@ -1931,11 +1933,17 @@
       (instr->representation().IsDouble() &&
        ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
   LOperand* external_pointer = UseRegister(instr->external_pointer());
-  LOperand* key = UseRegisterOrConstant(instr->key());
+  bool clobbers_key = ExternalArrayOpRequiresTemp(
+      instr->key()->representation(), elements_kind);
+  LOperand* key = clobbers_key
+      ? UseTempRegister(instr->key())
+      : UseRegisterOrConstant(instr->key());
+
   LLoadKeyedSpecializedArrayElement* result =
-      new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
+    new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
   LInstruction* load_instr = DefineAsRegister(result);
// An unsigned int array load might overflow and cause a deopt, make sure it
   // has an environment.
@@ -1961,7 +1969,8 @@
   bool needs_write_barrier = instr->NeedsWriteBarrier();
   ASSERT(instr->value()->representation().IsTagged());
   ASSERT(instr->object()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());

   LOperand* obj = UseRegister(instr->object());
   LOperand* val = needs_write_barrier
@@ -1978,7 +1987,8 @@
     HStoreKeyedFastDoubleElement* instr) {
   ASSERT(instr->value()->representation().IsDouble());
   ASSERT(instr->elements()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());

   LOperand* elements = UseRegisterAtStart(instr->elements());
   LOperand* val = UseTempRegister(instr->value());
@@ -1999,10 +2009,10 @@
        ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
   ASSERT(instr->external_pointer()->representation().IsExternal());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());

   LOperand* external_pointer = UseRegister(instr->external_pointer());
-  LOperand* key = UseRegisterOrConstant(instr->key());
   LOperand* val = NULL;
   if (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
       elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
@@ -2012,7 +2022,11 @@
   } else {
     val = UseRegister(instr->value());
   }
-
+  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);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Thu Jul 12 08:29:14 2012
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Fri Jul 20 04:00:33 2012
@@ -872,6 +872,7 @@
   LOperand* length() { return inputs_[1]; }

   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
+  DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
 };


@@ -1275,6 +1276,19 @@
   LOperand* key() { return inputs_[1]; }
   uint32_t additional_index() const { return hydrogen()->index_offset(); }
 };
+
+
+inline static bool ExternalArrayOpRequiresTemp(
+    Representation key_representation,
+    ElementsKind elements_kind) {
+ // Operations that require the key to be divided by two to be converted into
+  // an index cannot fold the scale operation into a load and need an extra
+  // temp register to do the work.
+  return key_representation.IsTagged() &&
+      (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
+       elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
+       elements_kind == EXTERNAL_PIXEL_ELEMENTS);
+}


class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Thu Jul 19 07:45:19 2012 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Jul 20 04:00:33 2012
@@ -2503,18 +2503,22 @@

 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
   Register result = ToRegister(instr->result());
-
- if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
-    // Sign extend key because it could be a 32 bit negative value
-    // and the dehoisted address computation happens in 64 bits.
-    Register key_reg = ToRegister(instr->key());
-    __ movsxlq(key_reg, key_reg);
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand()) {
+    Register key_reg = ToRegister(key);
+    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(),
-                                instr->key(),
+                                key,
                                 FAST_ELEMENTS,
                                 FixedArray::kHeaderSize - kHeapObjectTag,
                                 instr->additional_index()));
@@ -2535,12 +2539,16 @@
 void LCodeGen::DoLoadKeyedFastDoubleElement(
     LLoadKeyedFastDoubleElement* instr) {
   XMMRegister result(ToDoubleRegister(instr->result()));
-
- if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
-    // Sign extend key because it could be a 32 bit negative value
-    // and the dehoisted address computation happens in 64 bits
-    Register key_reg = ToRegister(instr->key());
-    __ movsxlq(key_reg, key_reg);
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand()) {
+    Register key_reg = ToRegister(key);
+    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);
+    }
   }

   if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -2548,7 +2556,7 @@
         sizeof(kHoleNanLower32);
     Operand hole_check_operand = BuildFastArrayOperand(
         instr->elements(),
-        instr->key(),
+        key,
         FAST_DOUBLE_ELEMENTS,
         offset,
         instr->additional_index());
@@ -2558,7 +2566,7 @@

   Operand double_load_operand = BuildFastArrayOperand(
       instr->elements(),
-      instr->key(),
+      key,
       FAST_DOUBLE_ELEMENTS,
       FixedDoubleArray::kHeaderSize - kHeapObjectTag,
       instr->additional_index());
@@ -2595,17 +2603,23 @@
 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
     LLoadKeyedSpecializedArrayElement* instr) {
   ElementsKind elements_kind = instr->elements_kind();
-  Operand operand(BuildFastArrayOperand(instr->external_pointer(),
-                                        instr->key(),
-                                        elements_kind,
-                                        0,
-                                        instr->additional_index()));
- if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
-    // Sign extend key because it could be a 32 bit negative value
-    // and the dehoisted address computation happens in 64 bits
-    Register key_reg = ToRegister(instr->key());
-    __ movsxlq(key_reg, key_reg);
-  }
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand()) {
+    Register key_reg = ToRegister(key);
+    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()));
@@ -3538,18 +3552,23 @@
 void LCodeGen::DoStoreKeyedSpecializedArrayElement(
     LStoreKeyedSpecializedArrayElement* instr) {
   ElementsKind elements_kind = instr->elements_kind();
-  Operand operand(BuildFastArrayOperand(instr->external_pointer(),
-                                        instr->key(),
-                                        elements_kind,
-                                        0,
-                                        instr->additional_index()));
-
- if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
-    // Sign extend key because it could be a 32 bit negative value
-    // and the dehoisted address computation happens in 64 bits
-    Register key_reg = ToRegister(instr->key());
-    __ movsxlq(key_reg, key_reg);
-  }
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand()) {
+    Register key_reg = ToRegister(key);
+    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()));
@@ -3593,7 +3612,8 @@
 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
   if (instr->length()->IsRegister()) {
     Register reg = ToRegister(instr->length());
-    if (FLAG_debug_code) {
+    if (FLAG_debug_code &&
+        !instr->hydrogen()->index()->representation().IsTagged()) {
       __ AbortIfNotZeroExtended(reg);
     }
     if (instr->index()->IsConstantOperand()) {
@@ -3601,7 +3621,8 @@
Immediate(ToInteger32(LConstantOperand::cast(instr->index()))));
     } else {
       Register reg2 = ToRegister(instr->index());
-      if (FLAG_debug_code) {
+      if (FLAG_debug_code &&
+          !instr->hydrogen()->index()->representation().IsTagged()) {
         __ AbortIfNotZeroExtended(reg2);
       }
       __ cmpq(reg, reg2);
@@ -3621,37 +3642,42 @@
 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;
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand()) {
+    Register key_reg = ToRegister(key);
+    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->object(),
-                            instr->key(),
+                            key,
                             FAST_ELEMENTS,
                             FixedArray::kHeaderSize - kHeapObjectTag,
                             instr->additional_index());

- if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
-    // Sign extend key because it could be a 32 bit negative value
-    // and the dehoisted address computation happens in 64 bits
-    Register key_reg = ToRegister(instr->key());
-    __ movsxlq(key_reg, key_reg);
-  }
-
-  __ movq(operand, value);
-
   if (instr->hydrogen()->NeedsWriteBarrier()) {
     ASSERT(!instr->key()->IsConstantOperand());
     HType type = instr->hydrogen()->value()->type();
     SmiCheck check_needed =
         type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
     // Compute address of modified element and store it into key register.
-    __ lea(key, operand);
+    Register key_reg(ToRegister(key));
+    __ lea(key_reg, operand);
+    __ movq(Operand(key_reg, 0), value);
     __ RecordWrite(elements,
-                   key,
+                   key_reg,
                    value,
                    kSaveFPRegs,
                    EMIT_REMEMBERED_SET,
                    check_needed);
+  } else {
+    __ movq(operand, value);
   }
 }

@@ -3659,6 +3685,17 @@
 void LCodeGen::DoStoreKeyedFastDoubleElement(
     LStoreKeyedFastDoubleElement* instr) {
   XMMRegister value = ToDoubleRegister(instr->value());
+  LOperand* key = instr->key();
+  if (!key->IsConstantOperand()) {
+    Register key_reg = ToRegister(key);
+    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);
+    }
+  }

   if (instr->NeedsCanonicalization()) {
     Label have_value;
@@ -3675,18 +3712,11 @@

   Operand double_store_operand = BuildFastArrayOperand(
       instr->elements(),
-      instr->key(),
+      key,
       FAST_DOUBLE_ELEMENTS,
       FixedDoubleArray::kHeaderSize - kHeapObjectTag,
       instr->additional_index());

- if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
-    // Sign extend key because it could be a 32 bit negative value
-    // and the dehoisted address computation happens in 64 bits
-    Register key_reg = ToRegister(instr->key());
-    __ movsxlq(key_reg, key_reg);
-  }
-
   __ movsd(double_store_operand, value);
 }

=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc      Thu Jul 12 08:29:14 2012
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc      Fri Jul 20 04:00:33 2012
@@ -1815,10 +1815,15 @@
 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
     HLoadKeyedFastElement* instr) {
   ASSERT(instr->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  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);
+  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);
 }
@@ -1827,9 +1832,13 @@
 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
     HLoadKeyedFastDoubleElement* instr) {
   ASSERT(instr->representation().IsDouble());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
   LOperand* elements = UseRegisterAtStart(instr->elements());
-  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+  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));
@@ -1846,9 +1855,13 @@
       (instr->representation().IsDouble() &&
        ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
   LOperand* external_pointer = UseRegister(instr->external_pointer());
-  LOperand* key = UseRegisterOrConstant(instr->key());
+  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);
@@ -1873,13 +1886,16 @@
   bool needs_write_barrier = instr->NeedsWriteBarrier();
   ASSERT(instr->value()->representation().IsTagged());
   ASSERT(instr->object()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  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
+  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);
@@ -1890,12 +1906,15 @@
     HStoreKeyedFastDoubleElement* instr) {
   ASSERT(instr->value()->representation().IsDouble());
   ASSERT(instr->elements()->representation().IsTagged());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());

   LOperand* elements = UseRegisterAtStart(instr->elements());
   LOperand* val = UseTempRegister(instr->value());
-  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
-
+  bool clobbers_key = instr->key()->representation().IsTagged();
+  LOperand* key = clobbers_key
+      ? UseTempRegister(instr->key())
+      : UseRegisterOrConstantAtStart(instr->key());
   return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
 }

@@ -1911,7 +1930,8 @@
        ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
   ASSERT(instr->external_pointer()->representation().IsExternal());
-  ASSERT(instr->key()->representation().IsInteger32());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());

   LOperand* external_pointer = UseRegister(instr->external_pointer());
   bool val_is_temp_register =
@@ -1920,11 +1940,12 @@
   LOperand* val = val_is_temp_register
       ? UseTempRegister(instr->value())
       : UseRegister(instr->value());
-  LOperand* key = UseRegisterOrConstant(instr->key());
-
+  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);
+                                                        key, val);
 }


=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h       Thu Jul 12 08:29:14 2012
+++ /branches/bleeding_edge/src/x64/lithium-x64.h       Fri Jul 20 04:00:33 2012
@@ -857,6 +857,7 @@
   LOperand* length() { return inputs_[1]; }

   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
+  DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
 };


=======================================
--- /branches/bleeding_edge/test/mjsunit/external-array.js Tue Jul 3 06:44:36 2012 +++ /branches/bleeding_edge/test/mjsunit/external-array.js Fri Jul 20 04:00:33 2012
@@ -663,3 +663,54 @@
 var b3 = b0.slice(2, 4)
 assertEquals(2, b3.byteLength)
 assertArrayPrefix([3, 4], Int8Array(b3))
+
+function goo(a, i) {
+  return a[i];
+}
+
+function boo(a, i, v) {
+  return a[i] = v;
+}
+
+function do_tagged_index_external_array_test(constructor) {
+  var t_array = new constructor([1, 2, 3, 4, 5, 6]);
+  assertEquals(1, goo(t_array, 0));
+  assertEquals(1, goo(t_array, 0));
+  boo(t_array, 0, 13);
+  assertEquals(13, goo(t_array, 0));
+  %OptimizeFunctionOnNextCall(goo);
+  %OptimizeFunctionOnNextCall(boo);
+  boo(t_array, 0, 15);
+  assertEquals(15, goo(t_array, 0));
+  %ClearFunctionTypeFeedback(goo);
+  %ClearFunctionTypeFeedback(boo);
+}
+
+do_tagged_index_external_array_test(Int8Array);
+do_tagged_index_external_array_test(Uint8Array);
+do_tagged_index_external_array_test(Int16Array);
+do_tagged_index_external_array_test(Uint16Array);
+do_tagged_index_external_array_test(Int32Array);
+do_tagged_index_external_array_test(Uint32Array);
+do_tagged_index_external_array_test(Float32Array);
+do_tagged_index_external_array_test(Float64Array);
+
+var built_in_array = new Array(1, 2, 3, 4, 5, 6);
+assertEquals(1, goo(built_in_array, 0));
+assertEquals(1, goo(built_in_array, 0));
+%OptimizeFunctionOnNextCall(goo);
+%OptimizeFunctionOnNextCall(boo);
+boo(built_in_array, 0, 11);
+assertEquals(11, goo(built_in_array, 0));
+%ClearFunctionTypeFeedback(goo);
+%ClearFunctionTypeFeedback(boo);
+
+built_in_array = new Array(1.5, 2, 3, 4, 5, 6);
+assertEquals(1.5, goo(built_in_array, 0));
+assertEquals(1.5, goo(built_in_array, 0));
+%OptimizeFunctionOnNextCall(goo);
+%OptimizeFunctionOnNextCall(boo);
+boo(built_in_array, 0, 2.5);
+assertEquals(2.5, goo(built_in_array, 0));
+%ClearFunctionTypeFeedback(goo);
+%ClearFunctionTypeFeedback(boo);

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to