| Index: src/compiler/js-typed-lowering.cc
|
| diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
|
| index 51ddc174cc94e9abc75dcf15c797e3f8fc386f6e..c881812f860c59fa76203943ff0f3276dd0616ea 100644
|
| --- a/src/compiler/js-typed-lowering.cc
|
| +++ b/src/compiler/js-typed-lowering.cc
|
| @@ -829,39 +829,40 @@ Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
|
| Node* key = NodeProperties::GetValueInput(node, 1);
|
| Node* base = NodeProperties::GetValueInput(node, 0);
|
| Type* key_type = NodeProperties::GetBounds(key).upper;
|
| - // TODO(mstarzinger): This lowering is not correct if:
|
| - // a) The typed array or it's buffer is neutered.
|
| HeapObjectMatcher<Object> mbase(base);
|
| if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) {
|
| Handle<JSTypedArray> const array =
|
| Handle<JSTypedArray>::cast(mbase.Value().handle());
|
| - array->GetBuffer()->set_is_neuterable(false);
|
| - BufferAccess const access(array->type());
|
| - size_t const k = ElementSizeLog2Of(access.machine_type());
|
| - double const byte_length = array->byte_length()->Number();
|
| - CHECK_LT(k, arraysize(shifted_int32_ranges_));
|
| - if (IsExternalArrayElementsKind(array->map()->elements_kind()) &&
|
| - key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
|
| - // JSLoadProperty(typed-array, int32)
|
| - Handle<ExternalArray> elements =
|
| - Handle<ExternalArray>::cast(handle(array->elements()));
|
| - Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
|
| - Node* length = jsgraph()->Constant(byte_length);
|
| - Node* effect = NodeProperties::GetEffectInput(node);
|
| - Node* control = NodeProperties::GetControlInput(node);
|
| - // Check if we can avoid the bounds check.
|
| - if (key_type->Min() >= 0 && key_type->Max() < array->length()->Number()) {
|
| - Node* load = graph()->NewNode(
|
| - simplified()->LoadElement(
|
| - AccessBuilder::ForTypedArrayElement(array->type(), true)),
|
| - buffer, key, effect, control);
|
| + if (!array->GetBuffer()->was_neutered()) {
|
| + array->GetBuffer()->set_is_neuterable(false);
|
| + BufferAccess const access(array->type());
|
| + size_t const k = ElementSizeLog2Of(access.machine_type());
|
| + double const byte_length = array->byte_length()->Number();
|
| + CHECK_LT(k, arraysize(shifted_int32_ranges_));
|
| + if (IsExternalArrayElementsKind(array->map()->elements_kind()) &&
|
| + key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
|
| + // JSLoadProperty(typed-array, int32)
|
| + Handle<ExternalArray> elements =
|
| + Handle<ExternalArray>::cast(handle(array->elements()));
|
| + Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
|
| + Node* length = jsgraph()->Constant(byte_length);
|
| + Node* effect = NodeProperties::GetEffectInput(node);
|
| + Node* control = NodeProperties::GetControlInput(node);
|
| + // Check if we can avoid the bounds check.
|
| + if (key_type->Min() >= 0 &&
|
| + key_type->Max() < array->length()->Number()) {
|
| + Node* load = graph()->NewNode(
|
| + simplified()->LoadElement(
|
| + AccessBuilder::ForTypedArrayElement(array->type(), true)),
|
| + buffer, key, effect, control);
|
| + return ReplaceEagerly(node, load);
|
| + }
|
| + // Compute byte offset.
|
| + Node* offset = Word32Shl(key, static_cast<int>(k));
|
| + Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer,
|
| + offset, length, effect, control);
|
| return ReplaceEagerly(node, load);
|
| }
|
| - // Compute byte offset.
|
| - Node* offset = Word32Shl(key, static_cast<int>(k));
|
| - Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer,
|
| - offset, length, effect, control);
|
| - return ReplaceEagerly(node, load);
|
| }
|
| }
|
| return NoChange();
|
| @@ -874,75 +875,76 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
|
| Node* value = NodeProperties::GetValueInput(node, 2);
|
| Type* key_type = NodeProperties::GetBounds(key).upper;
|
| Type* value_type = NodeProperties::GetBounds(value).upper;
|
| - // TODO(mstarzinger): This lowering is not correct if:
|
| - // a) The typed array or its buffer is neutered.
|
| HeapObjectMatcher<Object> mbase(base);
|
| if (mbase.HasValue() && mbase.Value().handle()->IsJSTypedArray()) {
|
| Handle<JSTypedArray> const array =
|
| Handle<JSTypedArray>::cast(mbase.Value().handle());
|
| - array->GetBuffer()->set_is_neuterable(false);
|
| - BufferAccess const access(array->type());
|
| - size_t const k = ElementSizeLog2Of(access.machine_type());
|
| - double const byte_length = array->byte_length()->Number();
|
| - CHECK_LT(k, arraysize(shifted_int32_ranges_));
|
| - if (IsExternalArrayElementsKind(array->map()->elements_kind()) &&
|
| - access.external_array_type() != kExternalUint8ClampedArray &&
|
| - key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
|
| - // JSLoadProperty(typed-array, int32)
|
| - Handle<ExternalArray> elements =
|
| - Handle<ExternalArray>::cast(handle(array->elements()));
|
| - Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
|
| - Node* length = jsgraph()->Constant(byte_length);
|
| - Node* context = NodeProperties::GetContextInput(node);
|
| - Node* effect = NodeProperties::GetEffectInput(node);
|
| - Node* control = NodeProperties::GetControlInput(node);
|
| - // Convert to a number first.
|
| - if (!value_type->Is(Type::Number())) {
|
| - Reduction number_reduction = ReduceJSToNumberInput(value);
|
| - if (number_reduction.Changed()) {
|
| - value = number_reduction.replacement();
|
| - } else {
|
| - Node* frame_state_for_to_number =
|
| - NodeProperties::GetFrameStateInput(node, 1);
|
| - value = effect =
|
| - graph()->NewNode(javascript()->ToNumber(), value, context,
|
| - frame_state_for_to_number, effect, control);
|
| + if (!array->GetBuffer()->was_neutered()) {
|
| + array->GetBuffer()->set_is_neuterable(false);
|
| + BufferAccess const access(array->type());
|
| + size_t const k = ElementSizeLog2Of(access.machine_type());
|
| + double const byte_length = array->byte_length()->Number();
|
| + CHECK_LT(k, arraysize(shifted_int32_ranges_));
|
| + if (IsExternalArrayElementsKind(array->map()->elements_kind()) &&
|
| + access.external_array_type() != kExternalUint8ClampedArray &&
|
| + key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
|
| + // JSLoadProperty(typed-array, int32)
|
| + Handle<ExternalArray> elements =
|
| + Handle<ExternalArray>::cast(handle(array->elements()));
|
| + Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
|
| + Node* length = jsgraph()->Constant(byte_length);
|
| + Node* context = NodeProperties::GetContextInput(node);
|
| + Node* effect = NodeProperties::GetEffectInput(node);
|
| + Node* control = NodeProperties::GetControlInput(node);
|
| + // Convert to a number first.
|
| + if (!value_type->Is(Type::Number())) {
|
| + Reduction number_reduction = ReduceJSToNumberInput(value);
|
| + if (number_reduction.Changed()) {
|
| + value = number_reduction.replacement();
|
| + } else {
|
| + Node* frame_state_for_to_number =
|
| + NodeProperties::GetFrameStateInput(node, 1);
|
| + value = effect =
|
| + graph()->NewNode(javascript()->ToNumber(), value, context,
|
| + frame_state_for_to_number, effect, control);
|
| + }
|
| }
|
| - }
|
| - // For integer-typed arrays, convert to the integer type.
|
| - if (TypeOf(access.machine_type()) == kTypeInt32 &&
|
| - !value_type->Is(Type::Signed32())) {
|
| - value = graph()->NewNode(simplified()->NumberToInt32(), value);
|
| - } else if (TypeOf(access.machine_type()) == kTypeUint32 &&
|
| - !value_type->Is(Type::Unsigned32())) {
|
| - value = graph()->NewNode(simplified()->NumberToUint32(), value);
|
| - }
|
| - // Check if we can avoid the bounds check.
|
| - if (key_type->Min() >= 0 && key_type->Max() < array->length()->Number()) {
|
| - node->set_op(simplified()->StoreElement(
|
| - AccessBuilder::ForTypedArrayElement(array->type(), true)));
|
| + // For integer-typed arrays, convert to the integer type.
|
| + if (TypeOf(access.machine_type()) == kTypeInt32 &&
|
| + !value_type->Is(Type::Signed32())) {
|
| + value = graph()->NewNode(simplified()->NumberToInt32(), value);
|
| + } else if (TypeOf(access.machine_type()) == kTypeUint32 &&
|
| + !value_type->Is(Type::Unsigned32())) {
|
| + value = graph()->NewNode(simplified()->NumberToUint32(), value);
|
| + }
|
| + // Check if we can avoid the bounds check.
|
| + if (key_type->Min() >= 0 &&
|
| + key_type->Max() < array->length()->Number()) {
|
| + node->set_op(simplified()->StoreElement(
|
| + AccessBuilder::ForTypedArrayElement(array->type(), true)));
|
| + node->ReplaceInput(0, buffer);
|
| + DCHECK_EQ(key, node->InputAt(1));
|
| + node->ReplaceInput(2, value);
|
| + node->ReplaceInput(3, effect);
|
| + node->ReplaceInput(4, control);
|
| + node->TrimInputCount(5);
|
| + RelaxControls(node);
|
| + return Changed(node);
|
| + }
|
| + // Compute byte offset.
|
| + Node* offset = Word32Shl(key, static_cast<int>(k));
|
| + // Turn into a StoreBuffer operation.
|
| + node->set_op(simplified()->StoreBuffer(access));
|
| node->ReplaceInput(0, buffer);
|
| - DCHECK_EQ(key, node->InputAt(1));
|
| - node->ReplaceInput(2, value);
|
| - node->ReplaceInput(3, effect);
|
| - node->ReplaceInput(4, control);
|
| - node->TrimInputCount(5);
|
| + node->ReplaceInput(1, offset);
|
| + node->ReplaceInput(2, length);
|
| + node->ReplaceInput(3, value);
|
| + node->ReplaceInput(4, effect);
|
| + node->ReplaceInput(5, control);
|
| + node->TrimInputCount(6);
|
| RelaxControls(node);
|
| return Changed(node);
|
| }
|
| - // Compute byte offset.
|
| - Node* offset = Word32Shl(key, static_cast<int>(k));
|
| - // Turn into a StoreBuffer operation.
|
| - node->set_op(simplified()->StoreBuffer(access));
|
| - node->ReplaceInput(0, buffer);
|
| - node->ReplaceInput(1, offset);
|
| - node->ReplaceInput(2, length);
|
| - node->ReplaceInput(3, value);
|
| - node->ReplaceInput(4, effect);
|
| - node->ReplaceInput(5, control);
|
| - node->TrimInputCount(6);
|
| - RelaxControls(node);
|
| - return Changed(node);
|
| }
|
| }
|
| return NoChange();
|
|
|