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(); |