Changeset 164205 in webkit
- Timestamp:
- Feb 16, 2014, 10:25:05 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 7 edited
-
ChangeLog (modified) (1 diff)
-
dfg/DFGOSREntry.cpp (modified) (3 diffs)
-
dfg/DFGOSREntry.h (modified) (1 diff)
-
dfg/DFGThunks.cpp (modified) (2 diffs)
-
dfg/DFGThunks.h (modified) (2 diffs)
-
jit/JITOpcodes.cpp (modified) (1 diff)
-
jit/JITOperations.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r164185 r164205 1 2014-02-16 Filip Pizlo <fpizlo@apple.com> 2 3 DFG::prepareOSREntry should be nice to the stack 4 https://bugs.webkit.org/show_bug.cgi?id=128883 5 6 Reviewed by Oliver Hunt. 7 8 Previously OSR entry had some FIXME's and some really badly commented-out code for 9 clearing stack entries to help GC. It also did some permutations on a stack frame 10 above us, in such a way that it wasn't obviously that we wouldn't clobber our own 11 stack frame. This function also crashed in ASan. 12 13 It just seems like there was too much badness to the whole idea of prepareOSREntry 14 directly editing the stack. So, I changed it to create a stack frame in a scratch 15 buffer on the side and then have some assembly code just copy it into place. This 16 works fine, fixes a FIXME, possibly fixes some stack clobbering, and might help us 17 make more progress with ASan. 18 19 * dfg/DFGOSREntry.cpp: 20 (JSC::DFG::prepareOSREntry): 21 * dfg/DFGOSREntry.h: 22 * dfg/DFGThunks.cpp: 23 (JSC::DFG::osrEntryThunkGenerator): 24 * dfg/DFGThunks.h: 25 * jit/JITOpcodes.cpp: 26 (JSC::JIT::emitSlow_op_loop_hint): 27 * jit/JITOperations.cpp: 28 1 29 2014-02-15 Filip Pizlo <fpizlo@apple.com> 2 30 -
trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
r163844 r164205 1 1 /* 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 189 189 // would have otherwise just kept running albeit less quickly. 190 190 191 unsigned frameSize = jitCode->common.requiredRegisterCountForExecutionAndExit();192 if (!vm->interpreter->stack().ensureCapacityFor(&exec->registers()[virtualRegisterForLocal(frameSize - 1).offset()])) {191 unsigned frameSizeForCheck = jitCode->common.requiredRegisterCountForExecutionAndExit(); 192 if (!vm->interpreter->stack().ensureCapacityFor(&exec->registers()[virtualRegisterForLocal(frameSizeForCheck - 1).offset()])) { 193 193 if (Options::verboseOSR()) 194 194 dataLogF(" OSR failed because stack growth failed.\n"); … … 198 198 if (Options::verboseOSR()) 199 199 dataLogF(" OSR should succeed.\n"); 200 201 // 3) Perform data format conversions. 202 for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) { 203 if (entry->m_localsForcedDouble.get(local)) 204 *bitwise_cast<double*>(exec->registers() + virtualRegisterForLocal(local).offset()) = exec->registers()[virtualRegisterForLocal(local).offset()].jsValue().asNumber(); 205 if (entry->m_localsForcedMachineInt.get(local)) 206 *bitwise_cast<int64_t*>(exec->registers() + virtualRegisterForLocal(local).offset()) = exec->registers()[virtualRegisterForLocal(local).offset()].jsValue().asMachineInt() << JSValue::int52ShiftAmount; 200 201 // At this point we're committed to entering. We will do some work to set things up, 202 // but we also rely on our caller recognizing that when we return a non-null pointer, 203 // that means that we're already past the point of no return and we must succeed at 204 // entering. 205 206 // 3) Set up the data in the scratch buffer and perform data format conversions. 207 208 unsigned frameSize = jitCode->common.frameRegisterCount; 209 210 Register* scratch = bitwise_cast<Register*>(vm->scratchBufferForSize(sizeof(Register) * (2 + JSStack::CallFrameHeaderSize + frameSize))->dataBuffer()); 211 212 *bitwise_cast<size_t*>(scratch + 0) = frameSize; 213 214 void* targetPC = codeBlock->jitCode()->executableAddressAtOffset(entry->m_machineCodeOffset); 215 if (Options::verboseOSR()) 216 dataLogF(" OSR using target PC %p.\n", targetPC); 217 RELEASE_ASSERT(targetPC); 218 *bitwise_cast<void**>(scratch + 1) = targetPC; 219 220 Register* pivot = scratch + 2 + JSStack::CallFrameHeaderSize; 221 222 for (int index = -JSStack::CallFrameHeaderSize; index < static_cast<int>(frameSize); ++index) { 223 VirtualRegister reg(-1 - index); 224 225 if (reg.isLocal()) { 226 if (entry->m_localsForcedDouble.get(reg.toLocal())) { 227 *bitwise_cast<double*>(pivot + index) = exec->registers()[reg.offset()].jsValue().asNumber(); 228 continue; 229 } 230 231 if (entry->m_localsForcedMachineInt.get(reg.toLocal())) { 232 *bitwise_cast<int64_t*>(pivot + index) = exec->registers()[reg.offset()].jsValue().asMachineInt() << JSValue::int52ShiftAmount; 233 continue; 234 } 235 } 236 237 pivot[index] = exec->registers()[reg.offset()].jsValue(); 207 238 } 208 239 209 240 // 4) Reshuffle those registers that need reshuffling. 210 211 Vector<EncodedJSValue> temporaryLocals(entry->m_reshufflings.size()); 212 EncodedJSValue* registers = bitwise_cast<EncodedJSValue*>(exec->registers()); 241 Vector<JSValue> temporaryLocals(entry->m_reshufflings.size()); 213 242 for (unsigned i = entry->m_reshufflings.size(); i--;) 214 temporaryLocals[i] = registers[entry->m_reshufflings[i].fromOffset];243 temporaryLocals[i] = pivot[VirtualRegister(entry->m_reshufflings[i].fromOffset).toLocal()].jsValue(); 215 244 for (unsigned i = entry->m_reshufflings.size(); i--;) 216 registers[entry->m_reshufflings[i].toOffset] = temporaryLocals[i]; 217 218 // 5) Clear those parts of the call frame that the DFG ain't using. This helps GC on some 219 // programs by eliminating some stale pointer pathologies. 220 221 #if 0 // FIXME: CStack - This needs to be verified before being enabled 245 pivot[VirtualRegister(entry->m_reshufflings[i].toOffset).toLocal()] = temporaryLocals[i]; 246 247 // 5) Clear those parts of the call frame that the DFG ain't using. This helps GC on 248 // some programs by eliminating some stale pointer pathologies. 222 249 for (unsigned i = frameSize; i--;) { 223 250 if (entry->m_machineStackUsed.get(i)) 224 251 continue; 225 registers[virtualRegisterForLocal(i).offset()] = JSValue::encode(JSValue()); 226 } 227 #endif 228 229 // 6) Fix the call frame. 230 231 exec->setCodeBlock(codeBlock); 232 233 // 7) Find and return the destination machine code address. 234 235 void* result = codeBlock->jitCode()->executableAddressAtOffset(entry->m_machineCodeOffset); 252 pivot[i] = JSValue(); 253 } 254 255 // 6) Fix the call frame to have the right code block. 256 257 *bitwise_cast<CodeBlock**>(pivot - 1 - JSStack::CodeBlock) = codeBlock; 236 258 237 259 if (Options::verboseOSR()) 238 dataLogF(" OSR returning machine code address %p.\n", result); 239 240 return result; 260 dataLogF(" OSR returning data buffer %p.\n", scratch); 261 return scratch; 241 262 } 242 263 -
trunk/Source/JavaScriptCore/dfg/DFGOSREntry.h
r159826 r164205 68 68 } 69 69 70 // Returns a pointer to a data buffer that the OSR entry thunk will recognize and 71 // parse. If this returns null, it means 70 72 void* prepareOSREntry(ExecState*, CodeBlock*, unsigned bytecodeIndex); 71 73 #else -
trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp
r163844 r164205 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 97 97 } 98 98 99 MacroAssemblerCodeRef osrEntryThunkGenerator(VM* vm) 100 { 101 MacroAssembler jit; 102 103 // We get passed the address of a scratch buffer. The first 8-byte slot of the buffer 104 // is the frame size. The second 8-byte slot is the pointer to where we are supposed to 105 // jump. The remaining bytes are the new call frame header followed by the locals. 106 107 ptrdiff_t offsetOfFrameSize = 0; // This is the DFG frame count. 108 ptrdiff_t offsetOfTargetPC = offsetOfFrameSize + sizeof(EncodedJSValue); 109 ptrdiff_t offsetOfPayload = offsetOfTargetPC + sizeof(EncodedJSValue); 110 ptrdiff_t offsetOfLocals = offsetOfPayload + sizeof(Register) * JSStack::CallFrameHeaderSize; 111 112 jit.move(GPRInfo::returnValueGPR2, GPRInfo::regT0); 113 jit.loadPtr(MacroAssembler::Address(GPRInfo::regT0, offsetOfFrameSize), GPRInfo::regT1); // Load the frame size. 114 jit.move(GPRInfo::regT1, GPRInfo::regT2); 115 jit.lshiftPtr(MacroAssembler::Imm32(3), GPRInfo::regT2); 116 jit.move(GPRInfo::callFrameRegister, MacroAssembler::stackPointerRegister); 117 jit.subPtr(GPRInfo::regT2, MacroAssembler::stackPointerRegister); 118 119 MacroAssembler::Label loop = jit.label(); 120 jit.subPtr(MacroAssembler::TrustedImm32(1), GPRInfo::regT1); 121 jit.move(GPRInfo::regT1, GPRInfo::regT4); 122 jit.negPtr(GPRInfo::regT4); 123 jit.load32(MacroAssembler::BaseIndex(GPRInfo::regT0, GPRInfo::regT1, MacroAssembler::TimesEight, offsetOfLocals), GPRInfo::regT2); 124 jit.load32(MacroAssembler::BaseIndex(GPRInfo::regT0, GPRInfo::regT1, MacroAssembler::TimesEight, offsetOfLocals + sizeof(int32_t)), GPRInfo::regT3); 125 jit.store32(GPRInfo::regT2, MacroAssembler::BaseIndex(GPRInfo::callFrameRegister, GPRInfo::regT4, MacroAssembler::TimesEight, -static_cast<intptr_t>(sizeof(Register)))); 126 jit.store32(GPRInfo::regT3, MacroAssembler::BaseIndex(GPRInfo::callFrameRegister, GPRInfo::regT4, MacroAssembler::TimesEight, -static_cast<intptr_t>(sizeof(Register)) + static_cast<intptr_t>(sizeof(int32_t)))); 127 jit.branchPtr(MacroAssembler::NotEqual, GPRInfo::regT1, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(-static_cast<intptr_t>(JSStack::CallFrameHeaderSize)))).linkTo(loop, &jit); 128 129 jit.loadPtr(MacroAssembler::Address(GPRInfo::regT0, offsetOfTargetPC), GPRInfo::regT1); 130 MacroAssembler::Jump ok = jit.branchPtr(MacroAssembler::Above, GPRInfo::regT1, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(static_cast<intptr_t>(1000)))); 131 jit.breakpoint(); 132 ok.link(&jit); 133 jit.jump(GPRInfo::regT1); 134 135 LinkBuffer patchBuffer(*vm, &jit, GLOBAL_THUNK_ID); 136 return FINALIZE_CODE(patchBuffer, ("DFG OSR entry thunk")); 137 } 138 99 139 } } // namespace JSC::DFG 100 140 -
trunk/Source/JavaScriptCore/dfg/DFGThunks.h
r156490 r164205 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 40 40 41 41 MacroAssemblerCodeRef osrExitGenerationThunkGenerator(VM*); 42 MacroAssemblerCodeRef osrEntryThunkGenerator(VM*); 42 43 43 44 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r164128 r164205 1107 1107 callOperation(operationOptimize, m_bytecodeOffset); 1108 1108 Jump noOptimizedEntry = branchTestPtr(Zero, returnValueGPR); 1109 move(returnValueGPR2, stackPointerRegister); 1109 if (!ASSERT_DISABLED) { 1110 Jump ok = branchPtr(MacroAssembler::Above, regT0, TrustedImmPtr(bitwise_cast<void*>(static_cast<intptr_t>(1000)))); 1111 breakpoint(); 1112 ok.link(this); 1113 } 1110 1114 jump(returnValueGPR); 1111 1115 noOptimizedEntry.link(this); -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r164119 r164205 33 33 #include "DFGDriver.h" 34 34 #include "DFGOSREntry.h" 35 #include "DFGThunks.h" 35 36 #include "DFGWorklist.h" 36 37 #include "Error.h" … … 1190 1191 ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType())); 1191 1192 1192 if (void* address= DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) {1193 if (void* dataBuffer = DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) { 1193 1194 if (Options::verboseOSR()) { 1194 1195 dataLog( 1195 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ", address ", 1196 RawPointer(OUR_RETURN_ADDRESS), " -> ", RawPointer(address), ".\n"); 1196 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ".\n"); 1197 1197 } 1198 1198 1199 1199 codeBlock->optimizeSoon(); 1200 ASSERT(exec->codeBlock() == optimizedCodeBlock); 1201 return encodeResult(address, exec->topOfFrame()); 1200 return encodeResult(vm.getCTIStub(DFG::osrEntryThunkGenerator).code().executableAddress(), dataBuffer); 1202 1201 } 1203 1202
Note:
See TracChangeset
for help on using the changeset viewer.