Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Unified Diff: test/cctest/compiler/test-simplified-lowering.cc

Issue 425003004: Implement representation selection as part of SimplifiedLowering. Representation selection also req… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Added better tests for Load/Store of fields and elements, with both tagged and untagged bases. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: test/cctest/compiler/test-simplified-lowering.cc
diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc
index bcf1531ca86ba357faac2de18177b16516a798cb..0d841d964370fad956b4a30bd319a07dc706f27f 100644
--- a/test/cctest/compiler/test-simplified-lowering.cc
+++ b/test/cctest/compiler/test-simplified-lowering.cc
@@ -142,12 +142,13 @@ TEST(RunLoadMap) {
t.LowerAllNodes();
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSObject> src = TestObject();
- Handle<Map> src_map(src->map());
- Object* result = t.Call(*src);
- CHECK_EQ(*src_map, result);
+ if (Pipeline::SupportedTarget()) {
+ t.GenerateCode();
+ Handle<JSObject> src = TestObject();
+ Handle<Map> src_map(src->map());
+ Object* result = t.Call(*src); // TODO(titzer): raw pointers in call
+ CHECK_EQ(*src_map, result);
+ }
}
@@ -155,18 +156,19 @@ TEST(RunStoreMap) {
SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged, kMachineTagged);
FieldAccess access = ForJSObjectMap();
t.StoreField(access, t.Parameter(1), t.Parameter(0));
- t.Return(t.Int32Constant(0));
+ t.Return(t.jsgraph.TrueConstant());
t.LowerAllNodes();
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSObject> src = TestObject();
- Handle<Map> src_map(src->map());
- Handle<JSObject> dst = TestObject();
- CHECK(src->map() != dst->map());
- t.Call(*src_map, *dst);
- CHECK(*src_map == dst->map());
+ if (Pipeline::SupportedTarget()) {
+ t.GenerateCode();
+ Handle<JSObject> src = TestObject();
+ Handle<Map> src_map(src->map());
+ Handle<JSObject> dst = TestObject();
+ CHECK(src->map() != dst->map());
+ t.Call(*src_map, *dst); // TODO(titzer): raw pointers in call
+ CHECK(*src_map == dst->map());
+ }
}
@@ -178,12 +180,13 @@ TEST(RunLoadProperties) {
t.LowerAllNodes();
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSObject> src = TestObject();
- Handle<FixedArray> src_props(src->properties());
- Object* result = t.Call(*src);
- CHECK_EQ(*src_props, result);
+ if (Pipeline::SupportedTarget()) {
+ t.GenerateCode();
+ Handle<JSObject> src = TestObject();
+ Handle<FixedArray> src_props(src->properties());
+ Object* result = t.Call(*src); // TODO(titzer): raw pointers in call
+ CHECK_EQ(*src_props, result);
+ }
}
@@ -196,16 +199,17 @@ TEST(RunLoadStoreMap) {
t.LowerAllNodes();
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSObject> src = TestObject();
- Handle<Map> src_map(src->map());
- Handle<JSObject> dst = TestObject();
- CHECK(src->map() != dst->map());
- Object* result = t.Call(*src, *dst);
- CHECK(result->IsMap());
- CHECK_EQ(*src_map, result);
- CHECK(*src_map == dst->map());
+ if (Pipeline::SupportedTarget()) {
+ t.GenerateCode();
+ Handle<JSObject> src = TestObject();
+ Handle<Map> src_map(src->map());
+ Handle<JSObject> dst = TestObject();
+ CHECK(src->map() != dst->map());
+ Object* result = t.Call(*src, *dst); // TODO(titzer): raw pointers in call
+ CHECK(result->IsMap());
+ CHECK_EQ(*src_map, result);
+ CHECK(*src_map == dst->map());
+ }
}
@@ -218,101 +222,53 @@ TEST(RunLoadStoreFixedArrayIndex) {
t.LowerAllNodes();
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<FixedArray> array = t.factory()->NewFixedArray(2);
- Handle<JSObject> src = TestObject();
- Handle<JSObject> dst = TestObject();
- array->set(0, *src);
- array->set(1, *dst);
- Object* result = t.Call(*array);
- CHECK_EQ(*src, result);
- CHECK_EQ(*src, array->get(0));
- CHECK_EQ(*src, array->get(1));
+ if (Pipeline::SupportedTarget()) {
+ t.GenerateCode();
+ Handle<FixedArray> array = t.factory()->NewFixedArray(2);
+ Handle<JSObject> src = TestObject();
+ Handle<JSObject> dst = TestObject();
+ array->set(0, *src);
+ array->set(1, *dst);
+ Object* result = t.Call(*array);
+ CHECK_EQ(*src, result);
+ CHECK_EQ(*src, array->get(0));
+ CHECK_EQ(*src, array->get(1));
+ }
}
TEST(RunLoadStoreArrayBuffer) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged);
+ SimplifiedGraphBuilderTester<Object*> t(kMachineTagged);
const int index = 12;
- FieldAccess access = ForArrayBufferBackingStore();
- Node* backing_store = t.LoadField(access, t.Parameter(0));
ElementAccess buffer_access = ForBackingStoreElement(kMachineWord8);
+ Node* backing_store =
+ t.LoadField(ForArrayBufferBackingStore(), t.Parameter(0));
Node* load =
t.LoadElement(buffer_access, backing_store, t.Int32Constant(index));
t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1),
load);
- t.Return(load);
-
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer();
- const int array_length = 2 * index;
- Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length);
- uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store());
- for (int i = 0; i < array_length; i++) {
- data[i] = i;
- }
- int32_t result = t.Call(*array);
- CHECK_EQ(index, result);
- for (int i = 0; i < array_length; i++) {
- uint8_t expected = i;
- if (i == (index + 1)) expected = result;
- CHECK_EQ(data[i], expected);
- }
-}
-
-
-TEST(RunCopyFixedArray) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged, kMachineTagged);
-
- const int kArraySize = 15;
- Node* one = t.Int32Constant(1);
- Node* index = t.Int32Constant(0);
- Node* limit = t.Int32Constant(kArraySize);
- t.environment()->Push(index);
- {
- LoopBuilder loop(&t);
- loop.BeginLoop();
- // Loop exit condition.
- index = t.environment()->Top();
- Node* condition = t.Int32LessThan(index, limit);
- loop.BreakUnless(condition);
- // src[index] = dst[index].
- index = t.environment()->Pop();
- ElementAccess access = ForFixedArrayElement();
- Node* src = t.Parameter(0);
- Node* load = t.LoadElement(access, src, index);
- Node* dst = t.Parameter(1);
- t.StoreElement(access, dst, index, load);
- // index++
- index = t.Int32Add(index, one);
- t.environment()->Push(index);
- // continue.
- loop.EndBody();
- loop.EndLoop();
- }
- index = t.environment()->Pop();
- t.Return(index);
+ t.Return(t.jsgraph.TrueConstant());
t.LowerAllNodes();
- if (!Pipeline::SupportedTarget()) return;
+ if (Pipeline::SupportedTarget()) {
+ t.GenerateCode();
+ Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer();
+ const int array_length = 2 * index;
+ Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length);
+ uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store());
+ for (int i = 0; i < array_length; i++) {
+ data[i] = i;
+ }
- Handle<FixedArray> src = t.factory()->NewFixedArray(kArraySize);
- Handle<FixedArray> src_copy = t.factory()->NewFixedArray(kArraySize);
- Handle<FixedArray> dst = t.factory()->NewFixedArray(kArraySize);
- for (int i = 0; i < kArraySize; i++) {
- src->set(i, *TestObject());
- src_copy->set(i, src->get(i));
- dst->set(i, *TestObject());
- CHECK_NE(src_copy->get(i), dst->get(i));
- }
- CHECK_EQ(kArraySize, t.Call(*src, *dst));
- for (int i = 0; i < kArraySize; i++) {
- CHECK_EQ(src_copy->get(i), dst->get(i));
+ // TODO(titzer): raw pointers in call
+ Object* result = t.Call(*array);
+ CHECK_EQ(t.isolate()->heap()->true_value(), result);
+ for (int i = 0; i < array_length; i++) {
+ uint8_t expected = i;
+ if (i == (index + 1)) expected = index;
+ CHECK_EQ(data[i], expected);
+ }
}
}
@@ -425,3 +381,246 @@ TEST(RunStoreElementFromUntaggedBase) {
}
}
}
+
+
+// A helper class for accessing fields and elements of various types, on both
+// tagged and untagged base pointers. Contains both tagged and untagged buffers
+// for testing direct memory access from generated code.
+template <typename E>
+class AccessTester : public HandleAndZoneScope {
+ public:
+ bool tagged;
+ MachineRepresentation rep;
+ E* original_elements;
+ int num_elements;
+ E* untagged_array;
+ Handle<ByteArray> tagged_array; // TODO(titzer): use FixedArray for tagged.
+
+ AccessTester(bool t, MachineRepresentation r, E* orig, int num)
+ : tagged(t),
+ rep(r),
+ original_elements(orig),
+ num_elements(num),
+ untagged_array(static_cast<E*>(malloc(ByteSize()))),
+ tagged_array(main_isolate()->factory()->NewByteArray(ByteSize())) {
+ Reinitialize();
+ }
+
+ ~AccessTester() { free(untagged_array); }
+
+ size_t ByteSize() { return num_elements * sizeof(E); }
+
+ // Nuke both {untagged_array} and {tagged_array} with {original_elements}.
+ void Reinitialize() {
+ memcpy(untagged_array, original_elements, ByteSize());
+ CHECK_EQ(ByteSize(), tagged_array->length());
+ E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress());
+ memcpy(raw, original_elements, ByteSize());
+ }
+
+ // Create and run code that copies the element in either {untagged_array}
+ // or {tagged_array} at index {from_index} to index {to_index}.
+ void RunCopyElement(int from_index, int to_index) {
+ // TODO(titzer): test element and field accesses where the base is not
+ // a constant in the code.
+ BoundsCheck(from_index);
+ BoundsCheck(to_index);
+ ElementAccess access = GetElementAccess();
+
+ SimplifiedGraphBuilderTester<Object*> t;
+ Node* ptr = GetBaseNode(&t);
+ Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index));
+ t.StoreElement(access, ptr, t.Int32Constant(to_index), load);
+ t.Return(t.jsgraph.TrueConstant());
+ t.LowerAllNodes();
+ t.GenerateCode();
+
+ if (Pipeline::SupportedTarget()) {
+ Object* result = t.Call();
+ CHECK_EQ(t.isolate()->heap()->true_value(), result);
+ }
+ }
+
+ // Create and run code that copies the field in either {untagged_array}
+ // or {tagged_array} at index {from_index} to index {to_index}.
+ void RunCopyField(int from_index, int to_index) {
+ BoundsCheck(from_index);
+ BoundsCheck(to_index);
+ FieldAccess from_access = GetFieldAccess(from_index);
+ FieldAccess to_access = GetFieldAccess(to_index);
+
+ SimplifiedGraphBuilderTester<Object*> t;
+ Node* ptr = GetBaseNode(&t);
+ Node* load = t.LoadField(from_access, ptr);
+ t.StoreField(to_access, ptr, load);
+ t.Return(t.jsgraph.TrueConstant());
+ t.LowerAllNodes();
+ t.GenerateCode();
+
+ if (Pipeline::SupportedTarget()) {
+ Object* result = t.Call();
+ CHECK_EQ(t.isolate()->heap()->true_value(), result);
+ }
+ }
+
+ // Create and run code that copies the elements from {this} to {that}.
+ void RunCopyElements(AccessTester<E>* that) {
+ SimplifiedGraphBuilderTester<Object*> t;
+
+ Node* one = t.Int32Constant(1);
+ Node* index = t.Int32Constant(0);
+ Node* limit = t.Int32Constant(num_elements);
+ t.environment()->Push(index);
+ Node* src = this->GetBaseNode(&t);
+ Node* dst = that->GetBaseNode(&t);
+ {
+ LoopBuilder loop(&t);
+ loop.BeginLoop();
+ // Loop exit condition
+ index = t.environment()->Top();
+ Node* condition = t.Int32LessThan(index, limit);
+ loop.BreakUnless(condition);
+ // dst[index] = src[index]
+ index = t.environment()->Pop();
+ Node* load = t.LoadElement(this->GetElementAccess(), src, index);
+ t.StoreElement(that->GetElementAccess(), dst, index, load);
+ // index++
+ index = t.Int32Add(index, one);
+ t.environment()->Push(index);
+ // continue
+ loop.EndBody();
+ loop.EndLoop();
+ }
+ index = t.environment()->Pop();
+ t.Return(t.jsgraph.TrueConstant());
+ t.LowerAllNodes();
+ t.GenerateCode();
+
+ if (Pipeline::SupportedTarget()) {
+ Object* result = t.Call();
+ CHECK_EQ(t.isolate()->heap()->true_value(), result);
+ }
+ }
+
+ E GetElement(int index) {
+ BoundsCheck(index);
+ if (tagged) {
+ E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress());
+ return raw[index];
+ } else {
+ return untagged_array[index];
+ }
+ }
+
+ private:
+ ElementAccess GetElementAccess() {
+ ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase,
+ tagged ? FixedArrayBase::kHeaderSize : 0,
+ Type::Any(), rep};
+ return access;
+ }
+
+ FieldAccess GetFieldAccess(int field) {
+ int offset = field * sizeof(E);
+ FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase,
+ offset + (tagged ? FixedArrayBase::kHeaderSize : 0),
+ Handle<Name>(), Type::Any(), rep};
+ return access;
+ }
+
+ template <typename T>
+ Node* GetBaseNode(SimplifiedGraphBuilderTester<T>* t) {
+ return tagged ? t->HeapConstant(tagged_array)
+ : t->PointerConstant(untagged_array);
+ }
+
+ void BoundsCheck(int index) {
+ CHECK_GE(index, 0);
+ CHECK_LT(index, num_elements);
+ CHECK_EQ(ByteSize(), tagged_array->length());
+ }
+};
+
+
+template <typename E>
+static void RunAccessTest(MachineRepresentation rep, E* original_elements,
+ size_t num) {
+ int num_elements = static_cast<int>(num);
+
+ for (int taggedness = 0; taggedness < 2; taggedness++) {
+ AccessTester<E> a(taggedness == 1, rep, original_elements, num_elements);
+ for (int field = 0; field < 2; field++) {
+ for (int i = 0; i < num_elements - 1; i++) {
+ a.Reinitialize();
+ if (field == 0) {
+ a.RunCopyField(i, i + 1); // Test field read/write.
+ } else {
+ a.RunCopyElement(i, i + 1); // Test element read/write.
+ }
+ if (Pipeline::SupportedTarget()) { // verify.
+ for (int j = 0; j < num_elements; j++) {
+ E expect =
+ j == (i + 1) ? original_elements[i] : original_elements[j];
+ CHECK_EQ(expect, a.GetElement(j));
+ }
+ }
+ }
+ }
+ }
+ // Test array copy.
+ for (int tf = 0; tf < 2; tf++) {
+ for (int tt = 0; tt < 2; tt++) {
+ AccessTester<E> a(tf == 1, rep, original_elements, num_elements);
+ AccessTester<E> b(tt == 1, rep, original_elements, num_elements);
+ a.RunCopyElements(&b);
+ if (Pipeline::SupportedTarget()) { // verify.
+ for (int i = 0; i < num_elements; i++) {
+ CHECK_EQ(a.GetElement(i), b.GetElement(i));
+ }
+ }
+ }
+ }
+}
+
+
+TEST(RunAccessTests_uint8) {
+ uint8_t data[] = {0x07, 0x16, 0x25, 0x34, 0x43, 0x99,
+ 0xab, 0x78, 0x89, 0x19, 0x2b, 0x38};
+ RunAccessTest<uint8_t>(kMachineWord8, data, ARRAY_SIZE(data));
+}
+
+
+TEST(RunAccessTests_uint16) {
+ uint16_t data[] = {0x071a, 0x162b, 0x253c, 0x344d, 0x435e, 0x7777};
+ RunAccessTest<uint16_t>(kMachineWord16, data, ARRAY_SIZE(data));
+}
+
+
+TEST(RunAccessTests_int32) {
+ int32_t data[] = {0xf10733aa, 0xf21644bb, 0xf32555cc,
+ 0xf43466dd, 0xf54377ee, 0x34455667};
+ RunAccessTest<int32_t>(kMachineWord32, data, ARRAY_SIZE(data));
+}
+
+
+TEST(RunAccessTests_int64) {
+ if (kPointerSize != 8) return;
+ int64_t data[] = {0x1011121314151617L, 0x2021222324252627L,
+ 0x3031323334353637L, 0xa0a1a2a3a4a5a6a7L,
+ 0xf0f1f2f3f4f5f6f7L};
+ RunAccessTest<int64_t>(kMachineWord64, data, ARRAY_SIZE(data));
+}
+
+
+TEST(RunAccessTests_float64) {
+ double data[] = {1.25, -1.25, 2.75, 11.0, 11100.8};
+ RunAccessTest<double>(kMachineFloat64, data, ARRAY_SIZE(data));
+}
+
+
+TEST(RunAccessTests_Smi) {
+ Smi* data[] = {Smi::FromInt(-1), Smi::FromInt(-9),
+ Smi::FromInt(0), Smi::FromInt(666),
+ Smi::FromInt(77777), Smi::FromInt(Smi::kMaxValue)};
+ RunAccessTest<Smi*>(kMachineTagged, data, ARRAY_SIZE(data));
+}
« src/compiler/simplified-lowering.cc ('K') | « test/cctest/compiler/test-changes-lowering.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698