Changeset 206136 in webkit
- Timestamp:
- Sep 19, 2016 6:05:50 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r206134 r206136 1 2016-09-19 Saam Barati <sbarati@apple.com> 2 3 Make HasOwnProperty faster 4 https://bugs.webkit.org/show_bug.cgi?id=161708 5 6 Reviewed by Geoffrey Garen. 7 8 * microbenchmarks/has-own-property-name-cache.js: Added. 9 (foo): 10 * stress/has-own-property-cache-basics.js: Added. 11 (assert): 12 (foo): 13 * stress/has-own-property-name-cache-string-keys.js: Added. 14 (assert): 15 (foo): 16 * stress/has-own-property-name-cache-symbol-keys.js: Added. 17 (assert): 18 (foo): 19 * stress/has-own-property-name-cache-symbols-and-strings.js: Added. 20 (assert): 21 (foo): 22 1 23 2016-09-19 Benjamin Poulain <bpoulain@apple.com> 2 24 -
trunk/Source/JavaScriptCore/ChangeLog
r206134 r206136 1 2016-09-19 Saam Barati <sbarati@apple.com> 2 3 Make HasOwnProperty faster 4 https://bugs.webkit.org/show_bug.cgi?id=161708 5 6 Reviewed by Geoffrey Garen. 7 8 This patch adds a cache for HasOwnProperty. The cache holds tuples 9 of {StructureID, UniquedStringImpl*, boolean} where the boolean indicates 10 the result of performing hasOwnProperty on an object with StructureID and 11 UniquedStringImpl*. If the cache contains an item, we can be guaranteed 12 that it contains the same result as performing hasOwnProperty on an 13 object O with a given structure and key. To guarantee this, we only add 14 items into the cache when the Structure of the given item is cacheable. 15 16 The caching strategy is simple: when adding new items into the cache, 17 we will evict any item that was in the location that the new item 18 is hashed into. We also clear the cache on every GC. This strategy 19 proves to be successful on speedometer, which sees a cache hit rate 20 over 90%. This caching strategy is now inlined into the DFG/FTL JITs 21 by now recognizing hasOwnProperty as an intrinsic with the corresponding 22 HasOwnProperty node. The goal of the node is to emit inlined code for 23 the cache lookup to prevent the overhead of the call for the common 24 case where we get a cache hit. 25 26 I'm seeing around a 1% to 1.5% percent improvement on Speedometer on 27 my machine. Hopefully the perf bots agree with my machine. 28 29 This patch also speeds up the microbenchmark I added by 2.5x. 30 31 * JavaScriptCore.xcodeproj/project.pbxproj: 32 * dfg/DFGAbstractInterpreterInlines.h: 33 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 34 * dfg/DFGByteCodeParser.cpp: 35 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 36 * dfg/DFGClobberize.h: 37 (JSC::DFG::clobberize): 38 * dfg/DFGDoesGC.cpp: 39 (JSC::DFG::doesGC): 40 * dfg/DFGFixupPhase.cpp: 41 (JSC::DFG::FixupPhase::fixupNode): 42 * dfg/DFGNodeType.h: 43 * dfg/DFGOperations.cpp: 44 * dfg/DFGOperations.h: 45 * dfg/DFGPredictionPropagationPhase.cpp: 46 * dfg/DFGSafeToExecute.h: 47 (JSC::DFG::safeToExecute): 48 * dfg/DFGSpeculativeJIT.h: 49 (JSC::DFG::SpeculativeJIT::callOperation): 50 (JSC::DFG::SpeculateCellOperand::SpeculateCellOperand): 51 * dfg/DFGSpeculativeJIT32_64.cpp: 52 (JSC::DFG::SpeculativeJIT::compile): 53 * dfg/DFGSpeculativeJIT64.cpp: 54 (JSC::DFG::SpeculativeJIT::compile): 55 * dfg/DFGValidate.cpp: 56 * ftl/FTLAbstractHeapRepository.h: 57 * ftl/FTLCapabilities.cpp: 58 (JSC::FTL::canCompile): 59 * ftl/FTLLowerDFGToB3.cpp: 60 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 61 (JSC::FTL::DFG::LowerDFGToB3::compileHasOwnProperty): 62 * heap/Heap.cpp: 63 (JSC::Heap::collectImpl): 64 * jit/JITOperations.h: 65 * runtime/HasOwnPropertyCache.h: Added. 66 (JSC::HasOwnPropertyCache::Entry::offsetOfStructureID): 67 (JSC::HasOwnPropertyCache::Entry::offsetOfImpl): 68 (JSC::HasOwnPropertyCache::Entry::offsetOfResult): 69 (JSC::HasOwnPropertyCache::operator delete): 70 (JSC::HasOwnPropertyCache::create): 71 (JSC::HasOwnPropertyCache::hash): 72 (JSC::HasOwnPropertyCache::get): 73 (JSC::HasOwnPropertyCache::tryAdd): 74 (JSC::HasOwnPropertyCache::clear): 75 (JSC::VM::ensureHasOwnPropertyCache): 76 * runtime/Intrinsic.h: 77 * runtime/JSObject.h: 78 * runtime/JSObjectInlines.h: 79 (JSC::JSObject::hasOwnProperty): 80 * runtime/ObjectPrototype.cpp: 81 (JSC::ObjectPrototype::finishCreation): 82 (JSC::objectProtoFuncHasOwnProperty): 83 * runtime/Symbol.h: 84 * runtime/VM.cpp: 85 * runtime/VM.h: 86 (JSC::VM::hasOwnPropertyCache): 87 1 88 2016-09-19 Benjamin Poulain <bpoulain@apple.com> 2 89 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r206110 r206136 1335 1335 79D5CD5A1C1106A900CECA07 /* SamplingProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79D5CD581C1106A900CECA07 /* SamplingProfiler.cpp */; }; 1336 1336 79D5CD5B1C1106A900CECA07 /* SamplingProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 79D5CD591C1106A900CECA07 /* SamplingProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1337 79DFCBDB1D88C59600527D03 /* HasOwnPropertyCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 79DFCBDA1D88C59600527D03 /* HasOwnPropertyCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1337 1338 79EE0BFF1B4AFB85000385C9 /* VariableEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79EE0BFD1B4AFB85000385C9 /* VariableEnvironment.cpp */; }; 1338 1339 79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3579 3580 79D5CD581C1106A900CECA07 /* SamplingProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingProfiler.cpp; sourceTree = "<group>"; }; 3580 3581 79D5CD591C1106A900CECA07 /* SamplingProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingProfiler.h; sourceTree = "<group>"; }; 3582 79DFCBDA1D88C59600527D03 /* HasOwnPropertyCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HasOwnPropertyCache.h; sourceTree = "<group>"; }; 3581 3583 79EE0BFD1B4AFB85000385C9 /* VariableEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableEnvironment.cpp; sourceTree = "<group>"; }; 3582 3584 79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableEnvironment.h; sourceTree = "<group>"; }; … … 5806 5808 79A0907D1D768465008B889B /* HashMapImpl.cpp */, 5807 5809 79A0907E1D768465008B889B /* HashMapImpl.h */, 5810 79DFCBDA1D88C59600527D03 /* HasOwnPropertyCache.h */, 5808 5811 933A349D038AE80F008635CE /* Identifier.cpp */, 5809 5812 933A349A038AE7C6008635CE /* Identifier.h */, … … 8289 8292 0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */, 8290 8293 A7E5AB391799E4B200D2833D /* UDis86Disassembler.h in Headers */, 8294 79DFCBDB1D88C59600527D03 /* HasOwnPropertyCache.h in Headers */, 8291 8295 A7A8AF4117ADB5F3005AB174 /* Uint16Array.h in Headers */, 8292 8296 866739D313BFDE710023D87C /* Uint16WithFraction.h in Headers */, -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r206134 r206136 2666 2666 break; 2667 2667 } 2668 2669 case HasOwnProperty: { 2670 clobberWorld(node->origin.semantic, clobberLimit); 2671 forNode(node).setType(SpecBoolean); 2672 break; 2673 } 2668 2674 2669 2675 case GetEnumerableLength: { -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r206134 r206136 2558 2558 Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(key), Edge(hash)); 2559 2559 Node* result = addToGraph(IsNonEmptyMapBucket, bucket); 2560 set(VirtualRegister(resultOperand), result); 2561 return true; 2562 } 2563 2564 case HasOwnPropertyIntrinsic: { 2565 if (argumentCountIncludingThis != 2) 2566 return false; 2567 2568 // This can be racy, that's fine. We know that once we observe that this is created, 2569 // that it will never be destroyed until the VM is destroyed. It's unlikely that 2570 // we'd ever get to the point where we inline this as an intrinsic without the 2571 // cache being created, however, it's possible if we always throw exceptions inside 2572 // hasOwnProperty. 2573 if (!m_vm->hasOwnPropertyCache()) 2574 return false; 2575 2576 insertChecks(); 2577 Node* object = get(virtualRegisterForArgument(0, registerOffset)); 2578 Node* key = get(virtualRegisterForArgument(1, registerOffset)); 2579 Node* result = addToGraph(HasOwnProperty, object, key); 2560 2580 set(VirtualRegister(resultOperand), result); 2561 2581 return true; -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r206134 r206136 502 502 case ToPrimitive: 503 503 case In: 504 case HasOwnProperty: 504 505 case ValueAdd: 505 506 case SetFunctionName: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r206098 r206136 174 174 case CallStringConstructor: 175 175 case In: 176 case HasOwnProperty: 176 177 case Jump: 177 178 case Branch: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r206134 r206136 1309 1309 1310 1310 fixEdge<CellUse>(node->child2()); 1311 break; 1312 } 1313 1314 case HasOwnProperty: { 1315 fixEdge<ObjectUse>(node->child1()); 1316 #if CPU(X86) && USE(JSVALUE32_64) 1317 // We don't have enough registers to do anything interesting on x86. 1318 fixEdge<UntypedUse>(node->child2()); 1319 #else 1320 if (node->child2()->shouldSpeculateString()) 1321 fixEdge<StringUse>(node->child2()); 1322 else if (node->child2()->shouldSpeculateSymbol()) 1323 fixEdge<SymbolUse>(node->child2()); 1324 else 1325 fixEdge<UntypedUse>(node->child2()); 1326 #endif 1311 1327 break; 1312 1328 } -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r206134 r206136 332 332 macro(ProfileControlFlow, NodeMustGenerate) \ 333 333 macro(SetFunctionName, NodeMustGenerate) \ 334 macro(HasOwnProperty, NodeResultBoolean) \ 334 335 \ 335 336 macro(CreateActivation, NodeResultJS) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r206134 r206136 43 43 #include "FTLOSREntry.h" 44 44 #include "GetterSetter.h" 45 #include "HasOwnPropertyCache.h" 45 46 #include "HostCallReturnValue.h" 46 47 #include "Interpreter.h" … … 1674 1675 } 1675 1676 1677 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey) 1678 { 1679 VM& vm = exec->vm(); 1680 NativeCallFrameTracer tracer(&vm, exec); 1681 auto scope = DECLARE_THROW_SCOPE(vm); 1682 1683 JSValue key = JSValue::decode(encodedKey); 1684 Identifier propertyName = key.toPropertyKey(exec); 1685 if (UNLIKELY(scope.exception())) 1686 return false; 1687 1688 PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty); 1689 bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot); 1690 if (UNLIKELY(scope.exception())) 1691 return false; 1692 1693 HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache(); 1694 ASSERT(hasOwnPropertyCache); 1695 hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result); 1696 return result; 1697 } 1698 1676 1699 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum) 1677 1700 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r206134 r206136 178 178 void JIT_OPERATION operationLoadVarargs(ExecState*, int32_t firstElementDest, EncodedJSValue arguments, int32_t offset, int32_t length, int32_t mandatoryMinimum); 179 179 180 int32_t JIT_OPERATION operationHasOwnProperty(ExecState*, JSObject*, EncodedJSValue); 181 180 182 JSCell* JIT_OPERATION operationResolveScope(ExecState*, JSScope*, UniquedStringImpl*); 181 183 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState*, JSObject* scope, UniquedStringImpl*, unsigned); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r206134 r206136 908 908 909 909 case In: 910 setPrediction(SpecBoolean); 911 break; 912 913 case HasOwnProperty: 910 914 setPrediction(SpecBoolean); 911 915 break; -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r206098 r206136 285 285 case MakeRope: 286 286 case In: 287 case HasOwnProperty: 287 288 case CreateActivation: 288 289 case CreateDirectArguments: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r206065 r206136 983 983 return appendCallSetResult(operation, result); 984 984 } 985 JITCompiler::Call callOperation(Z_JITOperation_EOI operation, GPRReg result, GPRReg obj, GPRReg impl) 986 { 987 m_jit.setupArgumentsWithExecState(obj, impl); 988 return appendCallSetResult(operation, result); 989 } 985 990 JITCompiler::Call callOperation(P_JITOperation_ESt operation, GPRReg result, Structure* structure) 986 991 { … … 1310 1315 1311 1316 #if USE(JSVALUE64) 1312 1317 JITCompiler::Call callOperation(Z_JITOperation_EOJ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1318 { 1319 m_jit.setupArgumentsWithExecState(arg1, arg2); 1320 return appendCallSetResult(operation, result); 1321 } 1313 1322 JITCompiler::Call callOperation(C_JITOperation_ECJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1314 1323 { … … 1316 1325 return appendCallSetResult(operation, result); 1317 1326 } 1318 1319 1327 JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC) 1320 1328 { … … 1322 1330 return appendCallSetResult(operation, result.gpr()); 1323 1331 } 1324 1325 1332 JITCompiler::Call callOperation(J_JITOperation_EJJI operation, GPRReg result, GPRReg arg1, GPRReg arg2, UniquedStringImpl* uid) 1326 1333 { … … 1750 1757 } 1751 1758 #else // USE(JSVALUE32_64) 1752 1759 JITCompiler::Call callOperation(Z_JITOperation_EOJ operation, GPRReg result, GPRReg arg1, JSValueRegs arg2) 1760 { 1761 m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR()); 1762 return appendCallSetResult(operation, result); 1763 } 1753 1764 JITCompiler::Call callOperation(C_JITOperation_ECJZ operation, GPRReg result, GPRReg arg1, JSValueRegs arg2, GPRReg arg3) 1754 1765 { … … 3523 3534 3524 3535 class SpeculateCellOperand { 3536 WTF_MAKE_NONCOPYABLE(SpeculateCellOperand); 3537 3525 3538 public: 3526 3539 explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) … … 3535 3548 if (jit->isFilled(node())) 3536 3549 gpr(); 3550 } 3551 3552 explicit SpeculateCellOperand(SpeculateCellOperand&& other) 3553 { 3554 m_jit = other.m_jit; 3555 m_edge = other.m_edge; 3556 m_gprOrInvalid = other.m_gprOrInvalid; 3557 3558 other.m_gprOrInvalid = InvalidGPRReg; 3559 other.m_edge = Edge(); 3537 3560 } 3538 3561 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r206098 r206136 38 38 #include "DirectArguments.h" 39 39 #include "GetterSetter.h" 40 #include "HasOwnPropertyCache.h" 40 41 #include "HashMapImpl.h" 41 42 #include "JSEnvironmentRecord.h" … … 4889 4890 break; 4890 4891 4892 case HasOwnProperty: { 4893 #if CPU(X86) 4894 ASSERT(node->child2().useKind() == UntypedUse); 4895 SpeculateCellOperand object(this, node->child1()); 4896 JSValueOperand key(this, node->child2()); 4897 GPRTemporary result(this, Reuse, object); 4898 4899 JSValueRegs keyRegs = key.jsValueRegs(); 4900 GPRReg objectGPR = object.gpr(); 4901 GPRReg resultGPR = result.gpr(); 4902 flushRegisters(); 4903 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyRegs); 4904 booleanResult(resultGPR, node); 4905 #else 4906 SpeculateCellOperand object(this, node->child1()); 4907 GPRTemporary uniquedStringImpl(this); 4908 GPRTemporary temp(this); 4909 GPRTemporary hash(this); 4910 GPRTemporary structureID(this); 4911 GPRTemporary result(this); 4912 4913 Optional<SpeculateCellOperand> keyAsCell; 4914 Optional<JSValueOperand> keyAsValue; 4915 JSValueRegs keyRegs; 4916 if (node->child2().useKind() == UntypedUse) { 4917 keyAsValue = JSValueOperand(this, node->child2()); 4918 keyRegs = keyAsValue->jsValueRegs(); 4919 } else { 4920 ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == SymbolUse); 4921 keyAsCell = SpeculateCellOperand(this, node->child2()); 4922 keyRegs = JSValueRegs::payloadOnly(keyAsCell->gpr()); 4923 } 4924 4925 GPRReg objectGPR = object.gpr(); 4926 GPRReg implGPR = uniquedStringImpl.gpr(); 4927 GPRReg tempGPR = temp.gpr(); 4928 GPRReg hashGPR = hash.gpr(); 4929 GPRReg structureIDGPR = structureID.gpr(); 4930 GPRReg resultGPR = result.gpr(); 4931 4932 speculateObject(node->child1()); 4933 4934 MacroAssembler::JumpList slowPath; 4935 switch (node->child2().useKind()) { 4936 case SymbolUse: { 4937 speculateSymbol(node->child2(), keyRegs.payloadGPR()); 4938 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), Symbol::offsetOfSymbolImpl()), implGPR); 4939 break; 4940 } 4941 case StringUse: { 4942 speculateString(node->child2(), keyRegs.payloadGPR()); 4943 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), JSString::offsetOfValue()), implGPR); 4944 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, implGPR)); 4945 slowPath.append(m_jit.branchTest32( 4946 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()), 4947 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic()))); 4948 break; 4949 } 4950 case UntypedUse: { 4951 slowPath.append(m_jit.branchIfNotCell(keyRegs)); 4952 auto isNotString = m_jit.branchIfNotString(keyRegs.payloadGPR()); 4953 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), JSString::offsetOfValue()), implGPR); 4954 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, implGPR)); 4955 slowPath.append(m_jit.branchTest32( 4956 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()), 4957 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic()))); 4958 auto hasUniquedImpl = m_jit.jump(); 4959 4960 isNotString.link(&m_jit); 4961 slowPath.append(m_jit.branchIfNotSymbol(keyRegs.payloadGPR())); 4962 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), Symbol::offsetOfSymbolImpl()), implGPR); 4963 4964 hasUniquedImpl.link(&m_jit); 4965 break; 4966 } 4967 default: 4968 RELEASE_ASSERT_NOT_REACHED(); 4969 } 4970 4971 // Note that we don't test if the hash is zero here. AtomicStringImpl's can't have a zero 4972 // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only 4973 // ever load the result from the cache if the cache entry matches what we are querying for. 4974 // So we either get super lucky and use zero for the hash and somehow collide with the entity 4975 // we're looking for, or we realize we're comparing against another entity, and go to the 4976 // slow path anyways. 4977 m_jit.load32(MacroAssembler::Address(implGPR, UniquedStringImpl::flagsOffset()), hashGPR); 4978 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), hashGPR); 4979 m_jit.load32(MacroAssembler::Address(objectGPR, JSCell::structureIDOffset()), structureIDGPR); 4980 m_jit.add32(structureIDGPR, hashGPR); 4981 m_jit.and32(TrustedImm32(HasOwnPropertyCache::mask), hashGPR); 4982 m_jit.mul32(TrustedImm32(sizeof(HasOwnPropertyCache::Entry)), hashGPR, hashGPR); 4983 ASSERT(m_jit.vm()->hasOwnPropertyCache()); 4984 m_jit.move(TrustedImmPtr(m_jit.vm()->hasOwnPropertyCache()), tempGPR); 4985 slowPath.append(m_jit.branchPtr(MacroAssembler::NotEqual, 4986 MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfImpl()), implGPR)); 4987 m_jit.load8(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfResult()), resultGPR); 4988 m_jit.load32(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfStructureID()), tempGPR); 4989 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, tempGPR, structureIDGPR)); 4990 auto done = m_jit.jump(); 4991 4992 slowPath.link(&m_jit); 4993 silentSpillAllRegisters(resultGPR); 4994 if (node->child2().useKind() != UntypedUse) { 4995 m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), tempGPR); 4996 keyRegs = JSValueRegs(tempGPR, keyRegs.payloadGPR()); 4997 } 4998 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyRegs); 4999 silentFillAllRegisters(resultGPR); 5000 m_jit.exceptionCheck(); 5001 5002 done.link(&m_jit); 5003 booleanResult(resultGPR, node); 5004 #endif // CPU(X86) 5005 break; 5006 } 5007 4891 5008 case StoreBarrier: { 4892 5009 compileStoreBarrier(node); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r206098 r206136 37 37 #include "DirectArguments.h" 38 38 #include "GetterSetter.h" 39 #include "HasOwnPropertyCache.h" 39 40 #include "JSCInlines.h" 40 41 #include "JSEnvironmentRecord.h" … … 4629 4630 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR)); 4630 4631 m_jit.load32(MacroAssembler::Address(resultGPR, StringImpl::flagsOffset()), resultGPR); 4631 m_jit.urshift 64(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), resultGPR);4632 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), resultGPR); 4632 4633 slowPath.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR)); 4633 4634 done.append(m_jit.jump()); … … 4936 4937 compileIn(node); 4937 4938 break; 4939 4940 case HasOwnProperty: { 4941 SpeculateCellOperand object(this, node->child1()); 4942 GPRTemporary uniquedStringImpl(this); 4943 GPRTemporary temp(this); 4944 GPRTemporary hash(this); 4945 GPRTemporary structureID(this); 4946 GPRTemporary result(this); 4947 4948 Optional<SpeculateCellOperand> keyAsCell; 4949 Optional<JSValueOperand> keyAsValue; 4950 GPRReg keyGPR; 4951 if (node->child2().useKind() == UntypedUse) { 4952 keyAsValue = JSValueOperand(this, node->child2()); 4953 keyGPR = keyAsValue->gpr(); 4954 } else { 4955 ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == SymbolUse); 4956 keyAsCell = SpeculateCellOperand(this, node->child2()); 4957 keyGPR = keyAsCell->gpr(); 4958 } 4959 4960 GPRReg objectGPR = object.gpr(); 4961 GPRReg implGPR = uniquedStringImpl.gpr(); 4962 GPRReg tempGPR = temp.gpr(); 4963 GPRReg hashGPR = hash.gpr(); 4964 GPRReg structureIDGPR = structureID.gpr(); 4965 GPRReg resultGPR = result.gpr(); 4966 4967 speculateObject(node->child1()); 4968 4969 MacroAssembler::JumpList slowPath; 4970 switch (node->child2().useKind()) { 4971 case SymbolUse: { 4972 speculateSymbol(node->child2(), keyGPR); 4973 m_jit.loadPtr(MacroAssembler::Address(keyGPR, Symbol::offsetOfSymbolImpl()), implGPR); 4974 break; 4975 } 4976 case StringUse: { 4977 speculateString(node->child2(), keyGPR); 4978 m_jit.loadPtr(MacroAssembler::Address(keyGPR, JSString::offsetOfValue()), implGPR); 4979 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, implGPR)); 4980 slowPath.append(m_jit.branchTest32( 4981 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()), 4982 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic()))); 4983 break; 4984 } 4985 case UntypedUse: { 4986 slowPath.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR))); 4987 auto isNotString = m_jit.branchIfNotString(keyGPR); 4988 m_jit.loadPtr(MacroAssembler::Address(keyGPR, JSString::offsetOfValue()), implGPR); 4989 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, implGPR)); 4990 slowPath.append(m_jit.branchTest32( 4991 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()), 4992 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic()))); 4993 auto hasUniquedImpl = m_jit.jump(); 4994 4995 isNotString.link(&m_jit); 4996 slowPath.append(m_jit.branchIfNotSymbol(keyGPR)); 4997 m_jit.loadPtr(MacroAssembler::Address(keyGPR, Symbol::offsetOfSymbolImpl()), implGPR); 4998 4999 hasUniquedImpl.link(&m_jit); 5000 break; 5001 } 5002 default: 5003 RELEASE_ASSERT_NOT_REACHED(); 5004 } 5005 5006 // Note that we don't test if the hash is zero here. AtomicStringImpl's can't have a zero 5007 // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only 5008 // ever load the result from the cache if the cache entry matches what we are querying for. 5009 // So we either get super lucky and use zero for the hash and somehow collide with the entity 5010 // we're looking for, or we realize we're comparing against another entity, and go to the 5011 // slow path anyways. 5012 m_jit.load32(MacroAssembler::Address(implGPR, UniquedStringImpl::flagsOffset()), hashGPR); 5013 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), hashGPR); 5014 m_jit.load32(MacroAssembler::Address(objectGPR, JSCell::structureIDOffset()), structureIDGPR); 5015 m_jit.add32(structureIDGPR, hashGPR); 5016 m_jit.and32(TrustedImm32(HasOwnPropertyCache::mask), hashGPR); 5017 static_assert(sizeof(HasOwnPropertyCache::Entry) == 16, "Strong assumption of that here."); 5018 m_jit.lshift32(TrustedImm32(4), hashGPR); 5019 ASSERT(m_jit.vm()->hasOwnPropertyCache()); 5020 m_jit.move(TrustedImmPtr(m_jit.vm()->hasOwnPropertyCache()), tempGPR); 5021 slowPath.append(m_jit.branchPtr(MacroAssembler::NotEqual, 5022 MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfImpl()), implGPR)); 5023 m_jit.load8(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfResult()), resultGPR); 5024 m_jit.load32(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfStructureID()), tempGPR); 5025 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, tempGPR, structureIDGPR)); 5026 auto done = m_jit.jump(); 5027 5028 slowPath.link(&m_jit); 5029 silentSpillAllRegisters(resultGPR); 5030 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyGPR); 5031 silentFillAllRegisters(resultGPR); 5032 m_jit.exceptionCheck(); 5033 5034 done.link(&m_jit); 5035 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 5036 jsValueResult(resultGPR, node, DataFormatJSBoolean); 5037 break; 5038 } 4938 5039 4939 5040 case CountExecution: -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r204466 r206136 310 310 // https://bugs.webkit.org/show_bug.cgi?id=159602 311 311 break; 312 case HasOwnProperty: { 313 VALIDATE((node), !!m_graph.m_vm.hasOwnPropertyCache()); 314 break; 315 } 312 316 default: 313 317 break; -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
r205520 r206136 32 32 #include "DFGArrayMode.h" 33 33 #include "FTLAbstractHeap.h" 34 #include "HasOwnPropertyCache.h" 34 35 #include "IndexingType.h" 35 36 #include "JSMap.h" 36 37 #include "JSSet.h" 38 #include "Symbol.h" 37 39 38 40 namespace JSC { namespace FTL { … … 111 113 macro(HashMapBucket_value, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()) \ 112 114 macro(HashMapBucket_key, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfKey()) \ 115 macro(Symbol_symbolImpl, Symbol::offsetOfSymbolImpl()) \ 113 116 114 117 #define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \ … … 129 132 macro(singleCharacterStrings, 0, sizeof(JSString*)) \ 130 133 macro(structureTable, 0, sizeof(Structure*)) \ 131 macro(variables, 0, sizeof(Register)) 134 macro(variables, 0, sizeof(Register)) \ 135 macro(HasOwnPropertyCache, 0, sizeof(HasOwnPropertyCache::Entry)) \ 132 136 133 137 #define FOR_EACH_NUMBERED_ABSTRACT_HEAP(macro) \ -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r206098 r206136 182 182 case Unreachable: 183 183 case In: 184 case HasOwnProperty: 184 185 case IsCellWithType: 185 186 case MapHash: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r206134 r206136 632 632 case In: 633 633 compileIn(); 634 break; 635 case HasOwnProperty: 636 compileHasOwnProperty(); 634 637 break; 635 638 case PutById: … … 6771 6774 6772 6775 setJSValue(vmCall(Int64, m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child1()))); 6776 } 6777 6778 void compileHasOwnProperty() 6779 { 6780 LBasicBlock slowCase = m_out.newBlock(); 6781 LBasicBlock continuation = m_out.newBlock(); 6782 LBasicBlock lastNext = nullptr; 6783 6784 LValue object = lowObject(m_node->child1()); 6785 LValue uniquedStringImpl; 6786 LValue keyAsValue = nullptr; 6787 switch (m_node->child2().useKind()) { 6788 case StringUse: { 6789 LBasicBlock isNonEmptyString = m_out.newBlock(); 6790 LBasicBlock isAtomicString = m_out.newBlock(); 6791 6792 keyAsValue = lowString(m_node->child2()); 6793 uniquedStringImpl = m_out.loadPtr(keyAsValue, m_heaps.JSString_value); 6794 m_out.branch(m_out.notNull(uniquedStringImpl), usually(isNonEmptyString), rarely(slowCase)); 6795 6796 lastNext = m_out.appendTo(isNonEmptyString, isAtomicString); 6797 LValue isNotAtomic = m_out.testIsZero32(m_out.load32(uniquedStringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::flagIsAtomic())); 6798 m_out.branch(isNotAtomic, rarely(slowCase), usually(isAtomicString)); 6799 6800 m_out.appendTo(isAtomicString, slowCase); 6801 break; 6802 } 6803 case SymbolUse: { 6804 keyAsValue = lowSymbol(m_node->child2()); 6805 uniquedStringImpl = m_out.loadPtr(keyAsValue, m_heaps.Symbol_symbolImpl); 6806 lastNext = m_out.insertNewBlocksBefore(slowCase); 6807 break; 6808 } 6809 case UntypedUse: { 6810 LBasicBlock isCellCase = m_out.newBlock(); 6811 LBasicBlock isStringCase = m_out.newBlock(); 6812 LBasicBlock notStringCase = m_out.newBlock(); 6813 LBasicBlock isNonEmptyString = m_out.newBlock(); 6814 LBasicBlock isSymbolCase = m_out.newBlock(); 6815 LBasicBlock hasUniquedStringImpl = m_out.newBlock(); 6816 6817 keyAsValue = lowJSValue(m_node->child2()); 6818 m_out.branch(isCell(keyAsValue), usually(isCellCase), rarely(slowCase)); 6819 6820 lastNext = m_out.appendTo(isCellCase, isStringCase); 6821 m_out.branch(isString(keyAsValue), unsure(isStringCase), unsure(notStringCase)); 6822 6823 m_out.appendTo(isStringCase, isNonEmptyString); 6824 LValue implFromString = m_out.loadPtr(keyAsValue, m_heaps.JSString_value); 6825 ValueFromBlock stringResult = m_out.anchor(implFromString); 6826 m_out.branch(m_out.notNull(implFromString), usually(isNonEmptyString), rarely(slowCase)); 6827 6828 m_out.appendTo(isNonEmptyString, notStringCase); 6829 LValue isNotAtomic = m_out.testIsZero32(m_out.load32(implFromString, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::flagIsAtomic())); 6830 m_out.branch(isNotAtomic, rarely(slowCase), usually(hasUniquedStringImpl)); 6831 6832 m_out.appendTo(notStringCase, isSymbolCase); 6833 m_out.branch(isSymbol(keyAsValue), unsure(isSymbolCase), unsure(slowCase)); 6834 6835 m_out.appendTo(isSymbolCase, hasUniquedStringImpl); 6836 ValueFromBlock symbolResult = m_out.anchor(m_out.loadPtr(keyAsValue, m_heaps.Symbol_symbolImpl)); 6837 m_out.jump(hasUniquedStringImpl); 6838 6839 m_out.appendTo(hasUniquedStringImpl, slowCase); 6840 uniquedStringImpl = m_out.phi(pointerType(), stringResult, symbolResult); 6841 break; 6842 } 6843 default: 6844 RELEASE_ASSERT_NOT_REACHED(); 6845 } 6846 6847 ASSERT(keyAsValue); 6848 6849 // Note that we don't test if the hash is zero here. AtomicStringImpl's can't have a zero 6850 // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only 6851 // ever load the result from the cache if the cache entry matches what we are querying for. 6852 // So we either get super lucky and use zero for the hash and somehow collide with the entity 6853 // we're looking for, or we realize we're comparing against another entity, and go to the 6854 // slow path anyways. 6855 LValue hash = m_out.lShr(m_out.load32(uniquedStringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::s_flagCount)); 6856 6857 LValue structureID = m_out.load32(object, m_heaps.JSCell_structureID); 6858 LValue index = m_out.add(hash, structureID); 6859 index = m_out.zeroExtPtr(m_out.bitAnd(index, m_out.constInt32(HasOwnPropertyCache::mask))); 6860 ASSERT(vm().hasOwnPropertyCache()); 6861 LValue cache = m_out.constIntPtr(vm().hasOwnPropertyCache()); 6862 6863 IndexedAbstractHeap& heap = m_heaps.HasOwnPropertyCache; 6864 LValue sameStructureID = m_out.equal(structureID, m_out.load32(m_out.baseIndex(heap, cache, index, JSValue(), HasOwnPropertyCache::Entry::offsetOfStructureID()))); 6865 LValue sameImpl = m_out.equal(uniquedStringImpl, m_out.loadPtr(m_out.baseIndex(heap, cache, index, JSValue(), HasOwnPropertyCache::Entry::offsetOfImpl()))); 6866 ValueFromBlock fastResult = m_out.anchor(m_out.load8ZeroExt32(m_out.baseIndex(heap, cache, index, JSValue(), HasOwnPropertyCache::Entry::offsetOfResult()))); 6867 LValue cacheHit = m_out.bitAnd(sameStructureID, sameImpl); 6868 6869 m_out.branch(m_out.notZero32(cacheHit), usually(continuation), rarely(slowCase)); 6870 6871 m_out.appendTo(slowCase, continuation); 6872 ValueFromBlock slowResult; 6873 slowResult = m_out.anchor(vmCall(Int32, m_out.operation(operationHasOwnProperty), m_callFrame, object, keyAsValue)); 6874 m_out.jump(continuation); 6875 6876 m_out.appendTo(continuation, lastNext); 6877 setBoolean(m_out.phi(Int32, fastResult, slowResult)); 6773 6878 } 6774 6879 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r205850 r206136 30 30 #include "GCIncomingRefCountedSetInlines.h" 31 31 #include "GCTypeMap.h" 32 #include "HasOwnPropertyCache.h" 32 33 #include "HeapHelperPool.h" 33 34 #include "HeapIterationScope.h" … … 1023 1024 prepareForMarking(); 1024 1025 flushWriteBarrierBuffer(); 1026 1027 if (HasOwnPropertyCache* cache = vm()->hasOwnPropertyCache()) 1028 cache->clear(); 1025 1029 } 1026 1030 -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r205675 r206136 222 222 typedef int32_t (JIT_OPERATION *Z_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t); 223 223 typedef int32_t (JIT_OPERATION *Z_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t); 224 typedef int32_t (JIT_OPERATION *Z_JITOperation_EOI)(ExecState*, JSObject*, UniquedStringImpl*); 225 typedef int32_t (JIT_OPERATION *Z_JITOperation_EOJ)(ExecState*, JSObject*, EncodedJSValue); 224 226 typedef size_t (JIT_OPERATION *S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*); 225 227 typedef size_t (JIT_OPERATION *S_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*); -
trunk/Source/JavaScriptCore/runtime/Intrinsic.h
r206104 r206136 66 66 JSMapHasIntrinsic, 67 67 JSSetHasIntrinsic, 68 HasOwnPropertyIntrinsic, 68 69 69 70 // Getter intrinsics. -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r205670 r206136 524 524 bool hasPropertyGeneric(ExecState*, PropertyName, PropertySlot::InternalMethodType) const; 525 525 bool hasPropertyGeneric(ExecState*, unsigned propertyName, PropertySlot::InternalMethodType) const; 526 bool hasOwnProperty(ExecState*, PropertyName, PropertySlot&) const; 526 527 bool hasOwnProperty(ExecState*, PropertyName) const; 527 528 bool hasOwnProperty(ExecState*, unsigned) const; -
trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h
r205753 r206136 200 200 // HasOwnProperty(O, P) from section 7.3.11 in the spec. 201 201 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-hasownproperty 202 ALWAYS_INLINE bool JSObject::hasOwnProperty(ExecState* exec, PropertyName propertyName ) const203 { 204 PropertySlot slot(this,PropertySlot::InternalMethodType::GetOwnProperty);202 ALWAYS_INLINE bool JSObject::hasOwnProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const 203 { 204 ASSERT(slot.internalMethodType() == PropertySlot::InternalMethodType::GetOwnProperty); 205 205 if (LIKELY(const_cast<JSObject*>(this)->methodTable(exec->vm())->getOwnPropertySlot == JSObject::getOwnPropertySlot)) 206 206 return JSObject::getOwnPropertySlot(const_cast<JSObject*>(this), exec, propertyName, slot); … … 208 208 } 209 209 210 ALWAYS_INLINE bool JSObject::hasOwnProperty(ExecState* exec, PropertyName propertyName) const 211 { 212 PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty); 213 return hasOwnProperty(exec, propertyName, slot); 214 } 215 210 216 ALWAYS_INLINE bool JSObject::hasOwnProperty(ExecState* exec, unsigned propertyName) const 211 217 { -
trunk/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
r205569 r206136 24 24 #include "Error.h" 25 25 #include "GetterSetter.h" 26 #include "HasOwnPropertyCache.h" 26 27 #include "JSFunction.h" 27 28 #include "JSString.h" … … 61 62 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toLocaleString, objectProtoFuncToLocaleString, DontEnum, 0); 62 63 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->valueOf, objectProtoFuncValueOf, DontEnum, 0); 63 JSC_NATIVE_ FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->hasOwnProperty, objectProtoFuncHasOwnProperty, DontEnum, 1);64 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->hasOwnProperty, objectProtoFuncHasOwnProperty, DontEnum, 1, HasOwnPropertyIntrinsic); 64 65 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable, DontEnum, 1); 65 66 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isPrototypeOf, objectProtoFuncIsPrototypeOf, DontEnum, 1); … … 98 99 return JSValue::encode(jsUndefined()); 99 100 JSObject* thisObject = thisValue.toObject(exec); 100 if ( !thisObject)101 if (UNLIKELY(!thisObject)) 101 102 return JSValue::encode(JSValue()); 102 return JSValue::encode(jsBoolean(thisObject->hasOwnProperty(exec, propertyName))); 103 104 Structure* structure = thisObject->structure(vm); 105 HasOwnPropertyCache* hasOwnPropertyCache = vm.ensureHasOwnPropertyCache(); 106 if (Optional<bool> result = hasOwnPropertyCache->get(structure, propertyName)) { 107 ASSERT(*result == thisObject->hasOwnProperty(exec, propertyName)); 108 ASSERT(!scope.exception()); 109 return JSValue::encode(jsBoolean(*result)); 110 } 111 112 PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty); 113 bool result = thisObject->hasOwnProperty(exec, propertyName, slot); 114 if (UNLIKELY(scope.exception())) 115 return JSValue::encode(jsUndefined()); 116 117 hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName, result); 118 return JSValue::encode(jsBoolean(result)); 103 119 } 104 120 -
trunk/Source/JavaScriptCore/runtime/Symbol.h
r205335 r206136 60 60 double toNumber(ExecState*) const; 61 61 62 static ptrdiff_t offsetOfSymbolImpl() 63 { 64 // PrivateName is just a Ref<SymbolImpl> which can just be used as a SymbolImpl*. 65 return OBJECT_OFFSETOF(Symbol, m_privateName); 66 } 67 62 68 protected: 63 69 static void destroy(JSCell*); -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r205917 r206136 48 48 #include "GCActivityCallback.h" 49 49 #include "GetterSetter.h" 50 #include "HasOwnPropertyCache.h" 50 51 #include "Heap.h" 51 52 #include "HeapIterationScope.h" -
trunk/Source/JavaScriptCore/runtime/VM.h
r205989 r206136 90 90 class TypeProfiler; 91 91 class TypeProfilerLog; 92 class HasOwnPropertyCache; 92 93 class HeapProfiler; 93 94 class Identifier; … … 555 556 ConcurrentJITLock m_regExpAllocatorLock; 556 557 558 std::unique_ptr<HasOwnPropertyCache> m_hasOwnPropertyCache; 559 ALWAYS_INLINE HasOwnPropertyCache* hasOwnPropertyCache() { return m_hasOwnPropertyCache.get(); } 560 HasOwnPropertyCache* ensureHasOwnPropertyCache(); 561 557 562 #if ENABLE(REGEXP_TRACING) 558 563 typedef ListHashSet<RegExp*> RTTraceList;
Note: See TracChangeset
for help on using the changeset viewer.