Title: [194175] trunk/Source/_javascript_Core
Revision
194175
Author
[email protected]
Date
2015-12-16 14:39:13 -0800 (Wed, 16 Dec 2015)

Log Message

Improve JSObject::put performance
https://bugs.webkit.org/show_bug.cgi?id=152347

Reviewed by Geoffrey Garen.

This adds a new benchmark called dynbench, which just uses the C++ API to create, modify, and
query objects. This also adds some optimizations to make the JSObject::put code faster by making
it inlinable in places that really need the performance, like JITOperations and LLIntSlowPaths.
Inlining it is optional because the put() method is large. If you want it inlined, call
putInline(). There's a putInline() variant of both JSObject::put() and JSValue::put().

This is up to a 20% improvement for JSObject::put calls that get inlined all the way (like from
JITOperations and the new benchmark) and it's also a speed-up, albeit a smaller one, for
JSObject::put calls that don't get inlined (i.e. those from the DOM and the JSC C++ library code).
Specific speed-ups are as follows. Note that "dynamic context" means that we told PutPropertySlot
that we're not a static put_by_id, which turns off some type inference.

Get By Id: 2% faster
Put By Id Replace: 23% faster
Put By Id Transition + object allocation: 11% faster
Get By Id w/ dynamic context: 5% faster
Put By Id Replace w/ dynamic context: 25% faster
Put By Id Transition + object allocation w/ dynamic context: 10% faster

* _javascript_Core.xcodeproj/project.pbxproj:
* dynbench.cpp: Added.
(JSC::benchmarkImpl):
(main):
* jit/CallFrameShuffler32_64.cpp:
* jit/CallFrameShuffler64.cpp:
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/ClassInfo.h:
(JSC::ClassInfo::hasStaticProperties):
* runtime/ConsoleClient.cpp:
* runtime/CustomGetterSetter.h:
* runtime/ErrorInstance.cpp:
(JSC::ErrorInstance::finishCreation):
(JSC::addErrorInfoAndGetBytecodeOffset): Deleted.
* runtime/GetterSetter.h:
(JSC::asGetterSetter):
* runtime/JSCInlines.h:
* runtime/JSCJSValue.h:
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::put):
(JSC::JSValue::putInternal):
(JSC::JSValue::putByIndex):
* runtime/JSObject.cpp:
(JSC::JSObject::put):
(JSC::JSObject::putByIndex):
* runtime/JSObject.h:
(JSC::JSObject::getVectorLength):
(JSC::JSObject::inlineGetOwnPropertySlot):
(JSC::JSObject::get):
(JSC::JSObject::putDirectInternal):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (194174 => 194175)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-16 22:39:13 UTC (rev 194175)
@@ -1,5 +1,64 @@
 2015-12-16  Filip Pizlo  <[email protected]>
 
+        Improve JSObject::put performance
+        https://bugs.webkit.org/show_bug.cgi?id=152347
+
+        Reviewed by Geoffrey Garen.
+
+        This adds a new benchmark called dynbench, which just uses the C++ API to create, modify, and
+        query objects. This also adds some optimizations to make the JSObject::put code faster by making
+        it inlinable in places that really need the performance, like JITOperations and LLIntSlowPaths.
+        Inlining it is optional because the put() method is large. If you want it inlined, call
+        putInline(). There's a putInline() variant of both JSObject::put() and JSValue::put().
+
+        This is up to a 20% improvement for JSObject::put calls that get inlined all the way (like from
+        JITOperations and the new benchmark) and it's also a speed-up, albeit a smaller one, for
+        JSObject::put calls that don't get inlined (i.e. those from the DOM and the JSC C++ library code).
+        Specific speed-ups are as follows. Note that "dynamic context" means that we told PutPropertySlot
+        that we're not a static put_by_id, which turns off some type inference.
+
+        Get By Id: 2% faster
+        Put By Id Replace: 23% faster
+        Put By Id Transition + object allocation: 11% faster
+        Get By Id w/ dynamic context: 5% faster
+        Put By Id Replace w/ dynamic context: 25% faster
+        Put By Id Transition + object allocation w/ dynamic context: 10% faster
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * dynbench.cpp: Added.
+        (JSC::benchmarkImpl):
+        (main):
+        * jit/CallFrameShuffler32_64.cpp:
+        * jit/CallFrameShuffler64.cpp:
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/ClassInfo.h:
+        (JSC::ClassInfo::hasStaticProperties):
+        * runtime/ConsoleClient.cpp:
+        * runtime/CustomGetterSetter.h:
+        * runtime/ErrorInstance.cpp:
+        (JSC::ErrorInstance::finishCreation):
+        (JSC::addErrorInfoAndGetBytecodeOffset): Deleted.
+        * runtime/GetterSetter.h:
+        (JSC::asGetterSetter):
+        * runtime/JSCInlines.h:
+        * runtime/JSCJSValue.h:
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::put):
+        (JSC::JSValue::putInternal):
+        (JSC::JSValue::putByIndex):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::put):
+        (JSC::JSObject::putByIndex):
+        * runtime/JSObject.h:
+        (JSC::JSObject::getVectorLength):
+        (JSC::JSObject::inlineGetOwnPropertySlot):
+        (JSC::JSObject::get):
+        (JSC::JSObject::putDirectInternal):
+
+2015-12-16  Filip Pizlo  <[email protected]>
+
         Work around a bug in LLVM by flipping the unification order
         https://bugs.webkit.org/show_bug.cgi?id=152341
         rdar://problem/23920749

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (194174 => 194175)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-12-16 22:39:13 UTC (rev 194175)
@@ -25,6 +25,7 @@
 			buildPhases = (
 			);
 			dependencies = (
+				0F93275D1C20BF3A00CF6564 /* PBXTargetDependency */,
 				0FEC85B11BDB5D8F0080FF74 /* PBXTargetDependency */,
 				5D6B2A4F152B9E23005231DE /* PBXTargetDependency */,
 				5D6B2A51152B9E23005231DE /* PBXTargetDependency */,
@@ -482,6 +483,10 @@
 		0F919D2615853CE3004A4E7D /* Watchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D2315853CDE004A4E7D /* Watchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D2715856770004A4E7D /* SymbolTable.cpp */; };
 		0F93274D1C1F66AA00CF6564 /* GPRInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93274C1C1F66AA00CF6564 /* GPRInfo.cpp */; };
+		0F9327521C20BCBA00CF6564 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; };
+		0F9327531C20BCBA00CF6564 /* _javascript_Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* _javascript_Core.framework */; };
+		0F93275B1C20BCDF00CF6564 /* dynbench.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93275A1C20BCDF00CF6564 /* dynbench.cpp */; };
+		0F93275F1C21EF7F00CF6564 /* JSObjectInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93275E1C21EF7F00CF6564 /* JSObjectInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */; };
 		0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */; };
@@ -2057,6 +2062,13 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+		0F93275C1C20BF3A00CF6564 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 0F93274E1C20BCBA00CF6564;
+			remoteInfo = dynbench;
+		};
 		0FCEFABC1805D66300472CE4 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
@@ -2594,6 +2606,9 @@
 		0F919D2315853CDE004A4E7D /* Watchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Watchpoint.h; sourceTree = "<group>"; };
 		0F919D2715856770004A4E7D /* SymbolTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolTable.cpp; sourceTree = "<group>"; };
 		0F93274C1C1F66AA00CF6564 /* GPRInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GPRInfo.cpp; sourceTree = "<group>"; };
+		0F9327591C20BCBA00CF6564 /* dynbench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dynbench; sourceTree = BUILT_PRODUCTS_DIR; };
+		0F93275A1C20BCDF00CF6564 /* dynbench.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dynbench.cpp; sourceTree = "<group>"; };
+		0F93275E1C21EF7F00CF6564 /* JSObjectInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectInlines.h; sourceTree = "<group>"; };
 		0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallLinkStatus.cpp; sourceTree = "<group>"; };
 		0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallLinkStatus.h; sourceTree = "<group>"; };
 		0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdStatus.cpp; sourceTree = "<group>"; };
@@ -4252,6 +4267,15 @@
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
+		0F9327511C20BCBA00CF6564 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				0F9327521C20BCBA00CF6564 /* Foundation.framework in Frameworks */,
+				0F9327531C20BCBA00CF6564 /* _javascript_Core.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		0FCEFAB31805D61600472CE4 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -4339,6 +4363,7 @@
 				14BD59BF0A3E8F9000BAF59C /* testapi */,
 				0FEC85AD1BDB5CF10080FF74 /* testb3 */,
 				6511230514046A4C002B101D /* testRegExp */,
+				0F9327591C20BCBA00CF6564 /* dynbench */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -4348,14 +4373,15 @@
 		0867D691FE84028FC02AAC07 /* _javascript_Core */ = {
 			isa = PBXGroup;
 			children = (
-				6529FB3018B2D63900C61102 /* generate-bytecode-files */,
 				8604F4F2143A6C4400B295F5 /* ChangeLog */,
+				F68EBB8C0255D4C601FF60F7 /* config.h */,
 				F692A8540255597D01FF60F7 /* create_hash_table */,
 				A718F8211178EB4B002465A7 /* create_regex_tables */,
+				937B63CC09E766D200A671DD /* DerivedSources.make */,
+				0F93275A1C20BCDF00CF6564 /* dynbench.cpp */,
+				6529FB3018B2D63900C61102 /* generate-bytecode-files */,
+				F5C290E60284F98E018635CA /* _javascript_CorePrefix.h */,
 				45E12D8806A49B0F00E9DF84 /* jsc.cpp */,
-				F68EBB8C0255D4C601FF60F7 /* config.h */,
-				F5C290E60284F98E018635CA /* _javascript_CorePrefix.h */,
-				937B63CC09E766D200A671DD /* DerivedSources.make */,
 				A7C225CC139981F100FF1662 /* KeywordLookupGenerator.py */,
 				1432EBD70A34CAD400717B9F /* API */,
 				9688CB120ED12B4E001D649F /* assembler */,
@@ -4364,9 +4390,12 @@
 				A7D8019F1880D66E0026C39B /* builtins */,
 				969A078F0ED1D3AE00F1F681 /* bytecode */,
 				7E39D81D0EC38EFA003AF11A /* bytecompiler */,
+				1C90513E0BA9E8830081E9D0 /* Configurations */,
 				1480DB9A0DDC2231003CFDF2 /* debugger */,
+				650FDF8D09D0FCA700769E54 /* Derived Sources */,
 				86EC9DB31328DF44002B2AD7 /* dfg */,
 				0FF4272E158EBCCE004CB9FF /* disassembler */,
+				0867D69AFE84028FC02AAC07 /* Frameworks */,
 				0FEA09FC1705137F00BB722C /* ftl */,
 				142E312A134FF0A600AFADB5 /* heap */,
 				A5BA15DF1823409200A82E69 /* inspector */,
@@ -4375,19 +4404,16 @@
 				0F46809C14BA7F4D00BFE272 /* llint */,
 				0FCEFAAD1805CA4400472CE4 /* llvm */,
 				7E39D8370EC3A388003AF11A /* parser */,
+				034768DFFF38A50411DB9C8B /* Products */,
 				95AB831A0DA42C6900BC83F3 /* profiler */,
 				99E45A0C18A01E930026D88F /* replay */,
+				932FC3C20824BB70005B3C75 /* Resources */,
 				7EF6E0BB0EB7A1EC0079AFAF /* runtime */,
+				9959E9251BD17F1E001AA413 /* Scripts */,
 				141211000A48772600480255 /* tests */,
 				8603CEF014C753EF00AE59E3 /* tools */,
 				7B98D1331B60CD1E0023B1A4 /* wasm */,
 				86EAC48C0F93E8B9008EC948 /* yarr */,
-				650FDF8D09D0FCA700769E54 /* Derived Sources */,
-				932FC3C20824BB70005B3C75 /* Resources */,
-				9959E9251BD17F1E001AA413 /* Scripts */,
-				0867D69AFE84028FC02AAC07 /* Frameworks */,
-				034768DFFF38A50411DB9C8B /* Products */,
-				1C90513E0BA9E8830081E9D0 /* Configurations */,
 			);
 			name = _javascript_Core;
 			sourceTree = "<group>";
@@ -5523,9 +5549,9 @@
 				E178633F0D9BEC0000D74E75 /* InitializeThreading.h */,
 				E35E035D1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp */,
 				E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */,
+				A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */,
 				A7A8AF2C17ADB5F3005AB174 /* Int16Array.h */,
 				A7A8AF2D17ADB5F3005AB174 /* Int32Array.h */,
-				A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */,
 				BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */,
 				BC11667A0E199C05008066DD /* InternalFunction.h */,
 				A1B9E2331B4E0D6700BC7FED /* IntlCollator.cpp */,
@@ -5614,9 +5640,9 @@
 				A59455911824744700CC3843 /* JSGlobalObjectDebuggable.h */,
 				BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */,
 				BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */,
+				0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */,
 				0F2B66CA17B6B5AB00A7AE3F /* JSInt16Array.h */,
 				0F2B66CB17B6B5AB00A7AE3F /* JSInt32Array.h */,
-				0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */,
 				E33F507E1B8429A400413856 /* JSInternalPromise.cpp */,
 				E33F507F1B8429A400413856 /* JSInternalPromise.h */,
 				E33F50761B84225700413856 /* JSInternalPromiseConstructor.cpp */,
@@ -5647,6 +5673,7 @@
 				A72700770DAC605600E548D7 /* JSNotAnObject.h */,
 				BC22A3980E16E14800AF21C8 /* JSObject.cpp */,
 				BC22A3990E16E14800AF21C8 /* JSObject.h */,
+				0F93275E1C21EF7F00CF6564 /* JSObjectInlines.h */,
 				A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */,
 				A7F9935D0FD7325100A0B2D0 /* JSONObject.h */,
 				7C184E1817BEDBD3007CB63A /* JSPromise.cpp */,
@@ -5694,10 +5721,10 @@
 				53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */,
 				53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */,
 				6507D2970E871E4A00D7D896 /* JSTypeInfo.h */,
+				0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */,
+				0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */,
 				0F2B66D417B6B5AB00A7AE3F /* JSUint16Array.h */,
 				0F2B66D517B6B5AB00A7AE3F /* JSUint32Array.h */,
-				0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */,
-				0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */,
 				A7CA3AE117DA41AE006538AF /* JSWeakMap.cpp */,
 				A7CA3AE217DA41AE006538AF /* JSWeakMap.h */,
 				709FB8611AE335C60039D069 /* JSWeakSet.cpp */,
@@ -5871,11 +5898,11 @@
 				0F2D4DE019832D91007D4B19 /* TypeProfilerLog.h */,
 				0F2D4DE319832D91007D4B19 /* TypeSet.cpp */,
 				0F2D4DE419832D91007D4B19 /* TypeSet.h */,
+				A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */,
+				A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */,
 				A7A8AF3217ADB5F3005AB174 /* Uint16Array.h */,
 				866739D113BFDE710023D87C /* Uint16WithFraction.h */,
 				A7A8AF3317ADB5F3005AB174 /* Uint32Array.h */,
-				A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */,
-				A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */,
 				0FE050231AA9095600D33B33 /* VarOffset.cpp */,
 				0FE050241AA9095600D33B33 /* VarOffset.h */,
 				E18E3A570DF9278C00D90B34 /* VM.cpp */,
@@ -7752,6 +7779,7 @@
 				0F5780A218FE1E98001E72D9 /* PureNaN.h in Headers */,
 				0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */,
 				0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */,
+				0F93275F1C21EF7F00CF6564 /* JSObjectInlines.h in Headers */,
 				0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */,
 				0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */,
 				0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */,
@@ -7950,6 +7978,22 @@
 /* End PBXHeadersBuildPhase section */
 
 /* Begin PBXNativeTarget section */
+		0F93274E1C20BCBA00CF6564 /* dynbench */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 0F9327541C20BCBA00CF6564 /* Build configuration list for PBXNativeTarget "dynbench" */;
+			buildPhases = (
+				0F93274F1C20BCBA00CF6564 /* Sources */,
+				0F9327511C20BCBA00CF6564 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = dynbench;
+			productName = testapi;
+			productReference = 0F9327591C20BCBA00CF6564 /* dynbench */;
+			productType = "com.apple.product-type.tool";
+		};
 		0FCEFAB51805D61600472CE4 /* llvmForJSC */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 0FCEFAB71805D61600472CE4 /* Build configuration list for PBXNativeTarget "llvmForJSC" */;
@@ -8140,6 +8184,7 @@
 				651122F714046A4C002B101D /* testRegExp */,
 				0FEC85941BDB5CF10080FF74 /* testb3 */,
 				5D6B2A47152B9E17005231DE /* Test Tools */,
+				0F93274E1C20BCBA00CF6564 /* dynbench */,
 			);
 		};
 /* End PBXProject section */
@@ -8376,6 +8421,14 @@
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
+		0F93274F1C20BCBA00CF6564 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				0F93275B1C20BCDF00CF6564 /* dynbench.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		0FCEFAB21805D61600472CE4 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -9235,6 +9288,11 @@
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
+		0F93275D1C20BF3A00CF6564 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 0F93274E1C20BCBA00CF6564 /* dynbench */;
+			targetProxy = 0F93275C1C20BF3A00CF6564 /* PBXContainerItemProxy */;
+		};
 		0FCEFABD1805D66300472CE4 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = 0FCEFAB51805D61600472CE4 /* llvmForJSC */;
@@ -9341,6 +9399,34 @@
 			};
 			name = Production;
 		};
+		0F9327551C20BCBA00CF6564 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
+			buildSettings = {
+			};
+			name = Debug;
+		};
+		0F9327561C20BCBA00CF6564 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
+			buildSettings = {
+			};
+			name = Release;
+		};
+		0F9327571C20BCBA00CF6564 /* Profiling */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
+			buildSettings = {
+			};
+			name = Profiling;
+		};
+		0F9327581C20BCBA00CF6564 /* Production */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
+			buildSettings = {
+			};
+			name = Production;
+		};
 		0FCEFAB81805D61600472CE4 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 0FCEFABE1805D86900472CE4 /* LLVMForJSC.xcconfig */;
@@ -9742,6 +9828,17 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Production;
 		};
+		0F9327541C20BCBA00CF6564 /* Build configuration list for PBXNativeTarget "dynbench" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				0F9327551C20BCBA00CF6564 /* Debug */,
+				0F9327561C20BCBA00CF6564 /* Release */,
+				0F9327571C20BCBA00CF6564 /* Profiling */,
+				0F9327581C20BCBA00CF6564 /* Production */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Production;
+		};
 		0FCEFAB71805D61600472CE4 /* Build configuration list for PBXNativeTarget "llvmForJSC" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (

Added: trunk/Source/_javascript_Core/dynbench.cpp (0 => 194175)


--- trunk/Source/_javascript_Core/dynbench.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/dynbench.cpp	2015-12-16 22:39:13 UTC (rev 194175)
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+
+#include "Identifier.h"
+#include "InitializeThreading.h"
+#include "JSCInlines.h"
+#include "JSCJSValue.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "JSObject.h"
+#include "VM.h"
+
+using namespace JSC;
+
+namespace {
+
+StaticLock crashLock;
+const char* nameFilter;
+unsigned requestedIterationCount;
+
+#define CHECK(x) do {                                                   \
+        if (!!(x))                                                      \
+            break;                                                      \
+        crashLock.lock();                                               \
+        WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #x); \
+        CRASH();                                                        \
+    } while (false)
+
+template<typename Callback>
+NEVER_INLINE void benchmarkImpl(const char* name, unsigned iterationCount, const Callback& callback)
+{
+    if (nameFilter && !strcasestr(name, nameFilter))
+        return;
+
+    if (requestedIterationCount)
+        iterationCount = requestedIterationCount;
+    
+    double before = monotonicallyIncreasingTimeMS();
+    callback(iterationCount);
+    double after = monotonicallyIncreasingTimeMS();
+    dataLog(name, ": ", after - before, " ms.\n");
+}
+
+} // anonymous namespace
+
+int main(int argc, char** argv)
+{
+    if (argc >= 2) {
+        if (argv[1][0] == '-') {
+            dataLog("Usage: dynbench [<filter> [<iteration count>]]\n");
+            return 1;
+        }
+
+        nameFilter = argv[1];
+
+        if (argc >= 3) {
+            if (sscanf(argv[2], "%u", &requestedIterationCount) != 1) {
+                dataLog("Could not parse iteration count ", argv[2], "\n");
+                return 1;
+            }
+        }
+    }
+    
+    WTF::initializeMainThread();
+    JSC::initializeThreading();
+
+    VM* vm = &VM::create(LargeHeap).leakRef();
+    {
+        JSLockHolder locker(vm);
+
+        JSGlobalObject* globalObject =
+            JSGlobalObject::create(*vm, JSGlobalObject::createStructure(*vm, jsNull()));
+        ExecState* exec = globalObject->globalExec();
+
+        Identifier identF = Identifier::fromString(exec, "f");
+        Identifier identG = Identifier::fromString(exec, "g");
+
+        Structure* objectStructure =
+            JSFinalObject::createStructure(*vm, globalObject, globalObject->objectPrototype(), 2);
+
+        // Non-strict dynamic get by id:
+        JSValue object = JSFinalObject::create(*vm, objectStructure);
+        {
+            PutPropertySlot slot(object, false, PutPropertySlot::PutById);
+            object.putInline(exec, identF, jsNumber(42), slot);
+        }
+        {
+            PutPropertySlot slot(object, false, PutPropertySlot::PutById);
+            object.putInline(exec, identG, jsNumber(43), slot);
+        }
+        benchmarkImpl(
+            "Non Strict Dynamic Get By Id",
+            1000000,
+            [&] (unsigned iterationCount) {
+                for (unsigned i = iterationCount; i--;) {
+                    JSValue result = object.get(exec, identF);
+                    CHECK(result == jsNumber(42));
+                    result = object.get(exec, identG);
+                    CHECK(result == jsNumber(43));
+                }
+            });
+
+        // Non-strict dynamic put by id replace:
+        object = JSFinalObject::create(*vm, objectStructure);
+        {
+            PutPropertySlot slot(object, false, PutPropertySlot::PutById);
+            object.putInline(exec, identF, jsNumber(42), slot);
+        }
+        {
+            PutPropertySlot slot(object, false, PutPropertySlot::PutById);
+            object.putInline(exec, identG, jsNumber(43), slot);
+        }
+        benchmarkImpl(
+            "Non Strict Dynamic Put By Id Replace",
+            1000000,
+            [&] (unsigned iterationCount) {
+                for (unsigned i = iterationCount; i--;) {
+                    {
+                        PutPropertySlot slot(object, false, PutPropertySlot::PutById);
+                        object.putInline(exec, identF, jsNumber(i), slot);
+                    }
+                    {
+                        PutPropertySlot slot(object, false, PutPropertySlot::PutById);
+                        object.putInline(exec, identG, jsNumber(i), slot);
+                    }
+                }
+            });
+
+        // Non-strict dynamic put by id transition with object allocation:
+        benchmarkImpl(
+            "Non Strict Dynamic Allocation and Put By Id Transition",
+            1000000,
+            [&] (unsigned iterationCount) {
+                for (unsigned i = iterationCount; i--;) {
+                    JSValue object = JSFinalObject::create(*vm, objectStructure);
+                    {
+                        PutPropertySlot slot(object, false, PutPropertySlot::PutById);
+                        object.putInline(exec, identF, jsNumber(i), slot);
+                    }
+                    {
+                        PutPropertySlot slot(object, false, PutPropertySlot::PutById);
+                        object.putInline(exec, identG, jsNumber(i), slot);
+                    }
+                }
+            });
+
+        // Non-strict dynamic get by id with dynamic store context:
+        object = JSFinalObject::create(*vm, objectStructure);
+        {
+            PutPropertySlot slot(object, false);
+            object.putInline(exec, identF, jsNumber(42), slot);
+        }
+        {
+            PutPropertySlot slot(object, false);
+            object.putInline(exec, identG, jsNumber(43), slot);
+        }
+        benchmarkImpl(
+            "Non Strict Dynamic Get By Id With Dynamic Store Context",
+            1000000,
+            [&] (unsigned iterationCount) {
+                for (unsigned i = iterationCount; i--;) {
+                    JSValue result = object.get(exec, identF);
+                    CHECK(result == jsNumber(42));
+                    result = object.get(exec, identG);
+                    CHECK(result == jsNumber(43));
+                }
+            });
+
+        // Non-strict dynamic put by id replace with dynamic store context:
+        object = JSFinalObject::create(*vm, objectStructure);
+        {
+            PutPropertySlot slot(object, false);
+            object.putInline(exec, identF, jsNumber(42), slot);
+        }
+        {
+            PutPropertySlot slot(object, false);
+            object.putInline(exec, identG, jsNumber(43), slot);
+        }
+        benchmarkImpl(
+            "Non Strict Dynamic Put By Id Replace With Dynamic Store Context",
+            1000000,
+            [&] (unsigned iterationCount) {
+                for (unsigned i = iterationCount; i--;) {
+                    {
+                        PutPropertySlot slot(object, false);
+                        object.putInline(exec, identF, jsNumber(i), slot);
+                    }
+                    {
+                        PutPropertySlot slot(object, false);
+                        object.putInline(exec, identG, jsNumber(i), slot);
+                    }
+                }
+            });
+
+        // Non-strict dynamic put by id transition with object allocation with dynamic store context:
+        benchmarkImpl(
+            "Non Strict Dynamic Allocation and Put By Id Transition With Dynamic Store Context",
+            1000000,
+            [&] (unsigned iterationCount) {
+                for (unsigned i = iterationCount; i--;) {
+                    JSValue object = JSFinalObject::create(*vm, objectStructure);
+                    {
+                        PutPropertySlot slot(object, false);
+                        object.putInline(exec, identF, jsNumber(i), slot);
+                    }
+                    {
+                        PutPropertySlot slot(object, false);
+                        object.putInline(exec, identG, jsNumber(i), slot);
+                    }
+                }
+            });
+    }
+
+    crashLock.lock();
+    return 0;
+}
+

Modified: trunk/Source/_javascript_Core/jit/CallFrameShuffler32_64.cpp (194174 => 194175)


--- trunk/Source/_javascript_Core/jit/CallFrameShuffler32_64.cpp	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/jit/CallFrameShuffler32_64.cpp	2015-12-16 22:39:13 UTC (rev 194175)
@@ -30,7 +30,7 @@
 
 #include "CCallHelpers.h"
 #include "DataFormat.h"
-#include "JSCJSValueInlines.h"
+#include "JSCInlines.h"
 
 namespace JSC {
 

Modified: trunk/Source/_javascript_Core/jit/CallFrameShuffler64.cpp (194174 => 194175)


--- trunk/Source/_javascript_Core/jit/CallFrameShuffler64.cpp	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/jit/CallFrameShuffler64.cpp	2015-12-16 22:39:13 UTC (rev 194175)
@@ -30,7 +30,7 @@
 
 #include "CCallHelpers.h"
 #include "DataFormat.h"
-#include "JSCJSValueInlines.h"
+#include "JSCInlines.h"
 
 namespace JSC {
 

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (194174 => 194175)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2015-12-16 22:39:13 UTC (rev 194175)
@@ -248,7 +248,7 @@
     
     Identifier ident = Identifier::fromUid(vm, uid);
     PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
-    JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
+    JSValue::decode(encodedBase).putInline(exec, ident, JSValue::decode(encodedValue), slot);
 }
 
 void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -260,7 +260,7 @@
     
     Identifier ident = Identifier::fromUid(vm, uid);
     PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
-    JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
+    JSValue::decode(encodedBase).putInline(exec, ident, JSValue::decode(encodedValue), slot);
 }
 
 void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -300,7 +300,7 @@
     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
 
     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
-    baseValue.put(exec, ident, value, slot);
+    baseValue.putInline(exec, ident, value, slot);
     
     if (accessType != static_cast<AccessType>(stubInfo->accessType))
         return;
@@ -322,7 +322,7 @@
     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
 
     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;    
-    baseValue.put(exec, ident, value, slot);
+    baseValue.putInline(exec, ident, value, slot);
     
     if (accessType != static_cast<AccessType>(stubInfo->accessType))
         return;
@@ -422,7 +422,7 @@
         byValInfo->tookSlowPath = true;
 
     PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
-    baseValue.put(callFrame, property, value, slot);
+    baseValue.putInline(callFrame, property, value, slot);
 }
 
 static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ByValInfo* byValInfo)

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (194174 => 194175)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2015-12-16 22:39:13 UTC (rev 194175)
@@ -620,7 +620,7 @@
     if (pc[8].u.putByIdFlags & PutByIdIsDirect)
         asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
     else
-        baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
+        baseValue.putInline(exec, ident, LLINT_OP_C(3).jsValue(), slot);
     LLINT_CHECK_EXCEPTION();
     
     if (!LLINT_ALWAYS_ACCESS_SLOW

Modified: trunk/Source/_javascript_Core/runtime/ClassInfo.h (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/ClassInfo.h	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/ClassInfo.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -181,7 +181,7 @@
         return false;
     }
 
-    bool hasStaticSetterOrReadonlyProperties() const;
+    JS_EXPORT_PRIVATE bool hasStaticSetterOrReadonlyProperties() const;
 
     const HashTable* staticPropHashTable;
 

Modified: trunk/Source/_javascript_Core/runtime/ConsoleClient.cpp (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/ConsoleClient.cpp	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/ConsoleClient.cpp	2015-12-16 22:39:13 UTC (rev 194175)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "ConsoleClient.h"
 
+#include "JSCInlines.h"
 #include "ScriptArguments.h"
 #include "ScriptCallStack.h"
 #include "ScriptCallStackFactory.h"

Modified: trunk/Source/_javascript_Core/runtime/CustomGetterSetter.h (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/CustomGetterSetter.h	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/CustomGetterSetter.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -70,7 +70,7 @@
     CustomSetter m_setter;
 };
 
-void callCustomSetter(ExecState*, JSValue customGetterSetter, JSObject* base, JSValue thisValue, JSValue value);
+JS_EXPORT_PRIVATE void callCustomSetter(ExecState*, JSValue customGetterSetter, JSObject* base, JSValue thisValue, JSValue value);
 
 } // namespace JSC
 

Modified: trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp	2015-12-16 22:39:13 UTC (rev 194175)
@@ -128,50 +128,6 @@
     unsigned m_index;
 };
 
-static bool addErrorInfoAndGetBytecodeOffset(ExecState* exec, VM& vm, JSObject* obj, bool useCurrentFrame, CallFrame*& callFrame, unsigned &bytecodeOffset)
-{
-    Vector<StackFrame> stackTrace = Vector<StackFrame>();
-
-    if (exec && stackTrace.isEmpty())
-        vm.interpreter->getStackTrace(stackTrace);
-
-    if (!stackTrace.isEmpty()) {
-
-        ASSERT(exec == vm.topCallFrame || exec == exec->lexicalGlobalObject()->globalExec() || exec == exec->vmEntryGlobalObject()->globalExec());
-
-        StackFrame* stackFrame;
-        for (unsigned i = 0 ; i < stackTrace.size(); ++i) {
-            stackFrame = &stackTrace.at(i);
-            if (stackFrame->bytecodeOffset)
-                break;
-        }
-
-        if (bytecodeOffset) {
-            FindFirstCallerFrameWithCodeblockFunctor functor(exec);
-            vm.topCallFrame->iterate(functor);
-            callFrame = functor.foundCallFrame();
-            unsigned stackIndex = functor.index();
-            bytecodeOffset = stackTrace.at(stackIndex).bytecodeOffset;
-        }
-        
-        unsigned line;
-        unsigned column;
-        stackFrame->computeLineAndColumn(line, column);
-        obj->putDirect(vm, vm.propertyNames->line, jsNumber(line), ReadOnly | DontDelete);
-        obj->putDirect(vm, vm.propertyNames->column, jsNumber(column), ReadOnly | DontDelete);
-
-        if (!stackFrame->sourceURL.isEmpty())
-            obj->putDirect(vm, vm.propertyNames->sourceURL, jsString(&vm, stackFrame->sourceURL), ReadOnly | DontDelete);
-    
-        if (!useCurrentFrame)
-            stackTrace.remove(0);
-        obj->putDirect(vm, vm.propertyNames->stack, vm.interpreter->stackTraceAsString(vm.topCallFrame, stackTrace), DontEnum);
-
-        return true;
-    }
-    return false;
-}
-
 void ErrorInstance::finishCreation(ExecState* exec, VM& vm, const String& message, bool useCurrentFrame)
 {
     Base::finishCreation(vm);

Modified: trunk/Source/_javascript_Core/runtime/GetterSetter.h (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/GetterSetter.h	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/GetterSetter.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -144,7 +144,7 @@
 }
 
 JSValue callGetter(ExecState*, JSValue base, JSValue getterSetter);
-void callSetter(ExecState*, JSValue base, JSValue getterSetter, JSValue, ECMAMode);
+JS_EXPORT_PRIVATE void callSetter(ExecState*, JSValue base, JSValue getterSetter, JSValue, ECMAMode);
 
 } // namespace JSC
 

Modified: trunk/Source/_javascript_Core/runtime/JSCInlines.h (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/JSCInlines.h	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/JSCInlines.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -45,6 +45,7 @@
 #include "JSArrayBufferViewInlines.h"
 #include "JSCJSValueInlines.h"
 #include "JSFunctionInlines.h"
+#include "JSObjectInlines.h"
 #include "JSProxy.h"
 #include "JSString.h"
 #include "Operations.h"

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValue.h (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/JSCJSValue.h	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValue.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -277,6 +277,7 @@
     bool getPropertySlot(ExecState*, PropertyName, PropertySlot&) const;
 
     void put(ExecState*, PropertyName, JSValue, PutPropertySlot&);
+    void putInline(ExecState*, PropertyName, JSValue, PutPropertySlot&);
     JS_EXPORT_PRIVATE void putToPrimitive(ExecState*, PropertyName, JSValue, PutPropertySlot&);
     JS_EXPORT_PRIVATE void putToPrimitiveByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
     void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -31,6 +31,7 @@
 #include "InternalFunction.h"
 #include "JSCJSValue.h"
 #include "JSCellInlines.h"
+#include "JSObject.h"
 #include "JSFunction.h"
 #include <wtf/text/StringImpl.h>
 
@@ -751,6 +752,24 @@
     asCell()->methodTable(exec->vm())->put(asCell(), exec, propertyName, value, slot);
 }
 
+ALWAYS_INLINE void JSValue::putInline(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+{
+    if (UNLIKELY(!isCell())) {
+        putToPrimitive(exec, propertyName, value, slot);
+        return;
+    }
+    JSCell* cell = asCell();
+    auto putMethod = cell->methodTable(exec->vm())->put;
+    if (LIKELY(putMethod == JSObject::put)) {
+        JSObject::putInline(cell, exec, propertyName, value, slot);
+        return;
+    }
+
+    PutPropertySlot otherSlot = slot;
+    putMethod(cell, exec, propertyName, value, otherSlot);
+    slot = otherSlot;
+}
+
 inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
 {
     if (UNLIKELY(!isCell())) {

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2015-12-16 22:39:13 UTC (rev 194175)
@@ -372,40 +372,20 @@
 // ECMA 8.6.2.2
 void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
 {
-    JSObject* thisObject = jsCast<JSObject*>(cell);
-    ASSERT(value);
-    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
+    putInline(cell, exec, propertyName, value, slot);
+}
+
+void JSObject::putInlineSlow(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+{
     VM& vm = exec->vm();
-    
-    // Try indexed put first. This is required for correctness, since loads on property names that appear like
-    // valid indices will never look in the named property storage.
-    if (Optional<uint32_t> index = parseIndex(propertyName)) {
-        putByIndex(thisObject, exec, index.value(), value, slot.isStrictMode());
-        return;
-    }
-    
-    // Check if there are any setters or getters in the prototype chain
-    JSValue prototype;
-    if (propertyName != exec->propertyNames().underscoreProto) {
-        for (JSObject* obj = thisObject; !obj->structure(vm)->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
-            prototype = obj->prototype();
-            if (prototype.isNull()) {
-                ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName));
-                if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot)
-                    && slot.isStrictMode())
-                    throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
-                return;
-            }
-        }
-    }
 
-    JSObject* obj;
-    for (obj = thisObject; ; obj = asObject(prototype)) {
+    JSObject* obj = this;
+    for (;;) {
         unsigned attributes;
         PropertyOffset offset = obj->structure(vm)->get(vm, propertyName, attributes);
         if (isValidOffset(offset)) {
             if (attributes & ReadOnly) {
-                ASSERT(thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == thisObject);
+                ASSERT(structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == this);
                 if (slot.isStrictMode())
                     exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError)));
                 return;
@@ -413,8 +393,8 @@
 
             JSValue gs = obj->getDirect(offset);
             if (gs.isGetterSetter()) {
-                callSetter(exec, cell, gs, value, slot.isStrictMode() ? StrictMode : NotStrictMode);
-                if (!thisObject->structure()->isDictionary())
+                callSetter(exec, this, gs, value, slot.isStrictMode() ? StrictMode : NotStrictMode);
+                if (!structure()->isDictionary())
                     slot.setCacheableSetter(obj, offset);
                 return;
             }
@@ -438,15 +418,15 @@
                 }
             }
         }
-        prototype = obj->prototype();
+        JSValue prototype = obj->prototype();
         if (prototype.isNull())
             break;
+        obj = asObject(prototype);
     }
     
-    ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == thisObject);
-    if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot) && slot.isStrictMode())
+    ASSERT(!structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == this);
+    if (!putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot) && slot.isStrictMode())
         throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
-    return;
 }
 
 void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -140,7 +140,9 @@
             return 0;
         return m_butterfly.get(this)->vectorLength();
     }
-        
+    
+    static void putInline(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
+    
     JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
     JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
         
@@ -852,11 +854,13 @@
     template<PutMode>
     bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&);
 
+    JS_EXPORT_PRIVATE NEVER_INLINE void putInlineSlow(ExecState*, PropertyName, JSValue, PutPropertySlot&);
+
     bool inlineGetOwnPropertySlot(VM&, Structure&, PropertyName, PropertySlot&);
     JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, JSValue, unsigned, PropertyOffset);
     void fillCustomGetterPropertySlot(PropertySlot&, JSValue, unsigned, Structure&);
 
-    const HashTableValue* findPropertyHashEntry(PropertyName) const;
+    JS_EXPORT_PRIVATE const HashTableValue* findPropertyHashEntry(PropertyName) const;
         
     void putIndexedDescriptor(ExecState*, SparseArrayEntry*, const PropertyDescriptor&, PropertyDescriptor& old);
         
@@ -1090,13 +1094,23 @@
         return false;
 
     JSValue value = getDirect(offset);
-    if (structure.hasGetterSetterProperties() && value.isGetterSetter())
-        fillGetterPropertySlot(slot, value, attributes, offset);
-    else if (structure.hasCustomGetterSetterProperties() && value.isCustomGetterSetter())
-        fillCustomGetterPropertySlot(slot, value, attributes, structure);
-    else
-        slot.setValue(this, attributes, value, offset);
-
+    if (value.isCell()) {
+        ASSERT(value);
+        JSCell* cell = value.asCell();
+        JSType type = cell->type();
+        switch (type) {
+        case GetterSetterType:
+            fillGetterPropertySlot(slot, value, attributes, offset);
+            return true;
+        case CustomGetterSetterType:
+            fillCustomGetterPropertySlot(slot, value, attributes, structure);
+            return true;
+        default:
+            break;
+        }
+    }
+    
+    slot.setValue(this, attributes, value, offset);
     return true;
 }
 
@@ -1187,7 +1201,7 @@
 }
 
 template<JSObject::PutMode mode>
-inline bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot)
+ALWAYS_INLINE bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot)
 {
     ASSERT(value);
     ASSERT(value.isGetterSetter() == !!(attributes & Accessor));

Added: trunk/Source/_javascript_Core/runtime/JSObjectInlines.h (0 => 194175)


--- trunk/Source/_javascript_Core/runtime/JSObjectInlines.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/JSObjectInlines.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -0,0 +1,69 @@
+/*
+ *  Copyright (C) 1999-2001 Harri Porten ([email protected])
+ *  Copyright (C) 2001 Peter Kelly ([email protected])
+ *  Copyright (C) 2003-2006, 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Eric Seidel ([email protected])
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSObjectInlines_h
+#define JSObjectInlines_h
+
+#include "Error.h"
+#include "JSObject.h"
+#include "Lookup.h"
+
+namespace JSC {
+
+// ECMA 8.6.2.2
+ALWAYS_INLINE void JSObject::putInline(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+{
+    JSObject* thisObject = jsCast<JSObject*>(cell);
+    ASSERT(value);
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
+    VM& vm = exec->vm();
+    
+    // Try indexed put first. This is required for correctness, since loads on property names that appear like
+    // valid indices will never look in the named property storage.
+    if (Optional<uint32_t> index = parseIndex(propertyName)) {
+        putByIndex(thisObject, exec, index.value(), value, slot.isStrictMode());
+        return;
+    }
+    
+    // Check if there are any setters or getters in the prototype chain
+    JSValue prototype;
+    if (propertyName != exec->propertyNames().underscoreProto) {
+        for (JSObject* obj = thisObject; !obj->structure(vm)->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
+            prototype = obj->prototype();
+            if (prototype.isNull()) {
+                ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName));
+                if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot)
+                    && slot.isStrictMode())
+                    throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
+                return;
+            }
+        }
+    }
+
+    thisObject->putInlineSlow(exec, propertyName, value, slot);
+}
+
+} // namespace JSC
+
+#endif // JSObjectInlines_h
+

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (194174 => 194175)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2015-12-16 22:08:06 UTC (rev 194174)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2015-12-16 22:39:13 UTC (rev 194175)
@@ -258,7 +258,7 @@
     static void visitChildren(JSCell*, SlotVisitor&);
         
     // Will just the prototype chain intercept this property access?
-    bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
+    JS_EXPORT_PRIVATE bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
         
     Structure* previousID() const
     {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to