[JSC] Reduce # of structures in JSGlobalObject initialization
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Mar 2019 21:55:00 +0000 (21:55 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Mar 2019 21:55:00 +0000 (21:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195498

Reviewed by Darin Adler.

Source/JavaScriptCore:

This patch reduces # of structure allocations in JSGlobalObject initialization. Now it becomes 141, it fits in one
MarkedBlock and this patch drops one MarkedBlock used for Structure previously.

* CMakeLists.txt:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* JavaScriptCore.xcodeproj/project.pbxproj:
* runtime/ArrayIteratorPrototype.cpp:
(JSC::ArrayIteratorPrototype::finishCreation): ArrayIteratorPrototype, MapIteratorPrototype, and StringIteratorPrototype's
"next" properties are referenced by JSGlobalObject::init, and it causes reification of the lazy "next" property and structure
transition anyway. So we should put it eagerly "without-transition" configuration to avoid one structure transition.

* runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::finishCreation): @@unscopable object's structure should be dictionary because (1) it is used as a dictionary
in with-scope-resolution and (2) since with-scope-resolution is C++ runtime function anyway, non-dictionary structure does not add
any performance benefit. This change saves several structures that are not useful.

* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::createStructure): Bake CloneArguments's structure with 'without-transition' manner.

* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init): Previously we are always call resetProtoype at the end of JSGlobalObject::init. But it is not necessary
since we do not change [[Prototype]] of JSGlobalObject. All we want is (1) fixupPrototypeChainWithObjectPrototype's operation and (2) setGlobalThis
operation. Since setGlobalThis part is done in JSGlobalObject::finishCreation, fixupPrototypeChainWithObjectPrototype is only the thing
we should do here.

(JSC::JSGlobalObject::fixupPrototypeChainWithObjectPrototype):
(JSC::JSGlobalObject::resetPrototype): If the [[Prototype]] is the same to the current [[Prototype]], we can skip the operation.

* runtime/JSGlobalObject.h:
* runtime/MapIteratorPrototype.cpp:
(JSC::MapIteratorPrototype::finishCreation):
* runtime/NullGetterFunction.h:
* runtime/NullSetterFunction.h: Since structures of them are allocated per JSGlobalObject and they are per-JSGlobalObject,
we can use without-transition property addition.

* runtime/StringIteratorPrototype.cpp:
(JSC::StringIteratorPrototype::finishCreation):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::setIteratorStructureSlow):
(JSC::VM::mapIteratorStructureSlow): These structures are only used in WebCore's main thread.
* runtime/VM.h:
(JSC::VM::setIteratorStructure):
(JSC::VM::mapIteratorStructure):

Source/WebCore:

* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::serialize):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242742 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/DerivedSources-output.xcfilelist
Source/JavaScriptCore/DerivedSources.make
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/ClonedArguments.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/MapIteratorPrototype.cpp
Source/JavaScriptCore/runtime/NullGetterFunction.h
Source/JavaScriptCore/runtime/NullSetterFunction.h
Source/JavaScriptCore/runtime/StringIteratorPrototype.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/SerializedScriptValue.cpp

index f03d0ad..30db16d 100644 (file)
@@ -59,7 +59,6 @@ set(JavaScriptCore_SYSTEM_INCLUDE_DIRECTORIES
 
 set(JavaScriptCore_OBJECT_LUT_SOURCES
     runtime/ArrayConstructor.cpp
-    runtime/ArrayIteratorPrototype.cpp
     runtime/AsyncFromSyncIteratorPrototype.cpp
     runtime/AsyncGeneratorPrototype.cpp
     runtime/BigIntConstructor.cpp
@@ -95,7 +94,6 @@ set(JavaScriptCore_OBJECT_LUT_SOURCES
     runtime/RegExpPrototype.cpp
     runtime/SetPrototype.cpp
     runtime/StringConstructor.cpp
-    runtime/StringIteratorPrototype.cpp
     runtime/StringPrototype.cpp
     runtime/SymbolConstructor.cpp
     runtime/SymbolPrototype.cpp
index e16e450..d766f49 100644 (file)
@@ -1,3 +1,56 @@
+2019-03-11  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Reduce # of structures in JSGlobalObject initialization
+        https://bugs.webkit.org/show_bug.cgi?id=195498
+
+        Reviewed by Darin Adler.
+
+        This patch reduces # of structure allocations in JSGlobalObject initialization. Now it becomes 141, it fits in one
+        MarkedBlock and this patch drops one MarkedBlock used for Structure previously.
+
+        * CMakeLists.txt:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * runtime/ArrayIteratorPrototype.cpp:
+        (JSC::ArrayIteratorPrototype::finishCreation): ArrayIteratorPrototype, MapIteratorPrototype, and StringIteratorPrototype's
+        "next" properties are referenced by JSGlobalObject::init, and it causes reification of the lazy "next" property and structure
+        transition anyway. So we should put it eagerly "without-transition" configuration to avoid one structure transition.
+
+        * runtime/ArrayPrototype.cpp:
+        (JSC::ArrayPrototype::finishCreation): @@unscopable object's structure should be dictionary because (1) it is used as a dictionary
+        in with-scope-resolution and (2) since with-scope-resolution is C++ runtime function anyway, non-dictionary structure does not add
+        any performance benefit. This change saves several structures that are not useful.
+
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::createStructure): Bake CloneArguments's structure with 'without-transition' manner.
+
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init): Previously we are always call resetProtoype at the end of JSGlobalObject::init. But it is not necessary
+        since we do not change [[Prototype]] of JSGlobalObject. All we want is (1) fixupPrototypeChainWithObjectPrototype's operation and (2) setGlobalThis
+        operation. Since setGlobalThis part is done in JSGlobalObject::finishCreation, fixupPrototypeChainWithObjectPrototype is only the thing
+        we should do here.
+
+        (JSC::JSGlobalObject::fixupPrototypeChainWithObjectPrototype):
+        (JSC::JSGlobalObject::resetPrototype): If the [[Prototype]] is the same to the current [[Prototype]], we can skip the operation.
+
+        * runtime/JSGlobalObject.h:
+        * runtime/MapIteratorPrototype.cpp:
+        (JSC::MapIteratorPrototype::finishCreation):
+        * runtime/NullGetterFunction.h:
+        * runtime/NullSetterFunction.h: Since structures of them are allocated per JSGlobalObject and they are per-JSGlobalObject,
+        we can use without-transition property addition.
+
+        * runtime/StringIteratorPrototype.cpp:
+        (JSC::StringIteratorPrototype::finishCreation):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::setIteratorStructureSlow):
+        (JSC::VM::mapIteratorStructureSlow): These structures are only used in WebCore's main thread.
+        * runtime/VM.h:
+        (JSC::VM::setIteratorStructure):
+        (JSC::VM::mapIteratorStructure):
+
 2019-03-08  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] BuiltinExecutables should behave like a WeakSet instead of generic WeakHandleOwner for memory footprint
index d2dee42..faaf16f 100644 (file)
@@ -3,7 +3,6 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/AirOpcode.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/AirOpcodeGenerated.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/AirOpcodeUtils.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/ArrayConstructor.lut.h
-$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/ArrayIteratorPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/AsyncFromSyncIteratorPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/AsyncGeneratorPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/BigIntConstructor.lut.h
@@ -52,7 +51,6 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/RegExpConstructor.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/RegExpJitTables.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/SetPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/StringConstructor.lut.h
-$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/StringIteratorPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/StringPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/SymbolConstructor.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/SymbolPrototype.lut.h
index 242e0cd..cbef4c1 100644 (file)
@@ -135,7 +135,6 @@ JSCBuiltins.h: $(BUILTINS_GENERATOR_SCRIPTS) $(JavaScriptCore_BUILTINS_SOURCES)
 OBJECT_LUT_HEADERS = \
     AsyncFromSyncIteratorPrototype.lut.h \
     ArrayConstructor.lut.h \
-    ArrayIteratorPrototype.lut.h \
     AsyncGeneratorPrototype.lut.h \
     BigIntConstructor.lut.h \
     BigIntPrototype.lut.h \
@@ -169,7 +168,6 @@ OBJECT_LUT_HEADERS = \
     RegExpConstructor.lut.h \
     SetPrototype.lut.h \
     StringConstructor.lut.h \
-    StringIteratorPrototype.lut.h \
     StringPrototype.lut.h \
     SymbolConstructor.lut.h \
     SymbolPrototype.lut.h \
index bb19f60..6f4b9bb 100644 (file)
                9959E9321BD18279001AA413 /* inline-and-minify-stylesheets-and-scripts.py in Headers */ = {isa = PBXBuildFile; fileRef = 9959E9301BD181F6001AA413 /* inline-and-minify-stylesheets-and-scripts.py */; settings = {ATTRIBUTES = (Private, ); }; };
                996231E918D1804200C03FDA /* InspectorBackendCommands.js in Headers */ = {isa = PBXBuildFile; fileRef = A53243961856A475002ED692 /* InspectorBackendCommands.js */; settings = {ATTRIBUTES = (Private, ); }; };
                996B73171BDA067F00331B84 /* ArrayConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73151BDA05AA00331B84 /* ArrayConstructor.lut.h */; };
-               996B73181BDA068000331B84 /* ArrayIteratorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73161BDA05AA00331B84 /* ArrayIteratorPrototype.lut.h */; };
                996B73191BDA068000331B84 /* BooleanPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73071BD9FA2C00331B84 /* BooleanPrototype.lut.h */; };
                996B731A1BDA08D100331B84 /* DateConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73081BD9FA2C00331B84 /* DateConstructor.lut.h */; };
                996B731B1BDA08D100331B84 /* ErrorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73091BD9FA2C00331B84 /* ErrorPrototype.lut.h */; };
                996B73221BDA08EF00331B84 /* ObjectConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B730E1BD9FA2C00331B84 /* ObjectConstructor.lut.h */; };
                996B73231BDA08EF00331B84 /* ReflectObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B730F1BD9FA2C00331B84 /* ReflectObject.lut.h */; };
                996B73251BDA08EF00331B84 /* StringConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73111BD9FA2C00331B84 /* StringConstructor.lut.h */; };
-               996B73261BDA08EF00331B84 /* StringIteratorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73121BD9FA2C00331B84 /* StringIteratorPrototype.lut.h */; };
                996B73271BDA08EF00331B84 /* SymbolConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73131BD9FA2C00331B84 /* SymbolConstructor.lut.h */; };
                996B73281BDA08EF00331B84 /* SymbolPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73141BD9FA2C00331B84 /* SymbolPrototype.lut.h */; };
                998ED6751BED768C00DD8017 /* RemoteControllableTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 998ED6731BED659A00DD8017 /* RemoteControllableTarget.h */; settings = {ATTRIBUTES = (Private, ); }; };
                996B730E1BD9FA2C00331B84 /* ObjectConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectConstructor.lut.h; sourceTree = "<group>"; };
                996B730F1BD9FA2C00331B84 /* ReflectObject.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReflectObject.lut.h; sourceTree = "<group>"; };
                996B73111BD9FA2C00331B84 /* StringConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringConstructor.lut.h; sourceTree = "<group>"; };
-               996B73121BD9FA2C00331B84 /* StringIteratorPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringIteratorPrototype.lut.h; sourceTree = "<group>"; };
                996B73131BD9FA2C00331B84 /* SymbolConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolConstructor.lut.h; sourceTree = "<group>"; };
                996B73141BD9FA2C00331B84 /* SymbolPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolPrototype.lut.h; sourceTree = "<group>"; };
                996B73151BDA05AA00331B84 /* ArrayConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayConstructor.lut.h; sourceTree = "<group>"; };
-               996B73161BDA05AA00331B84 /* ArrayIteratorPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayIteratorPrototype.lut.h; sourceTree = "<group>"; };
                998ED6721BED659A00DD8017 /* RemoteControllableTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteControllableTarget.cpp; sourceTree = "<group>"; };
                998ED6731BED659A00DD8017 /* RemoteControllableTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteControllableTarget.h; sourceTree = "<group>"; };
                99DA00991BD5992700F4575C /* __init__.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = __init__.py; sourceTree = "<group>"; };
                                0F6183341C45F3B60072450B /* AirOpcodeGenerated.h */,
                                0F6183351C45F3B60072450B /* AirOpcodeUtils.h */,
                                996B73151BDA05AA00331B84 /* ArrayConstructor.lut.h */,
-                               996B73161BDA05AA00331B84 /* ArrayIteratorPrototype.lut.h */,
                                E3893A1C2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h */,
                                8B3BF5E31E3D365A0076A87A /* AsyncGeneratorPrototype.lut.h */,
                                996B73071BD9FA2C00331B84 /* BooleanPrototype.lut.h */,
                                A718F61A11754A21002465A7 /* RegExpJitTables.h */,
                                7035587F1C418458004BD7BF /* SetPrototype.lut.h */,
                                996B73111BD9FA2C00331B84 /* StringConstructor.lut.h */,
-                               996B73121BD9FA2C00331B84 /* StringIteratorPrototype.lut.h */,
                                996B73131BD9FA2C00331B84 /* SymbolConstructor.lut.h */,
                                996B73141BD9FA2C00331B84 /* SymbolPrototype.lut.h */,
                                533B15DE1DC7F463004D500A /* WasmOps.h */,
                                996B73171BDA067F00331B84 /* ArrayConstructor.lut.h in Headers */,
                                0FB7F39515ED8E4600F167B2 /* ArrayConventions.h in Headers */,
                                A7BDAEC917F4EA1400F6140C /* ArrayIteratorPrototype.h in Headers */,
-                               996B73181BDA068000331B84 /* ArrayIteratorPrototype.lut.h in Headers */,
                                0F63945515D07057006A597C /* ArrayProfile.h in Headers */,
                                BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */,
                                0FB7F39615ED8E4600F167B2 /* ArrayStorage.h in Headers */,
                                BC18C4660E16F5CD00B34460 /* StringConstructor.h in Headers */,
                                996B73251BDA08EF00331B84 /* StringConstructor.lut.h in Headers */,
                                70EC0EC71AA0D7DA00B6AAFA /* StringIteratorPrototype.h in Headers */,
-                               996B73261BDA08EF00331B84 /* StringIteratorPrototype.lut.h in Headers */,
                                BC18C4680E16F5CD00B34460 /* StringObject.h in Headers */,
                                BC18C46A0E16F5CD00B34460 /* StringPrototype.h in Headers */,
                                E325A36022211590007349A1 /* StringPrototypeInlines.h in Headers */,
index b4e62a9..893320a 100644 (file)
@@ -26,7 +26,6 @@
 #include "config.h"
 #include "ArrayIteratorPrototype.h"
 
-#include "ArrayIteratorPrototype.lut.h"
 #include "IteratorOperations.h"
 #include "JSCInlines.h"
 #include "JSCJSValueInlines.h"
 
 namespace JSC {
 
-const ClassInfo ArrayIteratorPrototype::s_info = { "Array Iterator", &Base::s_info, &arrayIteratorPrototypeTable, nullptr, CREATE_METHOD_TABLE(ArrayIteratorPrototype) };
+const ClassInfo ArrayIteratorPrototype::s_info = { "Array Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ArrayIteratorPrototype) };
 
-/* Source for ArrayIteratorPrototype.lut.h
-@begin arrayIteratorPrototypeTable
-  next      JSBuiltin  DontEnum|Function 0
-@end
-*/
-
-void ArrayIteratorPrototype::finishCreation(VM& vm, JSGlobalObject*)
+void ArrayIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
 {
     Base::finishCreation(vm);
     ASSERT(inherits(vm, info()));
     putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Array Iterator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, arrayIteratorPrototypeNextCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     didBecomePrototype();
 }
 
index 1a37b3f..ec78932 100644 (file)
@@ -89,8 +89,8 @@ void ArrayPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, globalObject->arrayProtoValuesFunction(), static_cast<unsigned>(PropertyAttribute::DontEnum));
 
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toLocaleString, arrayProtoFuncToLocaleString, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("concat", arrayPrototypeConcatCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("fill", arrayPrototypeFillCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().concatPublicName(), arrayPrototypeConcatCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().fillPublicName(), arrayPrototypeFillCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->join, arrayProtoFuncJoin, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("pop", arrayProtoFuncPop, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, ArrayPopIntrinsic);
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().pushPublicName(), arrayProtoFuncPush, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, ArrayPushIntrinsic);
@@ -99,26 +99,26 @@ void ArrayPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().shiftPublicName(), arrayProtoFuncShift, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().shiftPrivateName(), arrayProtoFuncShift, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly, 0);
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, arrayProtoFuncSlice, static_cast<unsigned>(PropertyAttribute::DontEnum), 2, ArraySliceIntrinsic);
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("sort", arrayPrototypeSortCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().sortPublicName(), arrayPrototypeSortCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("splice", arrayProtoFuncSplice, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("unshift", arrayProtoFuncUnShift, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("every", arrayPrototypeEveryCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("forEach", arrayPrototypeForEachCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("some", arrayPrototypeSomeCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().everyPublicName(), arrayPrototypeEveryCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().forEachPublicName(), arrayPrototypeForEachCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().somePublicName(), arrayPrototypeSomeCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("indexOf", arrayProtoFuncIndexOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, ArrayIndexOfIntrinsic);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("lastIndexOf", arrayProtoFuncLastIndexOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("filter", arrayPrototypeFilterCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("flat", arrayPrototypeFlatCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("flatMap", arrayPrototypeFlatMapCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("reduce", arrayPrototypeReduceCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("reduceRight", arrayPrototypeReduceRightCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("map", arrayPrototypeMapCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().filterPublicName(), arrayPrototypeFilterCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().flatPublicName(), arrayPrototypeFlatCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().flatMapPublicName(), arrayPrototypeFlatMapCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().reducePublicName(), arrayPrototypeReduceCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().reduceRightPublicName(), arrayPrototypeReduceRightCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().mapPublicName(), arrayPrototypeMapCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), arrayPrototypeEntriesCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), arrayPrototypeKeysCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("find", arrayPrototypeFindCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("findIndex", arrayPrototypeFindIndexCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("includes", arrayPrototypeIncludesCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("copyWithin", arrayPrototypeCopyWithinCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().findPublicName(), arrayPrototypeFindCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().findIndexPublicName(), arrayPrototypeFindIndexCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().includesPublicName(), arrayPrototypeIncludesCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().copyWithinPublicName(), arrayPrototypeCopyWithinCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
 
     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().entriesPrivateName(), getDirect(vm, vm.propertyNames->builtinNames().entriesPublicName()), static_cast<unsigned>(PropertyAttribute::ReadOnly));
     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().forEachPrivateName(), getDirect(vm, vm.propertyNames->builtinNames().forEachPublicName()), static_cast<unsigned>(PropertyAttribute::ReadOnly));
@@ -126,18 +126,19 @@ void ArrayPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPrivateName(), globalObject->arrayProtoValuesFunction(), static_cast<unsigned>(PropertyAttribute::ReadOnly));
 
     JSObject* unscopables = constructEmptyObject(globalObject->globalExec(), globalObject->nullPrototypeObjectStructure());
-    const char* unscopableNames[] = {
-        "copyWithin",
-        "entries",
-        "fill",
-        "find",
-        "findIndex",
-        "includes",
-        "keys",
-        "values"
+    unscopables->convertToDictionary(vm);
+    const Identifier* const unscopableNames[] = {
+        &vm.propertyNames->builtinNames().copyWithinPublicName(),
+        &vm.propertyNames->builtinNames().entriesPublicName(),
+        &vm.propertyNames->builtinNames().fillPublicName(),
+        &vm.propertyNames->builtinNames().findPublicName(),
+        &vm.propertyNames->builtinNames().findIndexPublicName(),
+        &vm.propertyNames->builtinNames().includesPublicName(),
+        &vm.propertyNames->builtinNames().keysPublicName(),
+        &vm.propertyNames->builtinNames().valuesPublicName()
     };
-    for (const char* unscopableName : unscopableNames)
-        unscopables->putDirect(vm, Identifier::fromString(&vm, unscopableName), jsBoolean(true));
+    for (const auto* unscopableName : unscopableNames)
+        unscopables->putDirect(vm, *unscopableName, jsBoolean(true));
     putDirectWithoutTransition(vm, vm.propertyNames->unscopablesSymbol, unscopables, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
 }
 
index 1852155..8b074b2 100644 (file)
@@ -151,9 +151,12 @@ ClonedArguments* ClonedArguments::createByCopyingFrom(
 Structure* ClonedArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
 {
     Structure* structure = Structure::create(vm, globalObject, prototype, TypeInfo(ClonedArgumentsType, StructureFlags), info(), indexingType);
-    PropertyOffset offset;
-    structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->length, static_cast<unsigned>(PropertyAttribute::DontEnum), offset);
-    ASSERT(offset == clonedArgumentsLengthPropertyOffset);
+    structure->addPropertyWithoutTransition(
+        vm, vm.propertyNames->length, static_cast<unsigned>(PropertyAttribute::DontEnum),
+        [&] (const GCSafeConcurrentJSLocker&, PropertyOffset offset, PropertyOffset newLastOffset) {
+            RELEASE_ASSERT(offset == clonedArgumentsLengthPropertyOffset);
+            structure->setLastOffset(newLastOffset);
+        });
     return structure;
 }
 
index 20737f3..1a79df2 100644 (file)
@@ -1160,7 +1160,7 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
         m_numberProtoToStringFunction.set(vm, this, jsCast<JSFunction*>(numberPrototype->getDirect(vm, vm.propertyNames->toString)));
     }
 
-    resetPrototype(vm, getPrototypeDirect(vm));
+    fixupPrototypeChainWithObjectPrototype(vm);
 }
 
 bool JSGlobalObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
@@ -1585,16 +1585,21 @@ void JSGlobalObject::haveABadTime(VM& vm)
     }
 }
 
-// Set prototype, and also insert the object prototype at the end of the chain.
-void JSGlobalObject::resetPrototype(VM& vm, JSValue prototype)
+void JSGlobalObject::fixupPrototypeChainWithObjectPrototype(VM& vm)
 {
-    setPrototypeDirect(vm, prototype);
-
     JSObject* oldLastInPrototypeChain = lastInPrototypeChain(vm, this);
     JSObject* objectPrototype = m_objectPrototype.get();
     if (oldLastInPrototypeChain != objectPrototype)
         oldLastInPrototypeChain->setPrototypeDirect(vm, objectPrototype);
+}
 
+// Set prototype, and also insert the object prototype at the end of the chain.
+void JSGlobalObject::resetPrototype(VM& vm, JSValue prototype)
+{
+    if (getPrototypeDirect(vm) == prototype)
+        return;
+    setPrototypeDirect(vm, prototype);
+    fixupPrototypeChainWithObjectPrototype(vm);
     // Whenever we change the prototype of the global object, we need to create a new JSProxy with the correct prototype.
     setGlobalThis(vm, JSNonDestructibleProxy::create(vm, JSNonDestructibleProxy::createStructure(vm, this, prototype, PureForwardingProxyType), this));
 }
index a8548e5..224f08c 100644 (file)
@@ -1035,6 +1035,7 @@ private:
     void initializeErrorConstructor(LazyClassStructure::Initializer&);
 
     JS_EXPORT_PRIVATE void init(VM&);
+    void fixupPrototypeChainWithObjectPrototype(VM&);
 
     JS_EXPORT_PRIVATE static void clearRareData(JSCell*);
 
index aa577b7..705b42e 100644 (file)
@@ -39,8 +39,8 @@ void MapIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     ASSERT(inherits(vm, info()));
     didBecomePrototype();
 
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("next", mapIteratorPrototypeNextCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Map Iterator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, mapIteratorPrototypeNextCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
 }
 
 }
index 350eb7d..47a01de 100644 (file)
@@ -37,7 +37,7 @@ public:
     {
         // Since NullGetterFunction is per JSGlobalObject, we use put-without-transition in InternalFunction::finishCreation.
         NullGetterFunction* function = new (NotNull, allocateCell< NullGetterFunction>(vm.heap))  NullGetterFunction(vm, structure);
-        function->finishCreation(vm, String(), NameVisibility::Visible, NameAdditionMode::WithStructureTransition);
+        function->finishCreation(vm, String(), NameVisibility::Visible, NameAdditionMode::WithoutStructureTransition);
         return function;
     }
 
index ea05b2b..417d79a 100644 (file)
@@ -37,7 +37,7 @@ public:
     {
         // Since NullSetterFunction is per JSGlobalObject, we use put-without-transition in InternalFunction::finishCreation.
         NullSetterFunction* function = new (NotNull, allocateCell< NullSetterFunction>(vm.heap))  NullSetterFunction(vm, structure);
-        function->finishCreation(vm, String(), NameVisibility::Visible, NameAdditionMode::WithStructureTransition);
+        function->finishCreation(vm, String(), NameVisibility::Visible, NameAdditionMode::WithoutStructureTransition);
         return function;
     }
 
index 6ac0bef..ce71299 100644 (file)
 #include "JSStringIterator.h"
 #include "ObjectConstructor.h"
 
-#include "StringIteratorPrototype.lut.h"
-
 namespace JSC {
 
-const ClassInfo StringIteratorPrototype::s_info = { "String Iterator", &Base::s_info, &stringIteratorPrototypeTable, nullptr, CREATE_METHOD_TABLE(StringIteratorPrototype) };
-
-/* Source for StringIteratorPrototype.lut.h
-@begin stringIteratorPrototypeTable
-  next      JSBuiltin    DontEnum|Function 0
-@end
-*/
+const ClassInfo StringIteratorPrototype::s_info = { "String Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(StringIteratorPrototype) };
 
-void StringIteratorPrototype::finishCreation(VM& vm, JSGlobalObject*)
+void StringIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
 {
     Base::finishCreation(vm);
     ASSERT(inherits(vm, info()));
     putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "String Iterator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, stringIteratorPrototypeNextCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     didBecomePrototype();
 }
 
index 1dcff7c..e778045 100644 (file)
@@ -400,8 +400,6 @@ VM::VM(VMType vmType, HeapType heapType)
     functionCodeBlockStructure.set(*this, FunctionCodeBlock::createStructure(*this, 0, jsNull()));
     hashMapBucketSetStructure.set(*this, HashMapBucket<HashMapBucketDataKey>::createStructure(*this, 0, jsNull()));
     hashMapBucketMapStructure.set(*this, HashMapBucket<HashMapBucketDataKeyValue>::createStructure(*this, 0, jsNull()));
-    setIteratorStructure.set(*this, JSSetIterator::createStructure(*this, 0, jsNull()));
-    mapIteratorStructure.set(*this, JSMapIterator::createStructure(*this, 0, jsNull()));
     bigIntStructure.set(*this, JSBigInt::createStructure(*this, 0, jsNull()));
     executableToCodeBlockEdgeStructure.set(*this, ExecutableToCodeBlockEdge::createStructure(*this, nullptr, jsNull()));
 
@@ -1291,6 +1289,19 @@ DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(moduleProgramExecutableSpace, destructi
 
 #undef DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW
 
+Structure* VM::setIteratorStructureSlow()
+{
+    ASSERT(!m_setIteratorStructure);
+    m_setIteratorStructure.set(*this, JSSetIterator::createStructure(*this, 0, jsNull()));
+    return m_setIteratorStructure.get();
+}
+
+Structure* VM::mapIteratorStructureSlow()
+{
+    ASSERT(!m_mapIteratorStructure);
+    m_mapIteratorStructure.set(*this, JSMapIterator::createStructure(*this, 0, jsNull()));
+    return m_mapIteratorStructure.get();
+}
 
 JSCell* VM::sentinelSetBucketSlow()
 {
index 432614b..377d315 100644 (file)
@@ -533,11 +533,12 @@ public:
     Strong<Structure> functionCodeBlockStructure;
     Strong<Structure> hashMapBucketSetStructure;
     Strong<Structure> hashMapBucketMapStructure;
-    Strong<Structure> setIteratorStructure;
-    Strong<Structure> mapIteratorStructure;
     Strong<Structure> bigIntStructure;
     Strong<Structure> executableToCodeBlockEdgeStructure;
 
+    Strong<Structure> m_setIteratorStructure;
+    Strong<Structure> m_mapIteratorStructure;
+
     Strong<JSCell> emptyPropertyNameEnumerator;
 
     Strong<JSCell> m_sentinelSetBucket;
@@ -563,6 +564,20 @@ public:
     AtomicStringTable* atomicStringTable() const { return m_atomicStringTable; }
     WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; }
 
+    Structure* setIteratorStructure()
+    {
+        if (LIKELY(m_setIteratorStructure))
+            return m_setIteratorStructure.get();
+        return setIteratorStructureSlow();
+    }
+
+    Structure* mapIteratorStructure()
+    {
+        if (LIKELY(m_mapIteratorStructure))
+            return m_mapIteratorStructure.get();
+        return mapIteratorStructureSlow();
+    }
+
     JSCell* sentinelSetBucket()
     {
         if (LIKELY(m_sentinelSetBucket))
@@ -907,6 +922,8 @@ private:
     static VM*& sharedInstanceInternal();
     void createNativeThunk();
 
+    JS_EXPORT_PRIVATE Structure* setIteratorStructureSlow();
+    JS_EXPORT_PRIVATE Structure* mapIteratorStructureSlow();
     JSCell* sentinelSetBucketSlow();
     JSCell* sentinelMapBucketSlow();
 
index 3d3bdd7..4f862be 100644 (file)
@@ -1,3 +1,13 @@
+2019-03-11  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Reduce # of structures in JSGlobalObject initialization
+        https://bugs.webkit.org/show_bug.cgi?id=195498
+
+        Reviewed by Darin Adler.
+
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::serialize):
+
 2019-03-11  Brent Fulgham  <bfulgham@apple.com>
 
         Remove obsolete runtime flag for StorageAccess API Prompt
index 776ec43..4ffb312 100644 (file)
@@ -1623,7 +1623,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                 JSMap* inMap = jsCast<JSMap*>(inValue);
                 if (!startMap(inMap))
                     break;
-                JSMapIterator* iterator = JSMapIterator::create(vm, vm.mapIteratorStructure.get(), inMap, IterateKeyValue);
+                JSMapIterator* iterator = JSMapIterator::create(vm, vm.mapIteratorStructure(), inMap, IterateKeyValue);
                 m_gcBuffer.appendWithCrashOnOverflow(inMap);
                 m_gcBuffer.appendWithCrashOnOverflow(iterator);
                 mapIteratorStack.append(iterator);
@@ -1667,7 +1667,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                 JSSet* inSet = jsCast<JSSet*>(inValue);
                 if (!startSet(inSet))
                     break;
-                JSSetIterator* iterator = JSSetIterator::create(vm, vm.setIteratorStructure.get(), inSet, IterateKey);
+                JSSetIterator* iterator = JSSetIterator::create(vm, vm.setIteratorStructure(), inSet, IterateKey);
                 m_gcBuffer.appendWithCrashOnOverflow(inSet);
                 m_gcBuffer.appendWithCrashOnOverflow(iterator);
                 setIteratorStack.append(iterator);