Changeset 89861 in webkit
- Timestamp:
- Jun 27, 2011 2:38:09 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r89817 r89861 1 2011-06-27 Filip Pizlo <fpizlo@apple.com> 2 3 Reviewed by Gavin Barraclough. 4 5 DFG JIT does not perform put_by_id caching. 6 https://bugs.webkit.org/show_bug.cgi?id=63409 7 8 * bytecode/StructureStubInfo.h: 9 * dfg/DFGJITCodeGenerator.cpp: 10 (JSC::DFG::JITCodeGenerator::cachedPutById): 11 * dfg/DFGJITCodeGenerator.h: 12 * dfg/DFGJITCompiler.cpp: 13 (JSC::DFG::JITCompiler::compileFunction): 14 * dfg/DFGJITCompiler.h: 15 (JSC::DFG::JITCompiler::addPropertyAccess): 16 (JSC::DFG::JITCompiler::PropertyAccessRecord::PropertyAccessRecord): 17 * dfg/DFGNonSpeculativeJIT.cpp: 18 (JSC::DFG::NonSpeculativeJIT::compile): 19 * dfg/DFGOperations.cpp: 20 * dfg/DFGOperations.h: 21 * dfg/DFGRepatch.cpp: 22 (JSC::DFG::dfgRepatchByIdSelfAccess): 23 (JSC::DFG::tryCacheGetByID): 24 (JSC::DFG::appropriatePutByIdFunction): 25 (JSC::DFG::tryCachePutByID): 26 (JSC::DFG::dfgRepatchPutByID): 27 * dfg/DFGRepatch.h: 28 * dfg/DFGSpeculativeJIT.cpp: 29 (JSC::DFG::SpeculativeJIT::compile): 30 1 31 2011-06-27 Gustavo Noronha Silva <gns@gnome.org> 2 32 -
trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h
r87771 r89861 134 134 struct { 135 135 intptr_t deltaCheckToCall; 136 intptr_t deltaCallToLoad ;136 intptr_t deltaCallToLoadOrStore; 137 137 } unset; 138 138 struct { -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r89643 r89861 351 351 } 352 352 353 void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) 354 { 355 JITCompiler::DataLabelPtr structureToCompare; 356 JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::Equal, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); 357 358 if (slowPathTarget.isSet()) 359 slowPathTarget.link(&m_jit); 360 361 silentSpillAllRegisters(InvalidGPRReg, baseGPR, valueGPR); 362 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(valueGPR, baseGPR); 363 m_jit.move(JITCompiler::ImmPtr(identifier(identifierNumber)), GPRInfo::argumentGPR3); 364 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 365 V_DFGOperation_EJJI optimizedCall; 366 if (m_jit.codeBlock()->isStrictMode()) { 367 if (putKind == Direct) 368 optimizedCall = operationPutByIdDirectStrictOptimize; 369 else 370 optimizedCall = operationPutByIdStrictOptimize; 371 } else { 372 if (putKind == Direct) 373 optimizedCall = operationPutByIdDirectNonStrictOptimize; 374 else 375 optimizedCall = operationPutByIdNonStrictOptimize; 376 } 377 JITCompiler::Call functionCall = appendCallWithExceptionCheck(optimizedCall); 378 silentFillAllRegisters(InvalidGPRReg); 379 380 JITCompiler::Jump handledByC = m_jit.jump(); 381 structureCheck.link(&m_jit); 382 383 m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR); 384 JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0)); 385 386 intptr_t checkToCall = m_jit.differenceBetween(structureToCompare, functionCall); 387 intptr_t callToStore = m_jit.differenceBetween(functionCall, storeWithPatch); 388 389 handledByC.link(&m_jit); 390 391 m_jit.addPropertyAccess(functionCall, checkToCall, callToStore); 392 } 393 353 394 #ifndef NDEBUG 354 395 static const char* dataFormatString(DataFormat format) -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
r89643 r89861 502 502 503 503 void cachedGetById(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); 504 void cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); 504 505 505 506 // Called once a node has completed code generation but prior to setting -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r89611 r89861 389 389 info.callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall); 390 390 info.u.unset.deltaCheckToCall = m_propertyAccesses[i].m_deltaCheckToCall; 391 info.u.unset.deltaCallToLoad = m_propertyAccesses[i].m_deltaCallToLoad;391 info.u.unset.deltaCallToLoadOrStore = m_propertyAccesses[i].m_deltaCallToLoadOrStore; 392 392 } 393 393 -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h
r89611 r89861 233 233 #endif 234 234 235 void addPropertyAccess(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoad )236 { 237 m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckToCall, deltaCallToLoad ));235 void addPropertyAccess(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoadOrStore) 236 { 237 m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckToCall, deltaCallToLoadOrStore)); 238 238 } 239 239 … … 259 259 260 260 struct PropertyAccessRecord { 261 PropertyAccessRecord(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoad )261 PropertyAccessRecord(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoadOrStore) 262 262 : m_functionCall(functionCall) 263 263 , m_deltaCheckToCall(deltaCheckToCall) 264 , m_deltaCallToLoad (deltaCallToLoad)264 , m_deltaCallToLoadOrStore(deltaCallToLoadOrStore) 265 265 { 266 266 } … … 268 268 JITCompiler::Call m_functionCall; 269 269 intptr_t m_deltaCheckToCall; 270 intptr_t m_deltaCallToLoad ;270 intptr_t m_deltaCallToLoadOrStore; 271 271 }; 272 272 -
trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
r89772 r89861 771 771 JSValueOperand base(this, node.child1); 772 772 JSValueOperand value(this, node.child2); 773 GPRTemporary scratch(this, base); 773 774 GPRReg valueGPR = value.gpr(); 774 775 GPRReg baseGPR = base.gpr(); 775 flushRegisters(); 776 777 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber())); 776 777 JITCompiler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseGPR, GPRInfo::tagMaskRegister); 778 779 cachedPutById(baseGPR, valueGPR, scratch.gpr(), node.identifierNumber(), NotDirect, notCell); 780 778 781 noResult(m_compileIndex); 779 782 break; … … 783 786 JSValueOperand base(this, node.child1); 784 787 JSValueOperand value(this, node.child2); 788 GPRTemporary scratch(this, base); 785 789 GPRReg valueGPR = value.gpr(); 786 790 GPRReg baseGPR = base.gpr(); 787 flushRegisters(); 788 789 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber())); 791 792 JITCompiler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseGPR, GPRInfo::tagMaskRegister); 793 794 cachedPutById(baseGPR, valueGPR, scratch.gpr(), node.identifierNumber(), Direct, notCell); 795 790 796 noResult(m_compileIndex); 791 797 break; -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r89772 r89861 44 44 ); 45 45 #define FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx) 46 #define FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, r8) 46 47 47 48 namespace JSC { namespace DFG { … … 285 286 } 286 287 288 void operationPutByIdStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr); 289 FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdStrictOptimize); 290 void operationPutByIdStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress) 291 { 292 JSValue value = JSValue::decode(encodedValue); 293 JSValue base = JSValue::decode(encodedBase); 294 PutPropertySlot slot(true); 295 296 base.put(exec, *propertyName, value, slot); 297 298 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); 299 if (stubInfo.seen) 300 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, NotDirect); 301 else 302 stubInfo.seen = true; 303 } 304 305 void operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr); 306 FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdNonStrictOptimize); 307 void operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress) 308 { 309 JSValue value = JSValue::decode(encodedValue); 310 JSValue base = JSValue::decode(encodedBase); 311 PutPropertySlot slot(false); 312 313 base.put(exec, *propertyName, value, slot); 314 315 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); 316 if (stubInfo.seen) 317 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, NotDirect); 318 else 319 stubInfo.seen = true; 320 } 321 322 void operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr); 323 FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdDirectStrictOptimize); 324 void operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress) 325 { 326 JSValue value = JSValue::decode(encodedValue); 327 JSValue base = JSValue::decode(encodedBase); 328 PutPropertySlot slot(true); 329 330 base.putDirect(exec, *propertyName, value, slot); 331 332 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); 333 if (stubInfo.seen) 334 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct); 335 else 336 stubInfo.seen = true; 337 } 338 339 void operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr); 340 FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdDirectNonStrictOptimize); 341 void operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress) 342 { 343 JSValue value = JSValue::decode(encodedValue); 344 JSValue base = JSValue::decode(encodedBase); 345 PutPropertySlot slot(false); 346 347 base.putDirect(exec, *propertyName, value, slot); 348 349 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); 350 if (stubInfo.seen) 351 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct); 352 else 353 stubInfo.seen = true; 354 } 355 287 356 bool operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 288 357 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r89772 r89861 32 32 33 33 namespace JSC { namespace DFG { 34 35 enum PutKind { Direct, NotDirect }; 36 34 37 extern "C" { 35 38 … … 65 68 void operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); 66 69 void operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); 70 void operationPutByIdStrictOptimize(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); 71 void operationPutByIdNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); 72 void operationPutByIdDirectStrictOptimize(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); 73 void operationPutByIdDirectNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); 67 74 bool operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2); 68 75 bool operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2); -
trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp
r87431 r89861 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "DFGOperations.h"32 31 #include "RepatchBuffer.h" 33 32 … … 40 39 } 41 40 42 static void dfgRepatch GetByIdSelf(CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, size_t offset)41 static void dfgRepatchByIdSelfAccess(CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, size_t offset, const FunctionPtr &slowPathFunction, bool compact) 43 42 { 44 43 RepatchBuffer repatchBuffer(codeBlock); 45 44 46 45 // Only optimize once! 47 repatchBuffer.relink(stubInfo.callReturnLocation, operationGetById);46 repatchBuffer.relink(stubInfo.callReturnLocation, slowPathFunction); 48 47 49 48 // Patch the structure check & the offset of the load. 50 49 repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.u.unset.deltaCheckToCall), structure); 51 repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.u.unset.deltaCallToLoad), sizeof(JSValue) * offset); 50 if (compact) 51 repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.u.unset.deltaCallToLoadOrStore), sizeof(JSValue) * offset); 52 else 53 repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.u.unset.deltaCallToLoadOrStore), sizeof(JSValue) * offset); 52 54 } 53 55 … … 77 79 return false; 78 80 79 dfgRepatch GetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset());81 dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetById, true); 80 82 stubInfo.initGetByIdSelf(*globalData, codeBlock->ownerExecutable(), structure); 81 83 return true; … … 93 95 } 94 96 97 static V_DFGOperation_EJJI appropriatePutByIdFunction(const PutPropertySlot &slot, PutKind putKind) 98 { 99 if (slot.isStrictMode()) { 100 if (putKind == Direct) 101 return operationPutByIdDirectStrict; 102 return operationPutByIdStrict; 103 } 104 if (putKind == Direct) 105 return operationPutByIdDirectNonStrict; 106 return operationPutByIdNonStrict; 107 } 108 109 static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier&, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind) 110 { 111 CodeBlock* codeBlock = exec->codeBlock(); 112 JSGlobalData* globalData = &exec->globalData(); 113 114 if (!baseValue.isCell()) 115 return false; 116 JSCell* baseCell = baseValue.asCell(); 117 Structure* structure = baseCell->structure(); 118 if (!slot.isCacheable()) 119 return false; 120 if (structure->isUncacheableDictionary()) 121 return false; 122 123 // Optimize self access. 124 if (slot.base() == baseValue) { 125 if (slot.type() == PutPropertySlot::NewProperty) 126 return false; 127 128 dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), appropriatePutByIdFunction(slot, putKind), false); 129 stubInfo.initPutByIdReplace(*globalData, codeBlock->ownerExecutable(), structure); 130 return true; 131 } 132 133 // FIXME: should support the transition case! 134 return false; 135 } 136 137 void dfgRepatchPutByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind) 138 { 139 bool cached = tryCachePutByID(exec, baseValue, propertyName, slot, stubInfo, putKind); 140 if (!cached) 141 dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, appropriatePutByIdFunction(slot, putKind)); 142 } 143 95 144 } } // namespace JSC::DFG 96 145 -
trunk/Source/JavaScriptCore/dfg/DFGRepatch.h
r87431 r89861 30 30 31 31 #include <dfg/DFGJITCompiler.h> 32 #include <dfg/DFGOperations.h> 32 33 33 34 namespace JSC { namespace DFG { 34 35 35 36 void dfgRepatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&); 37 void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind); 36 38 37 39 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r89643 r89861 864 864 865 865 case PutById: { 866 JSValueOperand base(this, node.child1);866 SpeculateCellOperand base(this, node.child1); 867 867 JSValueOperand value(this, node.child2); 868 GPRReg valueGPR = value.gpr(); 869 GPRReg baseGPR = base.gpr(); 870 flushRegisters(); 871 872 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber())); 868 GPRTemporary scratch(this, base); 869 870 cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), NotDirect); 871 873 872 noResult(m_compileIndex); 874 873 break; … … 876 875 877 876 case PutByIdDirect: { 878 JSValueOperand base(this, node.child1);877 SpeculateCellOperand base(this, node.child1); 879 878 JSValueOperand value(this, node.child2); 880 GPRReg valueGPR = value.gpr(); 881 GPRReg baseGPR = base.gpr(); 882 flushRegisters(); 883 884 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber())); 879 GPRTemporary scratch(this, base); 880 881 cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), Direct); 882 885 883 noResult(m_compileIndex); 886 884 break;
Note: See TracChangeset
for help on using the changeset viewer.