Commit 9b2358d6 authored by Théotime Grohens's avatar Théotime Grohens Committed by Commit Bot

[turbofan] Create new Operator LoadDataViewElement

This CL creates a new Operator called LoadDataViewElement, similar to
LoadTypedArray, for DataView getters.

This operator will be used as a wrapper around all the computations
that DataViews need to do when loading values, due to the endianness
parameter of DataView loads.

Change-Id: Ie67d63c9669142e539a5c8d7ae82dc1018ce5858
Reviewed-on: https://chromium-review.googlesource.com/1125928
Commit-Queue: Théotime Grohens <theotime@google.com>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54217}
parent 417f8ee6
...@@ -935,6 +935,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, ...@@ -935,6 +935,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kLoadTypedElement: case IrOpcode::kLoadTypedElement:
result = LowerLoadTypedElement(node); result = LowerLoadTypedElement(node);
break; break;
case IrOpcode::kLoadDataViewElement:
result = LowerLoadDataViewElement(node);
break;
case IrOpcode::kStoreTypedElement: case IrOpcode::kStoreTypedElement:
LowerStoreTypedElement(node); LowerStoreTypedElement(node);
break; break;
...@@ -3742,6 +3745,22 @@ Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) { ...@@ -3742,6 +3745,22 @@ Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
return done.PhiAt(0); return done.PhiAt(0);
} }
Node* EffectControlLinearizer::LowerLoadDataViewElement(Node* node) {
ExternalArrayType element_type = ExternalArrayTypeOf(node->op());
Node* buffer = node->InputAt(0);
Node* storage = node->InputAt(1);
Node* index = node->InputAt(2);
// We need to keep the {buffer} alive so that the GC will not release the
// ArrayBuffer (if there's any) as long as we are still operating on it.
__ Retain(buffer);
// Perform the actual data view element access.
return __ LoadElement(AccessBuilder::ForTypedArrayElement(
element_type, true, LoadSensitivity::kCritical),
storage, index);
}
Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) { Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) {
ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
Node* buffer = node->InputAt(0); Node* buffer = node->InputAt(0);
......
...@@ -151,6 +151,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer { ...@@ -151,6 +151,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
void LowerTransitionElementsKind(Node* node); void LowerTransitionElementsKind(Node* node);
Node* LowerLoadFieldByIndex(Node* node); Node* LowerLoadFieldByIndex(Node* node);
Node* LowerLoadTypedElement(Node* node); Node* LowerLoadTypedElement(Node* node);
Node* LowerLoadDataViewElement(Node* node);
void LowerStoreTypedElement(Node* node); void LowerStoreTypedElement(Node* node);
void LowerStoreSignedSmallElement(Node* node); void LowerStoreSignedSmallElement(Node* node);
Node* LowerFindOrderedHashMapEntry(Node* node); Node* LowerFindOrderedHashMapEntry(Node* node);
......
...@@ -6563,6 +6563,20 @@ Reduction JSCallReducer::ReduceArrayBufferViewAccessor( ...@@ -6563,6 +6563,20 @@ Reduction JSCallReducer::ReduceArrayBufferViewAccessor(
return NoChange(); return NoChange();
} }
namespace {
int ExternalArrayElementSize(const ExternalArrayType element_type) {
switch (element_type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case kExternal##Type##Array: \
return size;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
default:
UNREACHABLE();
#undef TYPED_ARRAY_CASE
}
}
} // namespace
Reduction JSCallReducer::ReduceDataViewPrototypeGet( Reduction JSCallReducer::ReduceDataViewPrototypeGet(
Node* node, ExternalArrayType element_type) { Node* node, ExternalArrayType element_type) {
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
...@@ -6641,9 +6655,9 @@ Reduction JSCallReducer::ReduceDataViewPrototypeGet( ...@@ -6641,9 +6655,9 @@ Reduction JSCallReducer::ReduceDataViewPrototypeGet(
// The end offset is the offset plus the element size // The end offset is the offset plus the element size
// of the type that we want to load. // of the type that we want to load.
// Since we only load int8 and uint8 for now, that size is 1. int element_size = ExternalArrayElementSize(element_type);
Node* end_offset = graph()->NewNode(simplified()->NumberAdd(), offset, Node* end_offset = graph()->NewNode(simplified()->NumberAdd(), offset,
jsgraph()->OneConstant()); jsgraph()->Constant(element_size));
// We need to check that {end_offset} <= {byte_length}, ie // We need to check that {end_offset} <= {byte_length}, ie
// throw a RangeError if {byte_length} < {end_offset}. // throw a RangeError if {byte_length} < {end_offset}.
...@@ -6679,8 +6693,7 @@ Reduction JSCallReducer::ReduceDataViewPrototypeGet( ...@@ -6679,8 +6693,7 @@ Reduction JSCallReducer::ReduceDataViewPrototypeGet(
// Perform the load. // Perform the load.
vfalse_range = efalse_range = graph()->NewNode( vfalse_range = efalse_range = graph()->NewNode(
simplified()->LoadElement(AccessBuilder::ForTypedArrayElement( simplified()->LoadDataViewElement(element_type), buffer,
element_type, true, LoadSensitivity::kCritical)),
backing_store, buffer_index, efalse_range, if_false_range); backing_store, buffer_index, efalse_range, if_false_range);
} }
...@@ -6699,7 +6712,7 @@ Reduction JSCallReducer::ReduceDataViewPrototypeGet( ...@@ -6699,7 +6712,7 @@ Reduction JSCallReducer::ReduceDataViewPrototypeGet(
if_true_range); // We threw because out of bounds. if_true_range); // We threw because out of bounds.
if_true_range = graph()->NewNode(common()->IfSuccess(), if_true_range); if_true_range = graph()->NewNode(common()->IfSuccess(), if_true_range);
// We can't throw in LoadTypedElement(), // We can't throw in LoadDataViewElement(),
// so we don't need to handle that path here. // so we don't need to handle that path here.
// Join the exception edges. // Join the exception edges.
......
...@@ -380,6 +380,7 @@ ...@@ -380,6 +380,7 @@
V(LoadField) \ V(LoadField) \
V(LoadElement) \ V(LoadElement) \
V(LoadTypedElement) \ V(LoadTypedElement) \
V(LoadDataViewElement) \
V(StoreField) \ V(StoreField) \
V(StoreElement) \ V(StoreElement) \
V(StoreTypedElement) \ V(StoreTypedElement) \
......
...@@ -2630,6 +2630,16 @@ class RepresentationSelector { ...@@ -2630,6 +2630,16 @@ class RepresentationSelector {
SetOutput(node, rep); SetOutput(node, rep);
return; return;
} }
case IrOpcode::kLoadDataViewElement: {
MachineRepresentation const rep =
MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer
ProcessInput(node, 1, UseInfo::PointerInt()); // external pointer
ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index
ProcessRemainingInputs(node, 3);
SetOutput(node, rep);
return;
}
case IrOpcode::kStoreTypedElement: { case IrOpcode::kStoreTypedElement: {
MachineRepresentation const rep = MachineRepresentation const rep =
MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
......
...@@ -141,6 +141,7 @@ const ElementAccess& ElementAccessOf(const Operator* op) { ...@@ -141,6 +141,7 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
ExternalArrayType ExternalArrayTypeOf(const Operator* op) { ExternalArrayType ExternalArrayTypeOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kLoadTypedElement || DCHECK(op->opcode() == IrOpcode::kLoadTypedElement ||
op->opcode() == IrOpcode::kLoadDataViewElement ||
op->opcode() == IrOpcode::kStoreTypedElement); op->opcode() == IrOpcode::kStoreTypedElement);
return OpParameter<ExternalArrayType>(op); return OpParameter<ExternalArrayType>(op);
} }
...@@ -1529,7 +1530,8 @@ SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP) ...@@ -1529,7 +1530,8 @@ SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \ V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) \ V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) \
V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \ V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \
V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0) V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0) \
V(LoadDataViewElement, ExternalArrayType, Operator::kNoWrite, 3, 1, 1)
#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \ #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
output_count) \ output_count) \
......
...@@ -759,6 +759,9 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final ...@@ -759,6 +759,9 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
// load-typed-element buffer, [base + external + index] // load-typed-element buffer, [base + external + index]
const Operator* LoadTypedElement(ExternalArrayType const&); const Operator* LoadTypedElement(ExternalArrayType const&);
// load-data-view-element buffer, [base + index]
const Operator* LoadDataViewElement(ExternalArrayType const&);
// store-typed-element buffer, [base + external + index], value // store-typed-element buffer, [base + external + index], value
const Operator* StoreTypedElement(ExternalArrayType const&); const Operator* StoreTypedElement(ExternalArrayType const&);
......
...@@ -2043,6 +2043,17 @@ Type Typer::Visitor::TypeLoadTypedElement(Node* node) { ...@@ -2043,6 +2043,17 @@ Type Typer::Visitor::TypeLoadTypedElement(Node* node) {
UNREACHABLE(); UNREACHABLE();
} }
Type Typer::Visitor::TypeLoadDataViewElement(Node* node) {
switch (ExternalArrayTypeOf(node->op())) {
#define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype, size) \
case kExternal##ElemType##Array: \
return typer_->cache_.k##ElemType;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
}
UNREACHABLE();
}
Type Typer::Visitor::TypeStoreField(Node* node) { UNREACHABLE(); } Type Typer::Visitor::TypeStoreField(Node* node) { UNREACHABLE(); }
Type Typer::Visitor::TypeStoreElement(Node* node) { UNREACHABLE(); } Type Typer::Visitor::TypeStoreElement(Node* node) { UNREACHABLE(); }
......
...@@ -1498,6 +1498,8 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -1498,6 +1498,8 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
break; break;
case IrOpcode::kLoadTypedElement: case IrOpcode::kLoadTypedElement:
break; break;
case IrOpcode::kLoadDataViewElement:
break;
case IrOpcode::kStoreField: case IrOpcode::kStoreField:
// (Object, fieldtype) -> _|_ // (Object, fieldtype) -> _|_
// TODO(rossberg): activate once machine ops are typed. // TODO(rossberg): activate once machine ops are typed.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment