| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits> | 5 #include <limits> |
| 6 | 6 |
| 7 #include "src/compiler/control-builders.h" | 7 #include "src/compiler/control-builders.h" |
| 8 #include "src/compiler/generic-node-inl.h" | 8 #include "src/compiler/generic-node-inl.h" |
| 9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 | 135 |
| 136 | 136 |
| 137 TEST(RunLoadMap) { | 137 TEST(RunLoadMap) { |
| 138 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged); | 138 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged); |
| 139 FieldAccess access = ForJSObjectMap(); | 139 FieldAccess access = ForJSObjectMap(); |
| 140 Node* load = t.LoadField(access, t.Parameter(0)); | 140 Node* load = t.LoadField(access, t.Parameter(0)); |
| 141 t.Return(load); | 141 t.Return(load); |
| 142 | 142 |
| 143 t.LowerAllNodes(); | 143 t.LowerAllNodes(); |
| 144 | 144 |
| 145 if (!Pipeline::SupportedTarget()) return; | 145 if (Pipeline::SupportedTarget()) { |
| 146 | 146 t.GenerateCode(); |
| 147 Handle<JSObject> src = TestObject(); | 147 Handle<JSObject> src = TestObject(); |
| 148 Handle<Map> src_map(src->map()); | 148 Handle<Map> src_map(src->map()); |
| 149 Object* result = t.Call(*src); | 149 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call |
| 150 CHECK_EQ(*src_map, result); | 150 CHECK_EQ(*src_map, result); |
| 151 } |
| 151 } | 152 } |
| 152 | 153 |
| 153 | 154 |
| 154 TEST(RunStoreMap) { | 155 TEST(RunStoreMap) { |
| 155 SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged, kMachineTagged); | 156 SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged, kMachineTagged); |
| 156 FieldAccess access = ForJSObjectMap(); | 157 FieldAccess access = ForJSObjectMap(); |
| 157 t.StoreField(access, t.Parameter(1), t.Parameter(0)); | 158 t.StoreField(access, t.Parameter(1), t.Parameter(0)); |
| 158 t.Return(t.Int32Constant(0)); | 159 t.Return(t.jsgraph.TrueConstant()); |
| 159 | 160 |
| 160 t.LowerAllNodes(); | 161 t.LowerAllNodes(); |
| 161 | 162 |
| 162 if (!Pipeline::SupportedTarget()) return; | 163 if (Pipeline::SupportedTarget()) { |
| 163 | 164 t.GenerateCode(); |
| 164 Handle<JSObject> src = TestObject(); | 165 Handle<JSObject> src = TestObject(); |
| 165 Handle<Map> src_map(src->map()); | 166 Handle<Map> src_map(src->map()); |
| 166 Handle<JSObject> dst = TestObject(); | 167 Handle<JSObject> dst = TestObject(); |
| 167 CHECK(src->map() != dst->map()); | 168 CHECK(src->map() != dst->map()); |
| 168 t.Call(*src_map, *dst); | 169 t.Call(*src_map, *dst); // TODO(titzer): raw pointers in call |
| 169 CHECK(*src_map == dst->map()); | 170 CHECK(*src_map == dst->map()); |
| 171 } |
| 170 } | 172 } |
| 171 | 173 |
| 172 | 174 |
| 173 TEST(RunLoadProperties) { | 175 TEST(RunLoadProperties) { |
| 174 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged); | 176 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged); |
| 175 FieldAccess access = ForJSObjectProperties(); | 177 FieldAccess access = ForJSObjectProperties(); |
| 176 Node* load = t.LoadField(access, t.Parameter(0)); | 178 Node* load = t.LoadField(access, t.Parameter(0)); |
| 177 t.Return(load); | 179 t.Return(load); |
| 178 | 180 |
| 179 t.LowerAllNodes(); | 181 t.LowerAllNodes(); |
| 180 | 182 |
| 181 if (!Pipeline::SupportedTarget()) return; | 183 if (Pipeline::SupportedTarget()) { |
| 182 | 184 t.GenerateCode(); |
| 183 Handle<JSObject> src = TestObject(); | 185 Handle<JSObject> src = TestObject(); |
| 184 Handle<FixedArray> src_props(src->properties()); | 186 Handle<FixedArray> src_props(src->properties()); |
| 185 Object* result = t.Call(*src); | 187 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call |
| 186 CHECK_EQ(*src_props, result); | 188 CHECK_EQ(*src_props, result); |
| 189 } |
| 187 } | 190 } |
| 188 | 191 |
| 189 | 192 |
| 190 TEST(RunLoadStoreMap) { | 193 TEST(RunLoadStoreMap) { |
| 191 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged, kMachineTagged); | 194 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged, kMachineTagged); |
| 192 FieldAccess access = ForJSObjectMap(); | 195 FieldAccess access = ForJSObjectMap(); |
| 193 Node* load = t.LoadField(access, t.Parameter(0)); | 196 Node* load = t.LoadField(access, t.Parameter(0)); |
| 194 t.StoreField(access, t.Parameter(1), load); | 197 t.StoreField(access, t.Parameter(1), load); |
| 195 t.Return(load); | 198 t.Return(load); |
| 196 | 199 |
| 197 t.LowerAllNodes(); | 200 t.LowerAllNodes(); |
| 198 | 201 |
| 199 if (!Pipeline::SupportedTarget()) return; | 202 if (Pipeline::SupportedTarget()) { |
| 200 | 203 t.GenerateCode(); |
| 201 Handle<JSObject> src = TestObject(); | 204 Handle<JSObject> src = TestObject(); |
| 202 Handle<Map> src_map(src->map()); | 205 Handle<Map> src_map(src->map()); |
| 203 Handle<JSObject> dst = TestObject(); | 206 Handle<JSObject> dst = TestObject(); |
| 204 CHECK(src->map() != dst->map()); | 207 CHECK(src->map() != dst->map()); |
| 205 Object* result = t.Call(*src, *dst); | 208 Object* result = t.Call(*src, *dst); // TODO(titzer): raw pointers in call |
| 206 CHECK(result->IsMap()); | 209 CHECK(result->IsMap()); |
| 207 CHECK_EQ(*src_map, result); | 210 CHECK_EQ(*src_map, result); |
| 208 CHECK(*src_map == dst->map()); | 211 CHECK(*src_map == dst->map()); |
| 212 } |
| 209 } | 213 } |
| 210 | 214 |
| 211 | 215 |
| 212 TEST(RunLoadStoreFixedArrayIndex) { | 216 TEST(RunLoadStoreFixedArrayIndex) { |
| 213 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged); | 217 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged); |
| 214 ElementAccess access = ForFixedArrayElement(); | 218 ElementAccess access = ForFixedArrayElement(); |
| 215 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); | 219 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); |
| 216 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); | 220 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); |
| 217 t.Return(load); | 221 t.Return(load); |
| 218 | 222 |
| 219 t.LowerAllNodes(); | 223 t.LowerAllNodes(); |
| 220 | 224 |
| 221 if (!Pipeline::SupportedTarget()) return; | 225 if (Pipeline::SupportedTarget()) { |
| 222 | 226 t.GenerateCode(); |
| 223 Handle<FixedArray> array = t.factory()->NewFixedArray(2); | 227 Handle<FixedArray> array = t.factory()->NewFixedArray(2); |
| 224 Handle<JSObject> src = TestObject(); | 228 Handle<JSObject> src = TestObject(); |
| 225 Handle<JSObject> dst = TestObject(); | 229 Handle<JSObject> dst = TestObject(); |
| 226 array->set(0, *src); | 230 array->set(0, *src); |
| 227 array->set(1, *dst); | 231 array->set(1, *dst); |
| 228 Object* result = t.Call(*array); | 232 Object* result = t.Call(*array); |
| 229 CHECK_EQ(*src, result); | 233 CHECK_EQ(*src, result); |
| 230 CHECK_EQ(*src, array->get(0)); | 234 CHECK_EQ(*src, array->get(0)); |
| 231 CHECK_EQ(*src, array->get(1)); | 235 CHECK_EQ(*src, array->get(1)); |
| 236 } |
| 232 } | 237 } |
| 233 | 238 |
| 234 | 239 |
| 235 TEST(RunLoadStoreArrayBuffer) { | 240 TEST(RunLoadStoreArrayBuffer) { |
| 236 SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged); | 241 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged); |
| 237 const int index = 12; | 242 const int index = 12; |
| 238 FieldAccess access = ForArrayBufferBackingStore(); | |
| 239 Node* backing_store = t.LoadField(access, t.Parameter(0)); | |
| 240 ElementAccess buffer_access = ForBackingStoreElement(kMachineWord8); | 243 ElementAccess buffer_access = ForBackingStoreElement(kMachineWord8); |
| 244 Node* backing_store = |
| 245 t.LoadField(ForArrayBufferBackingStore(), t.Parameter(0)); |
| 241 Node* load = | 246 Node* load = |
| 242 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); | 247 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); |
| 243 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), | 248 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), |
| 244 load); | 249 load); |
| 245 t.Return(load); | 250 t.Return(t.jsgraph.TrueConstant()); |
| 246 | 251 |
| 247 t.LowerAllNodes(); | 252 t.LowerAllNodes(); |
| 248 | 253 |
| 249 if (!Pipeline::SupportedTarget()) return; | 254 if (Pipeline::SupportedTarget()) { |
| 255 t.GenerateCode(); |
| 256 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); |
| 257 const int array_length = 2 * index; |
| 258 Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); |
| 259 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); |
| 260 for (int i = 0; i < array_length; i++) { |
| 261 data[i] = i; |
| 262 } |
| 250 | 263 |
| 251 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); | 264 // TODO(titzer): raw pointers in call |
| 252 const int array_length = 2 * index; | 265 Object* result = t.Call(*array); |
| 253 Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); | 266 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 254 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); | 267 for (int i = 0; i < array_length; i++) { |
| 255 for (int i = 0; i < array_length; i++) { | 268 uint8_t expected = i; |
| 256 data[i] = i; | 269 if (i == (index + 1)) expected = index; |
| 257 } | 270 CHECK_EQ(data[i], expected); |
| 258 int32_t result = t.Call(*array); | 271 } |
| 259 CHECK_EQ(index, result); | |
| 260 for (int i = 0; i < array_length; i++) { | |
| 261 uint8_t expected = i; | |
| 262 if (i == (index + 1)) expected = result; | |
| 263 CHECK_EQ(data[i], expected); | |
| 264 } | 272 } |
| 265 } | 273 } |
| 266 | 274 |
| 267 | |
| 268 TEST(RunCopyFixedArray) { | |
| 269 SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged, kMachineTagged); | |
| 270 | |
| 271 const int kArraySize = 15; | |
| 272 Node* one = t.Int32Constant(1); | |
| 273 Node* index = t.Int32Constant(0); | |
| 274 Node* limit = t.Int32Constant(kArraySize); | |
| 275 t.environment()->Push(index); | |
| 276 { | |
| 277 LoopBuilder loop(&t); | |
| 278 loop.BeginLoop(); | |
| 279 // Loop exit condition. | |
| 280 index = t.environment()->Top(); | |
| 281 Node* condition = t.Int32LessThan(index, limit); | |
| 282 loop.BreakUnless(condition); | |
| 283 // src[index] = dst[index]. | |
| 284 index = t.environment()->Pop(); | |
| 285 ElementAccess access = ForFixedArrayElement(); | |
| 286 Node* src = t.Parameter(0); | |
| 287 Node* load = t.LoadElement(access, src, index); | |
| 288 Node* dst = t.Parameter(1); | |
| 289 t.StoreElement(access, dst, index, load); | |
| 290 // index++ | |
| 291 index = t.Int32Add(index, one); | |
| 292 t.environment()->Push(index); | |
| 293 // continue. | |
| 294 loop.EndBody(); | |
| 295 loop.EndLoop(); | |
| 296 } | |
| 297 index = t.environment()->Pop(); | |
| 298 t.Return(index); | |
| 299 | |
| 300 t.LowerAllNodes(); | |
| 301 | |
| 302 if (!Pipeline::SupportedTarget()) return; | |
| 303 | |
| 304 Handle<FixedArray> src = t.factory()->NewFixedArray(kArraySize); | |
| 305 Handle<FixedArray> src_copy = t.factory()->NewFixedArray(kArraySize); | |
| 306 Handle<FixedArray> dst = t.factory()->NewFixedArray(kArraySize); | |
| 307 for (int i = 0; i < kArraySize; i++) { | |
| 308 src->set(i, *TestObject()); | |
| 309 src_copy->set(i, src->get(i)); | |
| 310 dst->set(i, *TestObject()); | |
| 311 CHECK_NE(src_copy->get(i), dst->get(i)); | |
| 312 } | |
| 313 CHECK_EQ(kArraySize, t.Call(*src, *dst)); | |
| 314 for (int i = 0; i < kArraySize; i++) { | |
| 315 CHECK_EQ(src_copy->get(i), dst->get(i)); | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 | 275 |
| 320 TEST(RunLoadFieldFromUntaggedBase) { | 276 TEST(RunLoadFieldFromUntaggedBase) { |
| 321 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; | 277 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; |
| 322 | 278 |
| 323 for (size_t i = 0; i < ARRAY_SIZE(smis); i++) { | 279 for (size_t i = 0; i < ARRAY_SIZE(smis); i++) { |
| 324 int offset = static_cast<int>(i * sizeof(Smi*)); | 280 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 325 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), | 281 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), |
| 326 Type::Integral32(), kMachineTagged}; | 282 Type::Integral32(), kMachineTagged}; |
| 327 | 283 |
| 328 SimplifiedGraphBuilderTester<Object*> t; | 284 SimplifiedGraphBuilderTester<Object*> t; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 Smi* expected = Smi::FromInt(k); | 374 Smi* expected = Smi::FromInt(k); |
| 419 smis[i + j] = Smi::FromInt(-100); | 375 smis[i + j] = Smi::FromInt(-100); |
| 420 CHECK_EQ(expected, t.Call(expected)); | 376 CHECK_EQ(expected, t.Call(expected)); |
| 421 CHECK_EQ(expected, smis[i + j]); | 377 CHECK_EQ(expected, smis[i + j]); |
| 422 } | 378 } |
| 423 | 379 |
| 424 // TODO(titzer): assert the contents of the array. | 380 // TODO(titzer): assert the contents of the array. |
| 425 } | 381 } |
| 426 } | 382 } |
| 427 } | 383 } |
| 384 |
| 385 |
| 386 // A helper class for accessing fields and elements of various types, on both |
| 387 // tagged and untagged base pointers. Contains both tagged and untagged buffers |
| 388 // for testing direct memory access from generated code. |
| 389 template <typename E> |
| 390 class AccessTester : public HandleAndZoneScope { |
| 391 public: |
| 392 bool tagged; |
| 393 MachineRepresentation rep; |
| 394 E* original_elements; |
| 395 int num_elements; |
| 396 E* untagged_array; |
| 397 Handle<ByteArray> tagged_array; // TODO(titzer): use FixedArray for tagged. |
| 398 |
| 399 AccessTester(bool t, MachineRepresentation r, E* orig, int num) |
| 400 : tagged(t), |
| 401 rep(r), |
| 402 original_elements(orig), |
| 403 num_elements(num), |
| 404 untagged_array(static_cast<E*>(malloc(ByteSize()))), |
| 405 tagged_array(main_isolate()->factory()->NewByteArray(ByteSize())) { |
| 406 Reinitialize(); |
| 407 } |
| 408 |
| 409 ~AccessTester() { free(untagged_array); } |
| 410 |
| 411 size_t ByteSize() { return num_elements * sizeof(E); } |
| 412 |
| 413 // Nuke both {untagged_array} and {tagged_array} with {original_elements}. |
| 414 void Reinitialize() { |
| 415 memcpy(untagged_array, original_elements, ByteSize()); |
| 416 CHECK_EQ(ByteSize(), tagged_array->length()); |
| 417 E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress()); |
| 418 memcpy(raw, original_elements, ByteSize()); |
| 419 } |
| 420 |
| 421 // Create and run code that copies the element in either {untagged_array} |
| 422 // or {tagged_array} at index {from_index} to index {to_index}. |
| 423 void RunCopyElement(int from_index, int to_index) { |
| 424 // TODO(titzer): test element and field accesses where the base is not |
| 425 // a constant in the code. |
| 426 BoundsCheck(from_index); |
| 427 BoundsCheck(to_index); |
| 428 ElementAccess access = GetElementAccess(); |
| 429 |
| 430 SimplifiedGraphBuilderTester<Object*> t; |
| 431 Node* ptr = GetBaseNode(&t); |
| 432 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index)); |
| 433 t.StoreElement(access, ptr, t.Int32Constant(to_index), load); |
| 434 t.Return(t.jsgraph.TrueConstant()); |
| 435 t.LowerAllNodes(); |
| 436 t.GenerateCode(); |
| 437 |
| 438 if (Pipeline::SupportedTarget()) { |
| 439 Object* result = t.Call(); |
| 440 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 441 } |
| 442 } |
| 443 |
| 444 // Create and run code that copies the field in either {untagged_array} |
| 445 // or {tagged_array} at index {from_index} to index {to_index}. |
| 446 void RunCopyField(int from_index, int to_index) { |
| 447 BoundsCheck(from_index); |
| 448 BoundsCheck(to_index); |
| 449 FieldAccess from_access = GetFieldAccess(from_index); |
| 450 FieldAccess to_access = GetFieldAccess(to_index); |
| 451 |
| 452 SimplifiedGraphBuilderTester<Object*> t; |
| 453 Node* ptr = GetBaseNode(&t); |
| 454 Node* load = t.LoadField(from_access, ptr); |
| 455 t.StoreField(to_access, ptr, load); |
| 456 t.Return(t.jsgraph.TrueConstant()); |
| 457 t.LowerAllNodes(); |
| 458 t.GenerateCode(); |
| 459 |
| 460 if (Pipeline::SupportedTarget()) { |
| 461 Object* result = t.Call(); |
| 462 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 463 } |
| 464 } |
| 465 |
| 466 // Create and run code that copies the elements from {this} to {that}. |
| 467 void RunCopyElements(AccessTester<E>* that) { |
| 468 SimplifiedGraphBuilderTester<Object*> t; |
| 469 |
| 470 Node* one = t.Int32Constant(1); |
| 471 Node* index = t.Int32Constant(0); |
| 472 Node* limit = t.Int32Constant(num_elements); |
| 473 t.environment()->Push(index); |
| 474 Node* src = this->GetBaseNode(&t); |
| 475 Node* dst = that->GetBaseNode(&t); |
| 476 { |
| 477 LoopBuilder loop(&t); |
| 478 loop.BeginLoop(); |
| 479 // Loop exit condition |
| 480 index = t.environment()->Top(); |
| 481 Node* condition = t.Int32LessThan(index, limit); |
| 482 loop.BreakUnless(condition); |
| 483 // dst[index] = src[index] |
| 484 index = t.environment()->Pop(); |
| 485 Node* load = t.LoadElement(this->GetElementAccess(), src, index); |
| 486 t.StoreElement(that->GetElementAccess(), dst, index, load); |
| 487 // index++ |
| 488 index = t.Int32Add(index, one); |
| 489 t.environment()->Push(index); |
| 490 // continue |
| 491 loop.EndBody(); |
| 492 loop.EndLoop(); |
| 493 } |
| 494 index = t.environment()->Pop(); |
| 495 t.Return(t.jsgraph.TrueConstant()); |
| 496 t.LowerAllNodes(); |
| 497 t.GenerateCode(); |
| 498 |
| 499 if (Pipeline::SupportedTarget()) { |
| 500 Object* result = t.Call(); |
| 501 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 502 } |
| 503 } |
| 504 |
| 505 E GetElement(int index) { |
| 506 BoundsCheck(index); |
| 507 if (tagged) { |
| 508 E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress()); |
| 509 return raw[index]; |
| 510 } else { |
| 511 return untagged_array[index]; |
| 512 } |
| 513 } |
| 514 |
| 515 private: |
| 516 ElementAccess GetElementAccess() { |
| 517 ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase, |
| 518 tagged ? FixedArrayBase::kHeaderSize : 0, |
| 519 Type::Any(), rep}; |
| 520 return access; |
| 521 } |
| 522 |
| 523 FieldAccess GetFieldAccess(int field) { |
| 524 int offset = field * sizeof(E); |
| 525 FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase, |
| 526 offset + (tagged ? FixedArrayBase::kHeaderSize : 0), |
| 527 Handle<Name>(), Type::Any(), rep}; |
| 528 return access; |
| 529 } |
| 530 |
| 531 template <typename T> |
| 532 Node* GetBaseNode(SimplifiedGraphBuilderTester<T>* t) { |
| 533 return tagged ? t->HeapConstant(tagged_array) |
| 534 : t->PointerConstant(untagged_array); |
| 535 } |
| 536 |
| 537 void BoundsCheck(int index) { |
| 538 CHECK_GE(index, 0); |
| 539 CHECK_LT(index, num_elements); |
| 540 CHECK_EQ(ByteSize(), tagged_array->length()); |
| 541 } |
| 542 }; |
| 543 |
| 544 |
| 545 template <typename E> |
| 546 static void RunAccessTest(MachineRepresentation rep, E* original_elements, |
| 547 size_t num) { |
| 548 int num_elements = static_cast<int>(num); |
| 549 |
| 550 for (int taggedness = 0; taggedness < 2; taggedness++) { |
| 551 AccessTester<E> a(taggedness == 1, rep, original_elements, num_elements); |
| 552 for (int field = 0; field < 2; field++) { |
| 553 for (int i = 0; i < num_elements - 1; i++) { |
| 554 a.Reinitialize(); |
| 555 if (field == 0) { |
| 556 a.RunCopyField(i, i + 1); // Test field read/write. |
| 557 } else { |
| 558 a.RunCopyElement(i, i + 1); // Test element read/write. |
| 559 } |
| 560 if (Pipeline::SupportedTarget()) { // verify. |
| 561 for (int j = 0; j < num_elements; j++) { |
| 562 E expect = |
| 563 j == (i + 1) ? original_elements[i] : original_elements[j]; |
| 564 CHECK_EQ(expect, a.GetElement(j)); |
| 565 } |
| 566 } |
| 567 } |
| 568 } |
| 569 } |
| 570 // Test array copy. |
| 571 for (int tf = 0; tf < 2; tf++) { |
| 572 for (int tt = 0; tt < 2; tt++) { |
| 573 AccessTester<E> a(tf == 1, rep, original_elements, num_elements); |
| 574 AccessTester<E> b(tt == 1, rep, original_elements, num_elements); |
| 575 a.RunCopyElements(&b); |
| 576 if (Pipeline::SupportedTarget()) { // verify. |
| 577 for (int i = 0; i < num_elements; i++) { |
| 578 CHECK_EQ(a.GetElement(i), b.GetElement(i)); |
| 579 } |
| 580 } |
| 581 } |
| 582 } |
| 583 } |
| 584 |
| 585 |
| 586 TEST(RunAccessTests_uint8) { |
| 587 uint8_t data[] = {0x07, 0x16, 0x25, 0x34, 0x43, 0x99, |
| 588 0xab, 0x78, 0x89, 0x19, 0x2b, 0x38}; |
| 589 RunAccessTest<uint8_t>(kMachineWord8, data, ARRAY_SIZE(data)); |
| 590 } |
| 591 |
| 592 |
| 593 TEST(RunAccessTests_uint16) { |
| 594 uint16_t data[] = {0x071a, 0x162b, 0x253c, 0x344d, 0x435e, 0x7777}; |
| 595 RunAccessTest<uint16_t>(kMachineWord16, data, ARRAY_SIZE(data)); |
| 596 } |
| 597 |
| 598 |
| 599 TEST(RunAccessTests_int32) { |
| 600 int32_t data[] = {0xf10733aa, 0xf21644bb, 0xf32555cc, |
| 601 0xf43466dd, 0xf54377ee, 0x34455667}; |
| 602 RunAccessTest<int32_t>(kMachineWord32, data, ARRAY_SIZE(data)); |
| 603 } |
| 604 |
| 605 |
| 606 TEST(RunAccessTests_int64) { |
| 607 if (kPointerSize != 8) return; |
| 608 int64_t data[] = {0x1011121314151617L, 0x2021222324252627L, |
| 609 0x3031323334353637L, 0xa0a1a2a3a4a5a6a7L, |
| 610 0xf0f1f2f3f4f5f6f7L}; |
| 611 RunAccessTest<int64_t>(kMachineWord64, data, ARRAY_SIZE(data)); |
| 612 } |
| 613 |
| 614 |
| 615 TEST(RunAccessTests_float64) { |
| 616 double data[] = {1.25, -1.25, 2.75, 11.0, 11100.8}; |
| 617 RunAccessTest<double>(kMachineFloat64, data, ARRAY_SIZE(data)); |
| 618 } |
| 619 |
| 620 |
| 621 TEST(RunAccessTests_Smi) { |
| 622 Smi* data[] = {Smi::FromInt(-1), Smi::FromInt(-9), |
| 623 Smi::FromInt(0), Smi::FromInt(666), |
| 624 Smi::FromInt(77777), Smi::FromInt(Smi::kMaxValue)}; |
| 625 RunAccessTest<Smi*>(kMachineTagged, data, ARRAY_SIZE(data)); |
| 626 } |
| OLD | NEW |