diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index cc7e6f669b..f212fb96c4 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -411,13 +411,7 @@ JSTypedLowering::JSTypedLowering(Editor* editor, Type::Union(Type::SymbolOrReceiver(), empty_string_type_, graph()->zone()), graph()->zone())), - type_cache_(TypeCache::Get()) { - for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { - double min = kMinInt / (1 << k); - double max = kMaxInt / (1 << k); - shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); - } -} + type_cache_(TypeCache::Get()) {} Reduction JSTypedLowering::ReduceSpeculativeNumberAdd(Node* node) { JSBinopReduction r(this, node); @@ -1135,131 +1129,6 @@ Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) { return NoChange(); } -Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { - Node* key = NodeProperties::GetValueInput(node, 1); - Node* base = NodeProperties::GetValueInput(node, 0); - Type* key_type = NodeProperties::GetType(key); - HeapObjectMatcher mbase(base); - if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) { - Handle const array = - Handle::cast(mbase.Value()); - if (!array->GetBuffer()->was_neutered() && - !array->GetBuffer()->is_wasm_buffer()) { - array->GetBuffer()->set_is_neuterable(false); - BufferAccess const access(array->type()); - size_t const k = - ElementSizeLog2Of(access.machine_type().representation()); - double const byte_length = array->byte_length()->Number(); - CHECK_LT(k, arraysize(shifted_int32_ranges_)); - if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { - // JSLoadProperty(typed-array, int32) - Handle elements = - Handle::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_value()) { - Node* load = graph()->NewNode( - simplified()->LoadElement( - AccessBuilder::ForTypedArrayElement(array->type(), true)), - buffer, key, effect, control); - ReplaceWithValue(node, load, load); - return Replace(load); - } - // Compute byte offset. - Node* offset = - (k == 0) ? key : graph()->NewNode( - simplified()->NumberShiftLeft(), key, - jsgraph()->Constant(static_cast(k))); - Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer, - offset, length, effect, control); - ReplaceWithValue(node, load, load); - return Replace(load); - } - } - } - return NoChange(); -} - -Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { - Node* key = NodeProperties::GetValueInput(node, 1); - Node* base = NodeProperties::GetValueInput(node, 0); - Node* value = NodeProperties::GetValueInput(node, 2); - Type* key_type = NodeProperties::GetType(key); - Type* value_type = NodeProperties::GetType(value); - - if (!value_type->Is(Type::PlainPrimitive())) return NoChange(); - - HeapObjectMatcher mbase(base); - if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) { - Handle const array = - Handle::cast(mbase.Value()); - if (!array->GetBuffer()->was_neutered() && - !array->GetBuffer()->is_wasm_buffer()) { - array->GetBuffer()->set_is_neuterable(false); - BufferAccess const access(array->type()); - size_t const k = - ElementSizeLog2Of(access.machine_type().representation()); - double const byte_length = array->byte_length()->Number(); - CHECK_LT(k, arraysize(shifted_int32_ranges_)); - if (access.external_array_type() != kExternalUint8ClampedArray && - key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { - // JSLoadProperty(typed-array, int32) - Handle elements = - Handle::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); - // 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 { - value = - graph()->NewNode(simplified()->PlainPrimitiveToNumber(), value); - } - } - // Check if we can avoid the bounds check. - if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) { - RelaxControls(node); - 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); - NodeProperties::ChangeOp( - node, - simplified()->StoreElement( - AccessBuilder::ForTypedArrayElement(array->type(), true))); - return Changed(node); - } - // Compute byte offset. - Node* offset = - (k == 0) ? key : graph()->NewNode( - simplified()->NumberShiftLeft(), key, - jsgraph()->Constant(static_cast(k))); - // Turn into a StoreBuffer operation. - RelaxControls(node); - 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); - NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); - return Changed(node); - } - } - } - return NoChange(); -} - Reduction JSTypedLowering::ReduceJSHasInPrototypeChain(Node* node) { DCHECK_EQ(IrOpcode::kJSHasInPrototypeChain, node->opcode()); Node* value = NodeProperties::GetValueInput(node, 0); @@ -2264,10 +2133,6 @@ Reduction JSTypedLowering::Reduce(Node* node) { return ReduceJSTypeOf(node); case IrOpcode::kJSLoadNamed: return ReduceJSLoadNamed(node); - case IrOpcode::kJSLoadProperty: - return ReduceJSLoadProperty(node); - case IrOpcode::kJSStoreProperty: - return ReduceJSStoreProperty(node); case IrOpcode::kJSLoadContext: return ReduceJSLoadContext(node); case IrOpcode::kJSStoreContext: diff --git a/src/compiler/js-typed-lowering.h b/src/compiler/js-typed-lowering.h index baa7b04196..e3f5432d7a 100644 --- a/src/compiler/js-typed-lowering.h +++ b/src/compiler/js-typed-lowering.h @@ -44,8 +44,6 @@ class V8_EXPORT_PRIVATE JSTypedLowering final Reduction ReduceJSAdd(Node* node); Reduction ReduceJSComparison(Node* node); Reduction ReduceJSLoadNamed(Node* node); - Reduction ReduceJSLoadProperty(Node* node); - Reduction ReduceJSStoreProperty(Node* node); Reduction ReduceJSHasInPrototypeChain(Node* node); Reduction ReduceJSOrdinaryHasInstance(Node* node); Reduction ReduceJSLoadContext(Node* node); @@ -102,7 +100,6 @@ class V8_EXPORT_PRIVATE JSTypedLowering final CompilationDependencies* dependencies_; JSGraph* jsgraph_; Type* empty_string_type_; - Type* shifted_int32_ranges_[4]; Type* pointer_comparable_type_; TypeCache const& type_cache_; }; diff --git a/src/compiler/load-elimination.cc b/src/compiler/load-elimination.cc index daa14b1e31..4feee398d3 100644 --- a/src/compiler/load-elimination.cc +++ b/src/compiler/load-elimination.cc @@ -1081,7 +1081,6 @@ LoadElimination::AbstractState const* LoadElimination::ComputeLoopState( state = state->KillElement(object, index, zone()); break; } - case IrOpcode::kStoreBuffer: case IrOpcode::kStoreTypedElement: { // Doesn't affect anything we track with the state currently. break; diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index 5a8c98467b..146a4ced2e 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -338,11 +338,9 @@ V(ConvertTaggedHoleToUndefined) \ V(Allocate) \ V(LoadField) \ - V(LoadBuffer) \ V(LoadElement) \ V(LoadTypedElement) \ V(StoreField) \ - V(StoreBuffer) \ V(StoreElement) \ V(StoreTypedElement) \ V(TransitionAndStoreElement) \ diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 346ea727f6..6638bff26c 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -2492,53 +2492,6 @@ class RepresentationSelector { } return; } - case IrOpcode::kLoadBuffer: { - if (truncation.IsUnused()) return VisitUnused(node); - BufferAccess access = BufferAccessOf(node->op()); - ProcessInput(node, 0, UseInfo::PointerInt()); // buffer - ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset - ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length - ProcessRemainingInputs(node, 3); - - MachineRepresentation output; - if (truncation.IdentifiesUndefinedAndNaN()) { - if (truncation.IdentifiesUndefinedAndZero()) { - // If undefined is truncated to a non-NaN number, we can use - // the load's representation. - output = access.machine_type().representation(); - } else { - // If undefined is truncated to a number, but the use can - // observe NaN, we need to output at least the float32 - // representation. - if (access.machine_type().representation() == - MachineRepresentation::kFloat32) { - output = access.machine_type().representation(); - } else { - output = MachineRepresentation::kFloat64; - } - } - } else { - // If undefined is not truncated away, we need to have the tagged - // representation. - output = MachineRepresentation::kTagged; - } - SetOutput(node, output); - if (lower()) lowering->DoLoadBuffer(node, output, changer_); - return; - } - case IrOpcode::kStoreBuffer: { - BufferAccess access = BufferAccessOf(node->op()); - ProcessInput(node, 0, UseInfo::PointerInt()); // buffer - ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset - ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length - ProcessInput(node, 3, - TruncatingUseInfoFromRepresentation( - access.machine_type().representation())); // value - ProcessRemainingInputs(node, 4); - SetOutput(node, MachineRepresentation::kNone); - if (lower()) lowering->DoStoreBuffer(node); - return; - } case IrOpcode::kLoadElement: { if (truncation.IsUnused()) return VisitUnused(node); ElementAccess access = ElementAccessOf(node->op()); @@ -3220,75 +3173,6 @@ void SimplifiedLowering::DoJSToNumberTruncatesToWord32( selector->DeferReplacement(node, value); } -void SimplifiedLowering::DoLoadBuffer(Node* node, - MachineRepresentation output_rep, - RepresentationChanger* changer) { - DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode()); - DCHECK_NE(MachineRepresentation::kNone, output_rep); - MachineType const access_type = BufferAccessOf(node->op()).machine_type(); - if (output_rep != access_type.representation()) { - Node* const buffer = node->InputAt(0); - Node* const offset = node->InputAt(1); - Node* const length = node->InputAt(2); - Node* const effect = node->InputAt(3); - Node* const control = node->InputAt(4); - Node* const index = - machine()->Is64() - ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset) - : offset; - - Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); - Node* branch = - graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); - - Node* if_true = graph()->NewNode(common()->IfTrue(), branch); - Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index, - effect, if_true); - Type* element_type = - Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone()); - Node* vtrue = changer->GetRepresentationFor( - etrue, access_type.representation(), element_type, node, - UseInfo(output_rep, Truncation::None())); - - Node* if_false = graph()->NewNode(common()->IfFalse(), branch); - Node* efalse = effect; - Node* vfalse; - if (output_rep == MachineRepresentation::kTagged) { - vfalse = jsgraph()->UndefinedConstant(); - } else if (output_rep == MachineRepresentation::kFloat64) { - vfalse = - jsgraph()->Float64Constant(std::numeric_limits::quiet_NaN()); - } else if (output_rep == MachineRepresentation::kFloat32) { - vfalse = - jsgraph()->Float32Constant(std::numeric_limits::quiet_NaN()); - } else { - vfalse = jsgraph()->Int32Constant(0); - } - - Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); - Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); - - // Replace effect uses of {node} with the {ephi}. - NodeProperties::ReplaceUses(node, node, ephi); - - // Turn the {node} into a Phi. - node->ReplaceInput(0, vtrue); - node->ReplaceInput(1, vfalse); - node->ReplaceInput(2, merge); - node->TrimInputCount(3); - NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2)); - } else { - NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type)); - } -} - -void SimplifiedLowering::DoStoreBuffer(Node* node) { - DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode()); - MachineRepresentation const rep = - BufferAccessOf(node->op()).machine_type().representation(); - NodeProperties::ChangeOp(node, machine()->CheckedStore(rep)); -} - Node* SimplifiedLowering::Float64Round(Node* const node) { Node* const one = jsgraph()->Float64Constant(1.0); Node* const one_half = jsgraph()->Float64Constant(0.5); diff --git a/src/compiler/simplified-lowering.h b/src/compiler/simplified-lowering.h index 09e58ff18a..22fb77f8fa 100644 --- a/src/compiler/simplified-lowering.h +++ b/src/compiler/simplified-lowering.h @@ -34,11 +34,6 @@ class SimplifiedLowering final { RepresentationSelector* selector); void DoJSToNumberTruncatesToWord32(Node* node, RepresentationSelector* selector); - // TODO(turbofan): The representation can be removed once the result of the - // representation analysis is stored in the node bounds. - void DoLoadBuffer(Node* node, MachineRepresentation rep, - RepresentationChanger* changer); - void DoStoreBuffer(Node* node); void DoShift(Node* node, Operator const* op, Type* rhs_type); void DoStringToNumber(Node* node); void DoIntegral32ToBit(Node* node); diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index e6f3491e2a..a31bda00ea 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -29,63 +29,6 @@ std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) { UNREACHABLE(); } - -MachineType BufferAccess::machine_type() const { - switch (external_array_type_) { - case kExternalUint8Array: - case kExternalUint8ClampedArray: - return MachineType::Uint8(); - case kExternalInt8Array: - return MachineType::Int8(); - case kExternalUint16Array: - return MachineType::Uint16(); - case kExternalInt16Array: - return MachineType::Int16(); - case kExternalUint32Array: - return MachineType::Uint32(); - case kExternalInt32Array: - return MachineType::Int32(); - case kExternalFloat32Array: - return MachineType::Float32(); - case kExternalFloat64Array: - return MachineType::Float64(); - } - UNREACHABLE(); -} - - -bool operator==(BufferAccess lhs, BufferAccess rhs) { - return lhs.external_array_type() == rhs.external_array_type(); -} - - -bool operator!=(BufferAccess lhs, BufferAccess rhs) { return !(lhs == rhs); } - - -size_t hash_value(BufferAccess access) { - return base::hash()(access.external_array_type()); -} - - -std::ostream& operator<<(std::ostream& os, BufferAccess access) { - switch (access.external_array_type()) { -#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ - case kExternal##Type##Array: \ - return os << #Type; - TYPED_ARRAYS(TYPED_ARRAY_CASE) -#undef TYPED_ARRAY_CASE - } - UNREACHABLE(); -} - - -BufferAccess const BufferAccessOf(const Operator* op) { - DCHECK(op->opcode() == IrOpcode::kLoadBuffer || - op->opcode() == IrOpcode::kStoreBuffer); - return OpParameter(op); -} - - bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) { // On purpose we don't include the write barrier kind here, as this method is // really only relevant for eliminating loads and they don't care about the @@ -810,28 +753,6 @@ struct SimplifiedOperatorGlobalCache final { kSpeculativeToNumberNumberOperator; SpeculativeToNumberOperator kSpeculativeToNumberNumberOrOddballOperator; - -#define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \ - struct LoadBuffer##Type##Operator final : public Operator1 { \ - LoadBuffer##Type##Operator() \ - : Operator1( \ - IrOpcode::kLoadBuffer, \ - Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, \ - "LoadBuffer", 3, 1, 1, 1, 1, 0, \ - BufferAccess(kExternal##Type##Array)) {} \ - }; \ - struct StoreBuffer##Type##Operator final : public Operator1 { \ - StoreBuffer##Type##Operator() \ - : Operator1( \ - IrOpcode::kStoreBuffer, \ - Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow, \ - "StoreBuffer", 4, 1, 1, 0, 1, 0, \ - BufferAccess(kExternal##Type##Array)) {} \ - }; \ - LoadBuffer##Type##Operator kLoadBuffer##Type; \ - StoreBuffer##Type##Operator kStoreBuffer##Type; - TYPED_ARRAYS(BUFFER_ACCESS) -#undef BUFFER_ACCESS }; static base::LazyInstance::type @@ -1033,30 +954,6 @@ const Operator* SimplifiedOperatorBuilder::Allocate(Type* type, 1, 1, 1, 1, 1, 0, AllocateParameters(type, pretenure)); } - -const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) { - switch (access.external_array_type()) { -#define LOAD_BUFFER(Type, type, TYPE, ctype, size) \ - case kExternal##Type##Array: \ - return &cache_.kLoadBuffer##Type; - TYPED_ARRAYS(LOAD_BUFFER) -#undef LOAD_BUFFER - } - UNREACHABLE(); -} - - -const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) { - switch (access.external_array_type()) { -#define STORE_BUFFER(Type, type, TYPE, ctype, size) \ - case kExternal##Type##Array: \ - return &cache_.kStoreBuffer##Type; - TYPED_ARRAYS(STORE_BUFFER) -#undef STORE_BUFFER - } - UNREACHABLE(); -} - const Operator* SimplifiedOperatorBuilder::StringFromCodePoint( UnicodeEncoding encoding) { switch (encoding) { diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index cd7d5e2ce2..90e6894842 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -34,30 +34,6 @@ size_t hash_value(BaseTaggedness); std::ostream& operator<<(std::ostream&, BaseTaggedness); - -// An access descriptor for loads/stores of array buffers. -class BufferAccess final { - public: - explicit BufferAccess(ExternalArrayType external_array_type) - : external_array_type_(external_array_type) {} - - ExternalArrayType external_array_type() const { return external_array_type_; } - MachineType machine_type() const; - - private: - ExternalArrayType const external_array_type_; -}; - -V8_EXPORT_PRIVATE bool operator==(BufferAccess, BufferAccess); -bool operator!=(BufferAccess, BufferAccess); - -size_t hash_value(BufferAccess); - -V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BufferAccess); - -V8_EXPORT_PRIVATE BufferAccess const BufferAccessOf(const Operator* op) - WARN_UNUSED_RESULT; - // An access descriptor for loads/stores of fixed structures like field // accesses of heap objects. Accesses from either tagged or untagged base // pointers are supported; untagging is done automatically during lowering. @@ -486,12 +462,6 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final const Operator* LoadField(FieldAccess const&); const Operator* StoreField(FieldAccess const&); - // load-buffer buffer, offset, length - const Operator* LoadBuffer(BufferAccess); - - // store-buffer buffer, offset, length, value - const Operator* StoreBuffer(BufferAccess); - // load-element [base + index] const Operator* LoadElement(ElementAccess const&); diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index cb5a71a9cc..3012068240 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -1911,18 +1911,6 @@ Type* Typer::Visitor::TypeLoadField(Node* node) { return FieldAccessOf(node->op()).type; } -Type* Typer::Visitor::TypeLoadBuffer(Node* node) { - switch (BufferAccessOf(node->op()).external_array_type()) { -#define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype, size) \ - case kExternal##ElemType##Array: \ - return Type::Union(typer_->cache_.k##ElemType, Type::Undefined(), zone()); - TYPED_ARRAYS(TYPED_ARRAY_CASE) -#undef TYPED_ARRAY_CASE - } - UNREACHABLE(); -} - - Type* Typer::Visitor::TypeLoadElement(Node* node) { return ElementAccessOf(node->op()).type; } @@ -1942,12 +1930,6 @@ Type* Typer::Visitor::TypeStoreField(Node* node) { UNREACHABLE(); } - -Type* Typer::Visitor::TypeStoreBuffer(Node* node) { - UNREACHABLE(); -} - - Type* Typer::Visitor::TypeStoreElement(Node* node) { UNREACHABLE(); } diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index 47801b0d3d..5864c87ec7 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -1252,8 +1252,6 @@ void Verifier::Visitor::Check(Node* node) { // CheckValueInputIs(node, 0, Type::Object()); // CheckTypeIs(node, FieldAccessOf(node->op()).type)); break; - case IrOpcode::kLoadBuffer: - break; case IrOpcode::kLoadElement: // Object -> elementtype // TODO(rossberg): activate once machine ops are typed. @@ -1269,8 +1267,6 @@ void Verifier::Visitor::Check(Node* node) { // CheckValueInputIs(node, 1, FieldAccessOf(node->op()).type)); CheckNotTyped(node); break; - case IrOpcode::kStoreBuffer: - break; case IrOpcode::kStoreElement: // (Object, elementtype) -> _|_ // TODO(rossberg): activate once machine ops are typed. diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 08ca5066e8..89c8c26d43 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -25403,46 +25403,6 @@ TEST(StringConcatOverflow) { } -TEST(TurboAsmDisablesNeuter) { - i::FLAG_opt = true; - i::FLAG_allow_natives_syntax = true; - v8::V8::Initialize(); - v8::HandleScope scope(CcTest::isolate()); - LocalContext context; - const char* load = - "function Module(stdlib, foreign, heap) {" - " 'use asm';" - " var MEM32 = new stdlib.Int32Array(heap);" - " function load() { return MEM32[0]; }" - " return { load: load };" - "}" - "var buffer = new ArrayBuffer(4);" - "var module = Module(this, {}, buffer);" - "%OptimizeFunctionOnNextCall(module.load);" - "module.load();" - "buffer"; - - v8::Local result = CompileRun(load).As(); - CHECK(!result->IsNeuterable()); - - const char* store = - "function Module(stdlib, foreign, heap) {" - " 'use asm';" - " var MEM32 = new stdlib.Int32Array(heap);" - " function store() { MEM32[0] = 0; }" - " return { store: store };" - "}" - "var buffer = new ArrayBuffer(4);" - "var module = Module(this, {}, buffer);" - "%OptimizeFunctionOnNextCall(module.store);" - "module.store();" - "buffer"; - - result = CompileRun(store).As(); - CHECK(!result->IsNeuterable()); -} - - TEST(GetPrototypeAccessControl) { i::FLAG_allow_natives_syntax = true; v8::Isolate* isolate = CcTest::isolate(); diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc index 3b49ded496..527a2de552 100644 --- a/test/unittests/compiler/js-typed-lowering-unittest.cc +++ b/test/unittests/compiler/js-typed-lowering-unittest.cc @@ -28,19 +28,11 @@ namespace compiler { namespace { -const ExternalArrayType kExternalArrayTypes[] = { - kExternalUint8Array, kExternalInt8Array, kExternalUint16Array, - kExternalInt16Array, kExternalUint32Array, kExternalInt32Array, - kExternalFloat32Array, kExternalFloat64Array}; - const size_t kIndices[] = {0, 1, 42, 100, 1024}; Type* const kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(), Type::Number(), Type::String(), Type::Object()}; -STATIC_ASSERT(LANGUAGE_END == 2); -const LanguageMode kLanguageModes[] = {SLOPPY, STRICT}; - } // namespace @@ -449,212 +441,6 @@ TEST_F(JSTypedLoweringTest, JSStoreContext) { } -// ----------------------------------------------------------------------------- -// JSLoadProperty - - -TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) { - const size_t kLength = 17; - double backing_store[kLength]; - Handle buffer = - NewArrayBuffer(backing_store, sizeof(backing_store)); - VectorSlotPair feedback; - TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) { - Handle array = - factory()->NewJSTypedArray(type, buffer, 0, kLength); - int const element_size = static_cast(array->element_size()); - - Node* key = Parameter( - Type::Range(kMinInt / element_size, kMaxInt / element_size, zone())); - Node* base = HeapConstant(array); - Node* context = UndefinedConstant(); - Node* effect = graph()->start(); - Node* control = graph()->start(); - Reduction r = - Reduce(graph()->NewNode(javascript()->LoadProperty(feedback), base, key, - context, EmptyFrameState(), effect, control)); - - Matcher offset_matcher = - element_size == 1 - ? key - : IsNumberShiftLeft(key, - IsNumberConstant(WhichPowerOf2(element_size))); - - ASSERT_TRUE(r.Changed()); - EXPECT_THAT( - r.replacement(), - IsLoadBuffer(BufferAccess(type), - IsPointerConstant(bit_cast(&backing_store[0])), - offset_matcher, - IsNumberConstant(array->byte_length()->Number()), effect, - control)); - } -} - - -TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) { - const size_t kLength = 17; - double backing_store[kLength]; - Handle buffer = - NewArrayBuffer(backing_store, sizeof(backing_store)); - VectorSlotPair feedback; - TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) { - Handle array = - factory()->NewJSTypedArray(type, buffer, 0, kLength); - ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true); - - int min = random_number_generator()->NextInt(static_cast(kLength)); - int max = random_number_generator()->NextInt(static_cast(kLength)); - if (min > max) std::swap(min, max); - Node* key = Parameter(Type::Range(min, max, zone())); - Node* base = HeapConstant(array); - Node* context = UndefinedConstant(); - Node* effect = graph()->start(); - Node* control = graph()->start(); - Reduction r = - Reduce(graph()->NewNode(javascript()->LoadProperty(feedback), base, key, - context, EmptyFrameState(), effect, control)); - - ASSERT_TRUE(r.Changed()); - EXPECT_THAT( - r.replacement(), - IsLoadElement(access, - IsPointerConstant(bit_cast(&backing_store[0])), - key, effect, control)); - } -} - - -// ----------------------------------------------------------------------------- -// JSStoreProperty - - -TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) { - const size_t kLength = 17; - double backing_store[kLength]; - Handle buffer = - NewArrayBuffer(backing_store, sizeof(backing_store)); - TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) { - TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Handle array = - factory()->NewJSTypedArray(type, buffer, 0, kLength); - int const element_size = static_cast(array->element_size()); - - Node* key = Parameter( - Type::Range(kMinInt / element_size, kMaxInt / element_size, zone())); - Node* base = HeapConstant(array); - Node* value = - Parameter(AccessBuilder::ForTypedArrayElement(type, true).type); - Node* context = UndefinedConstant(); - Node* effect = graph()->start(); - Node* control = graph()->start(); - VectorSlotPair feedback; - const Operator* op = javascript()->StoreProperty(language_mode, feedback); - Node* node = graph()->NewNode(op, base, key, value, context, - EmptyFrameState(), effect, control); - Reduction r = Reduce(node); - - Matcher offset_matcher = - element_size == 1 - ? key - : IsNumberShiftLeft( - key, IsNumberConstant(WhichPowerOf2(element_size))); - - ASSERT_TRUE(r.Changed()); - EXPECT_THAT( - r.replacement(), - IsStoreBuffer( - BufferAccess(type), - IsPointerConstant(bit_cast(&backing_store[0])), - offset_matcher, IsNumberConstant(array->byte_length()->Number()), - value, effect, control)); - } - } -} - - -TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) { - const size_t kLength = 17; - double backing_store[kLength]; - Handle buffer = - NewArrayBuffer(backing_store, sizeof(backing_store)); - TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) { - TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Handle array = - factory()->NewJSTypedArray(type, buffer, 0, kLength); - int const element_size = static_cast(array->element_size()); - - Node* key = Parameter( - Type::Range(kMinInt / element_size, kMaxInt / element_size, zone())); - Node* base = HeapConstant(array); - Node* value = Parameter(Type::PlainPrimitive()); - Node* context = UndefinedConstant(); - Node* effect = graph()->start(); - Node* control = graph()->start(); - VectorSlotPair feedback; - const Operator* op = javascript()->StoreProperty(language_mode, feedback); - Node* node = graph()->NewNode(op, base, key, value, context, - EmptyFrameState(), effect, control); - Reduction r = Reduce(node); - - Matcher offset_matcher = - element_size == 1 - ? key - : IsNumberShiftLeft( - key, IsNumberConstant(WhichPowerOf2(element_size))); - - Matcher value_matcher = IsPlainPrimitiveToNumber(value); - - ASSERT_TRUE(r.Changed()); - EXPECT_THAT( - r.replacement(), - IsStoreBuffer( - BufferAccess(type), - IsPointerConstant(bit_cast(&backing_store[0])), - offset_matcher, IsNumberConstant(array->byte_length()->Number()), - value_matcher, effect, control)); - } - } -} - - -TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) { - const size_t kLength = 17; - double backing_store[kLength]; - Handle buffer = - NewArrayBuffer(backing_store, sizeof(backing_store)); - TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) { - TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Handle array = - factory()->NewJSTypedArray(type, buffer, 0, kLength); - ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true); - - int min = random_number_generator()->NextInt(static_cast(kLength)); - int max = random_number_generator()->NextInt(static_cast(kLength)); - if (min > max) std::swap(min, max); - Node* key = Parameter(Type::Range(min, max, zone())); - Node* base = HeapConstant(array); - Node* value = Parameter(access.type); - Node* context = UndefinedConstant(); - Node* effect = graph()->start(); - Node* control = graph()->start(); - VectorSlotPair feedback; - const Operator* op = javascript()->StoreProperty(language_mode, feedback); - Node* node = graph()->NewNode(op, base, key, value, context, - EmptyFrameState(), effect, control); - Reduction r = Reduce(node); - - ASSERT_TRUE(r.Changed()); - EXPECT_THAT( - r.replacement(), - IsStoreElement( - access, IsPointerConstant(bit_cast(&backing_store[0])), - key, value, effect, control)); - } - } -} - - // ----------------------------------------------------------------------------- // JSLoadNamed diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc index 764a4da2d7..0e903f9c76 100644 --- a/test/unittests/compiler/node-test-utils.cc +++ b/test/unittests/compiler/node-test-utils.cc @@ -966,132 +966,6 @@ class IsStoreFieldMatcher final : public NodeMatcher { const Matcher control_matcher_; }; - -class IsLoadBufferMatcher final : public NodeMatcher { - public: - IsLoadBufferMatcher(const Matcher& access_matcher, - const Matcher& buffer_matcher, - const Matcher& offset_matcher, - const Matcher& length_matcher, - const Matcher& effect_matcher, - const Matcher& control_matcher) - : NodeMatcher(IrOpcode::kLoadBuffer), - access_matcher_(access_matcher), - buffer_matcher_(buffer_matcher), - offset_matcher_(offset_matcher), - length_matcher_(length_matcher), - effect_matcher_(effect_matcher), - control_matcher_(control_matcher) {} - - void DescribeTo(std::ostream* os) const final { - NodeMatcher::DescribeTo(os); - *os << " whose access ("; - access_matcher_.DescribeTo(os); - *os << "), buffer ("; - buffer_matcher_.DescribeTo(os); - *os << "), offset ("; - offset_matcher_.DescribeTo(os); - *os << "), length ("; - length_matcher_.DescribeTo(os); - *os << "), effect ("; - effect_matcher_.DescribeTo(os); - *os << ") and control ("; - control_matcher_.DescribeTo(os); - *os << ")"; - } - - bool MatchAndExplain(Node* node, MatchResultListener* listener) const final { - return (NodeMatcher::MatchAndExplain(node, listener) && - PrintMatchAndExplain(BufferAccessOf(node->op()), "access", - access_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), - "buffer", buffer_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), - "offset", offset_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2), - "length", length_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", - effect_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetControlInput(node), - "control", control_matcher_, listener)); - } - - private: - const Matcher access_matcher_; - const Matcher buffer_matcher_; - const Matcher offset_matcher_; - const Matcher length_matcher_; - const Matcher effect_matcher_; - const Matcher control_matcher_; -}; - - -class IsStoreBufferMatcher final : public NodeMatcher { - public: - IsStoreBufferMatcher(const Matcher& access_matcher, - const Matcher& buffer_matcher, - const Matcher& offset_matcher, - const Matcher& length_matcher, - const Matcher& value_matcher, - const Matcher& effect_matcher, - const Matcher& control_matcher) - : NodeMatcher(IrOpcode::kStoreBuffer), - access_matcher_(access_matcher), - buffer_matcher_(buffer_matcher), - offset_matcher_(offset_matcher), - length_matcher_(length_matcher), - value_matcher_(value_matcher), - effect_matcher_(effect_matcher), - control_matcher_(control_matcher) {} - - void DescribeTo(std::ostream* os) const final { - NodeMatcher::DescribeTo(os); - *os << " whose access ("; - access_matcher_.DescribeTo(os); - *os << "), buffer ("; - buffer_matcher_.DescribeTo(os); - *os << "), offset ("; - offset_matcher_.DescribeTo(os); - *os << "), length ("; - length_matcher_.DescribeTo(os); - *os << "), value ("; - value_matcher_.DescribeTo(os); - *os << "), effect ("; - effect_matcher_.DescribeTo(os); - *os << ") and control ("; - control_matcher_.DescribeTo(os); - *os << ")"; - } - - bool MatchAndExplain(Node* node, MatchResultListener* listener) const final { - return (NodeMatcher::MatchAndExplain(node, listener) && - PrintMatchAndExplain(BufferAccessOf(node->op()), "access", - access_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), - "buffer", buffer_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), - "offset", offset_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2), - "length", length_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 3), - "value", value_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", - effect_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetControlInput(node), - "control", control_matcher_, listener)); - } - - private: - const Matcher access_matcher_; - const Matcher buffer_matcher_; - const Matcher offset_matcher_; - const Matcher length_matcher_; - const Matcher value_matcher_; - const Matcher effect_matcher_; - const Matcher control_matcher_; -}; - - class IsLoadElementMatcher final : public NodeMatcher { public: IsLoadElementMatcher(const Matcher& access_matcher, @@ -2088,32 +1962,6 @@ Matcher IsStoreField(const Matcher& access_matcher, control_matcher)); } - -Matcher IsLoadBuffer(const Matcher& access_matcher, - const Matcher& buffer_matcher, - const Matcher& offset_matcher, - const Matcher& length_matcher, - const Matcher& effect_matcher, - const Matcher& control_matcher) { - return MakeMatcher(new IsLoadBufferMatcher(access_matcher, buffer_matcher, - offset_matcher, length_matcher, - effect_matcher, control_matcher)); -} - - -Matcher IsStoreBuffer(const Matcher& access_matcher, - const Matcher& buffer_matcher, - const Matcher& offset_matcher, - const Matcher& length_matcher, - const Matcher& value_matcher, - const Matcher& effect_matcher, - const Matcher& control_matcher) { - return MakeMatcher(new IsStoreBufferMatcher( - access_matcher, buffer_matcher, offset_matcher, length_matcher, - value_matcher, effect_matcher, control_matcher)); -} - - Matcher IsLoadElement(const Matcher& access_matcher, const Matcher& base_matcher, const Matcher& index_matcher, diff --git a/test/unittests/compiler/simplified-operator-unittest.cc b/test/unittests/compiler/simplified-operator-unittest.cc index d32dcaec12..d77c762ce6 100644 --- a/test/unittests/compiler/simplified-operator-unittest.cc +++ b/test/unittests/compiler/simplified-operator-unittest.cc @@ -122,81 +122,6 @@ INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest, ::testing::ValuesIn(kPureOperators)); -// ----------------------------------------------------------------------------- -// Buffer access operators. - - -namespace { - -const ExternalArrayType kExternalArrayTypes[] = { - kExternalUint8Array, kExternalInt8Array, kExternalUint16Array, - kExternalInt16Array, kExternalUint32Array, kExternalInt32Array, - kExternalFloat32Array, kExternalFloat64Array}; - -} // namespace - - -class SimplifiedBufferAccessOperatorTest - : public TestWithZone, - public ::testing::WithParamInterface {}; - - -TEST_P(SimplifiedBufferAccessOperatorTest, InstancesAreGloballyShared) { - BufferAccess const access(GetParam()); - SimplifiedOperatorBuilder simplified1(zone()); - SimplifiedOperatorBuilder simplified2(zone()); - EXPECT_EQ(simplified1.LoadBuffer(access), simplified2.LoadBuffer(access)); - EXPECT_EQ(simplified1.StoreBuffer(access), simplified2.StoreBuffer(access)); -} - - -TEST_P(SimplifiedBufferAccessOperatorTest, LoadBuffer) { - SimplifiedOperatorBuilder simplified(zone()); - BufferAccess const access(GetParam()); - const Operator* op = simplified.LoadBuffer(access); - - EXPECT_EQ(IrOpcode::kLoadBuffer, op->opcode()); - EXPECT_EQ(Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, - op->properties()); - EXPECT_EQ(access, BufferAccessOf(op)); - - EXPECT_EQ(3, op->ValueInputCount()); - EXPECT_EQ(1, op->EffectInputCount()); - EXPECT_EQ(1, op->ControlInputCount()); - EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op)); - - EXPECT_EQ(1, op->ValueOutputCount()); - EXPECT_EQ(1, op->EffectOutputCount()); - EXPECT_EQ(0, op->ControlOutputCount()); -} - - -TEST_P(SimplifiedBufferAccessOperatorTest, StoreBuffer) { - SimplifiedOperatorBuilder simplified(zone()); - BufferAccess const access(GetParam()); - const Operator* op = simplified.StoreBuffer(access); - - EXPECT_EQ(IrOpcode::kStoreBuffer, op->opcode()); - EXPECT_EQ(Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow, - op->properties()); - EXPECT_EQ(access, BufferAccessOf(op)); - - EXPECT_EQ(4, op->ValueInputCount()); - EXPECT_EQ(1, op->EffectInputCount()); - EXPECT_EQ(1, op->ControlInputCount()); - EXPECT_EQ(6, OperatorProperties::GetTotalInputCount(op)); - - EXPECT_EQ(0, op->ValueOutputCount()); - EXPECT_EQ(1, op->EffectOutputCount()); - EXPECT_EQ(0, op->ControlOutputCount()); -} - - -INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, - SimplifiedBufferAccessOperatorTest, - ::testing::ValuesIn(kExternalArrayTypes)); - - // ----------------------------------------------------------------------------- // Element access operators.