// static
FieldAccess AccessBuilder::ForMap() {
- return {kTaggedBase, HeapObject::kMapOffset, MaybeHandle<Name>(), Type::Any(),
+ return {kTaggedBase, HeapObject::kMapOffset, Handle<Name>(), Type::Any(),
kMachAnyTagged};
}
// static
FieldAccess AccessBuilder::ForJSObjectProperties() {
- return {kTaggedBase, JSObject::kPropertiesOffset, MaybeHandle<Name>(),
- Type::Any(), kMachAnyTagged};
+ return {kTaggedBase, JSObject::kPropertiesOffset, Handle<Name>(), Type::Any(),
+ kMachAnyTagged};
}
// static
FieldAccess AccessBuilder::ForJSObjectElements() {
- return {kTaggedBase, JSObject::kElementsOffset, MaybeHandle<Name>(),
+ return {kTaggedBase, JSObject::kElementsOffset, Handle<Name>(),
Type::Internal(), kMachAnyTagged};
}
// static
FieldAccess AccessBuilder::ForJSFunctionContext() {
- return {kTaggedBase, JSFunction::kContextOffset, MaybeHandle<Name>(),
+ return {kTaggedBase, JSFunction::kContextOffset, Handle<Name>(),
Type::Internal(), kMachAnyTagged};
}
// static
FieldAccess AccessBuilder::ForJSArrayBufferBackingStore() {
- return {kTaggedBase, JSArrayBuffer::kBackingStoreOffset, MaybeHandle<Name>(),
+ return {kTaggedBase, JSArrayBuffer::kBackingStoreOffset, Handle<Name>(),
Type::UntaggedPtr(), kMachPtr};
}
// static
FieldAccess AccessBuilder::ForExternalArrayPointer() {
- return {kTaggedBase, ExternalArray::kExternalPointerOffset,
- MaybeHandle<Name>(), Type::UntaggedPtr(), kMachPtr};
+ return {kTaggedBase, ExternalArray::kExternalPointerOffset, Handle<Name>(),
+ Type::UntaggedPtr(), kMachPtr};
}
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.
- // b) The index is out of bounds.
+ // a) The typed array turns external (i.e. MaterializeArrayBuffer)
+ // b) The typed array or it's buffer is neutered.
+ // c) The index is out of bounds.
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())) {
- Handle<JSArrayBuffer> buffer =
- handle(JSArrayBuffer::cast(array->buffer()));
- ExternalArrayType type = array->type();
- uint32_t length;
- CHECK(array->length()->ToUint32(&length));
- Node* elements =
- graph()->NewNode(simplified()->LoadField(
- AccessBuilder::ForJSArrayBufferBackingStore()),
- jsgraph()->HeapConstant(buffer), graph()->start());
- Node* effect = NodeProperties::GetEffectInput(node);
- Node* control = NodeProperties::GetControlInput(node);
- node->set_op(simplified()->LoadElement(
- AccessBuilder::ForTypedArrayElement(type, true)));
- node->ReplaceInput(0, elements);
- node->ReplaceInput(2, jsgraph()->Uint32Constant(length));
- node->ReplaceInput(3, effect);
- node->ReplaceInput(4, control);
- node->TrimInputCount(5);
- return Changed(node);
+ JSTypedArray* array = JSTypedArray::cast(*base_type->AsConstant()->Value());
+ ElementsKind elements_kind = array->map()->elements_kind();
+ ExternalArrayType type = array->type();
+ uint32_t length;
+ CHECK(array->length()->ToUint32(&length));
+ ElementAccess element_access;
+ Node* elements = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForJSObjectElements()), base,
+ NodeProperties::GetEffectInput(node));
+ if (IsExternalArrayElementsKind(elements_kind)) {
+ elements = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForExternalArrayPointer()),
+ elements, NodeProperties::GetEffectInput(node));
+ element_access = AccessBuilder::ForTypedArrayElement(type, true);
+ } else {
+ DCHECK(IsFixedTypedArrayElementsKind(elements_kind));
+ element_access = AccessBuilder::ForTypedArrayElement(type, false);
}
+ Node* value = graph()->NewNode(
+ simplified()->LoadElement(element_access), elements, key,
+ jsgraph()->Uint32Constant(length), NodeProperties::GetEffectInput(node),
+ NodeProperties::GetControlInput(node));
+ return ReplaceEagerly(node, value);
}
return NoChange();
}
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.
+ // a) The typed array turns external (i.e. MaterializeArrayBuffer)
+ // b) The typed array or its buffer is neutered.
if (key_type->Is(Type::Integral32()) && base_type->IsConstant() &&
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())) {
- Handle<JSArrayBuffer> buffer =
- handle(JSArrayBuffer::cast(array->buffer()));
- ExternalArrayType type = array->type();
- uint32_t length;
- CHECK(array->length()->ToUint32(&length));
- Node* elements =
- graph()->NewNode(simplified()->LoadField(
- AccessBuilder::ForJSArrayBufferBackingStore()),
- jsgraph()->HeapConstant(buffer), graph()->start());
- Node* effect = NodeProperties::GetEffectInput(node);
- Node* control = NodeProperties::GetControlInput(node);
- node->set_op(simplified()->StoreElement(
- AccessBuilder::ForTypedArrayElement(type, true)));
- node->ReplaceInput(0, elements);
- node->ReplaceInput(2, jsgraph()->Uint32Constant(length));
- node->ReplaceInput(3, value);
- node->ReplaceInput(4, effect);
- node->ReplaceInput(5, control);
- node->TrimInputCount(6);
- return Changed(node);
+ JSTypedArray* array = JSTypedArray::cast(*base_type->AsConstant()->Value());
+ ElementsKind elements_kind = array->map()->elements_kind();
+ ExternalArrayType type = array->type();
+ uint32_t length;
+ CHECK(array->length()->ToUint32(&length));
+ ElementAccess element_access;
+ Node* elements = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForJSObjectElements()), base,
+ NodeProperties::GetEffectInput(node));
+ if (IsExternalArrayElementsKind(elements_kind)) {
+ elements = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForExternalArrayPointer()),
+ elements, NodeProperties::GetEffectInput(node));
+ element_access = AccessBuilder::ForTypedArrayElement(type, true);
+ } else {
+ DCHECK(IsFixedTypedArrayElementsKind(elements_kind));
+ element_access = AccessBuilder::ForTypedArrayElement(type, false);
}
+ Node* store =
+ graph()->NewNode(simplified()->StoreElement(element_access), elements,
+ key, jsgraph()->Uint32Constant(length), value,
+ NodeProperties::GetEffectInput(node),
+ NodeProperties::GetControlInput(node));
+ return ReplaceEagerly(node, store);
}
return NoChange();
}
}
-bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
- return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
- lhs.type == rhs.type && lhs.machine_type == rhs.machine_type;
-}
-
-
-bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) {
- return !(lhs == rhs);
-}
-
-
-std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
- os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
-#ifdef OBJECT_PRINT
- Handle<Name> name;
- if (access.name.ToHandle(&name)) {
- name->Print(os);
- os << ", ";
- }
-#endif
- access.type->PrintTo(os);
- os << ", " << access.machine_type << "]";
- return os;
-}
-
-
std::ostream& operator<<(std::ostream& os, BoundsCheckMode bounds_check_mode) {
switch (bounds_check_mode) {
case kNoBoundsCheck:
struct FieldAccess {
BaseTaggedness base_is_tagged; // specifies if the base pointer is tagged.
int offset; // offset of the field, without tag.
- MaybeHandle<Name> name; // debugging only.
+ Handle<Name> name; // debugging only.
Type* type; // type of the field.
MachineType machine_type; // machine type of the field.
int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
};
-bool operator==(FieldAccess const& lhs, FieldAccess const& rhs);
-bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs);
-
-std::ostream& operator<<(std::ostream&, FieldAccess const&);
-
enum BoundsCheckMode { kNoBoundsCheck, kTypedArrayBoundsCheck };
}
-namespace {
-
-ElementsKind GetExternalArrayElementsKind(ExternalArrayType type) {
- switch (type) {
-#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
- case kExternal##Type##Array: \
- return EXTERNAL_##TYPE##_ELEMENTS;
- TYPED_ARRAYS(TYPED_ARRAY_CASE)
- }
- UNREACHABLE();
- return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
-#undef TYPED_ARRAY_CASE
-}
-
-
-JSFunction* GetTypedArrayFun(ExternalArrayType type, Isolate* isolate) {
+static JSFunction* GetTypedArrayFun(ExternalArrayType type, Isolate* isolate) {
Context* native_context = isolate->context()->native_context();
switch (type) {
#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype, size) \
}
}
-} // namespace
-
Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type) {
Handle<JSFunction> typed_array_fun_handle(GetTypedArrayFun(type, isolate()));
}
-Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
- Handle<JSArrayBuffer> buffer,
- size_t length) {
- DCHECK(length <= static_cast<size_t>(kMaxInt));
- Handle<JSTypedArray> array = NewJSTypedArray(type);
- array->set_buffer(*buffer);
- array->set_weak_next(buffer->weak_first_view());
- buffer->set_weak_first_view(*array);
- array->set_byte_offset(Smi::FromInt(0));
- array->set_byte_length(buffer->byte_length());
- Handle<Object> length_handle = NewNumberFromSize(length);
- array->set_length(*length_handle);
- Handle<ExternalArray> elements =
- NewExternalArray(static_cast<int>(length), type, buffer->backing_store());
- JSObject::SetMapAndElements(array,
- JSObject::GetElementsTransitionMap(
- array, GetExternalArrayElementsKind(type)),
- elements);
- return array;
-}
-
-
Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler,
Handle<Object> prototype) {
// Allocate map.
Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type);
- // Creates a new JSTypedArray with the specified buffer.
- Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type,
- Handle<JSArrayBuffer> buffer,
- size_t length);
-
Handle<JSDataView> NewJSDataView();
// Allocates a Harmony proxy.
// Convert to a Handle with a type that can be upcasted to.
template <class S>
- V8_INLINE bool ToHandle(Handle<S>* out) const {
+ INLINE(bool ToHandle(Handle<S>* out)) {
if (location_ == NULL) {
*out = Handle<T>::null();
return false;
#include <ostream> // NOLINT(readability/streams)
#include "src/compiler/node-properties-inl.h"
-#include "src/compiler/simplified-operator.h"
using testing::_;
using testing::MakeMatcher;
}
-Node* GraphTest::HeapConstant(const Handle<HeapObject>& value) {
- return HeapConstant(Unique<HeapObject>::CreateUninitialized(value));
-}
-
-
Node* GraphTest::HeapConstant(const Unique<HeapObject>& value) {
- Node* node = graph()->NewNode(common()->HeapConstant(value));
- Type* type = Type::Constant(value.handle(), zone());
- NodeProperties::SetBounds(node, Bounds(type));
- return node;
+ return graph()->NewNode(common()->HeapConstant(value));
}
}
-Node* GraphTest::UndefinedConstant() {
- return HeapConstant(
- Unique<HeapObject>::CreateImmovable(factory()->undefined_value()));
-}
-
-
Matcher<Node*> GraphTest::IsFalseConstant() {
return IsHeapConstant(
Unique<HeapObject>::CreateImmovable(factory()->false_value()));
};
-class IsLoadFieldMatcher FINAL : public NodeMatcher {
- public:
- IsLoadFieldMatcher(const Matcher<FieldAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& effect_matcher)
- : NodeMatcher(IrOpcode::kLoadField),
- access_matcher_(access_matcher),
- base_matcher_(base_matcher),
- effect_matcher_(effect_matcher) {}
-
- virtual void DescribeTo(std::ostream* os) const OVERRIDE {
- NodeMatcher::DescribeTo(os);
- *os << " whose access (";
- access_matcher_.DescribeTo(os);
- *os << "), base (";
- base_matcher_.DescribeTo(os);
- *os << ") and effect (";
- effect_matcher_.DescribeTo(os);
- *os << ")";
- }
-
- virtual bool MatchAndExplain(Node* node,
- MatchResultListener* listener) const OVERRIDE {
- return (NodeMatcher::MatchAndExplain(node, listener) &&
- PrintMatchAndExplain(OpParameter<FieldAccess>(node), "access",
- access_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
- base_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
- effect_matcher_, listener));
- }
-
- private:
- const Matcher<FieldAccess> access_matcher_;
- const Matcher<Node*> base_matcher_;
- const Matcher<Node*> effect_matcher_;
-};
-
-
-class IsLoadElementMatcher FINAL : public NodeMatcher {
- public:
- IsLoadElementMatcher(const Matcher<ElementAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& length_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher)
- : NodeMatcher(IrOpcode::kLoadElement),
- access_matcher_(access_matcher),
- base_matcher_(base_matcher),
- index_matcher_(index_matcher),
- length_matcher_(length_matcher),
- effect_matcher_(effect_matcher),
- control_matcher_(control_matcher) {}
-
- virtual void DescribeTo(std::ostream* os) const OVERRIDE {
- NodeMatcher::DescribeTo(os);
- *os << " whose access (";
- access_matcher_.DescribeTo(os);
- *os << "), base (";
- base_matcher_.DescribeTo(os);
- *os << "), index (";
- index_matcher_.DescribeTo(os);
- *os << "), length (";
- length_matcher_.DescribeTo(os);
- *os << "), effect (";
- effect_matcher_.DescribeTo(os);
- *os << ") and control (";
- control_matcher_.DescribeTo(os);
- *os << ")";
- }
-
- virtual bool MatchAndExplain(Node* node,
- MatchResultListener* listener) const OVERRIDE {
- return (NodeMatcher::MatchAndExplain(node, listener) &&
- PrintMatchAndExplain(OpParameter<ElementAccess>(node), "access",
- access_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
- base_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
- "index", index_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<ElementAccess> access_matcher_;
- const Matcher<Node*> base_matcher_;
- const Matcher<Node*> index_matcher_;
- const Matcher<Node*> length_matcher_;
- const Matcher<Node*> effect_matcher_;
- const Matcher<Node*> control_matcher_;
-};
-
-
-class IsStoreElementMatcher FINAL : public NodeMatcher {
- public:
- IsStoreElementMatcher(const Matcher<ElementAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& length_matcher,
- const Matcher<Node*>& value_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher)
- : NodeMatcher(IrOpcode::kStoreElement),
- access_matcher_(access_matcher),
- base_matcher_(base_matcher),
- index_matcher_(index_matcher),
- length_matcher_(length_matcher),
- value_matcher_(value_matcher),
- effect_matcher_(effect_matcher),
- control_matcher_(control_matcher) {}
-
- virtual void DescribeTo(std::ostream* os) const OVERRIDE {
- NodeMatcher::DescribeTo(os);
- *os << " whose access (";
- access_matcher_.DescribeTo(os);
- *os << "), base (";
- base_matcher_.DescribeTo(os);
- *os << "), index (";
- index_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 << ")";
- }
-
- virtual bool MatchAndExplain(Node* node,
- MatchResultListener* listener) const OVERRIDE {
- return (NodeMatcher::MatchAndExplain(node, listener) &&
- PrintMatchAndExplain(OpParameter<ElementAccess>(node), "access",
- access_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
- base_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
- "index", index_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<ElementAccess> access_matcher_;
- const Matcher<Node*> base_matcher_;
- const Matcher<Node*> index_matcher_;
- const Matcher<Node*> length_matcher_;
- const Matcher<Node*> value_matcher_;
- const Matcher<Node*> effect_matcher_;
- const Matcher<Node*> control_matcher_;
-};
-
-
class IsLoadMatcher FINAL : public NodeMatcher {
public:
IsLoadMatcher(const Matcher<LoadRepresentation>& rep_matcher,
}
-Matcher<Node*> IsLoadField(const Matcher<FieldAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& effect_matcher) {
- return MakeMatcher(
- new IsLoadFieldMatcher(access_matcher, base_matcher, effect_matcher));
-}
-
-
-Matcher<Node*> IsLoadElement(const Matcher<ElementAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& length_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher) {
- return MakeMatcher(new IsLoadElementMatcher(access_matcher, base_matcher,
- index_matcher, length_matcher,
- effect_matcher, control_matcher));
-}
-
-
-Matcher<Node*> IsStoreElement(const Matcher<ElementAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& length_matcher,
- const Matcher<Node*>& value_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher) {
- return MakeMatcher(new IsStoreElementMatcher(
- access_matcher, base_matcher, index_matcher, length_matcher,
- value_matcher, effect_matcher, control_matcher));
-}
-
-
Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
const Matcher<Node*>& base_matcher,
const Matcher<Node*>& index_matcher,
namespace internal {
// Forward declarations.
-template <class T>
-class Handle;
class HeapObject;
template <class T>
class Unique;
namespace compiler {
-// Forward declarations.
-struct ElementAccess;
-struct FieldAccess;
-
-
using ::testing::Matcher;
Node* Int32Constant(int32_t value);
Node* Int64Constant(int64_t value);
Node* NumberConstant(volatile double value);
- Node* HeapConstant(const Handle<HeapObject>& value);
Node* HeapConstant(const Unique<HeapObject>& value);
Node* FalseConstant();
Node* TrueConstant();
- Node* UndefinedConstant();
Matcher<Node*> IsFalseConstant();
Matcher<Node*> IsTrueConstant();
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsNumberSubtract(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
-Matcher<Node*> IsLoadField(const Matcher<FieldAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& effect_matcher);
-Matcher<Node*> IsLoadElement(const Matcher<ElementAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& length_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher);
-Matcher<Node*> IsStoreElement(const Matcher<ElementAccess>& access_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& length_matcher,
- const Matcher<Node*>& value_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher);
Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
const Matcher<Node*>& base_matcher,
return n;
}
+ Node* UndefinedConstant() {
+ return HeapConstant(
+ Unique<HeapObject>::CreateImmovable(factory()->undefined_value()));
+ }
+
JSOperatorBuilder* javascript() { return &javascript_; }
private:
+++ /dev/null
-// 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"
-
-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* context = UndefinedConstant();
- Node* effect = graph()->start();
- Node* control = graph()->start();
- Node* node = graph()->NewNode(javascript()->LoadProperty(),
- HeapConstant(array), key, context);
- if (FLAG_turbo_deoptimization) {
- node->AppendInput(zone(), UndefinedConstant());
- }
- node->AppendInput(zone(), effect);
- node->AppendInput(zone(), control);
- Reduction r = Reduce(node);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsLoadElement(
- AccessBuilder::ForTypedArrayElement(type, true),
- IsLoadField(
- AccessBuilder::ForJSArrayBufferBackingStore(),
- IsHeapConstant(Unique<HeapObject>::CreateImmovable(buffer)),
- effect),
- 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* value = Parameter(Type::Any());
- Node* context = UndefinedConstant();
- Node* effect = graph()->start();
- Node* control = graph()->start();
- Node* node = graph()->NewNode(javascript()->StoreProperty(strict_mode),
- HeapConstant(array), key, value, context);
- if (FLAG_turbo_deoptimization) {
- node->AppendInput(zone(), UndefinedConstant());
- }
- node->AppendInput(zone(), effect);
- node->AppendInput(zone(), control);
- Reduction r = Reduce(node);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsStoreElement(
- AccessBuilder::ForTypedArrayElement(type, true),
- IsLoadField(
- AccessBuilder::ForJSArrayBufferBackingStore(),
- IsHeapConstant(Unique<HeapObject>::CreateImmovable(buffer)),
- effect),
- key, IsInt32Constant(static_cast<int>(kLength)), value, effect,
- control));
- }
- }
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
namespace v8 {
-std::ostream& operator<<(std::ostream& os, ExternalArrayType type) {
- switch (type) {
- case kExternalInt8Array:
- return os << "ExternalInt8Array";
- case kExternalUint8Array:
- return os << "ExternalUint8Array";
- case kExternalInt16Array:
- return os << "ExternalInt16Array";
- case kExternalUint16Array:
- return os << "ExternalUint16Array";
- case kExternalInt32Array:
- return os << "ExternalInt32Array";
- case kExternalUint32Array:
- return os << "ExternalUint32Array";
- case kExternalFloat32Array:
- return os << "ExternalFloat32Array";
- case kExternalFloat64Array:
- return os << "ExternalFloat64Array";
- case kExternalUint8ClampedArray:
- return os << "ExternalUint8ClampedArray";
- }
- UNREACHABLE();
- return os;
-}
-
-
// static
Isolate* TestWithIsolate::isolate_ = NULL;
namespace v8 {
-std::ostream& operator<<(std::ostream&, ExternalArrayType);
-
-
class TestWithIsolate : public ::testing::Test {
public:
TestWithIsolate();
'compiler/instruction-selector-unittest.h',
'compiler/js-builtin-reducer-unittest.cc',
'compiler/js-operator-unittest.cc',
- 'compiler/js-typed-lowering-unittest.cc',
'compiler/machine-operator-reducer-unittest.cc',
'compiler/machine-operator-unittest.cc',
'compiler/simplified-operator-reducer-unittest.cc',