Changeset 201363 in webkit
- Timestamp:
- May 24, 2016, 4:49:57 PM (10 years ago)
- Location:
- trunk/Source
- Files:
-
- 3 added
- 21 edited
-
JavaScriptCore/CMakeLists.txt (modified) (1 diff)
-
JavaScriptCore/ChangeLog (modified) (1 diff)
-
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (modified) (5 diffs)
-
JavaScriptCore/bytecode/BytecodeList.json (modified) (1 diff)
-
JavaScriptCore/bytecode/BytecodeUseDef.h (modified) (2 diffs)
-
JavaScriptCore/bytecode/CodeBlock.cpp (modified) (7 diffs)
-
JavaScriptCore/bytecode/CodeBlock.h (modified) (4 diffs)
-
JavaScriptCore/bytecode/GetByIdStatus.cpp (modified) (1 diff)
-
JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp (added)
-
JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h (added)
-
JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp (modified) (2 diffs)
-
JavaScriptCore/bytecode/ObjectPropertyConditionSet.h (modified) (1 diff)
-
JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (modified) (1 diff)
-
JavaScriptCore/dfg/DFGByteCodeParser.cpp (modified) (1 diff)
-
JavaScriptCore/dfg/DFGCapabilities.cpp (modified) (1 diff)
-
JavaScriptCore/jit/JIT.cpp (modified) (2 diffs)
-
JavaScriptCore/llint/LLIntSlowPaths.cpp (modified) (4 diffs)
-
JavaScriptCore/llint/LLIntSlowPaths.h (modified) (1 diff)
-
JavaScriptCore/llint/LowLevelInterpreter32_64.asm (modified) (2 diffs)
-
JavaScriptCore/llint/LowLevelInterpreter64.asm (modified) (1 diff)
-
JavaScriptCore/runtime/Options.h (modified) (1 diff)
-
JavaScriptCore/tests/stress/llint-get-by-id-cache-prototype-load-from-dictionary.js (added)
-
WTF/ChangeLog (modified) (1 diff)
-
WTF/wtf/Bag.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r201239 r201363 203 203 bytecode/InlineCallFrameSet.cpp 204 204 bytecode/JumpTable.cpp 205 bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp 205 206 bytecode/LazyOperandValueProfile.cpp 206 207 bytecode/MethodOfGettingAValueProfile.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r201361 r201363 1 2016-05-24 Keith Miller <keith_miller@apple.com> 2 3 LLInt should be able to cache prototype loads for values in GetById 4 https://bugs.webkit.org/show_bug.cgi?id=158032 5 6 Reviewed by Filip Pizlo. 7 8 This patch adds prototype value caching to the LLInt for op_get_by_id. 9 Two previously unused words in the op_get_by_id bytecode have been 10 repurposed to hold extra information for the cache. The first is a 11 counter that records the number of get_by_ids that hit a cacheable value 12 on a prototype. When the counter is decremented from one to zero we 13 attempt to cache the prototype load, which will be discussed further 14 below. The second word is used to hold the prototype object when we have 15 started caching. 16 17 When the counter is decremented to zero we first attempt to generate and 18 watch the property conditions needed to ensure the validity of prototype 19 load. If the watchpoints are successfully created and installed we 20 replace the op_get_by_id opcode with the new op_get_by_id_proto_load 21 opcode, which tells the LLInt to use the cache prototype object for the 22 load rather than the base value. 23 24 Prior to this patch there was not LLInt specific data onCodeBlocks. 25 Since the CodeBlock needs to own the Watchpoints for the cache, a weak 26 map from each base structure to a bag of Watchpoints created for that 27 structure by some op_get_by_id has been added to the CodeBlock. During 28 GC, if we find that the a structure in the map has not been marked we 29 free the associated bag on the CodeBlock. 30 31 * JavaScriptCore.xcodeproj/project.pbxproj: 32 * bytecode/BytecodeList.json: 33 * bytecode/BytecodeUseDef.h: 34 (JSC::computeUsesForBytecodeOffset): 35 (JSC::computeDefsForBytecodeOffset): 36 * bytecode/CodeBlock.cpp: 37 (JSC::CodeBlock::printGetByIdOp): 38 (JSC::CodeBlock::printGetByIdCacheStatus): 39 (JSC::CodeBlock::dumpBytecode): 40 (JSC::CodeBlock::finalizeLLIntInlineCaches): 41 * bytecode/CodeBlock.h: 42 (JSC::CodeBlock::llintGetByIdWatchpointMap): 43 (JSC::clearLLIntGetByIdCache): 44 * bytecode/GetByIdStatus.cpp: 45 (JSC::GetByIdStatus::computeFromLLInt): 46 * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp: Added. 47 (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint): 48 (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::install): 49 (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::fireInternal): 50 * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h: Added. 51 * bytecode/ObjectPropertyConditionSet.cpp: 52 (JSC::ObjectPropertyConditionSet::isValidAndWatchable): 53 * bytecode/ObjectPropertyConditionSet.h: 54 * bytecompiler/BytecodeGenerator.cpp: 55 (JSC::BytecodeGenerator::emitGetById): 56 * dfg/DFGByteCodeParser.cpp: 57 (JSC::DFG::ByteCodeParser::parseBlock): 58 * dfg/DFGCapabilities.cpp: 59 (JSC::DFG::capabilityLevel): 60 * jit/JIT.cpp: 61 (JSC::JIT::privateCompileMainPass): 62 (JSC::JIT::privateCompileSlowCases): 63 * llint/LLIntSlowPaths.cpp: 64 (JSC::LLInt::setupGetByIdPrototypeCache): 65 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 66 * llint/LLIntSlowPaths.h: 67 * llint/LowLevelInterpreter32_64.asm: 68 * llint/LowLevelInterpreter64.asm: 69 * runtime/Options.h: 70 * tests/stress/llint-get-by-id-cache-prototype-load-from-dictionary.js: Added. 71 (test): 72 1 73 2016-05-24 Keith Miller <keith_miller@apple.com> 2 74 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r201239 r201363 1182 1182 53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; }; 1183 1183 53F6BF6D1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1184 53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1185 53FA2AE31CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */; }; 1184 1186 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; 1185 1187 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; }; … … 3322 3324 53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewPrototype.cpp; sourceTree = "<group>"; }; 3323 3325 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InternalFunctionAllocationProfile.h; sourceTree = "<group>"; }; 3326 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; }; 3327 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; }; 3324 3328 593D43CCA0BBE06D89C59707 /* MapDataInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapDataInlines.h; sourceTree = "<group>"; }; 3325 3329 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = "<absolute>"; }; … … 6576 6580 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */, 6577 6581 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */, 6582 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */, 6583 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */, 6578 6584 0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */, 6579 6585 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */, … … 7911 7917 BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */, 7912 7918 0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */, 7919 53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */, 7913 7920 BC18C4560E16F5CD00B34460 /* Protect.h in Headers */, 7914 7921 1474C33B16AA2D950062F01D /* PrototypeMap.h in Headers */, … … 8636 8643 65C0285C1717966800351E35 /* ARMv7DOpcode.cpp in Sources */, 8637 8644 0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */, 8645 53FA2AE31CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp in Sources */, 8638 8646 A7A8AF3417ADB5F3005AB174 /* ArrayBuffer.cpp in Sources */, 8639 8647 0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.json
r201239 r201363 59 59 { "name" : "op_is_function", "length" : 3 }, 60 60 { "name" : "op_in", "length" : 4 }, 61 { "name" : "op_ try_get_by_id", "length" : 4},61 { "name" : "op_get_array_length", "length" : 9 }, 62 62 { "name" : "op_get_by_id", "length" : 9 }, 63 { "name" : "op_get_by_id_proto_load", "length" : 9 }, 63 64 { "name" : "op_get_by_id_with_this", "length" : 5 }, 64 65 { "name" : "op_get_by_val_with_this", "length" : 5 }, 65 { "name" : "op_ get_array_length", "length" : 9},66 { "name" : "op_try_get_by_id", "length" : 4 }, 66 67 { "name" : "op_put_by_id", "length" : 9 }, 67 68 { "name" : "op_put_by_id_with_this", "length" : 5 }, -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
r201239 r201363 159 159 case op_try_get_by_id: 160 160 case op_get_by_id: 161 case op_get_by_id_proto_load: 161 162 case op_get_array_length: 162 163 case op_typeof: … … 393 394 case op_try_get_by_id: 394 395 case op_get_by_id: 396 case op_get_by_id_proto_load: 395 397 case op_get_by_id_with_this: 396 398 case op_get_by_val_with_this: -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r201359 r201363 51 51 #include "JSModuleEnvironment.h" 52 52 #include "LLIntEntrypoint.h" 53 #include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" 53 54 #include "LowLevelInterpreter.h" 54 55 #include "JSCInlines.h" … … 346 347 op = "get_by_id"; 347 348 break; 349 case op_get_by_id_proto_load: 350 op = "get_by_id_proto_load"; 351 break; 348 352 case op_get_array_length: 349 353 op = "array_length"; … … 406 410 dumpStructure(out, "struct", structure, ident); 407 411 out.printf(")"); 412 if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_by_id_proto_load) 413 out.printf(" proto(%p)", instruction[6].u.pointer); 408 414 } 409 415 … … 1113 1119 } 1114 1120 case op_get_by_id: 1121 case op_get_by_id_proto_load: 1115 1122 case op_get_array_length: { 1116 1123 printGetByIdOp(out, exec, location, it); … … 2799 2806 Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]]; 2800 2807 switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) { 2801 case op_get_by_id: { 2808 case op_get_by_id: 2809 case op_get_by_id_proto_load: { 2802 2810 StructureID oldStructureID = curInstruction[4].u.structureID; 2803 2811 if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID))) … … 2805 2813 if (Options::verboseOSR()) 2806 2814 dataLogF("Clearing LLInt property access.\n"); 2807 curInstruction[4].u.structureID = 0; 2808 curInstruction[5].u.operand = 0; 2815 clearLLIntGetByIdCache(curInstruction); 2809 2816 break; 2810 2817 } … … 2879 2886 } 2880 2887 } 2888 2889 // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set 2890 // then cleared the cache without GCing in between. 2891 m_llintGetByIdWatchpointMap.removeIf([](const StructureWatchpointMap::KeyValuePairType& pair) -> bool { 2892 return !Heap::isMarked(pair.key); 2893 }); 2881 2894 2882 2895 for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) { -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r201180 r201363 57 57 #include "JumpTable.h" 58 58 #include "LLIntCallLinkInfo.h" 59 #include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" 59 60 #include "LazyOperandValueProfile.h" 60 61 #include "ObjectAllocationProfile.h" … … 678 679 return m_llintExecuteCounter; 679 680 } 681 682 typedef HashMap<Structure*, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>> StructureWatchpointMap; 683 StructureWatchpointMap& llintGetByIdWatchpointMap() { return m_llintGetByIdWatchpointMap; } 680 684 681 685 // Functions for controlling when tiered compilation kicks in. This … … 1020 1024 RefCountedArray<LLIntCallLinkInfo> m_llintCallLinkInfos; 1021 1025 SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo>> m_incomingLLIntCalls; 1026 StructureWatchpointMap m_llintGetByIdWatchpointMap; 1022 1027 RefPtr<JITCode> m_jitCode; 1023 1028 #if ENABLE(JIT) … … 1310 1315 #endif 1311 1316 1317 inline void clearLLIntGetByIdCache(Instruction* instruction) 1318 { 1319 instruction[0].u.opcode = LLInt::getOpcode(op_get_by_id); 1320 instruction[4].u.pointer = nullptr; 1321 instruction[5].u.pointer = nullptr; 1322 instruction[6].u.pointer = nullptr; 1323 } 1324 1312 1325 inline Register& ExecState::r(int index) 1313 1326 { -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
r199382 r201363 76 76 77 77 Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex; 78 79 if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length) || instruction[0].u.opcode == LLInt::getOpcode(op_try_get_by_id)) 78 79 Opcode opcode = instruction[0].u.opcode; 80 81 // FIXME: We should not just bail if we see a try_get_by_id or a get_by_id_proto_load. 82 // https://bugs.webkit.org/show_bug.cgi?id=158039 83 if (opcode == LLInt::getOpcode(op_get_array_length) || opcode == LLInt::getOpcode(op_try_get_by_id) || opcode == LLInt::getOpcode(op_get_by_id_proto_load)) 80 84 return GetByIdStatus(NoInformation, false); 81 85 -
trunk/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp
r197531 r201363 168 168 } 169 169 170 bool ObjectPropertyConditionSet::isValidAndWatchable() const 171 { 172 if (!isValid()) 173 return false; 174 175 for (ObjectPropertyCondition condition : m_data->vector) { 176 if (!condition.isWatchable()) 177 return false; 178 } 179 return true; 180 } 181 170 182 namespace { 171 183 … … 255 267 // treated as a dictionary. 256 268 if (structure->isDictionary()) { 257 if (concurrency == MainThread) 269 if (concurrency == MainThread) { 270 if (verbose) 271 dataLog("Flattening ", pointerDump(structure)); 258 272 structure->flattenDictionaryStructure(vm, object); 259 else {273 } else { 260 274 if (verbose) 261 275 dataLog("Cannot flatten dictionary when not on main thread, so invalid.\n"); -
trunk/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h
r197531 r201363 68 68 return !m_data || !m_data->vector.isEmpty(); 69 69 } 70 71 bool isValidAndWatchable() const; 70 72 71 73 bool isEmpty() const -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r201239 r201363 2432 2432 instructions().append(0); 2433 2433 instructions().append(0); 2434 instructions().append( 0);2434 instructions().append(Options::prototypeHitCountForLLIntCaching()); 2435 2435 instructions().append(profile); 2436 2436 return dst; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r201239 r201363 4082 4082 4083 4083 case op_get_by_id: 4084 case op_get_by_id_proto_load: 4084 4085 case op_get_array_length: { 4085 4086 SpeculatedType prediction = getPrediction(); -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r201239 r201363 155 155 case op_try_get_by_id: 156 156 case op_get_by_id: 157 case op_get_by_id_proto_load: 157 158 case op_get_by_id_with_this: 158 159 case op_get_by_val_with_this: -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r201239 r201363 241 241 DEFINE_OP(op_try_get_by_id) 242 242 case op_get_array_length: 243 case op_get_by_id_proto_load: 243 244 DEFINE_OP(op_get_by_id) 244 245 DEFINE_OP(op_get_by_id_with_this) … … 423 424 DEFINE_SLOWCASE_OP(op_try_get_by_id) 424 425 case op_get_array_length: 426 case op_get_by_id_proto_load: 425 427 DEFINE_SLOWCASE_OP(op_get_by_id) 426 428 DEFINE_SLOWCASE_OP(op_get_by_val) -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r201239 r201363 53 53 #include "LowLevelInterpreter.h" 54 54 #include "ObjectConstructor.h" 55 #include "ObjectPropertyConditionSet.h" 55 56 #include "ProtoCallFrame.h" 56 57 #include "ShadowChicken.h" … … 581 582 } 582 583 584 static void setupGetByIdPrototypeCache(ExecState* exec, VM& vm, Instruction* pc, JSCell* baseCell, PropertySlot& slot, const Identifier& ident) 585 { 586 CodeBlock* codeBlock = exec->codeBlock(); 587 Structure* structure = baseCell->structure(); 588 589 if (structure->typeInfo().prohibitsPropertyCaching() || structure->isDictionary()) 590 return; 591 592 ObjectPropertyConditionSet conditions = generateConditionsForPrototypePropertyHit(vm, codeBlock, exec, structure, slot.slotBase(), ident.impl()); 593 594 if (!conditions.isValid()) 595 return; 596 597 PropertyOffset offset = invalidOffset; 598 CodeBlock::StructureWatchpointMap& watchpointMap = codeBlock->llintGetByIdWatchpointMap(); 599 auto result = watchpointMap.add(structure, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>()); 600 for (ObjectPropertyCondition condition : conditions) { 601 if (!condition.isWatchable()) 602 return; 603 if (condition.condition().kind() == PropertyCondition::Presence) 604 offset = condition.condition().offset(); 605 result.iterator->value.add(condition, pc)->install(); 606 } 607 ASSERT(offset != invalidOffset); 608 609 ConcurrentJITLocker locker(codeBlock->m_lock); 610 611 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_load); 612 pc[4].u.structureID = structure->id(); 613 pc[5].u.operand = offset; 614 // We know that this pointer will remain valid because it is the prototype of some structure, s, 615 // watchpointed above. If any object with structure s were to change prototypes then the conditions 616 // for this cache would fail and this value will never be used again. 617 pc[6].u.pointer = slot.slotBase(); 618 } 619 620 583 621 LLINT_SLOW_PATH_DECL(slow_path_get_by_id) 584 622 { … … 595 633 if (!LLINT_ALWAYS_ACCESS_SLOW 596 634 && baseValue.isCell() 597 && slot.isCacheable()598 && slot.slotBase() == baseValue599 635 && slot.isCacheableValue()) { 600 636 601 637 JSCell* baseCell = baseValue.asCell(); 602 638 Structure* structure = baseCell->structure(); 639 if (slot.slotBase() == baseValue) { 640 // Start out by clearing out the old cache. 641 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id); 642 pc[4].u.pointer = nullptr; // old structure 643 pc[5].u.pointer = nullptr; // offset 644 645 // Prevent the prototype cache from ever happening. 646 pc[7].u.operand = 0; 603 647 604 // Start out by clearing out the old cache. 605 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id); 606 pc[4].u.pointer = nullptr; // old structure 607 pc[5].u.pointer = nullptr; // offset 608 609 if (!structure->isUncacheableDictionary() 610 && !structure->typeInfo().prohibitsPropertyCaching() 611 && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) { 612 vm.heap.writeBarrier(codeBlock); 613 614 ConcurrentJITLocker locker(codeBlock->m_lock); 615 616 pc[4].u.structureID = structure->id(); 617 pc[5].u.operand = slot.cachedOffset(); 648 if (structure->propertyAccessesAreCacheable()) { 649 vm.heap.writeBarrier(codeBlock); 650 651 ConcurrentJITLocker locker(codeBlock->m_lock); 652 653 pc[4].u.structureID = structure->id(); 654 pc[5].u.operand = slot.cachedOffset(); 655 } 656 } else if (UNLIKELY(pc[7].u.operand)) { 657 ASSERT(slot.slotBase() != baseValue); 658 659 if (!(--pc[7].u.operand)) 660 setupGetByIdPrototypeCache(exec, vm, pc, baseCell, slot, ident); 618 661 } 619 } 620 621 if (!LLINT_ALWAYS_ACCESS_SLOW 662 } else if (!LLINT_ALWAYS_ACCESS_SLOW 622 663 && isJSArray(baseValue) 623 664 && ident == exec->propertyNames().length) { … … 626 667 arrayProfile->observeStructure(baseValue.asCell()->structure()); 627 668 pc[4].u.arrayProfile = arrayProfile; 669 670 // Prevent the prototype cache from ever happening. 671 pc[7].u.operand = 0; 628 672 } 629 673 -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h
r201239 r201363 72 72 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_try_get_by_id); 73 73 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id); 74 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id_proto_load); 74 75 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length); 75 76 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id); -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r200981 r201363 1335 1335 1336 1336 # We only do monomorphic get_by_id caching for now, and we do not modify the 1337 # opcode . We do, however, allow for the cache to change anytime if fails, since1338 # ping-ponging is free. At best we get lucky and the get_by_id will continue1337 # opcode for own properties. We also allow for the cache to change anytime it fails, 1338 # since ping-ponging is free. At best we get lucky and the get_by_id will continue 1339 1339 # to take fast path on the new cache. At worst we take slow path, which is what 1340 # we would have been doing anyway. 1340 # we would have been doing anyway. For prototype properties, we will attempt to 1341 # convert opcode into a get_by_id_proto_load after a execution counter hits zero. 1341 1342 1342 1343 _llint_op_get_by_id: … … 1355 1356 1356 1357 .opGetByIdSlow: 1358 callSlowPath(_llint_slow_path_get_by_id) 1359 dispatch(9) 1360 1361 1362 1363 _llint_op_get_by_id_proto_load: 1364 traceExecution() 1365 loadi 8[PC], t0 1366 loadi 16[PC], t1 1367 loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdProtoSlow) 1368 loadi 20[PC], t2 1369 bineq JSCell::m_structureID[t3], t1, .opGetByIdProtoSlow 1370 loadpFromInstruction(6, t3) 1371 loadPropertyAtVariableOffset(t2, t3, t0, t1) 1372 loadi 4[PC], t2 1373 storei t0, TagOffset[cfr, t2, 8] 1374 storei t1, PayloadOffset[cfr, t2, 8] 1375 valueProfile(t0, t1, 32, t2) 1376 dispatch(9) 1377 1378 .opGetByIdProtoSlow: 1357 1379 callSlowPath(_llint_slow_path_get_by_id) 1358 1380 dispatch(9) -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r201335 r201363 1233 1233 1234 1234 1235 _llint_op_get_by_id_proto_load: 1236 traceExecution() 1237 loadisFromInstruction(2, t0) 1238 loadConstantOrVariableCell(t0, t3, .opGetByIdProtoSlow) 1239 loadi JSCell::m_structureID[t3], t1 1240 loadisFromInstruction(4, t2) 1241 bineq t2, t1, .opGetByIdProtoSlow 1242 loadisFromInstruction(5, t1) 1243 loadpFromInstruction(6, t3) 1244 loadisFromInstruction(1, t2) 1245 loadPropertyAtVariableOffset(t1, t3, t0) 1246 storeq t0, [cfr, t2, 8] 1247 valueProfile(t0, 8, t1) 1248 dispatch(9) 1249 1250 .opGetByIdProtoSlow: 1251 callSlowPath(_llint_slow_path_get_by_id) 1252 dispatch(9) 1253 1254 1235 1255 _llint_op_get_array_length: 1236 1256 traceExecution() -
trunk/Source/JavaScriptCore/runtime/Options.h
r201361 r201363 363 363 v(bool, useICStats, false, Normal, nullptr) \ 364 364 \ 365 v(unsigned, prototypeHitCountForLLIntCaching, 2, Normal, "Number of prototype property hits before caching a prototype in the LLInt. A count of 0 means never cache.") \ 366 \ 365 367 v(bool, dumpModuleRecord, false, Normal, nullptr) \ 366 368 v(bool, dumpModuleLoadingState, false, Normal, nullptr) \ -
trunk/Source/WTF/ChangeLog
r201333 r201363 1 2016-05-24 Keith Miller <keith_miller@apple.com> 2 3 LLInt should be able to cache prototype loads for values in GetById 4 https://bugs.webkit.org/show_bug.cgi?id=158032 5 6 Reviewed by Filip Pizlo. 7 8 Add move constructors/initializers to Bags. 9 10 * wtf/Bag.h: 11 (WTF::Bag::Bag): 12 (WTF::Bag::operator=): 13 1 14 2016-05-24 Chris Dumez <cdumez@apple.com> 2 15 -
trunk/Source/WTF/wtf/Bag.h
r195339 r201363 49 49 public: 50 50 Bag() 51 : m_head(nullptr)52 51 { 52 } 53 54 Bag(Bag<T>&& other) 55 { 56 ASSERT(!m_head); 57 m_head = other.m_head; 58 other.m_head = nullptr; 59 } 60 61 Bag& operator=(Bag<T>&& other) 62 { 63 m_head = other.m_head; 64 other.m_head = nullptr; 65 return *this; 53 66 } 54 67 … … 122 135 123 136 private: 124 Node* m_head ;137 Node* m_head { nullptr }; 125 138 }; 126 139
Note:
See TracChangeset
for help on using the changeset viewer.