Changeset 185772 in webkit
- Timestamp:
- Jun 19, 2015, 3:28:18 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
ftl/FTLCompile.cpp (modified) (5 diffs)
-
ftl/FTLJITFinalizer.cpp (modified) (1 diff)
-
ftl/FTLJITFinalizer.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r185770 r185772 1 2015-06-19 Michael Saboff <msaboff@apple.com> 2 3 Crash in com.apple.WebKit.WebContent at com.apple.JavaScriptCore: JSC::FTL::fixFunctionBasedOnStackMaps + 17225 4 https://bugs.webkit.org/show_bug.cgi?id=146133 5 6 Reviewed by Geoffrey Garen. 7 8 When generating code to put in inline caching areas, if there isn't enough space, 9 then create and link to an out of line area. We connect the inline code to this 10 out of line code area by planting a jump from the inline area to the out of line 11 code and appending a jump at the end of the out of line code bck to the instruction 12 following the inline area. We fill the unused inline area with nops, primarily to 13 ensure the disassembler doesn't get confused. 14 15 * ftl/FTLCompile.cpp: 16 (generateInlineIfPossibleOutOfLineIfNot): New function that determines if there is enough space 17 in the inline code area for the code to link. If so, it links inline, otherwise it links the 18 code out of line and plants appropriate jumps to/from the out of line code. 19 (generateICFastPath): 20 (generateCheckInICFastPath): 21 (fixFunctionBasedOnStackMaps): 22 Use generateInlineIfPossibleOutOfLineIfNot() to link code intended for inline cache space. 23 24 * ftl/FTLJITFinalizer.cpp: 25 (JSC::FTL::JITFinalizer::finalizeFunction): 26 * ftl/FTLJITFinalizer.h: 27 (JSC::FTL::OutOfLineCodeInfo::OutOfLineCodeInfo): 28 Added code to finalize any out of line LinkBuffer created by generateInlineIfPossibleOutOfLineIfNot(). 29 1 30 2015-06-19 Geoffrey Garen <ggaren@apple.com> 2 31 -
trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp
r184828 r185772 156 156 } 157 157 158 static void generateInlineIfPossibleOutOfLineIfNot(State& state, VM& vm, CodeBlock* codeBlock, CCallHelpers& code, char* startOfInlineCode, size_t sizeOfInlineCode, const char* codeDescription, const std::function<void(LinkBuffer&, CCallHelpers&, bool wasCompiledInline)>& callback) 159 { 160 std::unique_ptr<LinkBuffer> codeLinkBuffer; 161 size_t actualCodeSize = code.m_assembler.buffer().codeSize(); 162 163 if (actualCodeSize <= sizeOfInlineCode) { 164 LinkBuffer codeLinkBuffer(vm, code, startOfInlineCode, sizeOfInlineCode); 165 166 // Fill the remainder of the inline space with nops to avoid confusing the disassembler. 167 MacroAssembler::AssemblerType_T::fillNops(bitwise_cast<char*>(startOfInlineCode) + actualCodeSize, sizeOfInlineCode - actualCodeSize); 168 169 callback(codeLinkBuffer, code, true); 170 171 return; 172 } 173 174 // If there isn't enough space in the provided inline code area, allocate out of line 175 // executable memory to link the provided code. Place a jump at the beginning of the 176 // inline area and jump to the out of line code. Similarly return by appending a jump 177 // to the provided code that goes to the instruction after the inline code. 178 // Fill the middle with nop's. 179 MacroAssembler::Jump returnToMainline = code.jump(); 180 181 // Allocate out of line executable memory and link the provided code there. 182 codeLinkBuffer = std::make_unique<LinkBuffer>(vm, code, codeBlock, JITCompilationMustSucceed); 183 184 // Plant a jmp in the inline buffer to the out of line code. 185 MacroAssembler callToOutOfLineCode; 186 MacroAssembler::Jump jumpToOutOfLine = callToOutOfLineCode.jump(); 187 LinkBuffer inlineBuffer(vm, callToOutOfLineCode, startOfInlineCode, sizeOfInlineCode); 188 inlineBuffer.link(jumpToOutOfLine, codeLinkBuffer->entrypoint()); 189 190 // Fill the remainder of the inline space with nops to avoid confusing the disassembler. 191 MacroAssembler::AssemblerType_T::fillNops(bitwise_cast<char*>(startOfInlineCode) + inlineBuffer.size(), sizeOfInlineCode - inlineBuffer.size()); 192 193 // Link the end of the out of line code to right after the inline area. 194 codeLinkBuffer->link(returnToMainline, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(startOfInlineCode)).labelAtOffset(sizeOfInlineCode)); 195 196 callback(*codeLinkBuffer.get(), code, false); 197 198 state.finalizer->outOfLineCodeInfos.append(OutOfLineCodeInfo(WTF::move(codeLinkBuffer), codeDescription)); 199 } 200 158 201 template<typename DescriptorType> 159 202 void generateICFastPath( … … 182 225 char* startOfIC = 183 226 bitwise_cast<char*>(generatedFunction) + record.instructionOffset; 184 185 LinkBuffer linkBuffer(vm, fastPathJIT, startOfIC, sizeOfIC); 186 // Note: we could handle the !isValid() case. We just don't appear to have a 187 // reason to do so, yet. 188 RELEASE_ASSERT(linkBuffer.isValid()); 189 190 MacroAssembler::AssemblerType_T::fillNops( 191 startOfIC + linkBuffer.size(), sizeOfIC - linkBuffer.size()); 192 193 state.finalizer->sideCodeLinkBuffer->link( 194 ic.m_slowPathDone[i], CodeLocationLabel(startOfIC + sizeOfIC)); 195 196 linkBuffer.link( 197 generator.slowPathJump(), 198 state.finalizer->sideCodeLinkBuffer->locationOf(generator.slowPathBegin())); 199 200 generator.finalize(linkBuffer, *state.finalizer->sideCodeLinkBuffer); 227 228 generateInlineIfPossibleOutOfLineIfNot(state, vm, codeBlock, fastPathJIT, startOfIC, sizeOfIC, "inline cache fast path", [&] (LinkBuffer& linkBuffer, CCallHelpers&, bool) { 229 state.finalizer->sideCodeLinkBuffer->link(ic.m_slowPathDone[i], 230 CodeLocationLabel(startOfIC + sizeOfIC)); 231 232 linkBuffer.link(generator.slowPathJump(), 233 state.finalizer->sideCodeLinkBuffer->locationOf(generator.slowPathBegin())); 234 235 generator.finalize(linkBuffer, *state.finalizer->sideCodeLinkBuffer); 236 }); 201 237 } 202 238 } … … 233 269 char* startOfIC = 234 270 bitwise_cast<char*>(generatedFunction) + record.instructionOffset; 235 236 LinkBuffer fastPath(vm, fastPathJIT, startOfIC, sizeOfIC); 237 LinkBuffer& slowPath = *state.finalizer->sideCodeLinkBuffer; 238 // Note: we could handle the !isValid() case. We just don't appear to have a 239 // reason to do so, yet. 240 RELEASE_ASSERT(fastPath.isValid()); 241 242 MacroAssembler::AssemblerType_T::fillNops( 243 startOfIC + fastPath.size(), sizeOfIC - fastPath.size()); 244 245 state.finalizer->sideCodeLinkBuffer->link( 246 ic.m_slowPathDone[i], CodeLocationLabel(startOfIC + sizeOfIC)); 247 248 CodeLocationLabel slowPathBeginLoc = slowPath.locationOf(slowPathBegin); 249 fastPath.link(jump, slowPathBeginLoc); 250 251 CodeLocationCall callReturnLocation = slowPath.locationOf(call); 252 253 stubInfo.patch.deltaCallToDone = MacroAssembler::differenceBetweenCodePtr( 254 callReturnLocation, fastPath.locationOf(done)); 255 256 stubInfo.patch.deltaCallToJump = MacroAssembler::differenceBetweenCodePtr( 257 callReturnLocation, fastPath.locationOf(jump)); 258 stubInfo.callReturnLocation = callReturnLocation; 259 stubInfo.patch.deltaCallToSlowCase = MacroAssembler::differenceBetweenCodePtr( 260 callReturnLocation, slowPathBeginLoc); 261 271 272 auto postLink = [&] (LinkBuffer& fastPath, CCallHelpers&, bool) { 273 LinkBuffer& slowPath = *state.finalizer->sideCodeLinkBuffer; 274 275 state.finalizer->sideCodeLinkBuffer->link( 276 ic.m_slowPathDone[i], CodeLocationLabel(startOfIC + sizeOfIC)); 277 278 CodeLocationLabel slowPathBeginLoc = slowPath.locationOf(slowPathBegin); 279 fastPath.link(jump, slowPathBeginLoc); 280 281 CodeLocationCall callReturnLocation = slowPath.locationOf(call); 282 283 stubInfo.patch.deltaCallToDone = MacroAssembler::differenceBetweenCodePtr( 284 callReturnLocation, fastPath.locationOf(done)); 285 286 stubInfo.patch.deltaCallToJump = MacroAssembler::differenceBetweenCodePtr( 287 callReturnLocation, fastPath.locationOf(jump)); 288 stubInfo.callReturnLocation = callReturnLocation; 289 stubInfo.patch.deltaCallToSlowCase = MacroAssembler::differenceBetweenCodePtr( 290 callReturnLocation, slowPathBeginLoc); 291 }; 292 293 generateInlineIfPossibleOutOfLineIfNot(state, vm, codeBlock, fastPathJIT, startOfIC, sizeOfIC, "CheckIn inline cache", postLink); 262 294 } 263 295 } … … 560 592 CCallHelpers fastPathJIT(&vm, codeBlock); 561 593 call.emit(fastPathJIT); 562 594 563 595 char* startOfIC = bitwise_cast<char*>(generatedFunction) + call.m_instructionOffset; 564 565 LinkBuffer linkBuffer(vm, fastPathJIT, startOfIC, sizeOfCall()); 566 if (!linkBuffer.isValid()) { 567 dataLog("Failed to insert inline cache for call because we thought the size would be ", sizeOfCall(), " but it ended up being ", fastPathJIT.m_assembler.codeSize(), " prior to compaction.\n"); 568 RELEASE_ASSERT_NOT_REACHED(); 569 } 570 571 MacroAssembler::AssemblerType_T::fillNops( 572 startOfIC + linkBuffer.size(), sizeOfCall() - linkBuffer.size()); 573 574 call.link(vm, linkBuffer); 596 597 generateInlineIfPossibleOutOfLineIfNot(state, vm, codeBlock, fastPathJIT, startOfIC, sizeOfCall(), "JSCall inline cache", [&] (LinkBuffer& linkBuffer, CCallHelpers&, bool) { 598 call.link(vm, linkBuffer); 599 }); 575 600 } 576 601 … … 582 607 CCallHelpers fastPathJIT(&vm, codeBlock); 583 608 call.emit(fastPathJIT, varargsSpillSlotsOffset); 584 609 585 610 char* startOfIC = bitwise_cast<char*>(generatedFunction) + call.m_instructionOffset; 586 611 size_t sizeOfIC = sizeOfICFor(call.node()); 587 612 588 LinkBuffer linkBuffer(vm, fastPathJIT, startOfIC, sizeOfIC); 589 if (!linkBuffer.isValid()) { 590 dataLog("Failed to insert inline cache for varargs call (specifically, ", Graph::opName(call.node()->op()), ") because we thought the size would be ", sizeOfIC, " but it ended up being ", fastPathJIT.m_assembler.codeSize(), " prior to compaction.\n"); 591 RELEASE_ASSERT_NOT_REACHED(); 592 } 593 594 MacroAssembler::AssemblerType_T::fillNops( 595 startOfIC + linkBuffer.size(), sizeOfIC - linkBuffer.size()); 596 597 call.link(vm, linkBuffer, state.finalizer->handleExceptionsLinkBuffer->entrypoint()); 613 generateInlineIfPossibleOutOfLineIfNot(state, vm, codeBlock, fastPathJIT, startOfIC, sizeOfIC, "varargs call inline cache", [&] (LinkBuffer& linkBuffer, CCallHelpers&, bool) { 614 call.link(vm, linkBuffer, state.finalizer->handleExceptionsLinkBuffer->entrypoint()); 615 }); 598 616 } 599 617 -
trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp
r171076 r185772 128 128 .executableMemory()); 129 129 } 130 130 131 for (unsigned i = 0; i < outOfLineCodeInfos.size(); ++i) { 132 jitCode->addHandle(FINALIZE_DFG_CODE( 133 *outOfLineCodeInfos[i].m_linkBuffer, 134 ("FTL out of line code for %s", outOfLineCodeInfos[i].m_codeDescription)).executableMemory()); 135 } 136 131 137 jitCode->initializeArityCheckEntrypoint( 132 138 FINALIZE_DFG_CODE( -
trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.h
r177222 r185772 40 40 namespace JSC { namespace FTL { 41 41 42 class OutOfLineCodeInfo { 43 public: 44 OutOfLineCodeInfo(std::unique_ptr<LinkBuffer> linkBuffer, const char* codeDescription) 45 : m_linkBuffer(WTF::move(linkBuffer)) 46 , m_codeDescription(codeDescription) 47 { 48 } 49 50 std::unique_ptr<LinkBuffer> m_linkBuffer; 51 const char* m_codeDescription; 52 }; 53 42 54 class JITFinalizer : public DFG::Finalizer { 43 55 public: 44 56 JITFinalizer(DFG::Plan&); 45 57 virtual ~JITFinalizer(); 46 58 47 59 size_t codeSize() override; 48 60 bool finalize() override; … … 53 65 std::unique_ptr<LinkBuffer> sideCodeLinkBuffer; 54 66 std::unique_ptr<LinkBuffer> handleExceptionsLinkBuffer; 67 Vector<OutOfLineCodeInfo> outOfLineCodeInfos; 55 68 Vector<SlowPathCall> slowPathCalls; // Calls inside the side code. 56 69 Vector<OSRExitCompilationInfo> osrExit;
Note:
See TracChangeset
for help on using the changeset viewer.