| Index: src/code-stub-assembler.cc
 | 
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
 | 
| index 833b4b20ead9bf58d4b0a06ee172b0a7356875bd..2d6fa59b3be0f550613ef629956f8dc2b354715d 100644
 | 
| --- a/src/code-stub-assembler.cc
 | 
| +++ b/src/code-stub-assembler.cc
 | 
| @@ -3535,8 +3535,7 @@ compiler::Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
 | 
|                                                            ElementsKind kind,
 | 
|                                                            ParameterMode mode,
 | 
|                                                            int base_size) {
 | 
| -  bool is_double = IsFastDoubleElementsKind(kind);
 | 
| -  int element_size_shift = is_double ? kDoubleSizeLog2 : kPointerSizeLog2;
 | 
| +  int element_size_shift = ElementsKindToShiftSize(kind);
 | 
|    int element_size = 1 << element_size_shift;
 | 
|    int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize;
 | 
|    intptr_t index = 0;
 | 
| @@ -4637,6 +4636,252 @@ Node* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) {
 | 
|                IntPtrConstant(offset));
 | 
|  }
 | 
|  
 | 
| +Node* CodeStubAssembler::ClampedToUint8(Node* int32_value) {
 | 
| +  Label done(this);
 | 
| +  Node* int32_zero = Int32Constant(0);
 | 
| +  Node* int32_255 = Int32Constant(255);
 | 
| +  Variable var_value(this, MachineRepresentation::kWord32);
 | 
| +  var_value.Bind(int32_value);
 | 
| +  GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done);
 | 
| +  var_value.Bind(int32_zero);
 | 
| +  GotoIf(Int32LessThan(int32_value, int32_zero), &done);
 | 
| +  var_value.Bind(int32_255);
 | 
| +  Goto(&done);
 | 
| +  Bind(&done);
 | 
| +  return var_value.value();
 | 
| +}
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +// Converts typed array elements kind to a machine representations.
 | 
| +MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) {
 | 
| +  switch (kind) {
 | 
| +    case UINT8_CLAMPED_ELEMENTS:
 | 
| +    case UINT8_ELEMENTS:
 | 
| +    case INT8_ELEMENTS:
 | 
| +      return MachineRepresentation::kWord8;
 | 
| +    case UINT16_ELEMENTS:
 | 
| +    case INT16_ELEMENTS:
 | 
| +      return MachineRepresentation::kWord16;
 | 
| +    case UINT32_ELEMENTS:
 | 
| +    case INT32_ELEMENTS:
 | 
| +      return MachineRepresentation::kWord32;
 | 
| +    case FLOAT32_ELEMENTS:
 | 
| +      return MachineRepresentation::kFloat32;
 | 
| +    case FLOAT64_ELEMENTS:
 | 
| +      return MachineRepresentation::kFloat64;
 | 
| +    default:
 | 
| +      UNREACHABLE();
 | 
| +      return MachineRepresentation::kNone;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind,
 | 
| +                                     Node* index, Node* value,
 | 
| +                                     ParameterMode mode) {
 | 
| +  if (IsFixedTypedArrayElementsKind(kind)) {
 | 
| +    if (kind == UINT8_CLAMPED_ELEMENTS) {
 | 
| +      value = ClampedToUint8(value);
 | 
| +    }
 | 
| +    Node* offset = ElementOffsetFromIndex(index, kind, mode, 0);
 | 
| +    MachineRepresentation rep = ElementsKindToMachineRepresentation(kind);
 | 
| +    StoreNoWriteBarrier(rep, elements, offset, value);
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  WriteBarrierMode barrier_mode =
 | 
| +      IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
 | 
| +  if (IsFastDoubleElementsKind(kind)) {
 | 
| +    // Make sure we do not store signalling NaNs into double arrays.
 | 
| +    value = Float64SilenceNaN(value);
 | 
| +    StoreFixedDoubleArrayElement(elements, index, value, mode);
 | 
| +  } else {
 | 
| +    StoreFixedArrayElement(elements, index, value, barrier_mode, mode);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
 | 
| +                                         bool is_jsarray,
 | 
| +                                         ElementsKind elements_kind,
 | 
| +                                         KeyedAccessStoreMode store_mode,
 | 
| +                                         Label* bailout) {
 | 
| +  Node* elements = LoadElements(object);
 | 
| +  if (IsFastSmiOrObjectElementsKind(elements_kind) &&
 | 
| +      store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
 | 
| +    // Bailout in case of COW elements.
 | 
| +    GotoIf(WordNotEqual(LoadMap(elements),
 | 
| +                        LoadRoot(Heap::kFixedArrayMapRootIndex)),
 | 
| +           bailout);
 | 
| +  }
 | 
| +  // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode().
 | 
| +  ParameterMode parameter_mode = INTPTR_PARAMETERS;
 | 
| +  key = TryToIntptr(key, bailout);
 | 
| +
 | 
| +  if (IsFixedTypedArrayElementsKind(elements_kind)) {
 | 
| +    Label done(this);
 | 
| +    // TODO(ishell): call ToNumber() on value and don't bailout but be careful
 | 
| +    // to call it only once if we decide to bailout because of bounds checks.
 | 
| +
 | 
| +    if (IsFixedFloatElementsKind(elements_kind)) {
 | 
| +      // TODO(ishell): move float32 truncation into PrepareValueForWrite.
 | 
| +      value = PrepareValueForWrite(value, Representation::Double(), bailout);
 | 
| +      if (elements_kind == FLOAT32_ELEMENTS) {
 | 
| +        value = TruncateFloat64ToFloat32(value);
 | 
| +      }
 | 
| +    } else {
 | 
| +      // TODO(ishell): It's fine for word8/16/32 to truncate the result.
 | 
| +      value = TryToIntptr(value, bailout);
 | 
| +    }
 | 
| +
 | 
| +    // There must be no allocations between the buffer load and
 | 
| +    // and the actual store to backing store, because GC may decide that
 | 
| +    // the buffer is not alive or move the elements.
 | 
| +    // TODO(ishell): introduce DisallowHeapAllocationCode scope here.
 | 
| +
 | 
| +    // Check if buffer has been neutered.
 | 
| +    Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
 | 
| +    Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset,
 | 
| +                                     MachineType::Uint32());
 | 
| +    Node* neutered_bit =
 | 
| +        Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask));
 | 
| +    GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), bailout);
 | 
| +
 | 
| +    // Bounds check.
 | 
| +    Node* length = UntagParameter(
 | 
| +        LoadObjectField(object, JSTypedArray::kLengthOffset), parameter_mode);
 | 
| +
 | 
| +    if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
 | 
| +      // Skip the store if we write beyond the length.
 | 
| +      GotoUnless(IntPtrLessThan(key, length), &done);
 | 
| +      // ... but bailout if the key is negative.
 | 
| +    } else {
 | 
| +      DCHECK_EQ(STANDARD_STORE, store_mode);
 | 
| +    }
 | 
| +    GotoUnless(UintPtrLessThan(key, length), bailout);
 | 
| +
 | 
| +    // Backing store = external_pointer + base_pointer.
 | 
| +    Node* external_pointer =
 | 
| +        LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
 | 
| +                        MachineType::Pointer());
 | 
| +    Node* base_pointer =
 | 
| +        LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
 | 
| +    Node* backing_store = IntPtrAdd(external_pointer, base_pointer);
 | 
| +    StoreElement(backing_store, elements_kind, key, value, parameter_mode);
 | 
| +    Goto(&done);
 | 
| +
 | 
| +    Bind(&done);
 | 
| +    return;
 | 
| +  }
 | 
| +  DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
 | 
| +         IsFastDoubleElementsKind(elements_kind));
 | 
| +
 | 
| +  Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset)
 | 
| +                            : LoadFixedArrayBaseLength(elements);
 | 
| +  length = UntagParameter(length, parameter_mode);
 | 
| +
 | 
| +  // In case value is stored into a fast smi array, assure that the value is
 | 
| +  // a smi before manipulating the backing store. Otherwise the backing store
 | 
| +  // may be left in an invalid state.
 | 
| +  if (IsFastSmiElementsKind(elements_kind)) {
 | 
| +    GotoUnless(WordIsSmi(value), bailout);
 | 
| +  } else if (IsFastDoubleElementsKind(elements_kind)) {
 | 
| +    value = PrepareValueForWrite(value, Representation::Double(), bailout);
 | 
| +  }
 | 
| +
 | 
| +  if (IsGrowStoreMode(store_mode)) {
 | 
| +    elements = CheckForCapacityGrow(object, elements, elements_kind, length,
 | 
| +                                    key, parameter_mode, is_jsarray, bailout);
 | 
| +  } else {
 | 
| +    GotoUnless(UintPtrLessThan(key, length), bailout);
 | 
| +
 | 
| +    if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) &&
 | 
| +        IsFastSmiOrObjectElementsKind(elements_kind)) {
 | 
| +      elements = CopyElementsOnWrite(object, elements, elements_kind, length,
 | 
| +                                     parameter_mode, bailout);
 | 
| +    }
 | 
| +  }
 | 
| +  StoreElement(elements, elements_kind, key, value, parameter_mode);
 | 
| +}
 | 
| +
 | 
| +Node* CodeStubAssembler::CheckForCapacityGrow(Node* object, Node* elements,
 | 
| +                                              ElementsKind kind, Node* length,
 | 
| +                                              Node* key, ParameterMode mode,
 | 
| +                                              bool is_js_array,
 | 
| +                                              Label* bailout) {
 | 
| +  Variable checked_elements(this, MachineRepresentation::kTagged);
 | 
| +  Label grow_case(this), no_grow_case(this), done(this);
 | 
| +
 | 
| +  Node* condition;
 | 
| +  if (IsHoleyElementsKind(kind)) {
 | 
| +    condition = UintPtrGreaterThanOrEqual(key, length);
 | 
| +  } else {
 | 
| +    condition = WordEqual(key, length);
 | 
| +  }
 | 
| +  Branch(condition, &grow_case, &no_grow_case);
 | 
| +
 | 
| +  Bind(&grow_case);
 | 
| +  {
 | 
| +    Node* current_capacity =
 | 
| +        UntagParameter(LoadFixedArrayBaseLength(elements), mode);
 | 
| +
 | 
| +    checked_elements.Bind(elements);
 | 
| +
 | 
| +    Label fits_capacity(this);
 | 
| +    GotoIf(UintPtrLessThan(key, current_capacity), &fits_capacity);
 | 
| +    {
 | 
| +      Node* new_elements = TryGrowElementsCapacity(
 | 
| +          object, elements, kind, key, current_capacity, mode, bailout);
 | 
| +
 | 
| +      checked_elements.Bind(new_elements);
 | 
| +      Goto(&fits_capacity);
 | 
| +    }
 | 
| +    Bind(&fits_capacity);
 | 
| +
 | 
| +    if (is_js_array) {
 | 
| +      Node* new_length = IntPtrAdd(key, IntPtrOrSmiConstant(1, mode));
 | 
| +      StoreObjectFieldNoWriteBarrier(object, JSArray::kLengthOffset,
 | 
| +                                     TagParameter(new_length, mode));
 | 
| +    }
 | 
| +    Goto(&done);
 | 
| +  }
 | 
| +
 | 
| +  Bind(&no_grow_case);
 | 
| +  {
 | 
| +    GotoUnless(UintPtrLessThan(key, length), bailout);
 | 
| +    checked_elements.Bind(elements);
 | 
| +    Goto(&done);
 | 
| +  }
 | 
| +
 | 
| +  Bind(&done);
 | 
| +  return checked_elements.value();
 | 
| +}
 | 
| +
 | 
| +Node* CodeStubAssembler::CopyElementsOnWrite(Node* object, Node* elements,
 | 
| +                                             ElementsKind kind, Node* length,
 | 
| +                                             ParameterMode mode,
 | 
| +                                             Label* bailout) {
 | 
| +  Variable new_elements_var(this, MachineRepresentation::kTagged);
 | 
| +  Label done(this);
 | 
| +
 | 
| +  new_elements_var.Bind(elements);
 | 
| +  GotoUnless(
 | 
| +      WordEqual(LoadMap(elements), LoadRoot(Heap::kFixedCOWArrayMapRootIndex)),
 | 
| +      &done);
 | 
| +  {
 | 
| +    Node* capacity = UntagParameter(LoadFixedArrayBaseLength(elements), mode);
 | 
| +    Node* new_elements = GrowElementsCapacity(object, elements, kind, kind,
 | 
| +                                              length, capacity, mode, bailout);
 | 
| +
 | 
| +    new_elements_var.Bind(new_elements);
 | 
| +    Goto(&done);
 | 
| +  }
 | 
| +
 | 
| +  Bind(&done);
 | 
| +  return new_elements_var.value();
 | 
| +}
 | 
| +
 | 
|  Node* CodeStubAssembler::EnumLength(Node* map) {
 | 
|    Node* bitfield_3 = LoadMapBitField3(map);
 | 
|    Node* enum_length = BitFieldDecode<Map::EnumLengthBits>(bitfield_3);
 | 
| 
 |