Changeset 160878 in webkit
- Timestamp:
- Dec 19, 2013 4:49:58 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r160876 r160878 1 2013-12-19 Mark Hahnenberg <mhahnenberg@apple.com> 2 3 Put write barriers in the right places in the baseline JIT 4 https://bugs.webkit.org/show_bug.cgi?id=125975 5 6 Reviewed by Filip Pizlo. 7 8 * jit/JIT.cpp: 9 (JSC::JIT::privateCompileSlowCases): 10 * jit/JIT.h: 11 * jit/JITInlines.h: 12 (JSC::JIT::callOperation): 13 (JSC::JIT::emitArrayProfilingSite): 14 * jit/JITOpcodes.cpp: 15 (JSC::JIT::emit_op_enter): 16 (JSC::JIT::emitSlow_op_enter): 17 * jit/JITOpcodes32_64.cpp: 18 (JSC::JIT::emit_op_enter): 19 (JSC::JIT::emitSlow_op_enter): 20 * jit/JITPropertyAccess.cpp: 21 (JSC::JIT::emit_op_put_by_val): 22 (JSC::JIT::emitGenericContiguousPutByVal): 23 (JSC::JIT::emitArrayStoragePutByVal): 24 (JSC::JIT::emit_op_put_by_id): 25 (JSC::JIT::emitPutGlobalProperty): 26 (JSC::JIT::emitPutGlobalVar): 27 (JSC::JIT::emitPutClosureVar): 28 (JSC::JIT::emit_op_init_global_const): 29 (JSC::JIT::checkMarkWord): 30 (JSC::JIT::emitWriteBarrier): 31 (JSC::JIT::privateCompilePutByVal): 32 * jit/JITPropertyAccess32_64.cpp: 33 (JSC::JIT::emitGenericContiguousPutByVal): 34 (JSC::JIT::emitArrayStoragePutByVal): 35 (JSC::JIT::emit_op_put_by_id): 36 (JSC::JIT::emitSlow_op_put_by_id): 37 (JSC::JIT::emitPutGlobalProperty): 38 (JSC::JIT::emitPutGlobalVar): 39 (JSC::JIT::emitPutClosureVar): 40 (JSC::JIT::emit_op_init_global_const): 41 * jit/Repatch.cpp: 42 (JSC::emitPutReplaceStub): 43 (JSC::emitPutTransitionStub): 44 (JSC::repatchPutByID): 45 * runtime/CommonSlowPaths.cpp: 46 (JSC::SLOW_PATH_DECL): 47 * runtime/CommonSlowPaths.h: 48 1 49 2013-12-19 Brent Fulgham <bfulgham@apple.com> 2 50 -
trunk/Source/JavaScriptCore/jit/JIT.h
r160587 r160878 317 317 void testPrototype(JSValue, JumpList& failureCases, StructureStubInfo*); 318 318 319 enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilter Immediates};319 enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilterValue, ShouldFilterBaseAndValue }; 320 320 // value register in write barrier is used before any scratch registers 321 321 // so may safely be the same as either of the scratch registers. 322 void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch, RegisterID scratch2, WriteBarrierMode, WriteBarrierUseKind); 323 void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind); 322 Jump checkMarkWord(RegisterID owner, RegisterID scratch1, RegisterID scratch2); 323 Jump checkMarkWord(JSCell* owner); 324 void emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode); 325 void emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode); 326 /* 327 void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch1, RegisterID scratch2, WriteBarrierMode); 328 void emitWriteBarrier(JSCell* owner, RegisterID value, WriteBarrierMode); 329 */ 324 330 325 331 template<typename StructureType> // StructureType can be RegisterID or ImmPtr. … … 679 685 MacroAssembler::Call callOperation(J_JITOperation_EAapJcpZ, int, ArrayAllocationProfile*, const JSValue*, int32_t); 680 686 MacroAssembler::Call callOperation(J_JITOperation_EC, int, JSCell*); 687 MacroAssembler::Call callOperation(V_JITOperation_EC, JSCell*); 681 688 MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg); 682 689 #if USE(JSVALUE64) -
trunk/Source/JavaScriptCore/jit/JITInlines.h
r160244 r160878 200 200 } 201 201 202 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EC operation, JSCell* cell) 203 { 204 setupArgumentsWithExecState(TrustedImmPtr(cell)); 205 return appendCallWithExceptionCheck(operation); 206 } 207 202 208 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EP operation, int dst, void* pointer) 203 209 { -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r160213 r160878 792 792 } 793 793 794 void JIT::emit_op_enter(Instruction* )794 void JIT::emit_op_enter(Instruction* currentInstruction) 795 795 { 796 796 emitEnterOptimizationCheck(); … … 802 802 for (size_t j = 0; j < count; ++j) 803 803 emitInitRegister(virtualRegisterForLocal(j).offset()); 804 805 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enter); 806 slowPathCall.call(); 804 807 } 805 808 -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r160213 r160878 1013 1013 1014 1014 1015 void JIT::emit_op_enter(Instruction* )1015 void JIT::emit_op_enter(Instruction* currentInstruction) 1016 1016 { 1017 1017 emitEnterOptimizationCheck(); … … 1022 1022 for (int i = 0; i < m_codeBlock->m_numVars; ++i) 1023 1023 emitStore(virtualRegisterForLocal(i).offset(), jsUndefined()); 1024 1025 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enter); 1026 slowPathCall.call(); 1024 1027 } 1025 1028 -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r160092 r160878 350 350 m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done)); 351 351 352 emitWriteBarrier(regT0, regT3, regT1, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);353 352 } 354 353 … … 386 385 case ContiguousShape: 387 386 store64(regT3, BaseIndex(regT2, regT1, TimesEight)); 387 emitWriteBarrier(currentInstruction[1].u.operand, value, ShouldFilterValue); 388 388 break; 389 389 default: … … 424 424 emitGetVirtualRegister(value, regT3); 425 425 store64(regT3, BaseIndex(regT2, regT1, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); 426 emitWriteBarrier(currentInstruction[1].u.operand, value, ShouldFilterValue); 426 427 Jump end = jump(); 427 428 … … 553 554 unsigned direct = currentInstruction[8].u.operand; 554 555 556 emitWriteBarrier(baseVReg, valueVReg, ShouldFilterBaseAndValue); 557 555 558 // In order to be able to patch both the Structure, and the object offset, we store one pointer, 556 559 // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code … … 561 564 // Jump to a slow case if either the base object is an immediate, or if the Structure does not match. 562 565 emitJumpSlowCaseIfNotJSCell(regT0, baseVReg); 563 564 emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);565 566 566 567 JITPutByIdGenerator gen( … … 760 761 void JIT::emitPutGlobalProperty(uintptr_t* operandSlot, int value) 761 762 { 763 emitGetVirtualRegister(value, regT2); 764 762 765 loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0); 763 766 loadPtr(operandSlot, regT1); 764 767 negPtr(regT1); 765 emitGetVirtualRegister(value, regT2);766 768 storePtr(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue))); 767 769 } … … 823 825 case GlobalProperty: 824 826 case GlobalPropertyWithVarInjectionChecks: 827 emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue); 825 828 emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection. 826 829 emitPutGlobalProperty(operandSlot, value); … … 828 831 case GlobalVar: 829 832 case GlobalVarWithVarInjectionChecks: 833 emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue); 830 834 emitVarInjectionCheck(needsVarInjectionChecks(resolveType)); 831 835 emitPutGlobalVar(*operandSlot, value, currentInstruction[5].u.watchpointSet); … … 833 837 case ClosureVar: 834 838 case ClosureVarWithVarInjectionChecks: 839 emitWriteBarrier(scope, value, ShouldFilterValue); 835 840 emitVarInjectionCheck(needsVarInjectionChecks(resolveType)); 836 841 emitPutClosureVar(scope, *operandSlot, value); … … 861 866 { 862 867 JSGlobalObject* globalObject = m_codeBlock->globalObject(); 863 868 emitWriteBarrier(globalObject, currentInstruction[2].u.operand, ShouldFilterValue); 864 869 emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); 865 866 870 store64(regT0, currentInstruction[1].u.registerPointer); 867 if (Heap::isWriteBarrierEnabled())868 emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess);869 871 } 870 872 871 873 #endif // USE(JSVALUE64) 872 874 873 void JIT::emitWriteBarrier(RegisterID owner, RegisterID value, RegisterID scratch, RegisterID scratch2, WriteBarrierMode mode, WriteBarrierUseKind useKind) 874 { 875 JIT::Jump JIT::checkMarkWord(RegisterID owner, RegisterID scratch1, RegisterID scratch2) 876 { 877 move(owner, scratch1); 878 move(owner, scratch2); 879 880 andPtr(TrustedImmPtr(MarkedBlock::blockMask), scratch1); 881 andPtr(TrustedImmPtr(~MarkedBlock::blockMask), scratch2); 882 883 rshift32(TrustedImm32(3 + 4), scratch2); 884 885 return branchTest8(Zero, BaseIndex(scratch1, scratch2, TimesOne, MarkedBlock::offsetOfMarks())); 886 } 887 888 JIT::Jump JIT::checkMarkWord(JSCell* owner) 889 { 890 MarkedBlock* block = MarkedBlock::blockFor(owner); 891 size_t index = (reinterpret_cast<size_t>(owner) & ~MarkedBlock::blockMask) >> (3 + 4); 892 void* address = (reinterpret_cast<char*>(block) + MarkedBlock::offsetOfMarks()) + index; 893 894 return branchTest8(Zero, AbsoluteAddress(address)); 895 } 896 897 #if USE(JSVALUE64) 898 void JIT::emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode mode) 899 { 900 #if ENABLE(GGC) 901 emitGetVirtualRegister(value, regT0); 902 Jump valueNotCell; 903 if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue) 904 valueNotCell = branchTest64(NonZero, regT0, tagMaskRegister); 905 906 emitGetVirtualRegister(owner, regT0); 907 Jump ownerNotCell; 908 if (mode == ShouldFilterBaseAndValue) 909 ownerNotCell = branchTest64(NonZero, regT0, tagMaskRegister); 910 911 Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2); 912 callOperation(operationUnconditionalWriteBarrier, regT0); 913 ownerNotMarked.link(this); 914 915 if (mode == ShouldFilterBaseAndValue) 916 ownerNotCell.link(this); 917 if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue) 918 valueNotCell.link(this); 919 #else 875 920 UNUSED_PARAM(owner); 876 UNUSED_PARAM(scratch);877 UNUSED_PARAM(scratch2);878 UNUSED_PARAM(useKind);879 921 UNUSED_PARAM(value); 880 922 UNUSED_PARAM(mode); 881 ASSERT(owner != scratch); 882 ASSERT(owner != scratch2); 883 884 #if ENABLE(WRITE_BARRIER_PROFILING) 885 emitCount(WriteBarrierCounters::jitCounterFor(useKind)); 886 #endif 887 } 888 889 void JIT::emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode mode, WriteBarrierUseKind useKind) 890 { 923 #endif 924 } 925 926 void JIT::emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode mode) 927 { 928 #if ENABLE(GGC) 929 emitGetVirtualRegister(value, regT0); 930 Jump valueNotCell; 931 if (mode == ShouldFilterValue) 932 valueNotCell = branchTest64(NonZero, regT0, tagMaskRegister); 933 934 if (!MarkedBlock::blockFor(owner)->isMarked(owner)) { 935 Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2); 936 callOperation(operationUnconditionalWriteBarrier, owner); 937 ownerNotMarked.link(this); 938 } else 939 callOperation(operationUnconditionalWriteBarrier, owner); 940 941 if (mode == ShouldFilterValue) 942 valueNotCell.link(this); 943 #else 891 944 UNUSED_PARAM(owner); 892 UNUSED_PARAM(scratch);893 UNUSED_PARAM(useKind);894 945 UNUSED_PARAM(value); 895 946 UNUSED_PARAM(mode); 896 897 #if ENABLE(WRITE_BARRIER_PROFILING) 898 emitCount(WriteBarrierCounters::jitCounterFor(useKind)); 899 #endif 900 } 947 #endif 948 } 949 950 #else // USE(JSVALUE64) 951 952 void JIT::emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode mode) 953 { 954 #if ENABLE(GGC) 955 emitLoadTag(value, regT0); 956 Jump valueNotCell; 957 if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue) 958 valueNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag)); 959 960 emitLoad(owner, regT0, regT1); 961 Jump ownerNotCell; 962 if (mode == ShouldFilterBaseAndValue) 963 ownerNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag)); 964 965 Jump ownerNotMarked = checkMarkWord(regT1, regT0, regT2); 966 callOperation(operationUnconditionalWriteBarrier, regT1); 967 ownerNotMarked.link(this); 968 969 if (mode == ShouldFilterBaseAndValue) 970 ownerNotCell.link(this); 971 if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue) 972 valueNotCell.link(this); 973 #else 974 UNUSED_PARAM(owner); 975 UNUSED_PARAM(value); 976 UNUSED_PARAM(mode); 977 #endif 978 } 979 980 void JIT::emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode mode) 981 { 982 #if ENABLE(GGC) 983 emitLoadTag(value, regT0); 984 Jump valueNotCell; 985 if (mode == ShouldFilterValue) 986 valueNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag)); 987 988 if (!MarkedBlock::blockFor(owner)->isMarked(owner)) { 989 Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2); 990 callOperation(operationUnconditionalWriteBarrier, owner); 991 ownerNotMarked.link(this); 992 } else 993 callOperation(operationUnconditionalWriteBarrier, owner); 994 995 if (mode == ShouldFilterValue) 996 valueNotCell.link(this); 997 #else 998 UNUSED_PARAM(owner); 999 UNUSED_PARAM(value); 1000 UNUSED_PARAM(mode); 1001 #endif 1002 } 1003 1004 #endif // USE(JSVALUE64) 901 1005 902 1006 JIT::Jump JIT::addStructureTransitionCheck(JSCell* object, Structure* structure, StructureStubInfo* stubInfo, RegisterID scratch) … … 989 1093 PatchableJump badType; 990 1094 JumpList slowCases; 991 1095 1096 #if ENABLE(GGC) 1097 bool needsLinkForWriteBarrier = false; 1098 #endif 1099 992 1100 switch (arrayMode) { 993 1101 case JITInt32: … … 999 1107 case JITContiguous: 1000 1108 slowCases = emitContiguousPutByVal(currentInstruction, badType); 1109 #if ENABLE(GGC) 1110 needsLinkForWriteBarrier = true; 1111 #endif 1001 1112 break; 1002 1113 case JITArrayStorage: 1003 1114 slowCases = emitArrayStoragePutByVal(currentInstruction, badType); 1115 #if ENABLE(GGC) 1116 needsLinkForWriteBarrier = true; 1117 #endif 1004 1118 break; 1005 1119 default: … … 1015 1129 1016 1130 LinkBuffer patchBuffer(*m_vm, this, m_codeBlock); 1017 1018 1131 patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath)); 1019 1132 patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath)); 1020 1021 1133 patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone)); 1134 #if ENABLE(GGC) 1135 if (needsLinkForWriteBarrier) { 1136 ASSERT(m_calls.last().to == operationUnconditionalWriteBarrier); 1137 patchBuffer.link(m_calls.last().from, operationUnconditionalWriteBarrier); 1138 } 1139 #endif 1022 1140 1023 1141 bool isDirect = m_interpreter->getOpcodeID(currentInstruction->u.opcode) == op_put_by_val_direct; -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r160092 r160878 313 313 JIT::JumpList JIT::emitGenericContiguousPutByVal(Instruction* currentInstruction, PatchableJump& badType, IndexingType indexingShape) 314 314 { 315 int base = currentInstruction[1].u.operand; 315 316 int value = currentInstruction[3].u.operand; 316 317 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; … … 328 329 case Int32Shape: 329 330 slowCases.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 330 // Fall through. 331 store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 332 store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 333 break; 331 334 case ContiguousShape: 332 335 store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 333 336 store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 337 emitLoad(base, regT2, regT3); 338 emitWriteBarrier(base, value, ShouldFilterValue); 334 339 break; 335 340 case DoubleShape: { … … 362 367 done.link(this); 363 368 364 emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);365 366 369 return slowCases; 367 370 } … … 369 372 JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, PatchableJump& badType) 370 373 { 374 int base = currentInstruction[1].u.operand; 371 375 int value = currentInstruction[3].u.operand; 372 376 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; … … 398 402 end.link(this); 399 403 400 emitWriteBarrier( regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);404 emitWriteBarrier(base, value, ShouldFilterValue); 401 405 402 406 return slowCases; … … 516 520 int direct = currentInstruction[8].u.operand; 517 521 522 emitWriteBarrier(base, value, ShouldFilterBaseAndValue); 523 518 524 emitLoad2(base, regT1, regT0, value, regT3, regT2); 519 525 520 526 emitJumpSlowCaseIfNotJSCell(base, regT1); 521 527 522 emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess); 523 528 emitLoad(base, regT1, regT0); 529 emitLoad(value, regT3, regT2); 530 524 531 JITPutByIdGenerator gen( 525 532 m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(), … … 795 802 void JIT::emitPutGlobalProperty(uintptr_t* operandSlot, int value) 796 803 { 804 emitLoad(value, regT3, regT2); 805 797 806 loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0); 798 807 loadPtr(operandSlot, regT1); 799 808 negPtr(regT1); 800 emitLoad(value, regT3, regT2);801 809 store32(regT3, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); 802 810 store32(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); … … 867 875 case GlobalProperty: 868 876 case GlobalPropertyWithVarInjectionChecks: 877 emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue); 869 878 emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection. 870 879 emitPutGlobalProperty(operandSlot, value); … … 872 881 case GlobalVar: 873 882 case GlobalVarWithVarInjectionChecks: 883 emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue); 874 884 emitVarInjectionCheck(needsVarInjectionChecks(resolveType)); 875 885 emitPutGlobalVar(*operandSlot, value, currentInstruction[5].u.watchpointSet); … … 877 887 case ClosureVar: 878 888 case ClosureVarWithVarInjectionChecks: 889 emitWriteBarrier(scope, value, ShouldFilterValue); 879 890 emitVarInjectionCheck(needsVarInjectionChecks(resolveType)); 880 891 emitPutClosureVar(scope, *operandSlot, value); … … 909 920 JSGlobalObject* globalObject = m_codeBlock->globalObject(); 910 921 922 emitWriteBarrier(globalObject, value, ShouldFilterValue); 923 911 924 emitLoad(value, regT1, regT0); 912 925 913 if (Heap::isWriteBarrierEnabled()) {914 move(TrustedImmPtr(globalObject), regT2);915 916 emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess);917 }918 919 926 store32(regT1, registerPointer->tagPointer()); 920 927 store32(regT0, registerPointer->payloadPointer()); -
trunk/Source/JavaScriptCore/jit/Repatch.cpp
r160688 r160878 31 31 #include "CCallHelpers.h" 32 32 #include "CallFrameInlines.h" 33 #include "DFGOperations.h" 34 #include "DFGSpeculativeJIT.h" 33 35 #include "FTLThunks.h" 34 36 #include "GCAwareJITStubRoutine.h" … … 789 791 #endif 790 792 GPRReg valueGPR = static_cast<GPRReg>(stubInfo.patch.valueGPR); 791 GPRReg scratchGPR = TempRegisterSet(stubInfo.patch.usedRegisters).getFreeGPR(); 792 bool needToRestoreScratch = false; 793 #if ENABLE(WRITE_BARRIER_PROFILING) 794 GPRReg scratchGPR2; 795 const bool writeBarrierNeeded = true; 796 #else 797 const bool writeBarrierNeeded = false; 798 #endif 799 800 MacroAssembler stubJit; 801 802 if (scratchGPR == InvalidGPRReg && (writeBarrierNeeded || isOutOfLineOffset(slot.cachedOffset()))) { 803 #if USE(JSVALUE64) 804 scratchGPR = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR); 805 #else 806 scratchGPR = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, valueTagGPR); 807 #endif 808 needToRestoreScratch = true; 809 stubJit.pushToSave(scratchGPR); 810 } 793 794 ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters); 795 allocator.lock(baseGPR); 796 #if USE(JSVALUE32_64) 797 allocator.lock(valueTagGPR); 798 #endif 799 allocator.lock(valueGPR); 800 801 GPRReg scratchGPR1 = allocator.allocateScratchGPR(); 802 #if ENABLE(GGC) 803 GPRReg scratchGPR2 = allocator.allocateScratchGPR(); 804 #endif 805 806 CCallHelpers stubJit(vm, exec->codeBlock()); 807 808 allocator.preserveReusedRegistersByPushing(stubJit); 811 809 812 810 MacroAssembler::Jump badStructure = stubJit.branchPtr( … … 814 812 MacroAssembler::Address(baseGPR, JSCell::structureOffset()), 815 813 MacroAssembler::TrustedImmPtr(structure)); 816 817 #if ENABLE(WRITE_BARRIER_PROFILING) 818 #if USE(JSVALUE64) 819 scratchGPR2 = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, scratchGPR); 820 #else 821 scratchGPR2 = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, valueTagGPR, scratchGPR); 822 #endif 823 stubJit.pushToSave(scratchGPR2); 824 AssemblyHelpers::writeBarrier(stubJit, baseGPR, scratchGPR, scratchGPR2, WriteBarrierForPropertyAccess); 825 stubJit.popToRestore(scratchGPR2); 826 #endif 827 814 828 815 #if USE(JSVALUE64) 829 816 if (isInlineOffset(slot.cachedOffset())) 830 817 stubJit.store64(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue))); 831 818 else { 832 stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR );833 stubJit.store64(valueGPR, MacroAssembler::Address(scratchGPR , offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue)));819 stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR1); 820 stubJit.store64(valueGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue))); 834 821 } 835 822 #elif USE(JSVALUE32_64) … … 838 825 stubJit.store32(valueTagGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); 839 826 } else { 840 stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR); 841 stubJit.store32(valueGPR, MacroAssembler::Address(scratchGPR, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); 842 stubJit.store32(valueTagGPR, MacroAssembler::Address(scratchGPR, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); 843 } 827 stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR1); 828 stubJit.store32(valueGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); 829 stubJit.store32(valueTagGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); 830 } 831 #endif 832 833 #if ENABLE(GGC) 834 MacroAssembler::Call writeBarrierOperation = DFG::SpeculativeJIT::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2); 844 835 #endif 845 836 … … 847 838 MacroAssembler::Jump failure; 848 839 849 if ( needToRestoreScratch) {850 stubJit.popToRestore(scratchGPR);840 if (allocator.didReuseRegisters()) { 841 allocator.restoreReusedRegistersByPopping(stubJit); 851 842 success = stubJit.jump(); 852 843 853 844 badStructure.link(&stubJit); 854 stubJit.popToRestore(scratchGPR);845 allocator.restoreReusedRegistersByPopping(stubJit); 855 846 failure = stubJit.jump(); 856 847 } else { … … 860 851 861 852 LinkBuffer patchBuffer(*vm, &stubJit, exec->codeBlock()); 853 #if ENABLE(GGC) 854 patchBuffer.link(writeBarrierOperation, operationFlushWriteBarrierBuffer); 855 #endif 862 856 patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone)); 863 857 patchBuffer.link(failure, failureLabel); … … 901 895 CCallHelpers stubJit(vm); 902 896 897 bool needThirdScratch = false; 898 if (structure->outOfLineCapacity() != oldStructure->outOfLineCapacity() 899 && oldStructure->outOfLineCapacity()) { 900 needThirdScratch = true; 901 } 902 903 903 GPRReg scratchGPR1 = allocator.allocateScratchGPR(); 904 904 ASSERT(scratchGPR1 != baseGPR); 905 905 ASSERT(scratchGPR1 != valueGPR); 906 906 907 bool needSecondScratch = false; 908 bool needThirdScratch = false; 909 #if ENABLE(WRITE_BARRIER_PROFILING) 910 needSecondScratch = true; 911 #endif 912 if (structure->outOfLineCapacity() != oldStructure->outOfLineCapacity() 913 && oldStructure->outOfLineCapacity()) { 914 needSecondScratch = true; 915 needThirdScratch = true; 916 } 917 918 GPRReg scratchGPR2; 919 if (needSecondScratch) { 920 scratchGPR2 = allocator.allocateScratchGPR(); 921 ASSERT(scratchGPR2 != baseGPR); 922 ASSERT(scratchGPR2 != valueGPR); 923 ASSERT(scratchGPR2 != scratchGPR1); 924 } else 925 scratchGPR2 = InvalidGPRReg; 907 GPRReg scratchGPR2 = allocator.allocateScratchGPR(); 908 ASSERT(scratchGPR2 != baseGPR); 909 ASSERT(scratchGPR2 != valueGPR); 910 ASSERT(scratchGPR2 != scratchGPR1); 911 926 912 GPRReg scratchGPR3; 927 913 if (needThirdScratch) { … … 933 919 } else 934 920 scratchGPR3 = InvalidGPRReg; 935 921 936 922 allocator.preserveReusedRegistersByPushing(stubJit); 937 923 … … 954 940 } 955 941 956 #if ENABLE(WRITE_BARRIER_PROFILING)957 ASSERT(needSecondScratch);958 ASSERT(scratchGPR2 != InvalidGPRReg);959 // Must always emit this write barrier as the structure transition itself requires it960 AssemblyHelpers::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2, WriteBarrierForPropertyAccess);961 #endif962 963 942 MacroAssembler::JumpList slowPath; 964 943 … … 1019 998 #endif 1020 999 1000 #if ENABLE(GGC) 1001 MacroAssembler::Call writeBarrierOperation = DFG::SpeculativeJIT::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2); 1002 #endif 1003 1021 1004 MacroAssembler::Jump success; 1022 1005 MacroAssembler::Jump failure; … … 1052 1035 1053 1036 LinkBuffer patchBuffer(*vm, &stubJit, exec->codeBlock()); 1037 #if ENABLE(GGC) 1038 patchBuffer.link(writeBarrierOperation, operationFlushWriteBarrierBuffer); 1039 #endif 1054 1040 patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone)); 1055 1041 if (allocator.didReuseRegisters()) -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r160587 r160878 516 516 } 517 517 518 SLOW_PATH_DECL(slow_path_enter) 519 { 520 BEGIN(); 521 ScriptExecutable* ownerExecutable = exec->codeBlock()->ownerExecutable(); 522 Heap::heap(ownerExecutable)->writeBarrier(ownerExecutable); 523 END(); 524 } 525 518 526 } // namespace JSC 519 527 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h
r160665 r160878 164 164 SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments); 165 165 SLOW_PATH_HIDDEN_DECL(slow_path_create_this); 166 SLOW_PATH_HIDDEN_DECL(slow_path_enter); 166 167 SLOW_PATH_HIDDEN_DECL(slow_path_get_callee); 167 168 SLOW_PATH_HIDDEN_DECL(slow_path_to_this);
Note: See TracChangeset
for help on using the changeset viewer.