| Index: src/compiler/js-typed-lowering.cc
|
| diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
|
| index 0813136fc184df264e05ff38226ff8bf4aafb473..857a1c649b8ca1b1eb9815ca4e1d93bdd512fe90 100644
|
| --- a/src/compiler/js-typed-lowering.cc
|
| +++ b/src/compiler/js-typed-lowering.cc
|
| @@ -7,6 +7,7 @@
|
| #include "src/compiler/js-builtin-reducer.h"
|
| #include "src/compiler/js-typed-lowering.h"
|
| #include "src/compiler/node-aux-data-inl.h"
|
| +#include "src/compiler/node-matchers.h" // TODO(bmeurer): get rid of this?
|
| #include "src/compiler/node-properties-inl.h"
|
| #include "src/types.h"
|
|
|
| @@ -672,27 +673,48 @@ Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
|
| Node* base = NodeProperties::GetValueInput(node, 0);
|
| Type* key_type = NodeProperties::GetBounds(key).upper;
|
| Type* base_type = NodeProperties::GetBounds(base).upper;
|
| - // TODO(mstarzinger): This lowering is not correct if:
|
| - // a) The typed array or it's buffer is neutered.
|
| if (base_type->IsConstant() && key_type->Is(Type::Integral32()) &&
|
| base_type->AsConstant()->Value()->IsJSTypedArray()) {
|
| // JSLoadProperty(typed-array, int32)
|
| Handle<JSTypedArray> array =
|
| Handle<JSTypedArray>::cast(base_type->AsConstant()->Value());
|
| if (IsExternalArrayElementsKind(array->map()->elements_kind())) {
|
| - ExternalArrayType type = array->type();
|
| - double byte_length = array->byte_length()->Number();
|
| - if (byte_length <= kMaxInt) {
|
| - Handle<ExternalArray> elements =
|
| - Handle<ExternalArray>::cast(handle(array->elements()));
|
| + Handle<JSArrayBuffer> buffer =
|
| + Handle<JSArrayBuffer>::cast(handle(array->buffer(), isolate()));
|
| + size_t byte_length;
|
| + size_t const page_size = base::OS::CommitPageSize();
|
| + size_t const guard_size = buffer->is_guarded() ? page_size : 0;
|
| + if (array->byte_offset()->SameValue(Smi::FromInt(0)) &&
|
| + array->byte_length()->SameValue(buffer->byte_length()) &&
|
| + TryNumberToSize(isolate(), array->byte_length(), &byte_length) &&
|
| + byte_length <= 0x80000000u - guard_size) {
|
| + DCHECK((byte_length % array->element_size()) == 0);
|
| + BufferAccess const access(array->type(), guard_size);
|
| Node* pointer = jsgraph()->IntPtrConstant(
|
| - bit_cast<intptr_t>(elements->external_pointer()));
|
| - Node* length = jsgraph()->Constant(array->length()->Number());
|
| + bit_cast<intptr_t>(buffer->backing_store()));
|
| + Node* offset = key;
|
| + int const element_size_shift =
|
| + WhichPowerOf2(static_cast<int>(array->element_size()));
|
| + // TODO(bmeurer)
|
| + Factory* factory = zone()->isolate()->factory();
|
| + Handle<Object> min = factory->NewNumber(0);
|
| + Handle<Object> max =
|
| + factory->NewNumber((byte_length - 1) >> element_size_shift);
|
| + if (key_type->Is(Type::Range(min, max, zone()))) {
|
| + offset =
|
| + graph()->NewNode(machine()->Word32Shl(), key,
|
| + jsgraph()->Uint32Constant(element_size_shift));
|
| + } else if (element_size_shift != 0) {
|
| + if (offset->opcode() != IrOpcode::kWord32Sar) return NoChange();
|
| + NumberBinopMatcher moffset(offset);
|
| + if (!moffset.right().Is(element_size_shift)) return NoChange();
|
| + offset = moffset.left().node();
|
| + }
|
| + Node* length = jsgraph()->Constant(static_cast<double>(byte_length));
|
| Node* effect = NodeProperties::GetEffectInput(node);
|
| - Node* load = graph()->NewNode(
|
| - simplified()->LoadElement(
|
| - AccessBuilder::ForTypedArrayElement(type, true)),
|
| - pointer, key, length, effect);
|
| + Node* control = NodeProperties::GetControlInput(node);
|
| + Node* load = graph()->NewNode(simplified()->LoadBuffer(access), pointer,
|
| + offset, length, effect, control);
|
| return ReplaceEagerly(node, load);
|
| }
|
| }
|
| @@ -707,27 +729,48 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
|
| Node* value = NodeProperties::GetValueInput(node, 2);
|
| Type* key_type = NodeProperties::GetBounds(key).upper;
|
| Type* base_type = NodeProperties::GetBounds(base).upper;
|
| - // TODO(mstarzinger): This lowering is not correct if:
|
| - // a) The typed array or its buffer is neutered.
|
| - if (key_type->Is(Type::Integral32()) && base_type->IsConstant() &&
|
| + Type* value_type = NodeProperties::GetBounds(value).upper;
|
| + if (base_type->IsConstant() && key_type->Is(Type::Integral32()) &&
|
| base_type->AsConstant()->Value()->IsJSTypedArray()) {
|
| // JSStoreProperty(typed-array, int32, value)
|
| Handle<JSTypedArray> array =
|
| Handle<JSTypedArray>::cast(base_type->AsConstant()->Value());
|
| if (IsExternalArrayElementsKind(array->map()->elements_kind())) {
|
| - ExternalArrayType type = array->type();
|
| - double byte_length = array->byte_length()->Number();
|
| - if (byte_length <= kMaxInt) {
|
| - Handle<ExternalArray> elements =
|
| - Handle<ExternalArray>::cast(handle(array->elements()));
|
| + Handle<JSArrayBuffer> buffer =
|
| + Handle<JSArrayBuffer>::cast(handle(array->buffer(), isolate()));
|
| + size_t byte_length;
|
| + size_t const page_size = base::OS::CommitPageSize();
|
| + size_t const guard_size = buffer->is_guarded() ? page_size : 0;
|
| + if (array->byte_offset()->SameValue(Smi::FromInt(0)) &&
|
| + array->byte_length()->SameValue(buffer->byte_length()) &&
|
| + TryNumberToSize(isolate(), array->byte_length(), &byte_length) &&
|
| + byte_length <= 0x80000000u - guard_size) {
|
| + DCHECK((byte_length % array->element_size()) == 0);
|
| + BufferAccess const access(array->type(), guard_size);
|
| Node* pointer = jsgraph()->IntPtrConstant(
|
| - bit_cast<intptr_t>(elements->external_pointer()));
|
| - Node* length = jsgraph()->Constant(array->length()->Number());
|
| + bit_cast<intptr_t>(buffer->backing_store()));
|
| + Node* offset = key;
|
| + int const element_size_shift =
|
| + WhichPowerOf2(static_cast<int>(array->element_size()));
|
| + // TODO(bmeurer)
|
| + Factory* factory = zone()->isolate()->factory();
|
| + Handle<Object> min = factory->NewNumber(0);
|
| + Handle<Object> max =
|
| + factory->NewNumber((byte_length - 1) >> element_size_shift);
|
| + if (key_type->Is(Type::Range(min, max, zone()))) {
|
| + offset =
|
| + graph()->NewNode(machine()->Word32Shl(), key,
|
| + jsgraph()->Uint32Constant(element_size_shift));
|
| + } else if (element_size_shift != 0) {
|
| + if (offset->opcode() != IrOpcode::kWord32Sar) return NoChange();
|
| + NumberBinopMatcher moffset(offset);
|
| + if (!moffset.right().Is(element_size_shift)) return NoChange();
|
| + offset = moffset.left().node();
|
| + }
|
| + Node* length = jsgraph()->Constant(static_cast<double>(byte_length));
|
| Node* effect = NodeProperties::GetEffectInput(node);
|
| Node* control = NodeProperties::GetControlInput(node);
|
|
|
| - ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
|
| - Type* value_type = NodeProperties::GetBounds(value).upper;
|
| // If the value input does not have the required type, insert the
|
| // appropriate conversion.
|
|
|
| @@ -744,16 +787,16 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
|
| }
|
| }
|
| // For integer-typed arrays, convert to the integer type.
|
| - if (access.type->Is(Type::Signed32()) &&
|
| + if (TypeOf(access.machine_type()) == kTypeInt32 &&
|
| !value_type->Is(Type::Signed32())) {
|
| value = graph()->NewNode(simplified()->NumberToInt32(), value);
|
| - } else if (access.type->Is(Type::Unsigned32()) &&
|
| + } else if (TypeOf(access.machine_type()) == kTypeUint32 &&
|
| !value_type->Is(Type::Unsigned32())) {
|
| value = graph()->NewNode(simplified()->NumberToUint32(), value);
|
| }
|
|
|
| Node* store =
|
| - graph()->NewNode(simplified()->StoreElement(access), pointer, key,
|
| + graph()->NewNode(simplified()->StoreBuffer(access), pointer, offset,
|
| length, value, effect, control);
|
| return ReplaceEagerly(node, store);
|
| }
|
|
|