Changeset 140259 in webkit
- Timestamp:
- Jan 19, 2013 1:47:45 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r138472 r140259 270 270 runtime/PropertyNameArray.cpp 271 271 runtime/PropertySlot.cpp 272 runtime/PrototypeMap.cpp 272 273 runtime/RegExp.cpp 273 274 runtime/RegExpCache.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r140232 r140259 1 2013-01-19 Geoffrey Garen <ggaren@apple.com> 2 3 Track inheritance structures in a side table, instead of using a private 4 name in each prototype 5 https://bugs.webkit.org/show_bug.cgi?id=107378 6 7 Reviewed by Sam Weinig and Phil Pizlo. 8 9 This is a step toward object size inference. 10 11 Using a side table frees us to use a more complex key (a pair of 12 prototype and expected inline capacity). 13 14 It also avoids ruining inline caches for prototypes. (Adding a new private 15 name for a new inline capacity would change the prototype's structure, 16 possibly firing watchpoints, making inline caches go polymorphic, and 17 generally causing us to have a bad time.) 18 19 * CMakeLists.txt: 20 * GNUmakefile.list.am: 21 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: 22 * JavaScriptCore.xcodeproj/project.pbxproj: 23 * Target.pri: Buildage. 24 25 * runtime/ArrayPrototype.cpp: 26 (JSC::ArrayPrototype::finishCreation): Updated to use new side table API. 27 28 * runtime/JSFunction.cpp: 29 (JSC::JSFunction::cacheInheritorID): Updated to use new side table API. 30 31 (JSC::JSFunction::visitChildren): Fixed a long-standing bug where JSFunction 32 forgot to visit one of its data members (m_cachedInheritorID). This 33 wasn't a user-visible problem before because JSFunction would always 34 visit its .prototype property, which visited its m_cachedInheritorID. 35 But now, function.prototype only weakly owns function.m_cachedInheritorID. 36 37 * runtime/JSGlobalData.h: 38 (JSGlobalData): Added the map, taking care to make sure that its 39 destructor would run after the heap destructor. 40 41 * runtime/JSGlobalObject.cpp: 42 (JSC::JSGlobalObject::reset): Updated to use new side table API. 43 44 * runtime/JSObject.cpp: 45 (JSC::JSObject::notifyPresenceOfIndexedAccessors): 46 (JSC::JSObject::setPrototype): 47 * runtime/JSObject.h: 48 (JSObject): Updated to use new side table API, and removed lots of code 49 that used to manage the per-object private name. 50 51 * runtime/JSProxy.cpp: 52 (JSC::JSProxy::setTarget): 53 * runtime/ObjectConstructor.cpp: 54 (JSC::objectConstructorCreate): 55 * runtime/ObjectPrototype.cpp: 56 (JSC::ObjectPrototype::finishCreation): Updated to use new side table API. 57 58 * runtime/PrototypeMap.cpp: Added. 59 (JSC): 60 (JSC::PrototypeMap::addPrototype): 61 (JSC::PrototypeMap::emptyObjectStructureForPrototype): 62 * runtime/PrototypeMap.h: Added. 63 (PrototypeMap): 64 (JSC::PrototypeMap::isPrototype): 65 (JSC::PrototypeMap::clearEmptyObjectStructureForPrototype): New side table. 66 This is a simple weak map, mapping an object to the structure you should 67 use when inheriting from that object. (In future, inline capacity will 68 be a part of the mapping.) 69 70 I used two maps to preserve existing behavior that allowed us to speculate 71 about an object becoming a prototype, even if it wasn't one at the moment. 72 However, I suspect that behavior can be removed without harm. 73 74 * runtime/WeakGCMap.h: 75 (JSC::WeakGCMap::contains): 76 (WeakGCMap): I would rate myself a 6 / 10 in C++. 77 1 78 2013-01-18 Dan Bernstein <mitz@apple.com> 2 79 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r139765 r140259 696 696 Source/JavaScriptCore/runtime/PropertySlot.cpp \ 697 697 Source/JavaScriptCore/runtime/PropertySlot.h \ 698 Source/JavaScriptCore/runtime/PrototypeMap.cpp \ 699 Source/JavaScriptCore/runtime/PrototypeMap.h \ 698 700 Source/JavaScriptCore/runtime/PropertyStorage.h \ 699 701 Source/JavaScriptCore/runtime/Protect.h \ -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
r139682 r140259 1175 1175 </File> 1176 1176 <File 1177 RelativePath="..\..\runtime\PrototypeMap.cpp" 1178 > 1179 </File> 1180 <File 1181 RelativePath="..\..\runtime\PrototypeMap.h" 1182 > 1183 </File> 1184 <File 1177 1185 RelativePath="..\..\runtime\PropertyStorage.h" 1178 1186 > -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r140232 r140259 399 399 146B16D812EB5B59001BEC1B /* ConservativeRoots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */; }; 400 400 146FE51211A710430087AE66 /* JITCall32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 146FE51111A710430087AE66 /* JITCall32_64.cpp */; }; 401 1474C33B16AA2D950062F01D /* PrototypeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D844A316AA2C7000A65AF0 /* PrototypeMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; 402 1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14D844A216AA2C7000A65AF0 /* PrototypeMap.cpp */; }; 401 403 1478297B1379E8A800A7C2A3 /* HandleTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 146FA5A81378F6B0003627A3 /* HandleTypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; 402 404 147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 147B83AA0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h */; }; … … 1278 1280 14D2F3D9139F4BE200491031 /* MarkedSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedSpace.h; sourceTree = "<group>"; }; 1279 1281 14D792640DAA03FB001A9F05 /* JSStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStack.h; sourceTree = "<group>"; }; 1282 14D844A216AA2C7000A65AF0 /* PrototypeMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrototypeMap.cpp; sourceTree = "<group>"; }; 1283 14D844A316AA2C7000A65AF0 /* PrototypeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrototypeMap.h; sourceTree = "<group>"; }; 1280 1284 14D857740A4696C80032146C /* testapi.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = testapi.js; path = API/tests/testapi.js; sourceTree = "<group>"; }; 1281 1285 14DA818E0D99FD2000B0A4FB /* JSActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSActivation.h; sourceTree = "<group>"; }; … … 2322 2326 F692A85D0255597D01FF60F7 /* FunctionPrototype.h */, 2323 2327 C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */, 2324 C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */,2325 2328 DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */, 2326 2329 BC02E9B80E184545000F9297 /* GetterSetter.cpp */, … … 2440 2443 0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */, 2441 2444 65C02FBB0637462A003E7EE6 /* Protect.h */, 2445 14D844A216AA2C7000A65AF0 /* PrototypeMap.cpp */, 2446 14D844A316AA2C7000A65AF0 /* PrototypeMap.h */, 2442 2447 0F0CD4C015F1A6040032F1C0 /* PutDirectIndexMode.h */, 2443 2448 147B84620E6DE6B1004775A4 /* PutPropertySlot.h */, … … 2491 2496 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */, 2492 2497 A7DCB77912E3D90500911940 /* WriteBarrier.h */, 2498 C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */, 2493 2499 ); 2494 2500 path = runtime; … … 3271 3277 86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */, 3272 3278 0F9749711687ADE400A4FF6A /* JSCellInlines.h in Headers */, 3279 1474C33B16AA2D950062F01D /* PrototypeMap.h in Headers */, 3273 3280 ); 3274 3281 runOnlyForDeploymentPostprocessing = 0; … … 3898 3905 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */, 3899 3906 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */, 3907 1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */, 3900 3908 ); 3901 3909 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/JavaScriptCore/Target.pri
r138465 r140259 288 288 runtime/PropertyNameArray.cpp \ 289 289 runtime/PropertySlot.cpp \ 290 runtime/PrototypeMap.cpp \ 290 291 runtime/RegExpConstructor.cpp \ 291 292 runtime/RegExpCachedResult.cpp \ -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r134081 r140259 133 133 Base::finishCreation(globalData); 134 134 ASSERT(inherits(&s_info)); 135 notifyUsedAsPrototype(globalData);135 globalData.prototypeMap.addPrototype(this); 136 136 } 137 137 -
trunk/Source/JavaScriptCore/runtime/JSFunction.cpp
r139541 r140259 109 109 Structure* JSFunction::cacheInheritorID(ExecState* exec) 110 110 { 111 JSValue prototype = get(exec, exec->globalData().propertyNames->prototype); 111 JSGlobalData& globalData = exec->globalData(); 112 JSValue prototype = get(exec, globalData.propertyNames->prototype); 112 113 if (prototype.isObject()) 113 m_cachedInheritorID.set( exec->globalData(), this, asObject(prototype)->inheritorID(exec->globalData()));114 m_cachedInheritorID.set(globalData, this, globalData.prototypeMap.emptyObjectStructureForPrototype(asObject(prototype))); 114 115 else 115 m_cachedInheritorID.set( exec->globalData(), this, globalObject()->emptyObjectStructure());116 m_cachedInheritorID.set(globalData, this, globalData.prototypeMap.emptyObjectStructureForPrototype(globalObject()->objectPrototype())); 116 117 return m_cachedInheritorID.get(); 117 118 } … … 163 164 visitor.append(&thisObject->m_scope); 164 165 visitor.append(&thisObject->m_executable); 166 visitor.append(&thisObject->m_cachedInheritorID); 165 167 } 166 168 -
trunk/Source/JavaScriptCore/runtime/JSGlobalData.h
r139541 r140259 43 43 #include "ProfilerDatabase.h" 44 44 #include "PrivateName.h" 45 #include "PrototypeMap.h" 45 46 #include "SmallStrings.h" 46 47 #include "Strong.h" … … 287 288 #endif 288 289 289 Pr ivateName m_inheritorIDKey;290 PrototypeMap prototypeMap; 290 291 291 292 OwnPtr<ParserArena> parserArena; -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r139541 r140259 224 224 m_withScopeStructure.set(exec->globalData(), this, JSWithScope::createStructure(exec->globalData(), this, jsNull())); 225 225 226 m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData()));227 m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), this, jsNull()));226 m_emptyObjectStructure.set(exec->globalData(), this, globalData().prototypeMap.emptyObjectStructureForPrototype(m_objectPrototype.get())); 227 m_nullPrototypeObjectStructure.set(exec->globalData(), this, JSFinalObject::createStructure(globalData(), this, jsNull())); 228 228 229 229 m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), this, m_functionPrototype.get())); -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r139491 r140259 597 597 setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AddIndexedAccessors)); 598 598 599 if (! mayBeUsedAsPrototype(globalData))599 if (!globalData.prototypeMap.isPrototype(this)) 600 600 return; 601 601 … … 1150 1150 ASSERT(prototype); 1151 1151 if (prototype.isObject()) 1152 asObject(prototype)->notifyUsedAsPrototype(globalData);1152 globalData.prototypeMap.addPrototype(asObject(prototype)); 1153 1153 1154 1154 Structure* newStructure = Structure::changePrototypeTransition(globalData, structure(), prototype); … … 1158 1158 return; 1159 1159 1160 if ( mayBeUsedAsPrototype(globalData)) {1160 if (globalData.prototypeMap.isPrototype(this)) { 1161 1161 newStructure->globalObject()->haveABadTime(globalData); 1162 1162 return; … … 1186 1186 setPrototype(globalData, prototype); 1187 1187 return true; 1188 }1189 1190 void JSObject::resetInheritorID(JSGlobalData& globalData)1191 {1192 PropertyOffset offset = structure()->get(globalData, globalData.m_inheritorIDKey);1193 if (!isValidOffset(offset))1194 return;1195 1196 putDirect(globalData, offset, jsUndefined());1197 }1198 1199 Structure* JSObject::inheritorID(JSGlobalData& globalData)1200 {1201 if (JSValue value = getDirect(globalData, globalData.m_inheritorIDKey)) {1202 if (value.isCell()) {1203 Structure* inheritorID = jsCast<Structure*>(value);1204 ASSERT(inheritorID->isEmpty());1205 return inheritorID;1206 }1207 ASSERT(value.isUndefined());1208 }1209 return createInheritorID(globalData);1210 1188 } 1211 1189 … … 1662 1640 } else 1663 1641 slot.setUndefined(); 1664 }1665 1666 void JSObject::notifyUsedAsPrototype(JSGlobalData& globalData)1667 {1668 PropertyOffset offset = structure()->get(globalData, globalData.m_inheritorIDKey);1669 if (isValidOffset(offset))1670 return;1671 1672 PutPropertySlot slot;1673 putDirectInternal<PutModeDefineOwnProperty>(globalData, globalData.m_inheritorIDKey, jsUndefined(), DontEnum, slot, 0);1674 1675 // Note that this method makes the somewhat odd decision to not check if this1676 // object currently has indexed accessors. We could do that check here, and if1677 // indexed accessors were found, we could tell the global object to have a bad1678 // time. But we avoid this, to allow the following to be always fast:1679 //1680 // 1) Create an object.1681 // 2) Give it a setter or read-only property that happens to have a numeric name.1682 // 3) Allocate objects that use this object as a prototype.1683 //1684 // This avoids anyone having a bad time. Even if the instance objects end up1685 // having indexed storage, the creation of indexed storage leads to a prototype1686 // chain walk that detects the presence of indexed setters and then does the1687 // right thing. As a result, having a bad time only happens if you add an1688 // indexed setter (or getter, or read-only field) to an object that is already1689 // used as a prototype.1690 }1691 1692 Structure* JSObject::createInheritorID(JSGlobalData& globalData)1693 {1694 Structure* inheritorID = createEmptyObjectStructure(globalData, globalObject(), this);1695 ASSERT(inheritorID->isEmpty());1696 1697 PutPropertySlot slot;1698 putDirectInternal<PutModeDefineOwnProperty>(globalData, globalData.m_inheritorIDKey, inheritorID, DontEnum, slot, 0);1699 return inheritorID;1700 1642 } 1701 1643 -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r139541 r140259 125 125 bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype); 126 126 127 Structure* inheritorID(JSGlobalData&);128 void notifyUsedAsPrototype(JSGlobalData&);129 130 bool mayBeUsedAsPrototype(JSGlobalData& globalData)131 {132 return isValidOffset(structure()->get(globalData, globalData.m_inheritorIDKey));133 }134 135 127 bool mayInterceptIndexedAccesses() 136 128 { … … 719 711 JSObject(JSGlobalData&, Structure*, Butterfly* = 0); 720 712 721 void resetInheritorID(JSGlobalData&);722 723 713 void visitButterfly(SlotVisitor&, Butterfly*, size_t storageSize); 724 714 void copyButterfly(CopyVisitor&, Butterfly*, size_t storageSize); … … 935 925 936 926 const HashEntry* findPropertyHashEntry(ExecState*, PropertyName) const; 937 Structure* createInheritorID(JSGlobalData&);938 927 939 928 void putIndexedDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old); … … 1124 1113 ASSERT(result == ConstructTypeNone || value.isValidCallee()); 1125 1114 return result; 1126 }1127 1128 inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)1129 {1130 return JSFinalObject::createStructure(globalData, globalObject, prototype);1131 1115 } 1132 1116 -
trunk/Source/JavaScriptCore/runtime/JSProxy.cpp
r139541 r140259 53 53 m_target.set(globalData, this, globalObject); 54 54 setPrototype(globalData, globalObject->prototype()); 55 resetInheritorID(globalData);55 globalData.prototypeMap.clearEmptyObjectStructureForPrototype(this); 56 56 } 57 57 -
trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
r139541 r140259 351 351 return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object prototype may only be an Object or null."))); 352 352 JSValue proto = exec->argument(0); 353 JSObject* newObject = proto.isObject() ? constructEmptyObject(exec, asObject(proto)->inheritorID(exec->globalData())) : constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure()); 353 JSObject* newObject = proto.isObject() 354 ? constructEmptyObject(exec, exec->globalData().prototypeMap.emptyObjectStructureForPrototype(asObject(proto))) 355 : constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure()); 354 356 if (exec->argument(1).isUndefined()) 355 357 return JSValue::encode(newObject); -
trunk/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
r139541 r140259 74 74 Base::finishCreation(globalData); 75 75 ASSERT(inherits(&s_info)); 76 notifyUsedAsPrototype(globalData);76 globalData.prototypeMap.addPrototype(this); 77 77 } 78 78 -
trunk/Source/JavaScriptCore/runtime/WeakGCMap.h
r140211 r140259 89 89 } 90 90 91 template<typename T, typename HashTranslator> bool contains(const T& key) const91 bool contains(const KeyType& key) const 92 92 { 93 93 return find(key) != end(); … … 95 95 96 96 private: 97 static const int minGCThreshold ;97 static const int minGCThreshold = 3; 98 98 99 99 void gcMap() … … 122 122 123 123 template<typename KeyArg, typename RawMappedArg, typename HashArg, typename KeyTraitsArg> 124 const int WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg>::minGCThreshold = 3;124 const int WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg>::minGCThreshold; 125 125 126 126 } // namespace JSC
Note: See TracChangeset
for help on using the changeset viewer.