| Index: test/unittests/compiler/js-typed-lowering-unittest.cc
|
| diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3f3506ff63183d93847c6cb38f36837fab1ece49
|
| --- /dev/null
|
| +++ b/test/unittests/compiler/js-typed-lowering-unittest.cc
|
| @@ -0,0 +1,164 @@
|
| +// Copyright 2014 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "src/compiler/access-builder.h"
|
| +#include "src/compiler/js-graph.h"
|
| +#include "src/compiler/js-operator.h"
|
| +#include "src/compiler/js-typed-lowering.h"
|
| +#include "src/compiler/machine-operator.h"
|
| +#include "src/compiler/node-properties-inl.h"
|
| +#include "src/compiler/typer.h"
|
| +#include "test/unittests/compiler/compiler-test-utils.h"
|
| +#include "test/unittests/compiler/graph-unittest.h"
|
| +#include "testing/gmock-support.h"
|
| +
|
| +using testing::_;
|
| +using testing::AllOf;
|
| +using testing::Capture;
|
| +using testing::CaptureEq;
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +namespace compiler {
|
| +
|
| +namespace {
|
| +
|
| +const ExternalArrayType kExternalArrayTypes[] = {
|
| +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) kExternal##Type##Array,
|
| + TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
| +#undef TYPED_ARRAY_CASE
|
| +};
|
| +
|
| +
|
| +const StrictMode kStrictModes[] = {SLOPPY, STRICT};
|
| +
|
| +} // namespace
|
| +
|
| +
|
| +class JSTypedLoweringTest : public GraphTest {
|
| + public:
|
| + JSTypedLoweringTest() : GraphTest(3), javascript_(zone()) {}
|
| + virtual ~JSTypedLoweringTest() {}
|
| +
|
| + protected:
|
| + Reduction Reduce(Node* node) {
|
| + Typer typer(zone());
|
| + MachineOperatorBuilder machine;
|
| + JSGraph jsgraph(graph(), common(), javascript(), &typer, &machine);
|
| + JSTypedLowering reducer(&jsgraph);
|
| + return reducer.Reduce(node);
|
| + }
|
| +
|
| + Node* Parameter(Type* type, int index = 0) {
|
| + Node* node = graph()->NewNode(common()->Parameter(index), graph()->start());
|
| + NodeProperties::SetBounds(node, Bounds(Type::None(), type));
|
| + return node;
|
| + }
|
| +
|
| + Handle<JSArrayBuffer> NewArrayBuffer(void* bytes, size_t byte_length) {
|
| + Handle<JSArrayBuffer> buffer = factory()->NewJSArrayBuffer();
|
| + Runtime::SetupArrayBuffer(isolate(), buffer, true, bytes, byte_length);
|
| + return buffer;
|
| + }
|
| +
|
| + JSOperatorBuilder* javascript() { return &javascript_; }
|
| +
|
| + private:
|
| + JSOperatorBuilder javascript_;
|
| +};
|
| +
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +// JSLoadProperty
|
| +
|
| +
|
| +TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
|
| + const size_t kLength = 17;
|
| + uint8_t backing_store[kLength * 8];
|
| + Handle<JSArrayBuffer> buffer =
|
| + NewArrayBuffer(backing_store, arraysize(backing_store));
|
| + TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
|
| + Handle<JSTypedArray> array =
|
| + factory()->NewJSTypedArray(type, buffer, kLength);
|
| +
|
| + Node* key = Parameter(Type::Integral32());
|
| + Node* base = HeapConstant(array);
|
| + Node* context = UndefinedConstant();
|
| + Node* effect = graph()->start();
|
| + Node* control = graph()->start();
|
| + Node* node =
|
| + graph()->NewNode(javascript()->LoadProperty(), base, key, context);
|
| + if (FLAG_turbo_deoptimization) {
|
| + node->AppendInput(zone(), UndefinedConstant());
|
| + }
|
| + node->AppendInput(zone(), effect);
|
| + node->AppendInput(zone(), control);
|
| + Reduction r = Reduce(node);
|
| +
|
| + Capture<Node*> elements;
|
| + ASSERT_TRUE(r.Changed());
|
| + EXPECT_THAT(
|
| + r.replacement(),
|
| + IsLoadElement(
|
| + AccessBuilder::ForTypedArrayElement(type, true),
|
| + IsLoadField(AccessBuilder::ForExternalArrayPointer(),
|
| + AllOf(CaptureEq(&elements),
|
| + IsLoadField(AccessBuilder::ForJSObjectElements(),
|
| + base, _)),
|
| + CaptureEq(&elements)),
|
| + key, IsInt32Constant(static_cast<int>(kLength)), effect, control));
|
| + }
|
| +}
|
| +
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +// JSStoreProperty
|
| +
|
| +
|
| +TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
|
| + const size_t kLength = 17;
|
| + uint8_t backing_store[kLength * 8];
|
| + Handle<JSArrayBuffer> buffer =
|
| + NewArrayBuffer(backing_store, arraysize(backing_store));
|
| + TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
|
| + TRACED_FOREACH(StrictMode, strict_mode, kStrictModes) {
|
| + Handle<JSTypedArray> array =
|
| + factory()->NewJSTypedArray(type, buffer, kLength);
|
| +
|
| + Node* key = Parameter(Type::Integral32());
|
| + Node* base = HeapConstant(array);
|
| + Node* value = Parameter(Type::Any());
|
| + Node* context = UndefinedConstant();
|
| + Node* effect = graph()->start();
|
| + Node* control = graph()->start();
|
| + Node* node = graph()->NewNode(javascript()->StoreProperty(strict_mode),
|
| + base, key, value, context);
|
| + if (FLAG_turbo_deoptimization) {
|
| + node->AppendInput(zone(), UndefinedConstant());
|
| + }
|
| + node->AppendInput(zone(), effect);
|
| + node->AppendInput(zone(), control);
|
| + Reduction r = Reduce(node);
|
| +
|
| + Capture<Node*> elements;
|
| + ASSERT_TRUE(r.Changed());
|
| + EXPECT_THAT(
|
| + r.replacement(),
|
| + IsStoreElement(
|
| + AccessBuilder::ForTypedArrayElement(type, true),
|
| + IsLoadField(
|
| + AccessBuilder::ForExternalArrayPointer(),
|
| + AllOf(CaptureEq(&elements),
|
| + IsLoadField(AccessBuilder::ForJSObjectElements(), base,
|
| + _)),
|
| + CaptureEq(&elements)),
|
| + key, IsInt32Constant(static_cast<int>(kLength)), value, effect,
|
| + control));
|
| + }
|
| + }
|
| +}
|
| +
|
| +} // namespace compiler
|
| +} // namespace internal
|
| +} // namespace v8
|
|
|