Changeset 213714 in webkit for trunk/Source/JavaScriptCore/b3/testb3.cpp
- Timestamp:
- Mar 10, 2017, 9:49:42 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/b3/testb3.cpp
r211896 r213714 31 31 #include "AllowMacroScratchRegisterUsage.h" 32 32 #include "B3ArgumentRegValue.h" 33 #include "B3AtomicValue.h" 33 34 #include "B3BasicBlockInlines.h" 34 35 #include "B3CCallValue.h" … … 45 46 #include "B3MemoryValue.h" 46 47 #include "B3MoveConstants.h" 48 #include "B3NativeTraits.h" 47 49 #include "B3Procedure.h" 48 50 #include "B3ReduceStrength.h" … … 298 300 } 299 301 302 void testLoadAcq42() 303 { 304 Procedure proc; 305 BasicBlock* root = proc.addBlock(); 306 int x = 42; 307 root->appendNewControlValue( 308 proc, Return, Origin(), 309 root->appendNew<MemoryValue>( 310 proc, Load, Int32, Origin(), 311 root->appendNew<ConstPtrValue>(proc, Origin(), &x), 312 0, HeapRange(42), HeapRange(42))); 313 314 auto code = compile(proc); 315 if (isARM64()) 316 checkUsesInstruction(*code, "lda"); 317 CHECK(invoke<int>(*code) == 42); 318 } 319 300 320 void testLoadWithOffsetImpl(int32_t offset64, int32_t offset32) 301 321 { … … 5749 5769 } 5750 5770 5771 void testStoreRelAddLoadAcq32(int amount) 5772 { 5773 Procedure proc; 5774 BasicBlock* root = proc.addBlock(); 5775 int slot = 37; 5776 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); 5777 root->appendNew<MemoryValue>( 5778 proc, Store, Origin(), 5779 root->appendNew<Value>( 5780 proc, Add, Origin(), 5781 root->appendNew<MemoryValue>( 5782 proc, Load, Int32, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)), 5783 root->appendNew<Value>( 5784 proc, Trunc, Origin(), 5785 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 5786 slotPtr, 0, HeapRange(42), HeapRange(42)); 5787 root->appendNewControlValue( 5788 proc, Return, Origin(), 5789 root->appendNew<Const32Value>(proc, Origin(), 0)); 5790 5791 auto code = compile(proc); 5792 if (isARM64()) { 5793 checkUsesInstruction(*code, "lda"); 5794 checkUsesInstruction(*code, "stl"); 5795 } 5796 CHECK(!invoke<int>(*code, amount)); 5797 CHECK(slot == 37 + amount); 5798 } 5799 5751 5800 void testStoreAddLoadImm32(int amount) 5752 5801 { … … 5793 5842 } 5794 5843 5844 void testStoreRelAddLoadAcq8(int amount, B3::Opcode loadOpcode) 5845 { 5846 Procedure proc; 5847 BasicBlock* root = proc.addBlock(); 5848 int8_t slot = 37; 5849 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); 5850 root->appendNew<MemoryValue>( 5851 proc, Store8, Origin(), 5852 root->appendNew<Value>( 5853 proc, Add, Origin(), 5854 root->appendNew<MemoryValue>( 5855 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)), 5856 root->appendNew<Value>( 5857 proc, Trunc, Origin(), 5858 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 5859 slotPtr, 0, HeapRange(42), HeapRange(42)); 5860 root->appendNewControlValue( 5861 proc, Return, Origin(), 5862 root->appendNew<Const32Value>(proc, Origin(), 0)); 5863 5864 auto code = compile(proc); 5865 if (isARM64()) { 5866 checkUsesInstruction(*code, "lda"); 5867 checkUsesInstruction(*code, "stl"); 5868 } 5869 CHECK(!invoke<int>(*code, amount)); 5870 CHECK(slot == 37 + amount); 5871 } 5872 5873 void testStoreRelAddFenceLoadAcq8(int amount, B3::Opcode loadOpcode) 5874 { 5875 Procedure proc; 5876 BasicBlock* root = proc.addBlock(); 5877 int8_t slot = 37; 5878 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); 5879 Value* loadedValue = root->appendNew<MemoryValue>( 5880 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)); 5881 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin()); 5882 patchpoint->clobber(RegisterSet::macroScratchRegisters()); 5883 patchpoint->setGenerator( 5884 [&] (CCallHelpers& jit, const StackmapGenerationParams&) { 5885 AllowMacroScratchRegisterUsage allowScratch(jit); 5886 jit.store8(CCallHelpers::TrustedImm32(0xbeef), &slot); 5887 }); 5888 patchpoint->effects = Effects::none(); 5889 patchpoint->effects.fence = true; 5890 root->appendNew<MemoryValue>( 5891 proc, Store8, Origin(), 5892 root->appendNew<Value>( 5893 proc, Add, Origin(), 5894 loadedValue, 5895 root->appendNew<Value>( 5896 proc, Trunc, Origin(), 5897 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 5898 slotPtr, 0, HeapRange(42), HeapRange(42)); 5899 root->appendNewControlValue( 5900 proc, Return, Origin(), 5901 root->appendNew<Const32Value>(proc, Origin(), 0)); 5902 5903 auto code = compile(proc); 5904 if (isARM64()) { 5905 checkUsesInstruction(*code, "lda"); 5906 checkUsesInstruction(*code, "stl"); 5907 } 5908 CHECK(!invoke<int>(*code, amount)); 5909 CHECK(slot == 37 + amount); 5910 } 5911 5795 5912 void testStoreAddLoadImm8(int amount, B3::Opcode loadOpcode) 5796 5913 { … … 5837 5954 } 5838 5955 5839 void testStore AddLoadImm16(int amount, B3::Opcode loadOpcode)5956 void testStoreRelAddLoadAcq16(int amount, B3::Opcode loadOpcode) 5840 5957 { 5841 5958 Procedure proc; … … 5847 5964 root->appendNew<Value>( 5848 5965 proc, Add, Origin(), 5966 root->appendNew<MemoryValue>( 5967 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)), 5968 root->appendNew<Value>( 5969 proc, Trunc, Origin(), 5970 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 5971 slotPtr, 0, HeapRange(42), HeapRange(42)); 5972 root->appendNewControlValue( 5973 proc, Return, Origin(), 5974 root->appendNew<Const32Value>(proc, Origin(), 0)); 5975 5976 auto code = compile(proc); 5977 if (isARM64()) { 5978 checkUsesInstruction(*code, "lda"); 5979 checkUsesInstruction(*code, "stl"); 5980 } 5981 CHECK(!invoke<int>(*code, amount)); 5982 CHECK(slot == 37 + amount); 5983 } 5984 5985 void testStoreAddLoadImm16(int amount, B3::Opcode loadOpcode) 5986 { 5987 Procedure proc; 5988 BasicBlock* root = proc.addBlock(); 5989 int16_t slot = 37; 5990 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); 5991 root->appendNew<MemoryValue>( 5992 proc, Store16, Origin(), 5993 root->appendNew<Value>( 5994 proc, Add, Origin(), 5849 5995 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), 5850 5996 root->appendNew<Const32Value>(proc, Origin(), amount)), … … 5876 6022 5877 6023 CHECK(!compileAndRun<int>(proc, amount)); 6024 CHECK(slot == 37000000000ll + amount); 6025 } 6026 6027 void testStoreRelAddLoadAcq64(int amount) 6028 { 6029 Procedure proc; 6030 BasicBlock* root = proc.addBlock(); 6031 int64_t slot = 37000000000ll; 6032 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); 6033 root->appendNew<MemoryValue>( 6034 proc, Store, Origin(), 6035 root->appendNew<Value>( 6036 proc, Add, Origin(), 6037 root->appendNew<MemoryValue>( 6038 proc, Load, Int64, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)), 6039 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), 6040 slotPtr, 0, HeapRange(42), HeapRange(42)); 6041 root->appendNewControlValue( 6042 proc, Return, Origin(), 6043 root->appendNew<Const32Value>(proc, Origin(), 0)); 6044 6045 auto code = compile(proc); 6046 if (isARM64()) { 6047 checkUsesInstruction(*code, "lda"); 6048 checkUsesInstruction(*code, "stl"); 6049 } 6050 CHECK(!invoke<int>(*code, amount)); 5878 6051 CHECK(slot == 37000000000ll + amount); 5879 6052 } … … 13792 13965 unsigned storeCount = 0; 13793 13966 for (Value* value : proc.values()) { 13794 if ( MemoryValue::isStore(value->opcode()))13967 if (isStore(value->opcode())) 13795 13968 storeCount++; 13796 13969 } … … 13998 14171 13999 14172 auto code = compile(proc); 14173 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), (1 + 2) + 100); 14000 14174 checkDisassembly( 14001 14175 *code, … … 14005 14179 }, 14006 14180 "Expected to find something like lea 0x64(%rdi,%rsi), %rax but didn't!"); 14007 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), (1 + 2) + 100);14008 14181 } 14009 14182 … … 14042 14215 14043 14216 auto code = compile(proc); 14217 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + 2); 14044 14218 checkDisassembly( 14045 14219 *code, … … 14049 14223 }, 14050 14224 "Expected to find something like lea (%rdi,%rsi), %rax but didn't!"); 14051 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + 2);14052 14225 } 14053 14226 … … 14278 14451 } 14279 14452 14453 template<typename T> 14454 void testAtomicWeakCAS() 14455 { 14456 Type type = NativeTraits<T>::type; 14457 Width width = NativeTraits<T>::width; 14458 14459 auto checkMyDisassembly = [&] (Compilation& compilation, bool fenced) { 14460 if (isX86()) { 14461 checkUsesInstruction(compilation, "lock"); 14462 checkUsesInstruction(compilation, "cmpxchg"); 14463 } else { 14464 if (fenced) { 14465 checkUsesInstruction(compilation, "ldax"); 14466 checkUsesInstruction(compilation, "stlx"); 14467 } else { 14468 checkUsesInstruction(compilation, "ldx"); 14469 checkUsesInstruction(compilation, "stx"); 14470 } 14471 } 14472 }; 14473 14474 { 14475 Procedure proc; 14476 BasicBlock* root = proc.addBlock(); 14477 BasicBlock* reloop = proc.addBlock(); 14478 BasicBlock* done = proc.addBlock(); 14479 14480 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 14481 root->appendNew<Value>(proc, Jump, Origin()); 14482 root->setSuccessors(reloop); 14483 14484 reloop->appendNew<Value>( 14485 proc, Branch, Origin(), 14486 reloop->appendNew<AtomicValue>( 14487 proc, AtomicWeakCAS, Origin(), width, 14488 reloop->appendIntConstant(proc, Origin(), type, 42), 14489 reloop->appendIntConstant(proc, Origin(), type, 0xbeef), 14490 ptr)); 14491 reloop->setSuccessors(done, reloop); 14492 14493 done->appendNew<Value>(proc, Return, Origin()); 14494 14495 auto code = compile(proc); 14496 T value[2]; 14497 value[0] = 42; 14498 value[1] = 13; 14499 invoke<void>(*code, value); 14500 CHECK_EQ(value[0], static_cast<T>(0xbeef)); 14501 CHECK_EQ(value[1], 13); 14502 checkMyDisassembly(*code, true); 14503 } 14504 14505 { 14506 Procedure proc; 14507 BasicBlock* root = proc.addBlock(); 14508 BasicBlock* reloop = proc.addBlock(); 14509 BasicBlock* done = proc.addBlock(); 14510 14511 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 14512 root->appendNew<Value>(proc, Jump, Origin()); 14513 root->setSuccessors(reloop); 14514 14515 reloop->appendNew<Value>( 14516 proc, Branch, Origin(), 14517 reloop->appendNew<AtomicValue>( 14518 proc, AtomicWeakCAS, Origin(), width, 14519 reloop->appendIntConstant(proc, Origin(), type, 42), 14520 reloop->appendIntConstant(proc, Origin(), type, 0xbeef), 14521 ptr, 0, HeapRange(42), HeapRange())); 14522 reloop->setSuccessors(done, reloop); 14523 14524 done->appendNew<Value>(proc, Return, Origin()); 14525 14526 auto code = compile(proc); 14527 T value[2]; 14528 value[0] = 42; 14529 value[1] = 13; 14530 invoke<void>(*code, value); 14531 CHECK_EQ(value[0], static_cast<T>(0xbeef)); 14532 CHECK_EQ(value[1], 13); 14533 checkMyDisassembly(*code, false); 14534 } 14535 14536 { 14537 Procedure proc; 14538 BasicBlock* root = proc.addBlock(); 14539 BasicBlock* succ = proc.addBlock(); 14540 BasicBlock* fail = proc.addBlock(); 14541 14542 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 14543 root->appendNew<Value>( 14544 proc, Branch, Origin(), 14545 root->appendNew<AtomicValue>( 14546 proc, AtomicWeakCAS, Origin(), width, 14547 root->appendIntConstant(proc, Origin(), type, 42), 14548 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14549 ptr)); 14550 root->setSuccessors(succ, fail); 14551 14552 succ->appendNew<MemoryValue>( 14553 proc, storeOpcode(GP, width), Origin(), 14554 succ->appendIntConstant(proc, Origin(), type, 100), 14555 ptr); 14556 succ->appendNew<Value>(proc, Return, Origin()); 14557 14558 fail->appendNew<Value>(proc, Return, Origin()); 14559 14560 auto code = compile(proc); 14561 T value[2]; 14562 value[0] = 42; 14563 value[1] = 13; 14564 while (value[0] == 42) 14565 invoke<void>(*code, value); 14566 CHECK_EQ(value[0], static_cast<T>(100)); 14567 CHECK_EQ(value[1], 13); 14568 value[0] = static_cast<T>(300); 14569 invoke<void>(*code, value); 14570 CHECK_EQ(value[0], static_cast<T>(300)); 14571 CHECK_EQ(value[1], 13); 14572 checkMyDisassembly(*code, true); 14573 } 14574 14575 { 14576 Procedure proc; 14577 BasicBlock* root = proc.addBlock(); 14578 BasicBlock* succ = proc.addBlock(); 14579 BasicBlock* fail = proc.addBlock(); 14580 14581 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 14582 root->appendNew<Value>( 14583 proc, Branch, Origin(), 14584 root->appendNew<Value>( 14585 proc, Equal, Origin(), 14586 root->appendNew<AtomicValue>( 14587 proc, AtomicWeakCAS, Origin(), width, 14588 root->appendIntConstant(proc, Origin(), type, 42), 14589 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14590 ptr), 14591 root->appendIntConstant(proc, Origin(), Int32, 0))); 14592 root->setSuccessors(fail, succ); 14593 14594 succ->appendNew<MemoryValue>( 14595 proc, storeOpcode(GP, width), Origin(), 14596 succ->appendIntConstant(proc, Origin(), type, 100), 14597 ptr); 14598 succ->appendNew<Value>(proc, Return, Origin()); 14599 14600 fail->appendNew<Value>(proc, Return, Origin()); 14601 14602 auto code = compile(proc); 14603 T value[2]; 14604 value[0] = 42; 14605 value[1] = 13; 14606 while (value[0] == 42) 14607 invoke<void>(*code, value); 14608 CHECK_EQ(value[0], static_cast<T>(100)); 14609 CHECK_EQ(value[1], 13); 14610 value[0] = static_cast<T>(300); 14611 invoke<void>(*code, value); 14612 CHECK_EQ(value[0], static_cast<T>(300)); 14613 CHECK_EQ(value[1], 13); 14614 checkMyDisassembly(*code, true); 14615 } 14616 14617 { 14618 Procedure proc; 14619 BasicBlock* root = proc.addBlock(); 14620 root->appendNew<Value>( 14621 proc, Return, Origin(), 14622 root->appendNew<AtomicValue>( 14623 proc, AtomicWeakCAS, Origin(), width, 14624 root->appendIntConstant(proc, Origin(), type, 42), 14625 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14626 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); 14627 14628 auto code = compile(proc); 14629 T value[2]; 14630 value[0] = 42; 14631 value[1] = 13; 14632 while (!invoke<bool>(*code, value)) { } 14633 CHECK_EQ(value[0], static_cast<T>(0xbeef)); 14634 CHECK_EQ(value[1], 13); 14635 14636 value[0] = static_cast<T>(300); 14637 CHECK(!invoke<bool>(*code, value)); 14638 CHECK_EQ(value[0], static_cast<T>(300)); 14639 CHECK_EQ(value[1], 13); 14640 checkMyDisassembly(*code, true); 14641 } 14642 14643 { 14644 Procedure proc; 14645 BasicBlock* root = proc.addBlock(); 14646 root->appendNew<Value>( 14647 proc, Return, Origin(), 14648 root->appendNew<Value>( 14649 proc, Equal, Origin(), 14650 root->appendNew<AtomicValue>( 14651 proc, AtomicWeakCAS, Origin(), width, 14652 root->appendIntConstant(proc, Origin(), type, 42), 14653 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14654 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), 14655 root->appendNew<Const32Value>(proc, Origin(), 0))); 14656 14657 auto code = compile(proc); 14658 T value[2]; 14659 value[0] = 42; 14660 value[1] = 13; 14661 while (invoke<bool>(*code, value)) { } 14662 CHECK_EQ(value[0], static_cast<T>(0xbeef)); 14663 CHECK_EQ(value[1], 13); 14664 14665 value[0] = static_cast<T>(300); 14666 CHECK(invoke<bool>(*code, value)); 14667 CHECK_EQ(value[0], static_cast<T>(300)); 14668 CHECK_EQ(value[1], 13); 14669 checkMyDisassembly(*code, true); 14670 } 14671 14672 { 14673 Procedure proc; 14674 BasicBlock* root = proc.addBlock(); 14675 root->appendNew<Value>( 14676 proc, Return, Origin(), 14677 root->appendNew<AtomicValue>( 14678 proc, AtomicWeakCAS, Origin(), width, 14679 root->appendIntConstant(proc, Origin(), type, 42), 14680 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14681 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), 14682 42)); 14683 14684 auto code = compile(proc); 14685 T value[2]; 14686 value[0] = 42; 14687 value[1] = 13; 14688 while (!invoke<bool>(*code, bitwise_cast<intptr_t>(value) - 42)) { } 14689 CHECK_EQ(value[0], static_cast<T>(0xbeef)); 14690 CHECK_EQ(value[1], 13); 14691 14692 value[0] = static_cast<T>(300); 14693 CHECK(!invoke<bool>(*code, bitwise_cast<intptr_t>(value) - 42)); 14694 CHECK_EQ(value[0], static_cast<T>(300)); 14695 CHECK_EQ(value[1], 13); 14696 checkMyDisassembly(*code, true); 14697 } 14698 } 14699 14700 template<typename T> 14701 void testAtomicStrongCAS() 14702 { 14703 Type type = NativeTraits<T>::type; 14704 Width width = NativeTraits<T>::width; 14705 14706 auto checkMyDisassembly = [&] (Compilation& compilation, bool fenced) { 14707 if (isX86()) { 14708 checkUsesInstruction(compilation, "lock"); 14709 checkUsesInstruction(compilation, "cmpxchg"); 14710 } else { 14711 if (fenced) { 14712 checkUsesInstruction(compilation, "ldax"); 14713 checkUsesInstruction(compilation, "stlx"); 14714 } else { 14715 checkUsesInstruction(compilation, "ldx"); 14716 checkUsesInstruction(compilation, "stx"); 14717 } 14718 } 14719 }; 14720 14721 { 14722 Procedure proc; 14723 BasicBlock* root = proc.addBlock(); 14724 BasicBlock* succ = proc.addBlock(); 14725 BasicBlock* fail = proc.addBlock(); 14726 14727 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 14728 root->appendNew<Value>( 14729 proc, Branch, Origin(), 14730 root->appendNew<Value>( 14731 proc, Equal, Origin(), 14732 root->appendNew<AtomicValue>( 14733 proc, AtomicStrongCAS, Origin(), width, 14734 root->appendIntConstant(proc, Origin(), type, 42), 14735 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14736 ptr), 14737 root->appendIntConstant(proc, Origin(), type, 42))); 14738 root->setSuccessors(succ, fail); 14739 14740 succ->appendNew<MemoryValue>( 14741 proc, storeOpcode(GP, width), Origin(), 14742 succ->appendIntConstant(proc, Origin(), type, 100), 14743 ptr); 14744 succ->appendNew<Value>(proc, Return, Origin()); 14745 14746 fail->appendNew<Value>(proc, Return, Origin()); 14747 14748 auto code = compile(proc); 14749 T value[2]; 14750 value[0] = 42; 14751 value[1] = 13; 14752 invoke<void>(*code, value); 14753 CHECK_EQ(value[0], static_cast<T>(100)); 14754 CHECK_EQ(value[1], 13); 14755 value[0] = static_cast<T>(300); 14756 invoke<void>(*code, value); 14757 CHECK_EQ(value[0], static_cast<T>(300)); 14758 CHECK_EQ(value[1], 13); 14759 checkMyDisassembly(*code, true); 14760 } 14761 14762 { 14763 Procedure proc; 14764 BasicBlock* root = proc.addBlock(); 14765 BasicBlock* succ = proc.addBlock(); 14766 BasicBlock* fail = proc.addBlock(); 14767 14768 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 14769 root->appendNew<Value>( 14770 proc, Branch, Origin(), 14771 root->appendNew<Value>( 14772 proc, Equal, Origin(), 14773 root->appendNew<AtomicValue>( 14774 proc, AtomicStrongCAS, Origin(), width, 14775 root->appendIntConstant(proc, Origin(), type, 42), 14776 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14777 ptr, 0, HeapRange(42), HeapRange()), 14778 root->appendIntConstant(proc, Origin(), type, 42))); 14779 root->setSuccessors(succ, fail); 14780 14781 succ->appendNew<MemoryValue>( 14782 proc, storeOpcode(GP, width), Origin(), 14783 succ->appendIntConstant(proc, Origin(), type, 100), 14784 ptr); 14785 succ->appendNew<Value>(proc, Return, Origin()); 14786 14787 fail->appendNew<Value>(proc, Return, Origin()); 14788 14789 auto code = compile(proc); 14790 T value[2]; 14791 value[0] = 42; 14792 value[1] = 13; 14793 invoke<void>(*code, value); 14794 CHECK_EQ(value[0], static_cast<T>(100)); 14795 CHECK_EQ(value[1], 13); 14796 value[0] = static_cast<T>(300); 14797 invoke<void>(*code, value); 14798 CHECK_EQ(value[0], static_cast<T>(300)); 14799 CHECK_EQ(value[1], 13); 14800 checkMyDisassembly(*code, false); 14801 } 14802 14803 { 14804 Procedure proc; 14805 BasicBlock* root = proc.addBlock(); 14806 BasicBlock* succ = proc.addBlock(); 14807 BasicBlock* fail = proc.addBlock(); 14808 14809 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 14810 root->appendNew<Value>( 14811 proc, Branch, Origin(), 14812 root->appendNew<Value>( 14813 proc, NotEqual, Origin(), 14814 root->appendNew<AtomicValue>( 14815 proc, AtomicStrongCAS, Origin(), width, 14816 root->appendIntConstant(proc, Origin(), type, 42), 14817 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14818 ptr), 14819 root->appendIntConstant(proc, Origin(), type, 42))); 14820 root->setSuccessors(fail, succ); 14821 14822 succ->appendNew<MemoryValue>( 14823 proc, storeOpcode(GP, width), Origin(), 14824 succ->appendIntConstant(proc, Origin(), type, 100), 14825 ptr); 14826 succ->appendNew<Value>(proc, Return, Origin()); 14827 14828 fail->appendNew<Value>(proc, Return, Origin()); 14829 14830 auto code = compile(proc); 14831 T value[2]; 14832 value[0] = 42; 14833 value[1] = 13; 14834 invoke<void>(*code, value); 14835 CHECK_EQ(value[0], static_cast<T>(100)); 14836 CHECK_EQ(value[1], 13); 14837 value[0] = static_cast<T>(300); 14838 invoke<void>(*code, value); 14839 CHECK_EQ(value[0], static_cast<T>(300)); 14840 CHECK_EQ(value[1], 13); 14841 checkMyDisassembly(*code, true); 14842 } 14843 14844 { 14845 Procedure proc; 14846 BasicBlock* root = proc.addBlock(); 14847 root->appendNew<Value>( 14848 proc, Return, Origin(), 14849 root->appendNew<AtomicValue>( 14850 proc, AtomicStrongCAS, Origin(), width, 14851 root->appendIntConstant(proc, Origin(), type, 42), 14852 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14853 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); 14854 14855 auto code = compile(proc); 14856 T value[2]; 14857 value[0] = 42; 14858 value[1] = 13; 14859 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), 42); 14860 CHECK_EQ(value[0], static_cast<T>(0xbeef)); 14861 CHECK_EQ(value[1], 13); 14862 value[0] = static_cast<T>(300); 14863 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), static_cast<typename NativeTraits<T>::CanonicalType>(static_cast<T>(300))); 14864 CHECK_EQ(value[0], static_cast<T>(300)); 14865 CHECK_EQ(value[1], 13); 14866 value[0] = static_cast<T>(-1); 14867 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), static_cast<typename NativeTraits<T>::CanonicalType>(static_cast<T>(-1))); 14868 CHECK_EQ(value[0], static_cast<T>(-1)); 14869 CHECK_EQ(value[1], 13); 14870 checkMyDisassembly(*code, true); 14871 } 14872 14873 { 14874 Procedure proc; 14875 BasicBlock* root = proc.addBlock(); 14876 root->appendNew<Value>( 14877 proc, Return, Origin(), 14878 root->appendNew<Value>( 14879 proc, Equal, Origin(), 14880 root->appendNew<AtomicValue>( 14881 proc, AtomicStrongCAS, Origin(), width, 14882 root->appendIntConstant(proc, Origin(), type, 42), 14883 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14884 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), 14885 root->appendIntConstant(proc, Origin(), type, 42))); 14886 14887 auto code = compile(proc); 14888 T value[2]; 14889 value[0] = 42; 14890 value[1] = 13; 14891 CHECK(invoke<bool>(*code, value)); 14892 CHECK_EQ(value[0], static_cast<T>(0xbeef)); 14893 CHECK_EQ(value[1], 13); 14894 value[0] = static_cast<T>(300); 14895 CHECK(!invoke<bool>(*code, value)); 14896 CHECK_EQ(value[0], static_cast<T>(300)); 14897 CHECK_EQ(value[1], 13); 14898 checkMyDisassembly(*code, true); 14899 } 14900 14901 { 14902 Procedure proc; 14903 BasicBlock* root = proc.addBlock(); 14904 root->appendNew<Value>( 14905 proc, Return, Origin(), 14906 root->appendNew<Value>( 14907 proc, Equal, Origin(), 14908 root->appendNew<Value>( 14909 proc, NotEqual, Origin(), 14910 root->appendNew<AtomicValue>( 14911 proc, AtomicStrongCAS, Origin(), width, 14912 root->appendIntConstant(proc, Origin(), type, 42), 14913 root->appendIntConstant(proc, Origin(), type, 0xbeef), 14914 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), 14915 root->appendIntConstant(proc, Origin(), type, 42)), 14916 root->appendNew<Const32Value>(proc, Origin(), 0))); 14917 14918 auto code = compile(proc); 14919 T value[2]; 14920 value[0] = 42; 14921 value[1] = 13; 14922 CHECK(invoke<bool>(*code, value)); 14923 CHECK_EQ(value[0], static_cast<T>(0xbeef)); 14924 CHECK_EQ(value[1], 13); 14925 value[0] = static_cast<T>(300); 14926 CHECK(!invoke<bool>(*code, &value)); 14927 CHECK_EQ(value[0], static_cast<T>(300)); 14928 CHECK_EQ(value[1], 13); 14929 checkMyDisassembly(*code, true); 14930 } 14931 } 14932 14933 template<typename T> 14934 void testAtomicXchg(B3::Opcode opcode) 14935 { 14936 Type type = NativeTraits<T>::type; 14937 Width width = NativeTraits<T>::width; 14938 14939 auto doTheMath = [&] (T& memory, T operand) -> T { 14940 T oldValue = memory; 14941 switch (opcode) { 14942 case AtomicXchgAdd: 14943 memory += operand; 14944 break; 14945 case AtomicXchgAnd: 14946 memory &= operand; 14947 break; 14948 case AtomicXchgOr: 14949 memory |= operand; 14950 break; 14951 case AtomicXchgSub: 14952 memory -= operand; 14953 break; 14954 case AtomicXchgXor: 14955 memory ^= operand; 14956 break; 14957 case AtomicXchg: 14958 memory = operand; 14959 break; 14960 default: 14961 RELEASE_ASSERT_NOT_REACHED(); 14962 } 14963 return oldValue; 14964 }; 14965 14966 auto oldValue = [&] (T memory, T operand) -> T { 14967 return doTheMath(memory, operand); 14968 }; 14969 14970 auto newValue = [&] (T memory, T operand) -> T { 14971 doTheMath(memory, operand); 14972 return memory; 14973 }; 14974 14975 auto checkMyDisassembly = [&] (Compilation& compilation, bool fenced) { 14976 if (isX86()) 14977 checkUsesInstruction(compilation, "lock"); 14978 else { 14979 if (fenced) { 14980 checkUsesInstruction(compilation, "ldax"); 14981 checkUsesInstruction(compilation, "stlx"); 14982 } else { 14983 checkUsesInstruction(compilation, "ldx"); 14984 checkUsesInstruction(compilation, "stx"); 14985 } 14986 } 14987 }; 14988 14989 { 14990 Procedure proc; 14991 BasicBlock* root = proc.addBlock(); 14992 root->appendNew<Value>( 14993 proc, Return, Origin(), 14994 root->appendNew<AtomicValue>( 14995 proc, opcode, Origin(), width, 14996 root->appendIntConstant(proc, Origin(), type, 1), 14997 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); 14998 14999 auto code = compile(proc); 15000 T value[2]; 15001 value[0] = 5; 15002 value[1] = 100; 15003 CHECK_EQ(invoke<T>(*code, value), oldValue(5, 1)); 15004 CHECK_EQ(value[0], newValue(5, 1)); 15005 CHECK_EQ(value[1], 100); 15006 checkMyDisassembly(*code, true); 15007 } 15008 15009 { 15010 Procedure proc; 15011 BasicBlock* root = proc.addBlock(); 15012 root->appendNew<Value>( 15013 proc, Return, Origin(), 15014 root->appendNew<AtomicValue>( 15015 proc, opcode, Origin(), width, 15016 root->appendIntConstant(proc, Origin(), type, 42), 15017 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); 15018 15019 auto code = compile(proc); 15020 T value[2]; 15021 value[0] = 5; 15022 value[1] = 100; 15023 CHECK_EQ(invoke<T>(*code, value), oldValue(5, 42)); 15024 CHECK_EQ(value[0], newValue(5, 42)); 15025 CHECK_EQ(value[1], 100); 15026 checkMyDisassembly(*code, true); 15027 } 15028 15029 { 15030 Procedure proc; 15031 BasicBlock* root = proc.addBlock(); 15032 root->appendNew<AtomicValue>( 15033 proc, opcode, Origin(), width, 15034 root->appendIntConstant(proc, Origin(), type, 42), 15035 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); 15036 root->appendNew<Value>(proc, Return, Origin()); 15037 15038 auto code = compile(proc); 15039 T value[2]; 15040 value[0] = 5; 15041 value[1] = 100; 15042 invoke<T>(*code, value); 15043 CHECK_EQ(value[0], newValue(5, 42)); 15044 CHECK_EQ(value[1], 100); 15045 checkMyDisassembly(*code, true); 15046 } 15047 15048 { 15049 Procedure proc; 15050 BasicBlock* root = proc.addBlock(); 15051 root->appendNew<AtomicValue>( 15052 proc, opcode, Origin(), width, 15053 root->appendIntConstant(proc, Origin(), type, 42), 15054 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), 15055 0, HeapRange(42), HeapRange()); 15056 root->appendNew<Value>(proc, Return, Origin()); 15057 15058 auto code = compile(proc); 15059 T value[2]; 15060 value[0] = 5; 15061 value[1] = 100; 15062 invoke<T>(*code, value); 15063 CHECK_EQ(value[0], newValue(5, 42)); 15064 CHECK_EQ(value[1], 100); 15065 checkMyDisassembly(*code, false); 15066 } 15067 } 15068 15069 void testDepend32() 15070 { 15071 Procedure proc; 15072 BasicBlock* root = proc.addBlock(); 15073 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 15074 Value* first = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), ptr, 0); 15075 Value* second = root->appendNew<MemoryValue>( 15076 proc, Load, Int32, Origin(), 15077 root->appendNew<Value>( 15078 proc, Add, Origin(), ptr, 15079 root->appendNew<Value>( 15080 proc, ZExt32, Origin(), 15081 root->appendNew<Value>(proc, Depend, Origin(), first))), 15082 4); 15083 root->appendNew<Value>( 15084 proc, Return, Origin(), 15085 root->appendNew<Value>(proc, Add, Origin(), first, second)); 15086 15087 int32_t values[2]; 15088 values[0] = 42; 15089 values[1] = 0xbeef; 15090 15091 auto code = compile(proc); 15092 if (isARM64()) 15093 checkUsesInstruction(*code, "eor"); 15094 else if (isX86()) { 15095 checkDoesNotUseInstruction(*code, "mfence"); 15096 checkDoesNotUseInstruction(*code, "lock"); 15097 } 15098 CHECK_EQ(invoke<int32_t>(*code, values), 42 + 0xbeef); 15099 } 15100 15101 void testDepend64() 15102 { 15103 Procedure proc; 15104 BasicBlock* root = proc.addBlock(); 15105 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 15106 Value* first = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), ptr, 0); 15107 Value* second = root->appendNew<MemoryValue>( 15108 proc, Load, Int64, Origin(), 15109 root->appendNew<Value>( 15110 proc, Add, Origin(), ptr, 15111 root->appendNew<Value>(proc, Depend, Origin(), first)), 15112 8); 15113 root->appendNew<Value>( 15114 proc, Return, Origin(), 15115 root->appendNew<Value>(proc, Add, Origin(), first, second)); 15116 15117 int64_t values[2]; 15118 values[0] = 42; 15119 values[1] = 0xbeef; 15120 15121 auto code = compile(proc); 15122 if (isARM64()) 15123 checkUsesInstruction(*code, "eor"); 15124 else if (isX86()) { 15125 checkDoesNotUseInstruction(*code, "mfence"); 15126 checkDoesNotUseInstruction(*code, "lock"); 15127 } 15128 CHECK_EQ(invoke<int64_t>(*code, values), 42 + 0xbeef); 15129 } 15130 14280 15131 void testWasmBoundsCheck(unsigned offset) 14281 15132 { … … 14371 15222 } 14372 15223 15224 #define RUN_NOW(test) do { \ 15225 if (!shouldRun(#test)) \ 15226 break; \ 15227 dataLog(#test "...\n"); \ 15228 test; \ 15229 dataLog(#test ": OK!\n"); \ 15230 } while (false) 14373 15231 #define RUN(test) do { \ 14374 15232 if (!shouldRun(#test)) \ … … 14422 15280 }; 14423 15281 14424 // We run this test first because it fiddles with some 14425 // JSC options. 14426 testTerminalPatchpointThatNeedsToBeSpilled2(); 15282 RUN_NOW(testTerminalPatchpointThatNeedsToBeSpilled2()); 14427 15283 14428 15284 RUN(test42()); 14429 15285 RUN(testLoad42()); 15286 RUN(testLoadAcq42()); 14430 15287 RUN(testLoadOffsetImm9Max()); 14431 15288 RUN(testLoadOffsetImm9MaxPlusOne()); … … 15100 15957 RUN(testNegPtr(53)); 15101 15958 RUN(testStoreAddLoad32(46)); 15959 RUN(testStoreRelAddLoadAcq32(46)); 15102 15960 RUN(testStoreAddLoadImm32(46)); 15103 15961 RUN(testStoreAddLoad64(4600)); 15962 RUN(testStoreRelAddLoadAcq64(4600)); 15104 15963 RUN(testStoreAddLoadImm64(4600)); 15105 15964 RUN(testStoreAddLoad8(4, Load8Z)); 15965 RUN(testStoreRelAddLoadAcq8(4, Load8Z)); 15966 RUN(testStoreRelAddFenceLoadAcq8(4, Load8Z)); 15106 15967 RUN(testStoreAddLoadImm8(4, Load8Z)); 15107 15968 RUN(testStoreAddLoad8(4, Load8S)); 15969 RUN(testStoreRelAddLoadAcq8(4, Load8S)); 15108 15970 RUN(testStoreAddLoadImm8(4, Load8S)); 15109 15971 RUN(testStoreAddLoad16(6, Load16Z)); 15972 RUN(testStoreRelAddLoadAcq16(6, Load16Z)); 15110 15973 RUN(testStoreAddLoadImm16(6, Load16Z)); 15111 15974 RUN(testStoreAddLoad16(6, Load16S)); 15975 RUN(testStoreRelAddLoadAcq16(6, Load16S)); 15112 15976 RUN(testStoreAddLoadImm16(6, Load16S)); 15113 15977 RUN(testStoreAddLoad32Index(46)); … … 15832 16696 RUN(testLoadBaseIndexShift32()); 15833 16697 RUN(testOptimizeMaterialization()); 16698 16699 RUN(testAtomicWeakCAS<int8_t>()); 16700 RUN(testAtomicWeakCAS<int16_t>()); 16701 RUN(testAtomicWeakCAS<int32_t>()); 16702 RUN(testAtomicWeakCAS<int64_t>()); 16703 RUN(testAtomicStrongCAS<int8_t>()); 16704 RUN(testAtomicStrongCAS<int16_t>()); 16705 RUN(testAtomicStrongCAS<int32_t>()); 16706 RUN(testAtomicStrongCAS<int64_t>()); 16707 RUN(testAtomicXchg<int8_t>(AtomicXchgAdd)); 16708 RUN(testAtomicXchg<int16_t>(AtomicXchgAdd)); 16709 RUN(testAtomicXchg<int32_t>(AtomicXchgAdd)); 16710 RUN(testAtomicXchg<int64_t>(AtomicXchgAdd)); 16711 RUN(testAtomicXchg<int8_t>(AtomicXchgAnd)); 16712 RUN(testAtomicXchg<int16_t>(AtomicXchgAnd)); 16713 RUN(testAtomicXchg<int32_t>(AtomicXchgAnd)); 16714 RUN(testAtomicXchg<int64_t>(AtomicXchgAnd)); 16715 RUN(testAtomicXchg<int8_t>(AtomicXchgOr)); 16716 RUN(testAtomicXchg<int16_t>(AtomicXchgOr)); 16717 RUN(testAtomicXchg<int32_t>(AtomicXchgOr)); 16718 RUN(testAtomicXchg<int64_t>(AtomicXchgOr)); 16719 RUN(testAtomicXchg<int8_t>(AtomicXchgSub)); 16720 RUN(testAtomicXchg<int16_t>(AtomicXchgSub)); 16721 RUN(testAtomicXchg<int32_t>(AtomicXchgSub)); 16722 RUN(testAtomicXchg<int64_t>(AtomicXchgSub)); 16723 RUN(testAtomicXchg<int8_t>(AtomicXchgXor)); 16724 RUN(testAtomicXchg<int16_t>(AtomicXchgXor)); 16725 RUN(testAtomicXchg<int32_t>(AtomicXchgXor)); 16726 RUN(testAtomicXchg<int64_t>(AtomicXchgXor)); 16727 RUN(testAtomicXchg<int8_t>(AtomicXchg)); 16728 RUN(testAtomicXchg<int16_t>(AtomicXchg)); 16729 RUN(testAtomicXchg<int32_t>(AtomicXchg)); 16730 RUN(testAtomicXchg<int64_t>(AtomicXchg)); 16731 RUN(testDepend32()); 16732 RUN(testDepend64()); 15834 16733 15835 16734 RUN(testWasmBoundsCheck(0));
Note:
See TracChangeset
for help on using the changeset viewer.