[JSC] Introduce LinkTimeConstant mechanism
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Nov 2019 02:52:02 +0000 (02:52 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Nov 2019 02:52:02 +0000 (02:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153792

Reviewed by Saam Barati.

Source/JavaScriptCore:

We are using private-name-variables of JSGlobalObject as a way to access to constants that are materialized per JSGlobalObject.
And we also have special-pointers and old link-time-constants to access to per JSGlobalObject constants.
We have bytecode intrinsic constants, but it is only available for per VM values.

However, these ones have multiple problems.

1. private-name-variables is too costly. We need to have an entry in JSGlobalObject's variable, this makes SymbolTable of JSGlobalObject large.
   It also requires WatchpointSet to make it constant-fold in DFG. And accessing these variables from builtin JS takes op_resolve_scope and op_get_from_scope,
   enlarging bytecode and slow in interpreter and baseline compared to just getting them as a constant register.
2. special-pointers are tailored to op_jne_ptr opcode, and not usable in the other bytecode since this is completely separate from VirtualRegister.
3. Old link-time-constants implementation is putting array of all link-time-constants on each UnlinkedCodeBlock, even if it is not used. If you increase # of
   link-time-constant, it increases sizeof(UnlinkedCodeBlock).

In this patch, we introduce a new link-time-constant mechanism and remove the above old ones mostly. (private-name-variables still exists for WebCore and @assert).
We manage link-time-constants in BytecodeIntrinsicRegistry, and emit Int32:LinkTimeConstantID constant when generating an UnlinkedCodeBlock. Later, this constant
is alternated to an actual value when we link UnlinkedCodeBlock to CodeBlock with specific JSGlobalObject. private-name-variables accesses are now converted to
constant register so that it is very efficiently accessed and it reduces memory used for SymbolTable and WatchpointSet. op_jne_ptr takes link-time-constant
VirtualRegisters instead of special-pointers, so that we can remove special-pointers mechanism. We also replace old link-time-constants with new one, which reduces
sizeof(UnlinkedCodeBlock).

Furthermore, new link-time-constant supports lazy initialization by using LazyProperty in JSGlobalObject. This allows us to lazily generate many internal functions
that are previously initialized eagerly. This reduces # of allocated JSFunction significantly when initializing JSGlobalObject.

This patch also manually adds 256 to MarkedSpace's size-class. We empirically know that adding 256 here makes sequence of size-class better for memory consumption.
But this was achieved by adding `sizeof(UnlinkedFunctionCodeBlock)`. Now sizeof(UnlinkedFunctionCodeBlock) is changed by this patch, and this patch unintentionally
breaks that sequence. We should explicitly add 256 instead of adding sizeof(UnlinkedFunctionCodeBlock) adhocly.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Scripts/wkbuiltins/builtins_generate_combined_header.py:
(generate_section_for_global_private_code_name_macro):
* Sources.txt:
* builtins/BuiltinNames.h:
* builtins/PromiseConstructor.js:
(nakedConstructor.Promise):
(nakedConstructor.InternalPromise):
(nakedConstructor.Promise.reject): Deleted.
(nakedConstructor.InternalPromise.reject): Deleted.
* bytecode/BytecodeDumper.cpp:
(JSC::CodeBlockBytecodeDumper<Block>::dumpConstants):
* bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
(JSC::BytecodeIntrinsicRegistry::lookup const):
* bytecode/BytecodeIntrinsicRegistry.h:
(JSC::BytecodeIntrinsicRegistry::Entry::Entry):
(JSC::BytecodeIntrinsicRegistry::Entry::type const):
(JSC::BytecodeIntrinsicRegistry::Entry::linkTimeConstant const):
(JSC::BytecodeIntrinsicRegistry::Entry::emitter const):
* bytecode/BytecodeList.rb:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::setConstantRegisters):
* bytecode/Fits.h:
* bytecode/LinkTimeConstant.cpp: Renamed from Source/JavaScriptCore/bytecode/SpecialPointer.h.
(WTF::printInternal):
* bytecode/LinkTimeConstant.h: Added.
* bytecode/SpecialPointer.cpp: Removed.
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::addConstant):
(JSC::UnlinkedCodeBlock::registerIndexForLinkTimeConstant): Deleted.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitJumpIfNotFunctionCall):
(JSC::BytecodeGenerator::emitJumpIfNotFunctionApply):
(JSC::BytecodeGenerator::emitExpectedFunctionSnippet):
(JSC::BytecodeGenerator::emitCallDefineProperty):
(JSC::BytecodeGenerator::emitGetAsyncIterator):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ImportNode::emitBytecode):
(JSC::BytecodeIntrinsicNode::emitBytecode):
(JSC::promiseInternalFieldIndex):
(JSC::generatorInternalFieldIndex):
(JSC::asyncGeneratorInternalFieldIndex):
(JSC::FunctionNode::emitBytecode):
(JSC::ObjectPatternNode::bindValue const):
(JSC::ObjectSpreadExpressionNode::emitBytecode):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* heap/MarkedSpace.cpp:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_jneq_ptr):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_jneq_ptr):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createResolve):
(JSC::ASTBuilder::makeFunctionCallNode):
* parser/NodeConstructors.h:
(JSC::BytecodeIntrinsicNode::BytecodeIntrinsicNode):
* parser/Nodes.h:
* runtime/CachedTypes.cpp:
(JSC::CachedCodeBlock<CodeBlockType>::decode const):
(JSC::CachedCodeBlock<CodeBlockType>::encode):
* runtime/JSCJSValue.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::JSGlobalObject):
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::linkTimeConstant const):
(JSC::JSGlobalObject::callFunction const): Deleted.
(JSC::JSGlobalObject::applyFunction const): Deleted.
(JSC::JSGlobalObject::throwTypeErrorFunction const): Deleted.
(JSC::JSGlobalObject::newPromiseCapabilityFunction const): Deleted.
(JSC::JSGlobalObject::resolvePromiseFunction const): Deleted.
(JSC::JSGlobalObject::rejectPromiseFunction const): Deleted.
(JSC::JSGlobalObject::promiseProtoThenFunction const): Deleted.
(JSC::JSGlobalObject::regExpProtoExecFunction const): Deleted.
(JSC::JSGlobalObject::regExpProtoGlobalGetter const): Deleted.
(JSC::JSGlobalObject::regExpProtoUnicodeGetter const): Deleted.
(JSC::JSGlobalObject::actualPointerFor): Deleted.
(JSC::JSGlobalObject::jsCellForLinkTimeConstant): Deleted.
* runtime/JSGlobalObjectInlines.h:
(JSC::JSGlobalObject::throwTypeErrorFunction const):
(JSC::JSGlobalObject::newPromiseCapabilityFunction const):
(JSC::JSGlobalObject::resolvePromiseFunction const):
(JSC::JSGlobalObject::rejectPromiseFunction const):
(JSC::JSGlobalObject::promiseProtoThenFunction const):
(JSC::JSGlobalObject::regExpProtoExecFunction const):
(JSC::JSGlobalObject::regExpProtoGlobalGetter const):
(JSC::JSGlobalObject::regExpProtoUnicodeGetter const):

LayoutTests:

* inspector/debugger/tail-deleted-frames/tail-deleted-frames-this-value-expected.txt:

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

37 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/debugger/tail-deleted-frames/tail-deleted-frames-this-value-expected.txt
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Scripts/wkbuiltins/builtins_generate_combined_header.py
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/builtins/BuiltinNames.h
Source/JavaScriptCore/builtins/PromiseConstructor.js
Source/JavaScriptCore/bytecode/BytecodeDumper.cpp
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
Source/JavaScriptCore/bytecode/BytecodeList.rb
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/Fits.h
Source/JavaScriptCore/bytecode/LinkTimeConstant.cpp [moved from Source/JavaScriptCore/bytecode/SpecialPointer.h with 59% similarity]
Source/JavaScriptCore/bytecode/LinkTimeConstant.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/SpecialPointer.cpp [deleted file]
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/heap/MarkedSpace.cpp
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/NodeConstructors.h
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/runtime/CachedTypes.cpp
Source/JavaScriptCore/runtime/JSCJSValue.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSGlobalObjectInlines.h

index d469623..bca17be 100644 (file)
@@ -1,3 +1,12 @@
+2019-11-04  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Introduce LinkTimeConstant mechanism
+        https://bugs.webkit.org/show_bug.cgi?id=153792
+
+        Reviewed by Saam Barati.
+
+        * inspector/debugger/tail-deleted-frames/tail-deleted-frames-this-value-expected.txt:
+
 2019-11-04  Yury Semikhatsky  <yurys@chromium.org>
 
         [GTK] Inspector protocol tests timing out on the bots
index f39a484..0e96650 100644 (file)
@@ -522,6 +522,7 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS
     bytecode/LLIntCallLinkInfo.h
     bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h
     bytecode/LazyOperandValueProfile.h
+    bytecode/LinkTimeConstant.h
     bytecode/MetadataTable.h
     bytecode/ObjectAllocationProfile.h
     bytecode/ObjectPropertyCondition.h
@@ -529,7 +530,6 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS
     bytecode/OpcodeSize.h
     bytecode/PropertyCondition.h
     bytecode/PutByIdFlags.h
-    bytecode/SpecialPointer.h
     bytecode/SpeculatedType.h
     bytecode/StructureSet.h
     bytecode/SuperSampler.h
index fe56b0d..003a68c 100644 (file)
@@ -1,3 +1,136 @@
+2019-11-04  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Introduce LinkTimeConstant mechanism
+        https://bugs.webkit.org/show_bug.cgi?id=153792
+
+        Reviewed by Saam Barati.
+
+        We are using private-name-variables of JSGlobalObject as a way to access to constants that are materialized per JSGlobalObject.
+        And we also have special-pointers and old link-time-constants to access to per JSGlobalObject constants.
+        We have bytecode intrinsic constants, but it is only available for per VM values.
+
+        However, these ones have multiple problems.
+
+        1. private-name-variables is too costly. We need to have an entry in JSGlobalObject's variable, this makes SymbolTable of JSGlobalObject large.
+           It also requires WatchpointSet to make it constant-fold in DFG. And accessing these variables from builtin JS takes op_resolve_scope and op_get_from_scope,
+           enlarging bytecode and slow in interpreter and baseline compared to just getting them as a constant register.
+        2. special-pointers are tailored to op_jne_ptr opcode, and not usable in the other bytecode since this is completely separate from VirtualRegister.
+        3. Old link-time-constants implementation is putting array of all link-time-constants on each UnlinkedCodeBlock, even if it is not used. If you increase # of
+           link-time-constant, it increases sizeof(UnlinkedCodeBlock).
+
+        In this patch, we introduce a new link-time-constant mechanism and remove the above old ones mostly. (private-name-variables still exists for WebCore and @assert).
+        We manage link-time-constants in BytecodeIntrinsicRegistry, and emit Int32:LinkTimeConstantID constant when generating an UnlinkedCodeBlock. Later, this constant
+        is alternated to an actual value when we link UnlinkedCodeBlock to CodeBlock with specific JSGlobalObject. private-name-variables accesses are now converted to
+        constant register so that it is very efficiently accessed and it reduces memory used for SymbolTable and WatchpointSet. op_jne_ptr takes link-time-constant
+        VirtualRegisters instead of special-pointers, so that we can remove special-pointers mechanism. We also replace old link-time-constants with new one, which reduces
+        sizeof(UnlinkedCodeBlock).
+
+        Furthermore, new link-time-constant supports lazy initialization by using LazyProperty in JSGlobalObject. This allows us to lazily generate many internal functions
+        that are previously initialized eagerly. This reduces # of allocated JSFunction significantly when initializing JSGlobalObject.
+
+        This patch also manually adds 256 to MarkedSpace's size-class. We empirically know that adding 256 here makes sequence of size-class better for memory consumption.
+        But this was achieved by adding `sizeof(UnlinkedFunctionCodeBlock)`. Now sizeof(UnlinkedFunctionCodeBlock) is changed by this patch, and this patch unintentionally
+        breaks that sequence. We should explicitly add 256 instead of adding sizeof(UnlinkedFunctionCodeBlock) adhocly.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Scripts/wkbuiltins/builtins_generate_combined_header.py:
+        (generate_section_for_global_private_code_name_macro):
+        * Sources.txt:
+        * builtins/BuiltinNames.h:
+        * builtins/PromiseConstructor.js:
+        (nakedConstructor.Promise):
+        (nakedConstructor.InternalPromise):
+        (nakedConstructor.Promise.reject): Deleted.
+        (nakedConstructor.InternalPromise.reject): Deleted.
+        * bytecode/BytecodeDumper.cpp:
+        (JSC::CodeBlockBytecodeDumper<Block>::dumpConstants):
+        * bytecode/BytecodeIntrinsicRegistry.cpp:
+        (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
+        (JSC::BytecodeIntrinsicRegistry::lookup const):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        (JSC::BytecodeIntrinsicRegistry::Entry::Entry):
+        (JSC::BytecodeIntrinsicRegistry::Entry::type const):
+        (JSC::BytecodeIntrinsicRegistry::Entry::linkTimeConstant const):
+        (JSC::BytecodeIntrinsicRegistry::Entry::emitter const):
+        * bytecode/BytecodeList.rb:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        (JSC::CodeBlock::setConstantRegisters):
+        * bytecode/Fits.h:
+        * bytecode/LinkTimeConstant.cpp: Renamed from Source/JavaScriptCore/bytecode/SpecialPointer.h.
+        (WTF::printInternal):
+        * bytecode/LinkTimeConstant.h: Added.
+        * bytecode/SpecialPointer.cpp: Removed.
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::addConstant):
+        (JSC::UnlinkedCodeBlock::registerIndexForLinkTimeConstant): Deleted.
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitJumpIfNotFunctionCall):
+        (JSC::BytecodeGenerator::emitJumpIfNotFunctionApply):
+        (JSC::BytecodeGenerator::emitExpectedFunctionSnippet):
+        (JSC::BytecodeGenerator::emitCallDefineProperty):
+        (JSC::BytecodeGenerator::emitGetAsyncIterator):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ImportNode::emitBytecode):
+        (JSC::BytecodeIntrinsicNode::emitBytecode):
+        (JSC::promiseInternalFieldIndex):
+        (JSC::generatorInternalFieldIndex):
+        (JSC::asyncGeneratorInternalFieldIndex):
+        (JSC::FunctionNode::emitBytecode):
+        (JSC::ObjectPatternNode::bindValue const):
+        (JSC::ObjectSpreadExpressionNode::emitBytecode):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * heap/MarkedSpace.cpp:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_jneq_ptr):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_jneq_ptr):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createResolve):
+        (JSC::ASTBuilder::makeFunctionCallNode):
+        * parser/NodeConstructors.h:
+        (JSC::BytecodeIntrinsicNode::BytecodeIntrinsicNode):
+        * parser/Nodes.h:
+        * runtime/CachedTypes.cpp:
+        (JSC::CachedCodeBlock<CodeBlockType>::decode const):
+        (JSC::CachedCodeBlock<CodeBlockType>::encode):
+        * runtime/JSCJSValue.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::JSGlobalObject):
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::linkTimeConstant const):
+        (JSC::JSGlobalObject::callFunction const): Deleted.
+        (JSC::JSGlobalObject::applyFunction const): Deleted.
+        (JSC::JSGlobalObject::throwTypeErrorFunction const): Deleted.
+        (JSC::JSGlobalObject::newPromiseCapabilityFunction const): Deleted.
+        (JSC::JSGlobalObject::resolvePromiseFunction const): Deleted.
+        (JSC::JSGlobalObject::rejectPromiseFunction const): Deleted.
+        (JSC::JSGlobalObject::promiseProtoThenFunction const): Deleted.
+        (JSC::JSGlobalObject::regExpProtoExecFunction const): Deleted.
+        (JSC::JSGlobalObject::regExpProtoGlobalGetter const): Deleted.
+        (JSC::JSGlobalObject::regExpProtoUnicodeGetter const): Deleted.
+        (JSC::JSGlobalObject::actualPointerFor): Deleted.
+        (JSC::JSGlobalObject::jsCellForLinkTimeConstant): Deleted.
+        * runtime/JSGlobalObjectInlines.h:
+        (JSC::JSGlobalObject::throwTypeErrorFunction const):
+        (JSC::JSGlobalObject::newPromiseCapabilityFunction const):
+        (JSC::JSGlobalObject::resolvePromiseFunction const):
+        (JSC::JSGlobalObject::rejectPromiseFunction const):
+        (JSC::JSGlobalObject::promiseProtoThenFunction const):
+        (JSC::JSGlobalObject::regExpProtoExecFunction const):
+        (JSC::JSGlobalObject::regExpProtoGlobalGetter const):
+        (JSC::JSGlobalObject::regExpProtoUnicodeGetter const):
+
 2019-11-04  Ross Kirsling  <ross.kirsling@sony.com>
 
         Unreviewed fix for non-unified build.
index 0b315c4..ad07f68 100644 (file)
                0F4F828C1E31B9760075184C /* StochasticSpaceTimeMutatorScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4F828A1E31B9710075184C /* StochasticSpaceTimeMutatorScheduler.h */; };
                0F50AF3C193E8B3900674EE8 /* DFGStructureClobberState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F50AF3B193E8B3900674EE8 /* DFGStructureClobberState.h */; };
                0F5513A61D5A682C00C32BD8 /* FreeList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5513A51D5A682A00C32BD8 /* FreeList.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               0F5541B21613C1FB00CE3E25 /* SpecialPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5541B01613C1FB00CE3E25 /* SpecialPointer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F55989817C86C5800A1E543 /* ToNativeFromValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F55989717C86C5600A1E543 /* ToNativeFromValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F55F0F214D1063600AC7649 /* AbstractPC.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F56A1D115000F31002992B1 /* ExecutionCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1521DBC3A5600F83516 /* DOMJITHeapRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35CA1561DBC3A5F00F83516 /* DOMJITAbstractHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35E03601B7AB43E0073AD2A /* InspectorInstrumentationObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               E3637EE9236E56B00096BD0A /* LinkTimeConstant.h in Headers */ = {isa = PBXBuildFile; fileRef = E3637EE7236E56B00096BD0A /* LinkTimeConstant.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E36B767022F8D61900D09818 /* WasmOMGForOSREntryPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = E36B766F22F8D61100D09818 /* WasmOMGForOSREntryPlan.h */; };
                E36CC9472086314F0051FFD6 /* WasmCreationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = E36CC9462086314F0051FFD6 /* WasmCreationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F50AF3B193E8B3900674EE8 /* DFGStructureClobberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureClobberState.h; path = dfg/DFGStructureClobberState.h; sourceTree = "<group>"; };
                0F5513A51D5A682A00C32BD8 /* FreeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FreeList.h; sourceTree = "<group>"; };
                0F5513A71D5A68CB00C32BD8 /* FreeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FreeList.cpp; sourceTree = "<group>"; };
-               0F5541AF1613C1FB00CE3E25 /* SpecialPointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpecialPointer.cpp; sourceTree = "<group>"; };
-               0F5541B01613C1FB00CE3E25 /* SpecialPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecialPointer.h; sourceTree = "<group>"; };
                0F55989717C86C5600A1E543 /* ToNativeFromValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ToNativeFromValue.h; sourceTree = "<group>"; };
                0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractValue.cpp; path = dfg/DFGAbstractValue.cpp; sourceTree = "<group>"; };
                0F55F0F114D1063600AC7649 /* AbstractPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractPC.cpp; sourceTree = "<group>"; };
                E35E035D1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorInstrumentationObject.cpp; sourceTree = "<group>"; };
                E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorInstrumentationObject.h; sourceTree = "<group>"; };
                E35E03611B7AB4850073AD2A /* InspectorInstrumentationObject.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = InspectorInstrumentationObject.js; sourceTree = "<group>"; };
+               E3637EE7236E56B00096BD0A /* LinkTimeConstant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkTimeConstant.h; sourceTree = "<group>"; };
+               E3637EE8236E56B00096BD0A /* LinkTimeConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkTimeConstant.cpp; sourceTree = "<group>"; };
                E36B766E22F8D61100D09818 /* WasmOMGForOSREntryPlan.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmOMGForOSREntryPlan.cpp; sourceTree = "<group>"; };
                E36B766F22F8D61100D09818 /* WasmOMGForOSREntryPlan.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmOMGForOSREntryPlan.h; sourceTree = "<group>"; };
                E36CC9462086314F0051FFD6 /* WasmCreationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCreationMode.h; sourceTree = "<group>"; };
                                BCFD8C910EEB2EE700283848 /* JumpTable.h */,
                                0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */,
                                0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */,
+                               E3637EE8236E56B00096BD0A /* LinkTimeConstant.cpp */,
+                               E3637EE7236E56B00096BD0A /* LinkTimeConstant.h */,
                                0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */,
                                53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */,
                                53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */,
                                0F44A7AA20BF685E0022B171 /* RecordedStatuses.h */,
                                0FF60ABF16740F8100029779 /* ReduceWhitespace.cpp */,
                                0FF60AC016740F8100029779 /* ReduceWhitespace.h */,
-                               0F5541AF1613C1FB00CE3E25 /* SpecialPointer.cpp */,
-                               0F5541B01613C1FB00CE3E25 /* SpecialPointer.h */,
                                0FD82E84141F3FDA00179C94 /* SpeculatedType.cpp */,
                                0FD82E4F141DAEA100179C94 /* SpeculatedType.h */,
                                0FB438A219270B1D00E1FBC9 /* StructureSet.cpp */,
                                BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */,
                                BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */,
                                86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */,
+                               E3637EE9236E56B00096BD0A /* LinkTimeConstant.h in Headers */,
                                A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */,
                                70DE9A091BE7D69E005D89D9 /* LLIntAssembly.h in Headers */,
                                0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */,
                                0FDE87FC1DFE6E510064C390 /* SpaceTimeMutatorScheduler.h in Headers */,
                                0FB7F39E15ED8E4600F167B2 /* SparseArrayValueMap.h in Headers */,
                                A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */,
-                               0F5541B21613C1FB00CE3E25 /* SpecialPointer.h in Headers */,
                                0FD82E54141DAEEE00179C94 /* SpeculatedType.h in Headers */,
                                A785F6BC18C553FE00F10626 /* SpillRegistersMode.h in Headers */,
                                0F3AC752183EA1040032029F /* StackAlignment.h in Headers */,
index 33419f5..042b322 100644 (file)
@@ -172,11 +172,10 @@ extern const JSC::ConstructorKind s_%(codeName)sConstructorKind;""" % function_a
         functions.sort(key=lambda x: x.function_name)
         for function in functions:
             function_args = {
-                'varName': get_var_name(function),
                 'funcName': function.function_name,
                 'codeName': BuiltinsGenerator.mangledNameForFunction(function),
             }
 
-            lines.append("    macro(%(varName)s, %(funcName)s, %(codeName)s) \\" % function_args)
+            lines.append("    macro(%(funcName)s, %(codeName)s) \\" % function_args)
 
         return '\n'.join(lines)
index c908afb..51921d7 100644 (file)
@@ -244,6 +244,7 @@ bytecode/IntrinsicGetterAccessCase.cpp
 bytecode/JumpTable.cpp
 bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp
 bytecode/LazyOperandValueProfile.cpp
+bytecode/LinkTimeConstant.cpp
 bytecode/MetadataTable.cpp
 bytecode/MethodOfGettingAValueProfile.cpp
 bytecode/ModuleNamespaceAccessCase.cpp
@@ -263,7 +264,6 @@ bytecode/PutByIdStatus.cpp
 bytecode/PutByIdVariant.cpp
 bytecode/RecordedStatuses.cpp
 bytecode/ReduceWhitespace.cpp
-bytecode/SpecialPointer.cpp
 bytecode/SpeculatedType.cpp
 bytecode/StructureSet.cpp
 bytecode/StructureStubClearingWatchpoint.cpp
index dd33ca8..d43e48f 100644 (file)
@@ -45,6 +45,7 @@ namespace JSC {
     JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \
     JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \
     macro(add) \
+    macro(applyFunction) \
     macro(arrayIteratorNextIndex) \
     macro(arrayIterationKind) \
     macro(arrayIteratorNext) \
@@ -52,6 +53,7 @@ namespace JSC {
     macro(arrayIteratorKind) \
     macro(arraySpeciesCreate) \
     macro(assert) \
+    macro(callFunction) \
     macro(charCodeAt) \
     macro(executor) \
     macro(isView) \
@@ -73,6 +75,7 @@ namespace JSC {
     macro(getOwnPropertyNames) \
     macro(ownKeys) \
     macro(Set) \
+    macro(throwTypeErrorFunction) \
     macro(typedArrayLength) \
     macro(typedArraySort) \
     macro(typedArrayGetOriginalConstructor) \
index 30fc66e..66f951f 100644 (file)
@@ -237,19 +237,16 @@ function Promise(executor)
     var promise = @createPromise(this, /* isInternalPromise */ false);
     var capturedPromise = promise;
 
-    // FIXME: We should allow using function-declaration here.
-    // https://bugs.webkit.org/show_bug.cgi?id=203502
-    var @reject = function @reject(reason) {
-        return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
-    };
-
     try {
         executor(
             function @resolve(resolution) {
                 return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
-            }, @reject);
+            },
+            function @reject(reason) {
+                return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
+            });
     } catch (error) {
-        @reject(error);
+        @rejectPromiseWithFirstResolvingFunctionCallCheck(promise, error);
     }
 
     return promise;
@@ -266,19 +263,16 @@ function InternalPromise(executor)
     var promise = @createPromise(this, /* isInternalPromise */ true);
     var capturedPromise = promise;
 
-    // FIXME: We should allow using function-declaration here.
-    // https://bugs.webkit.org/show_bug.cgi?id=203502
-    var @reject = function @reject(reason) {
-        return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
-    };
-
     try {
         executor(
             function @resolve(resolution) {
                 return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
-            }, @reject);
+            },
+            function @reject(reason) {
+                return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
+            });
     } catch (error) {
-        @reject(error);
+        @rejectPromiseWithFirstResolvingFunctionCallCheck(promise, error);
     }
 
     return promise;
index af80769..858ab90 100644 (file)
@@ -136,6 +136,9 @@ void CodeBlockBytecodeDumper<Block>::dumpConstants()
             case SourceCodeRepresentation::Other:
                 sourceCodeRepresentationDescription = "";
                 break;
+            case SourceCodeRepresentation::LinkTimeConstant:
+                sourceCodeRepresentationDescription = ": in source as linke-time-constant";
+                break;
             }
             this->m_out.printf("   k%u = %s%s\n", static_cast<unsigned>(i), toCString(constant.get()).data(), sourceCodeRepresentationDescription);
             ++i;
index d41633c..99f3ebb 100644 (file)
@@ -42,7 +42,8 @@
 
 namespace JSC {
 
-#define INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET(name) m_bytecodeIntrinsicMap.add(vm.propertyNames->builtinNames().name##PrivateName().impl(), &BytecodeIntrinsicNode::emit_intrinsic_##name);
+#define INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET(name) m_bytecodeIntrinsicMap.add(vm.propertyNames->builtinNames().name##PrivateName().impl(), Entry(&BytecodeIntrinsicNode::emit_intrinsic_##name));
+#define INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET_FOR_LINK_TIME_CONSTANT(name, code) m_bytecodeIntrinsicMap.add(vm.propertyNames->builtinNames().name##PrivateName().impl(), JSC::LinkTimeConstant::name);
 
 BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
     : m_vm(vm)
@@ -50,6 +51,7 @@ BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
 {
     JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET)
     JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET)
+    JSC_FOREACH_LINK_TIME_CONSTANTS(INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET_FOR_LINK_TIME_CONSTANT)
 
     m_undefined.set(m_vm, jsUndefined());
     m_Infinity.set(m_vm, jsDoubleNumber(std::numeric_limits<double>::infinity()));
@@ -98,13 +100,13 @@ BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
     m_AsyncGeneratorSuspendReasonNone.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorSuspendReason::None)));
 }
 
-BytecodeIntrinsicNode::EmitterType BytecodeIntrinsicRegistry::lookup(const Identifier& ident) const
+Optional<BytecodeIntrinsicRegistry::Entry> BytecodeIntrinsicRegistry::lookup(const Identifier& ident) const
 {
     if (!ident.isPrivateName())
-        return nullptr;
+        return WTF::nullopt;
     auto iterator = m_bytecodeIntrinsicMap.find(ident.impl());
     if (iterator == m_bytecodeIntrinsicMap.end())
-        return nullptr;
+        return WTF::nullopt;
     return iterator->value;
 }
 
index faeb238..f76f785 100644 (file)
@@ -35,6 +35,7 @@ class CommonIdentifiers;
 class BytecodeGenerator;
 class BytecodeIntrinsicNode;
 class RegisterID;
+enum class LinkTimeConstant : int32_t;
 
 #define JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \
     macro(argument) \
@@ -137,7 +138,44 @@ public:
 
     typedef RegisterID* (BytecodeIntrinsicNode::* EmitterType)(BytecodeGenerator&, RegisterID*);
 
-    EmitterType lookup(const Identifier&) const;
+    enum class Type : uint8_t {
+        Emitter = 0,
+        LinkTimeConstant = 1,
+    };
+
+    class Entry {
+    public:
+        Entry()
+            : m_type(Type::Emitter)
+        {
+            m_emitter = nullptr;
+        }
+
+        Entry(EmitterType emitter)
+            : m_type(Type::Emitter)
+        {
+            m_emitter = emitter;
+        }
+
+        Entry(LinkTimeConstant linkTimeConstant)
+            : m_type(Type::LinkTimeConstant)
+        {
+            m_linkTimeConstant = linkTimeConstant;
+        }
+
+        Type type() const { return m_type; }
+        LinkTimeConstant linkTimeConstant() const { return m_linkTimeConstant; }
+        EmitterType emitter() const { return m_emitter; }
+
+    private:
+        union {
+            EmitterType m_emitter;
+            LinkTimeConstant m_linkTimeConstant;
+        };
+        Type m_type;
+    };
+
+    Optional<Entry> lookup(const Identifier&) const;
 
 #define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) JSValue name##Value(BytecodeGenerator&);
     JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
@@ -145,7 +183,7 @@ public:
 
 private:
     VM& m_vm;
-    HashMap<RefPtr<UniquedStringImpl>, EmitterType, IdentifierRepHash> m_bytecodeIntrinsicMap;
+    HashMap<RefPtr<UniquedStringImpl>, Entry, IdentifierRepHash> m_bytecodeIntrinsicMap;
 
 #define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) Strong<Unknown> m_##name;
     JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_SIMPLE_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
index d652b65..34c152a 100644 (file)
@@ -64,10 +64,6 @@ types [
     :ObjectAllocationProfile,
 ]
 
-namespace :Special do
-    types [ :Pointer ]
-end
-
 templates [
     :WriteBarrier,
     :WriteBarrierBase,
@@ -675,7 +671,7 @@ op :jnundefined_or_null,
 op :jneq_ptr,
     args: {
         value: VirtualRegister,
-        specialPointer: Special::Pointer,
+        specialPointer: VirtualRegister,
         targetLabel: BoundLabel,
     },
     metadata: {
index 5ec246c..0f8e7f8 100644 (file)
@@ -399,12 +399,6 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
     setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation(), topLevelExecutable);
     RETURN_IF_EXCEPTION(throwScope, false);
 
-    for (unsigned i = 0; i < LinkTimeConstantCount; i++) {
-        LinkTimeConstant type = static_cast<LinkTimeConstant>(i);
-        if (unsigned registerIndex = unlinkedCodeBlock->registerIndexForLinkTimeConstant(type))
-            m_constantRegisters[registerIndex].set(vm, this, m_globalObject->jsCellForLinkTimeConstant(type));
-    }
-
     // We already have the cloned symbol table for the module environment since we need to instantiate
     // the module environments before linking the code block. We replace the stored symbol table with the already cloned one.
     if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast<UnlinkedModuleProgramCodeBlock*>(vm, unlinkedCodeBlock)) {
@@ -905,29 +899,36 @@ void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& consta
     }
     for (size_t i = 0; i < count; i++) {
         JSValue constant = constants[i].get();
-
-        if (!constant.isEmpty()) {
-            if (constant.isCell()) {
-                JSCell* cell = constant.asCell();
-                if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(vm, cell)) {
-                    if (m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes()) {
-                        ConcurrentJSLocker locker(symbolTable->m_lock);
-                        symbolTable->prepareForTypeProfiling(locker);
+        switch (constantsSourceCodeRepresentation[i]) {
+        case SourceCodeRepresentation::LinkTimeConstant:
+            constant = globalObject->linkTimeConstant(static_cast<LinkTimeConstant>(constant.asInt32AsAnyInt()));
+            break;
+        case SourceCodeRepresentation::Other:
+        case SourceCodeRepresentation::Integer:
+        case SourceCodeRepresentation::Double:
+            if (!constant.isEmpty()) {
+                if (constant.isCell()) {
+                    JSCell* cell = constant.asCell();
+                    if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(vm, cell)) {
+                        if (m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes()) {
+                            ConcurrentJSLocker locker(symbolTable->m_lock);
+                            symbolTable->prepareForTypeProfiling(locker);
+                        }
+
+                        SymbolTable* clone = symbolTable->cloneScopePart(vm);
+                        if (wasCompiledWithDebuggingOpcodes())
+                            clone->setRareDataCodeBlock(this);
+
+                        constant = clone;
+                    } else if (auto* descriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) {
+                        auto* templateObject = topLevelExecutable->createTemplateObject(globalObject, descriptor);
+                        RETURN_IF_EXCEPTION(scope, void());
+                        constant = templateObject;
                     }
-
-                    SymbolTable* clone = symbolTable->cloneScopePart(vm);
-                    if (wasCompiledWithDebuggingOpcodes())
-                        clone->setRareDataCodeBlock(this);
-
-                    constant = clone;
-                } else if (auto* descriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) {
-                    auto* templateObject = topLevelExecutable->createTemplateObject(globalObject, descriptor);
-                    RETURN_IF_EXCEPTION(scope, void());
-                    constant = templateObject;
                 }
             }
+            break;
         }
-
         m_constantRegisters[i].set(vm, this, constant);
     }
 
index e244fd6..eda24be 100644 (file)
@@ -32,7 +32,6 @@
 #include "ProfileTypeBytecodeFlag.h"
 #include "PutByIdFlags.h"
 #include "ResultType.h"
-#include "SpecialPointer.h"
 #include "SymbolTableOrScopeDepth.h"
 #include "VirtualRegister.h"
 #include <type_traits>
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 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. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#pragma once
+#include "config.h"
+#include "LinkTimeConstant.h"
 
-namespace JSC {
+#include <wtf/PrintStream.h>
 
-class CodeBlock;
-class JSGlobalObject;
+namespace JSC {
 
-namespace Special {
-enum Pointer : unsigned {
-    CallFunction,
-    ApplyFunction,
-    ObjectConstructor,
-    ArrayConstructor,
-    TableSize // Not a real special pointer. Use this to determine the number of pointers.
-};
-} // namespace Special
+} // namespace JSC
 
-enum class LinkTimeConstant {
-    ThrowTypeErrorFunction,
-};
-const unsigned LinkTimeConstantCount = 1;
+namespace WTF {
 
-inline bool pointerIsFunction(Special::Pointer pointer)
-{
-    ASSERT_UNUSED(pointer, pointer < Special::TableSize);
-    return true;
-}
+#define PRINT_LINK_TIME_CONSTANT(name, code) \
+    case JSC::LinkTimeConstant::name: \
+        out.print(#name); \
+        return;
 
-inline bool pointerIsCell(Special::Pointer pointer)
+void printInternal(PrintStream& out, JSC::LinkTimeConstant constant)
 {
-    ASSERT_UNUSED(pointer, pointer < Special::TableSize);
-    return true;
+    switch (constant) {
+        JSC_FOREACH_LINK_TIME_CONSTANTS(PRINT_LINK_TIME_CONSTANT)
+    }
 }
 
-void* actualPointerFor(JSGlobalObject*, Special::Pointer);
-void* actualPointerFor(CodeBlock*, Special::Pointer);
-
-} // namespace JSC
-
-namespace WTF {
-
-class PrintStream;
-
-void printInternal(PrintStream&, JSC::Special::Pointer);
+#undef PRINT_LINK_TIME_CONSTANT
 
 } // namespace WTF
diff --git a/Source/JavaScriptCore/bytecode/LinkTimeConstant.h b/Source/JavaScriptCore/bytecode/LinkTimeConstant.h
new file mode 100644 (file)
index 0000000..1b6e726
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include "JSCBuiltins.h"
+
+namespace JSC {
+
+class CodeBlock;
+class JSGlobalObject;
+
+#define JSC_FOREACH_LINK_TIME_CONSTANTS(v) \
+    JSC_FOREACH_BUILTIN_FUNCTION_PRIVATE_GLOBAL_NAME(v) \
+    v(throwTypeErrorFunction, nullptr) \
+    v(importModule, nullptr) \
+    v(mapBucketHead, nullptr) \
+    v(mapBucketNext, nullptr) \
+    v(mapBucketKey, nullptr) \
+    v(mapBucketValue, nullptr) \
+    v(setBucketHead, nullptr) \
+    v(setBucketNext, nullptr) \
+    v(setBucketKey, nullptr) \
+    v(propertyIsEnumerable, nullptr) \
+    v(ownKeys, nullptr) \
+    v(enqueueJob, nullptr) \
+    v(makeTypeError, nullptr) \
+    v(typedArrayLength, nullptr) \
+    v(typedArrayGetOriginalConstructor, nullptr) \
+    v(typedArraySort, nullptr) \
+    v(isTypedArrayView, nullptr) \
+    v(typedArraySubarrayCreate, nullptr) \
+    v(isBoundFunction, nullptr) \
+    v(hasInstanceBoundFunction, nullptr) \
+    v(instanceOf, nullptr) \
+    v(BuiltinLog, nullptr) \
+    v(BuiltinDescribe, nullptr) \
+    v(RegExp, nullptr) \
+    v(trunc, nullptr) \
+    v(Promise, nullptr) \
+    v(InternalPromise, nullptr) \
+    v(defaultPromiseThen, nullptr) \
+    v(repeatCharacter, nullptr) \
+    v(arraySpeciesCreate, nullptr) \
+    v(isArray, nullptr) \
+    v(isArraySlow, nullptr) \
+    v(concatMemcpy, nullptr) \
+    v(appendMemcpy, nullptr) \
+    v(hostPromiseRejectionTracker, nullptr) \
+    v(InspectorInstrumentation, nullptr) \
+    v(Set, nullptr) \
+    v(thisTimeValue, nullptr) \
+    v(isConstructor, nullptr) \
+    v(regExpProtoFlagsGetter, nullptr) \
+    v(regExpProtoGlobalGetter, nullptr) \
+    v(regExpProtoIgnoreCaseGetter, nullptr) \
+    v(regExpProtoMultilineGetter, nullptr) \
+    v(regExpProtoSourceGetter, nullptr) \
+    v(regExpProtoStickyGetter, nullptr) \
+    v(regExpProtoUnicodeGetter, nullptr) \
+    v(regExpBuiltinExec, nullptr) \
+    v(regExpCreate, nullptr) \
+    v(isRegExp, nullptr) \
+    v(regExpMatchFast, nullptr) \
+    v(regExpSearchFast, nullptr) \
+    v(regExpSplitFast, nullptr) \
+    v(regExpPrototypeSymbolReplace, nullptr) \
+    v(regExpTestFast, nullptr) \
+    v(stringIncludesInternal, nullptr) \
+    v(stringSplitFast, nullptr) \
+    v(stringSubstrInternal, nullptr) \
+    v(makeBoundFunction, nullptr) \
+    v(hasOwnLengthProperty, nullptr) \
+    v(dateTimeFormat, nullptr) \
+    v(webAssemblyCompileStreamingInternal, nullptr) \
+    v(webAssemblyInstantiateStreamingInternal, nullptr) \
+    v(Object, nullptr) \
+    v(Array, nullptr) \
+    v(applyFunction, nullptr) \
+    v(callFunction, nullptr) \
+
+
+#define DECLARE_LINK_TIME_CONSTANT(name, code) name,
+enum class LinkTimeConstant : int32_t {
+    JSC_FOREACH_LINK_TIME_CONSTANTS(DECLARE_LINK_TIME_CONSTANT)
+};
+#undef DECLARE_LINK_TIME_CONSTANT
+#define COUNT_LINK_TIME_CONSTANT(name, code) 1 +
+static constexpr unsigned numberOfLinkTimeConstants = JSC_FOREACH_LINK_TIME_CONSTANTS(COUNT_LINK_TIME_CONSTANT) 0;
+#undef COUNT_LINK_TIME_CONSTANT
+
+} // namespace JSC
+
+namespace WTF {
+
+class PrintStream;
+
+void printInternal(PrintStream&, JSC::LinkTimeConstant);
+
+} // namespace WTF
diff --git a/Source/JavaScriptCore/bytecode/SpecialPointer.cpp b/Source/JavaScriptCore/bytecode/SpecialPointer.cpp
deleted file mode 100644 (file)
index 5ad3f24..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2012 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 "SpecialPointer.h"
-
-#include "CodeBlock.h"
-#include "JSGlobalObject.h"
-#include "JSCInlines.h"
-
-namespace JSC {
-
-void* actualPointerFor(JSGlobalObject* globalObject, Special::Pointer pointer)
-{
-    return globalObject->actualPointerFor(pointer);
-}
-
-void* actualPointerFor(CodeBlock* codeBlock, Special::Pointer pointer)
-{
-    return actualPointerFor(codeBlock->globalObject(), pointer);
-}
-
-} // namespace JSC
-
-namespace WTF {
-
-void printInternal(PrintStream& out, JSC::Special::Pointer pointer)
-{
-    switch (pointer) {
-    case JSC::Special::CallFunction:
-        out.print("CallFunction");
-        return;
-    case JSC::Special::ApplyFunction:
-        out.print("ApplyFunction");
-        return;
-    case JSC::Special::ObjectConstructor:
-        out.print("ObjectConstructor");
-        return;
-    case JSC::Special::ArrayConstructor:
-        out.print("ArrayConstructor");
-        return;
-    case JSC::Special::TableSize:
-        out.print("TableSize");
-        return;
-    }
-}
-
-} // namespace WTF
index 234fa57..d5ddee8 100644 (file)
@@ -76,8 +76,6 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM& vm, Structure* structure, CodeType code
     , m_codeGenerationMode(codeGenerationMode)
     , m_metadata(UnlinkedMetadataTable::create())
 {
-    for (auto& constantRegisterIndex : m_linkTimeConstants)
-        constantRegisterIndex = 0;
     ASSERT(m_constructorKind == static_cast<unsigned>(info.constructorKind()));
     ASSERT(m_codeType == static_cast<unsigned>(codeType));
     ASSERT(m_didOptimize == static_cast<unsigned>(MixedTriState));
index 4739da7..6c050a2 100644 (file)
@@ -37,7 +37,6 @@
 #include "Opcode.h"
 #include "ParserModes.h"
 #include "RegExp.h"
-#include "SpecialPointer.h"
 #include "UnlinkedFunctionExecutable.h"
 #include "UnlinkedMetadataTable.h"
 #include "VirtualRegister.h"
@@ -63,6 +62,7 @@ class UnlinkedCodeBlock;
 class UnlinkedFunctionCodeBlock;
 class UnlinkedFunctionExecutable;
 struct ExecutableInfo;
+enum class LinkTimeConstant : int32_t;
 
 template<typename CodeBlockType>
 class CachedCodeBlock;
@@ -180,27 +180,17 @@ public:
         m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation);
         return result;
     }
-    unsigned addConstant(LinkTimeConstant type)
+    unsigned addConstant(LinkTimeConstant linkTimeConstant)
     {
         VM& vm = this->vm();
         auto locker = lockDuringMarking(vm.heap, cellLock());
         unsigned result = m_constantRegisters.size();
-        ASSERT(result);
-        unsigned index = static_cast<unsigned>(type);
-        ASSERT(index < LinkTimeConstantCount);
-        m_linkTimeConstants[index] = result;
         m_constantRegisters.append(WriteBarrier<Unknown>());
-        m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
+        m_constantRegisters.last().set(vm, this, jsNumber(static_cast<int32_t>(linkTimeConstant)));
+        m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::LinkTimeConstant);
         return result;
     }
 
-    unsigned registerIndexForLinkTimeConstant(LinkTimeConstant type)
-    {
-        unsigned index = static_cast<unsigned>(type);
-        ASSERT(index < LinkTimeConstantCount);
-        return m_linkTimeConstants[index];
-    }
-
     const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
     const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
     ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
@@ -406,8 +396,6 @@ private:
     VirtualRegister m_thisRegister;
     VirtualRegister m_scopeRegister;
 
-    std::array<unsigned, LinkTimeConstantCount> m_linkTimeConstants;
-
     unsigned m_usesEval : 1;
     unsigned m_isStrictMode : 1;
     unsigned m_isConstructor : 1;
index 2db818f..e3831d2 100644 (file)
@@ -50,6 +50,7 @@
 #include "JSImmutableButterfly.h"
 #include "JSLexicalEnvironment.h"
 #include "JSTemplateObjectDescriptor.h"
+#include "LinkTimeConstant.h"
 #include "LowLevelInterpreter.h"
 #include "Options.h"
 #include "PreciseJumpTargetsInlines.h"
@@ -308,9 +309,6 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedP
 {
     ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());
 
-    for (auto& constantRegister : m_linkTimeConstantRegisters)
-        constantRegister = nullptr;
-
     m_codeBlock->setNumParameters(1); // Allocate space for "this"
 
     emitEnter();
@@ -360,9 +358,6 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
     , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction() || functionNode->usesEval())
     , m_derivedContextType(codeBlock->derivedContextType())
 {
-    for (auto& constantRegister : m_linkTimeConstantRegisters)
-        constantRegister = nullptr;
-
     SymbolTable* functionSymbolTable = SymbolTable::create(m_vm);
     functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
     int symbolTableConstantIndex = 0;
@@ -788,11 +783,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
 
         // @rejectPromiseWithFirstResolvingFunctionCallCheck(@promise, thrownValue);
         // return @promise;
-        auto varRejectPromise = variable(propertyNames().builtinNames().rejectPromiseWithFirstResolvingFunctionCallCheckPrivateName());
-        RefPtr<RegisterID> scope = newTemporary();
-        move(scope.get(), emitResolveScope(scope.get(), varRejectPromise));
-        RefPtr<RegisterID> rejectPromise = emitGetFromScope(newTemporary(), scope.get(), varRejectPromise, ThrowIfNotFound);
-
+        RefPtr<RegisterID> rejectPromise = moveLinkTimeConstant(nullptr, LinkTimeConstant::rejectPromiseWithFirstResolvingFunctionCallCheck);
         CallArguments args(*this, nullptr, 2);
         emitLoad(args.thisRegister(), jsUndefined());
         move(args.argumentRegister(0), promiseRegister());
@@ -848,9 +839,6 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod
     , m_needsToUpdateArrowFunctionContext(evalNode->usesArrowFunction() || evalNode->usesEval())
     , m_derivedContextType(codeBlock->derivedContextType())
 {
-    for (auto& constantRegister : m_linkTimeConstantRegisters)
-        constantRegister = nullptr;
-
     m_codeBlock->setNumParameters(1);
 
     pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);
@@ -910,9 +898,6 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod
 {
     ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());
 
-    for (auto& constantRegister : m_linkTimeConstantRegisters)
-        constantRegister = nullptr;
-
     SymbolTable* moduleEnvironmentSymbolTable = SymbolTable::create(m_vm);
     moduleEnvironmentSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
     moduleEnvironmentSymbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope);
@@ -1442,12 +1427,12 @@ void BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label& target)
 
 void BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label& target)
 {
-    OpJneqPtr::emit(this, cond, Special::CallFunction, target.bind(this));
+    OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::callFunction), target.bind(this));
 }
 
 void BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label& target)
 {
-    OpJneqPtr::emit(this, cond, Special::ApplyFunction, target.bind(this));
+    OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::applyFunction), target.bind(this));
 }
 
 bool BytecodeGenerator::hasConstant(const Identifier& ident) const
@@ -1499,17 +1484,15 @@ RegisterID* BytecodeGenerator::addConstantValue(JSValue v, SourceCodeRepresentat
 
 RegisterID* BytecodeGenerator::moveLinkTimeConstant(RegisterID* dst, LinkTimeConstant type)
 {
-    unsigned constantIndex = static_cast<unsigned>(type);
-    if (!m_linkTimeConstantRegisters[constantIndex]) {
+    RegisterID* constant = m_linkTimeConstantRegisters.ensure(type, [&] {
         int index = addConstantIndex();
         m_codeBlock->addConstant(type);
-        m_linkTimeConstantRegisters[constantIndex] = &m_constantPoolRegisters[index];
-    }
-
+        return &m_constantPoolRegisters[index];
+    }).iterator->value;
     if (!dst)
-        return m_linkTimeConstantRegisters[constantIndex];
+        return constant;
 
-    OpMov::emit(this, dst, m_linkTimeConstantRegisters[constantIndex]);
+    OpMov::emit(this, dst, constant);
 
     return dst;
 }
@@ -3101,7 +3084,7 @@ ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst,
         if (callArguments.argumentCountIncludingThis() >= 2)
             return NoExpectedFunction;
         
-        OpJneqPtr::emit(this, func, Special::ObjectConstructor, realCall->bind(this));
+        OpJneqPtr::emit(this, func, moveLinkTimeConstant(nullptr, LinkTimeConstant::Object), realCall->bind(this));
         
         if (dst != ignoredResult())
             emitNewObject(dst);
@@ -3117,7 +3100,7 @@ ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst,
         if (callArguments.argumentCountIncludingThis() > 2)
             return NoExpectedFunction;
         
-        OpJneqPtr::emit(this, func, Special::ArrayConstructor, realCall->bind(this));
+        OpJneqPtr::emit(this, func, moveLinkTimeConstant(nullptr, LinkTimeConstant::Array), realCall->bind(this));
         
         if (dst != ignoredResult()) {
             if (callArguments.argumentCountIncludingThis() == 2)
@@ -3285,7 +3268,7 @@ void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* p
     if (attributes.hasGet() || attributes.hasSet()) {
         RefPtr<RegisterID> throwTypeErrorFunction;
         if (!attributes.hasGet() || !attributes.hasSet())
-            throwTypeErrorFunction = moveLinkTimeConstant(nullptr, LinkTimeConstant::ThrowTypeErrorFunction);
+            throwTypeErrorFunction = moveLinkTimeConstant(nullptr, LinkTimeConstant::throwTypeErrorFunction);
 
         RefPtr<RegisterID> getter;
         if (attributes.hasGet())
@@ -4474,10 +4457,7 @@ RegisterID* BytecodeGenerator::emitGetAsyncIterator(RegisterID* argument, Throwa
 
     RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next);
 
-    auto varCreateAsyncFromSyncIterator = variable(propertyNames().builtinNames().createAsyncFromSyncIteratorPrivateName());
-    RefPtr<RegisterID> scope = newTemporary();
-    move(scope.get(), emitResolveScope(scope.get(), varCreateAsyncFromSyncIterator));
-    RefPtr<RegisterID> createAsyncFromSyncIterator = emitGetFromScope(newTemporary(), scope.get(), varCreateAsyncFromSyncIterator, ThrowIfNotFound);
+    RefPtr<RegisterID> createAsyncFromSyncIterator = moveLinkTimeConstant(nullptr, LinkTimeConstant::createAsyncFromSyncIterator);
 
     CallArguments args(*this, nullptr, 2);
     emitLoad(args.thisRegister(), jsUndefined());
index 2d721eb..862ce12 100644 (file)
@@ -73,6 +73,7 @@ namespace JSC {
 
     enum class DebuggableCall { Yes, No };
     enum class ThisResolutionType { Local, Scoped };
+    enum class LinkTimeConstant : int32_t;
     
     class CallArguments {
     public:
@@ -1216,7 +1217,7 @@ namespace JSC {
         RegisterID* m_emptyValueRegister { nullptr };
         RegisterID* m_newTargetRegister { nullptr };
         RegisterID* m_isDerivedConstuctor { nullptr };
-        RegisterID* m_linkTimeConstantRegisters[LinkTimeConstantCount];
+        HashMap<LinkTimeConstant, RegisterID*, WTF::IntHash<LinkTimeConstant>, WTF::StrongEnumHashTraits<LinkTimeConstant>> m_linkTimeConstantRegisters;
         RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
         RegisterID* m_promiseRegister { nullptr };
 
index 2e03be0..52468e1 100644 (file)
@@ -211,7 +211,7 @@ RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
 
 RegisterID* ImportNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
-    RefPtr<RegisterID> importModule = generator.emitGetGlobalPrivate(generator.newTemporary(), generator.propertyNames().builtinNames().importModulePrivateName());
+    RefPtr<RegisterID> importModule = generator.moveLinkTimeConstant(nullptr, LinkTimeConstant::importModule);
     CallArguments arguments(generator, nullptr, 1);
     generator.emitLoad(arguments.thisRegister(), jsUndefined());
     generator.emitNode(arguments.argumentRegister(0), m_expr);
@@ -985,7 +985,11 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
 
 RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
-    return (this->*m_emitter)(generator, dst);
+    if (m_entry.type() == BytecodeIntrinsicRegistry::Type::Emitter)
+        return (this->*m_entry.emitter())(generator, dst);
+    if (dst == generator.ignoredResult())
+        return nullptr;
+    return generator.moveLinkTimeConstant(dst, m_entry.linkTimeConstant());
 }
 
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getByIdDirect(BytecodeGenerator& generator, RegisterID* dst)
@@ -1013,9 +1017,10 @@ RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getByIdDirectPrivate(BytecodeG
 
 static JSPromise::Field promiseInternalFieldIndex(BytecodeIntrinsicNode* node)
 {
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_promiseFieldFlags)
+    ASSERT(node->entry().type() == BytecodeIntrinsicRegistry::Type::Emitter);
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_promiseFieldFlags)
         return JSPromise::Field::Flags;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_promiseFieldReactionsOrResult)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_promiseFieldReactionsOrResult)
         return JSPromise::Field::ReactionsOrResult;
     RELEASE_ASSERT_NOT_REACHED();
     return JSPromise::Field::Flags;
@@ -1023,13 +1028,14 @@ static JSPromise::Field promiseInternalFieldIndex(BytecodeIntrinsicNode* node)
 
 static JSGenerator::Field generatorInternalFieldIndex(BytecodeIntrinsicNode* node)
 {
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldState)
+    ASSERT(node->entry().type() == BytecodeIntrinsicRegistry::Type::Emitter);
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldState)
         return JSGenerator::Field::State;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldNext)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldNext)
         return JSGenerator::Field::Next;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldThis)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldThis)
         return JSGenerator::Field::This;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldFrame)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldFrame)
         return JSGenerator::Field::Frame;
     RELEASE_ASSERT_NOT_REACHED();
     return JSGenerator::Field::State;
@@ -1037,19 +1043,20 @@ static JSGenerator::Field generatorInternalFieldIndex(BytecodeIntrinsicNode* nod
 
 static JSAsyncGenerator::Field asyncGeneratorInternalFieldIndex(BytecodeIntrinsicNode* node)
 {
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldState)
+    ASSERT(node->entry().type() == BytecodeIntrinsicRegistry::Type::Emitter);
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldState)
         return JSAsyncGenerator::Field::State;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldNext)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldNext)
         return JSAsyncGenerator::Field::Next;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldThis)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldThis)
         return JSAsyncGenerator::Field::This;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldFrame)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldFrame)
         return JSAsyncGenerator::Field::Frame;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldSuspendReason)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldSuspendReason)
         return JSAsyncGenerator::Field::SuspendReason;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldQueueFirst)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldQueueFirst)
         return JSAsyncGenerator::Field::QueueFirst;
-    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldQueueLast)
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldQueueLast)
         return JSAsyncGenerator::Field::QueueLast;
     RELEASE_ASSERT_NOT_REACHED();
     return JSAsyncGenerator::Field::State;
@@ -4096,10 +4103,7 @@ void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
         generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
 
         // load and call @asyncFunctionResume
-        auto var = generator.variable(generator.propertyNames().builtinNames().asyncFunctionResumePrivateName());
-        RefPtr<RegisterID> scope = generator.newTemporary();
-        generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
-        RefPtr<RegisterID> asyncFunctionResume = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
+        RefPtr<RegisterID> asyncFunctionResume = generator.moveLinkTimeConstant(nullptr, LinkTimeConstant::asyncFunctionResume);
 
         CallArguments args(generator, nullptr, 4);
         unsigned argumentCount = 0;
@@ -4578,11 +4582,7 @@ void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs)
     IdentifierSet excludedSet;
     RefPtr<RegisterID> addMethod;
     if (m_containsRestElement && m_containsComputedProperty) {
-        auto var = generator.variable(generator.propertyNames().builtinNames().SetPrivateName());
-
-        RefPtr<RegisterID> scope = generator.newTemporary();
-        generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
-        RefPtr<RegisterID> setConstructor = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
+        RefPtr<RegisterID> setConstructor = generator.moveLinkTimeConstant(nullptr, LinkTimeConstant::Set);
 
         CallArguments args(generator, nullptr, 0);
         excludedList = generator.emitConstruct(generator.newTemporary(), setConstructor.get(), setConstructor.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
@@ -4633,11 +4633,7 @@ void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs)
             RefPtr<RegisterID> newObject = generator.emitNewObject(generator.newTemporary());
             
             // load and call @copyDataProperties
-            auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
-            
-            RefPtr<RegisterID> scope = generator.newTemporary();
-            generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
-            RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
+            RefPtr<RegisterID> copyDataProperties = generator.moveLinkTimeConstant(nullptr, LinkTimeConstant::copyDataProperties);
             
             CallArguments args(generator, nullptr, 3);
             generator.emitLoad(args.thisRegister(), jsUndefined());
@@ -4810,11 +4806,7 @@ RegisterID* ObjectSpreadExpressionNode::emitBytecode(BytecodeGenerator& generato
     generator.emitNode(src.get(), m_expression);
     
     // load and call @copyDataPropertiesNoExclusions
-    auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesNoExclusionsPrivateName());
-    
-    RefPtr<RegisterID> scope = generator.newTemporary();
-    generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
-    RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
+    RefPtr<RegisterID> copyDataProperties = generator.moveLinkTimeConstant(nullptr, LinkTimeConstant::copyDataPropertiesNoExclusions);
     
     CallArguments args(generator, nullptr, 2);
     generator.emitLoad(args.thisRegister(), jsUndefined());
index e0eef49..3378ad0 100644 (file)
@@ -6342,11 +6342,7 @@ void ByteCodeParser::parseBlock(unsigned limit)
             
         case op_jneq_ptr: {
             auto bytecode = currentInstruction->as<OpJneqPtr>();
-            Special::Pointer specialPointer = bytecode.m_specialPointer;
-            ASSERT(pointerIsCell(specialPointer));
-            JSCell* actualPointer = static_cast<JSCell*>(
-                actualPointerFor(m_inlineStackTop->m_codeBlock, specialPointer));
-            FrozenValue* frozenPointer = m_graph.freeze(actualPointer);
+            FrozenValue* frozenPointer = m_graph.freezeStrong(m_inlineStackTop->m_codeBlock->getConstant(bytecode.m_specialPointer.offset()));
             unsigned relativeOffset = jumpTarget(bytecode.m_targetLabel);
             Node* child = get(bytecode.m_value);
             if (bytecode.metadata(codeBlock).m_hasJumped) {
index ca0f126..77e178f 100644 (file)
@@ -139,8 +139,7 @@ const Vector<size_t>& sizeClasses()
             // Manually inject size classes for objects we know will be allocated in high volume.
             // FIXME: All of these things should have IsoSubspaces.
             // https://bugs.webkit.org/show_bug.cgi?id=179876
-            add(sizeof(UnlinkedFunctionCodeBlock));
-            add(sizeof(JSString));
+            add(256);
 
             {
                 // Sort and deduplicate.
index 0d04994..8ebe49f 100644 (file)
@@ -471,11 +471,12 @@ void JIT::emit_op_jneq_ptr(const Instruction* currentInstruction)
     auto bytecode = currentInstruction->as<OpJneqPtr>();
     auto& metadata = bytecode.metadata(m_codeBlock);
     int src = bytecode.m_value.offset();
-    Special::Pointer ptr = bytecode.m_specialPointer;
+    JSValue specialPointer = getConstantOperand(bytecode.m_specialPointer.offset());
+    ASSERT(specialPointer.isCell());
     unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
     
     emitGetVirtualRegister(src, regT0);
-    CCallHelpers::Jump equal = branchPtr(Equal, regT0, TrustedImmPtr(actualPointerFor(m_codeBlock, ptr)));
+    CCallHelpers::Jump equal = branchPtr(Equal, regT0, TrustedImmPtr(specialPointer.asCell()));
     store8(TrustedImm32(1), &metadata.m_hasJumped);
     addJump(jump(), target);
     equal.link(this);
index 3e0ceb4..4e94245 100644 (file)
@@ -478,12 +478,13 @@ void JIT::emit_op_jneq_ptr(const Instruction* currentInstruction)
     auto bytecode = currentInstruction->as<OpJneqPtr>();
     auto& metadata = bytecode.metadata(m_codeBlock);
     int src = bytecode.m_value.offset();
-    Special::Pointer ptr = bytecode.m_specialPointer;
+    JSValue specialPointer = getConstantOperand(bytecode.m_specialPointer.offset());
+    ASSERT(specialPointer.isCell());
     unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
 
     emitLoad(src, regT1, regT0);
     Jump notCell = branchIfNotCell(regT1);
-    Jump equal = branchPtr(Equal, regT0, TrustedImmPtr(actualPointerFor(m_codeBlock, ptr)));
+    Jump equal = branchPtr(Equal, regT0, TrustedImmPtr(specialPointer.asCell()));
     notCell.link(this);
     store8(TrustedImm32(1), &metadata.m_hasJumped);
     addJump(jump(), target);
index 337ee22..d15d967 100644 (file)
@@ -464,6 +464,18 @@ end
 
 # Index, tag, and payload must be different registers. Index is not
 # changed.
+macro loadConstant(size, index, tag, payload)
+    size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide16, FirstConstantRegisterIndexWide32, macro (FirstConstantRegisterIndex)
+        loadp CodeBlock[cfr], payload
+        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
+        subp FirstConstantRegisterIndex, index
+        loadp TagOffset[payload, index, 8], tag
+        loadp PayloadOffset[payload, index, 8], payload
+    end)
+end
+
+# Index, tag, and payload must be different registers. Index is not
+# changed.
 macro loadConstantOrVariable(size, index, tag, payload)
     size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide16, FirstConstantRegisterIndexWide32, macro (FirstConstantRegisterIndex)
         bigteq index, FirstConstantRegisterIndex, .constant
@@ -471,11 +483,7 @@ macro loadConstantOrVariable(size, index, tag, payload)
         loadi PayloadOffset[cfr, index, 8], payload
         jmp .done
     .constant:
-        loadp CodeBlock[cfr], payload
-        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
-        subp FirstConstantRegisterIndex, index
-        loadp TagOffset[payload, index, 8], tag
-        loadp PayloadOffset[payload, index, 8], payload
+        loadConstant(size, index, tag, payload)
     .done:
     end)
 end
@@ -1710,12 +1718,10 @@ undefinedOrNullJumpOp(jnundefined_or_null, OpJnundefinedOrNull,
 
 llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
     get(m_value, t0)
-    getu(size, OpJneqPtr, m_specialPointer, t1)
-    loadp CodeBlock[cfr], t2
-    loadp CodeBlock::m_globalObject[t2], t2
+    get(m_specialPointer, t1)
+    loadConstant(size, t1, t3, t2)
     bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch
-    loadp JSGlobalObject::m_specialPointers[t2, t1, 4], t1
-    bpeq PayloadOffset[cfr, t0, 8], t1, .opJneqPtrFallThrough
+    bpeq PayloadOffset[cfr, t0, 8], t2, .opJneqPtrFallThrough
 .opJneqPtrBranch:
     metadata(t5, t2)
     storeb 1, OpJneqPtr::Metadata::m_hasJumped[t5]
index 0443f0c..95c0f68 100644 (file)
@@ -466,15 +466,37 @@ macro loadVariable(get, fieldName, valueReg)
 end
 
 # Index and value must be different registers. Index may be clobbered.
+macro loadConstant(size, index, value)
+    macro loadNarrow()
+        loadp CodeBlock[cfr], value
+        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
+        loadq -(FirstConstantRegisterIndexNarrow * 8)[value, index, 8], value
+    end
+
+    macro loadWide16()
+        loadp CodeBlock[cfr], value
+        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
+        loadq -(FirstConstantRegisterIndexWide16 * 8)[value, index, 8], value
+    end
+
+    macro loadWide32()
+        loadp CodeBlock[cfr], value
+        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
+        subp FirstConstantRegisterIndexWide32, index
+        loadq [value, index, 8], value
+    end
+
+    size(loadNarrow, loadWide16, loadWide32, macro (load) load() end)
+end
+
+# Index and value must be different registers. Index may be clobbered.
 macro loadConstantOrVariable(size, index, value)
     macro loadNarrow()
         bpgteq index, FirstConstantRegisterIndexNarrow, .constant
         loadq [cfr, index, 8], value
         jmp .done
     .constant:
-        loadp CodeBlock[cfr], value
-        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
-        loadq -(FirstConstantRegisterIndexNarrow * 8)[value, index, 8], value
+        loadConstant(size, index, value)
     .done:
     end
 
@@ -483,9 +505,7 @@ macro loadConstantOrVariable(size, index, value)
         loadq [cfr, index, 8], value
         jmp .done
     .constant:
-        loadp CodeBlock[cfr], value
-        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
-        loadq -(FirstConstantRegisterIndexWide16 * 8)[value, index, 8], value
+        loadConstant(size, index, value)
     .done:
     end
 
@@ -494,10 +514,7 @@ macro loadConstantOrVariable(size, index, value)
         loadq [cfr, index, 8], value
         jmp .done
     .constant:
-        loadp CodeBlock[cfr], value
-        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
-        subp FirstConstantRegisterIndexWide32, index
-        loadq [value, index, 8], value
+        loadConstant(size, index, value)
     .done:
     end
 
@@ -1816,11 +1833,9 @@ undefinedOrNullJumpOp(jnundefined_or_null, OpJnundefinedOrNull,
 
 llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
     get(m_value, t0)
-    getu(size, OpJneqPtr, m_specialPointer, t1)
-    loadp CodeBlock[cfr], t2
-    loadp CodeBlock::m_globalObject[t2], t2
-    loadp JSGlobalObject::m_specialPointers[t2, t1, PtrSize], t1
-    bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
+    get(m_specialPointer, t1)
+    loadConstant(size, t1, t2)
+    bpneq t2, [cfr, t0, 8], .opJneqPtrTarget
     dispatch()
 
 .opJneqPtrTarget:
index caf0308..cc597f5 100644 (file)
@@ -200,8 +200,9 @@ public:
             usesArguments();
 
         if (ident.isSymbol()) {
-            if (BytecodeIntrinsicNode::EmitterType emitter = m_vm.bytecodeIntrinsicRegistry().lookup(ident))
-                return new (m_parserArena) BytecodeIntrinsicNode(BytecodeIntrinsicNode::Type::Constant, location, emitter, ident, nullptr, start, start, end);
+            auto entry = m_vm.bytecodeIntrinsicRegistry().lookup(ident);
+            if (entry)
+                return new (m_parserArena) BytecodeIntrinsicNode(BytecodeIntrinsicNode::Type::Constant, location, entry.value(), ident, nullptr, start, start, end);
         }
 
         return new (m_parserArena) ResolveNode(location, ident, start);
@@ -1384,8 +1385,8 @@ ExpressionNode* ASTBuilder::makeFunctionCallNode(const JSTokenLocation& location
     if (func->isBytecodeIntrinsicNode()) {
         ASSERT(!isOptionalCall);
         BytecodeIntrinsicNode* intrinsic = static_cast<BytecodeIntrinsicNode*>(func);
-        if (intrinsic->type() == BytecodeIntrinsicNode::Type::Constant)
-            return new (m_parserArena) BytecodeIntrinsicNode(BytecodeIntrinsicNode::Type::Function, location, intrinsic->emitter(), intrinsic->identifier(), args, divot, divotStart, divotEnd);
+        if (intrinsic->type() == BytecodeIntrinsicNode::Type::Constant && intrinsic->entry().type() == BytecodeIntrinsicRegistry::Type::Emitter)
+            return new (m_parserArena) BytecodeIntrinsicNode(BytecodeIntrinsicNode::Type::Function, location, intrinsic->entry(), intrinsic->identifier(), args, divot, divotStart, divotEnd);
     }
 
     if (func->isOptionalChain()) {
index 7589d7c..9c7b9a2 100644 (file)
@@ -413,10 +413,10 @@ namespace JSC {
     {
     }
 
-    inline BytecodeIntrinsicNode::BytecodeIntrinsicNode(Type type, const JSTokenLocation& location, EmitterType emitter, const Identifier& ident, ArgumentsNode* args, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+    inline BytecodeIntrinsicNode::BytecodeIntrinsicNode(Type type, const JSTokenLocation& location, BytecodeIntrinsicRegistry::Entry entry, const Identifier& ident, ArgumentsNode* args, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
         : ExpressionNode(location)
         , ThrowableExpressionData(divot, divotStart, divotEnd)
-        , m_emitter(emitter)
+        , m_entry(entry)
         , m_ident(ident)
         , m_args(args)
         , m_type(type)
index aa44866..fad5328 100644 (file)
@@ -944,14 +944,12 @@ namespace JSC {
             Function
         };
 
-        typedef RegisterID* (BytecodeIntrinsicNode::* EmitterType)(BytecodeGenerator&, RegisterID*);
-
-        BytecodeIntrinsicNode(Type, const JSTokenLocation&, EmitterType, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        BytecodeIntrinsicNode(Type, const JSTokenLocation&, BytecodeIntrinsicRegistry::Entry, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
 
         bool isBytecodeIntrinsicNode() const override { return true; }
 
         Type type() const { return m_type; }
-        EmitterType emitter() const { return m_emitter; }
+        BytecodeIntrinsicRegistry::Entry entry() const { return m_entry; }
         const Identifier& identifier() const { return m_ident; }
 
 #define JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS(name) RegisterID* emit_intrinsic_##name(BytecodeGenerator&, RegisterID*);
@@ -964,7 +962,7 @@ namespace JSC {
 
         bool isFunctionCall() const override { return m_type == Type::Function; }
 
-        EmitterType m_emitter;
+        BytecodeIntrinsicRegistry::Entry m_entry;
         const Identifier& m_ident;
         ArgumentsNode* m_args;
         Type m_type;
index 6035a49..eb9d993 100644 (file)
@@ -1801,7 +1801,6 @@ public:
 private:
     VirtualRegister m_thisRegister;
     VirtualRegister m_scopeRegister;
-    std::array<unsigned, LinkTimeConstantCount> m_linkTimeConstants;
 
     unsigned m_usesEval : 1;
     unsigned m_isStrictMode : 1;
@@ -2039,9 +2038,6 @@ ALWAYS_INLINE UnlinkedCodeBlock::UnlinkedCodeBlock(Decoder& decoder, Structure*
 template<typename CodeBlockType>
 ALWAYS_INLINE void CachedCodeBlock<CodeBlockType>::decode(Decoder& decoder, UnlinkedCodeBlock& codeBlock) const
 {
-    for (unsigned i = LinkTimeConstantCount; i--;)
-        codeBlock.m_linkTimeConstants[i] = m_linkTimeConstants[i];
-
     m_constantRegisters.decode(decoder, codeBlock.m_constantRegisters, &codeBlock);
     m_constantsSourceCodeRepresentation.decode(decoder, codeBlock.m_constantsSourceCodeRepresentation);
     m_expressionInfo.decode(decoder, codeBlock.m_expressionInfo);
@@ -2207,9 +2203,6 @@ ALWAYS_INLINE void CachedCodeBlock<CodeBlockType>::encode(Encoder& encoder, cons
     m_codeGenerationMode = codeBlock.m_codeGenerationMode;
     m_codeType = codeBlock.m_codeType;
 
-    for (unsigned i = LinkTimeConstantCount; i--;)
-        m_linkTimeConstants[i] = codeBlock.m_linkTimeConstants[i];
-
     m_metadata.encode(encoder, codeBlock.m_metadata.get());
     m_rareData.encode(encoder, codeBlock.m_rareData.get());
 
index 47fcd33..2599e2c 100644 (file)
@@ -129,7 +129,8 @@ bool isInt52(double);
 enum class SourceCodeRepresentation : uint8_t {
     Other,
     Integer,
-    Double
+    Double,
+    LinkTimeConstant,
 };
 
 class JSValue {
index c65b0b3..b862b4d 100644 (file)
 #include "JSWithScope.h"
 #include "LazyClassStructureInlines.h"
 #include "LazyPropertyInlines.h"
+#include "LinkTimeConstant.h"
 #include "Lookup.h"
 #include "MapConstructor.h"
 #include "MapIteratorPrototype.h"
@@ -411,6 +412,7 @@ static EncodedJSValue JSC_HOST_CALL enqueueJob(JSGlobalObject* globalObject, Cal
 JSGlobalObject::JSGlobalObject(VM& vm, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable)
     : Base(vm, structure, 0)
     , m_vm(&vm)
+    , m_linkTimeConstants(numberOfLinkTimeConstants)
     , m_masqueradesAsUndefinedWatchpoint(adoptRef(new WatchpointSet(IsWatched)))
     , m_havingABadTimeWatchpoint(adoptRef(new WatchpointSet(IsWatched)))
     , m_varInjectionWatchpoint(adoptRef(new WatchpointSet(IsWatched)))
@@ -522,8 +524,6 @@ void JSGlobalObject::init(VM& vm)
     JSFunction* applyFunction = nullptr;
     JSFunction* hasInstanceSymbolFunction = nullptr;
     m_functionPrototype->addFunctionProperties(vm, this, &callFunction, &applyFunction, &hasInstanceSymbolFunction);
-    m_callFunction.set(vm, this, callFunction);
-    m_applyFunction.set(vm, this, applyFunction);
     m_arrayProtoToStringFunction.initLater(
         [] (const Initializer<JSFunction>& init) {
             init.set(JSFunction::create(init.vm, init.owner, 0, init.vm.propertyNames->toString.string(), arrayProtoFuncToString, NoIntrinsic));
@@ -723,7 +723,8 @@ void JSGlobalObject::init(VM& vm)
     m_generatorPrototype.set(vm, this, GeneratorPrototype::create(vm, this, GeneratorPrototype::createStructure(vm, this, m_iteratorPrototype.get())));
     m_asyncGeneratorPrototype.set(vm, this, AsyncGeneratorPrototype::create(vm, this, AsyncGeneratorPrototype::createStructure(vm, this, m_asyncIteratorPrototype.get())));
 
-    m_promiseProtoThenFunction.set(vm, this, JSFunction::create(vm, promisePrototypeThenCodeGenerator(vm), this));
+    JSFunction* defaultPromiseThen = JSFunction::create(vm, promisePrototypeThenCodeGenerator(vm), this);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::defaultPromiseThen)].set(vm, this, defaultPromiseThen);
 
 #define CREATE_PROTOTYPE_FOR_SIMPLE_TYPE(capitalName, lowerName, properName, instanceType, jsName, prototypeBase, featureFlag) if (featureFlag) { \
         m_ ## lowerName ## Prototype.set(vm, this, capitalName##Prototype::create(vm, this, capitalName##Prototype::createStructure(vm, this, m_ ## prototypeBase ## Prototype.get()))); \
@@ -750,18 +751,21 @@ void JSGlobalObject::init(VM& vm)
 
     ObjectConstructor* objectConstructor = ObjectConstructor::create(vm, this, ObjectConstructor::createStructure(vm, this, m_functionPrototype.get()), m_objectPrototype.get());
     m_objectConstructor.set(vm, this, objectConstructor);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::Object)].set(vm, this, objectConstructor);
 
     JSFunction* throwTypeErrorFunction = JSFunction::create(vm, this, 0, String(), globalFuncThrowTypeError);
-    m_throwTypeErrorFunction.set(vm, this, throwTypeErrorFunction);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::throwTypeErrorFunction)].set(vm, this, throwTypeErrorFunction);
 
     FunctionConstructor* functionConstructor = FunctionConstructor::create(vm, FunctionConstructor::createStructure(vm, this, m_functionPrototype.get()), m_functionPrototype.get());
     m_functionConstructor.set(vm, this, functionConstructor);
 
     ArrayConstructor* arrayConstructor = ArrayConstructor::create(vm, this, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get(), m_speciesGetterSetter.get());
     m_arrayConstructor.set(vm, this, arrayConstructor);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::Array)].set(vm, this, arrayConstructor);
     
     RegExpConstructor* regExpConstructor = RegExpConstructor::create(vm, RegExpConstructor::createStructure(vm, this, m_functionPrototype.get()), m_regExpPrototype.get(), m_speciesGetterSetter.get());
     m_regExpConstructor.set(vm, this, regExpConstructor);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::RegExp)].set(vm, this, regExpConstructor);
     m_regExpGlobalData.cachedResult().record(vm, this, nullptr, jsEmptyString(vm), MatchResult(0, 0));
     
 #if ENABLE(SHARED_ARRAY_BUFFER)
@@ -783,6 +787,8 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
 
     m_promiseConstructor.set(vm, this, promiseConstructor);
     m_internalPromiseConstructor.set(vm, this, internalPromiseConstructor);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::Promise)].set(vm, this, promiseConstructor);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::InternalPromise)].set(vm, this, internalPromiseConstructor);
     
     m_evalErrorStructure.initLater(
         [] (LazyClassStructure::Initializer& init) {
@@ -842,9 +848,6 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
     putDirectWithoutTransition(vm, vm.propertyNames->Array, arrayConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->RegExp, regExpConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
 
-    putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().ObjectPrivateName(), objectConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
-    putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().ArrayPrivateName(), arrayConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
-
 #if ENABLE(SHARED_ARRAY_BUFFER)
     putDirectWithoutTransition(vm, vm.propertyNames->SharedArrayBuffer, sharedArrayBufferConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, Identifier::fromString(vm, "Atomics"), atomicsObject, static_cast<unsigned>(PropertyAttribute::DontEnum));
@@ -917,180 +920,226 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
     if (Options::exposeInternalModuleLoader())
         putDirectWithoutTransition(vm, vm.propertyNames->Loader, moduleLoader(), static_cast<unsigned>(PropertyAttribute::DontEnum));
 
-    JSFunction* builtinLog = JSFunction::create(vm, this, 1, vm.propertyNames->emptyIdentifier.string(), globalFuncBuiltinLog);
-    JSFunction* builtinDescribe = JSFunction::create(vm, this, 1, vm.propertyNames->emptyIdentifier.string(), globalFuncBuiltinDescribe);
-
-    JSFunction* privateFuncTrunc = JSFunction::create(vm, this, 0, String(), mathProtoFuncTrunc, TruncIntrinsic);
-
-    JSFunction* privateFuncPropertyIsEnumerable = JSFunction::create(vm, this, 0, String(), globalFuncPropertyIsEnumerable);
-    JSFunction* privateFuncOwnKeys = JSFunction::create(vm, this, 0, String(), globalFuncOwnKeys);
-    JSFunction* privateFuncImportModule = JSFunction::create(vm, this, 0, String(), globalFuncImportModule);
-    JSFunction* privateFuncMakeTypeError = JSFunction::create(vm, this, 0, String(), globalFuncMakeTypeError);
-    JSFunction* privateFuncTypedArrayLength = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncLength);
-    JSFunction* privateFuncTypedArrayGetOriginalConstructor = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncGetOriginalConstructor);
-    JSFunction* privateFuncTypedArraySort = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSort);
-    JSFunction* privateFuncIsTypedArrayView = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncIsTypedArrayView, IsTypedArrayViewIntrinsic);
-    JSFunction* privateFuncTypedArraySubarrayCreate = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSubarrayCreate);
-    JSFunction* privateFuncIsBoundFunction = JSFunction::create(vm, this, 0, String(), isBoundFunction);
-    JSFunction* privateFuncHasInstanceBoundFunction = JSFunction::create(vm, this, 0, String(), hasInstanceBoundFunction);
-    JSFunction* privateFuncInstanceOf = JSFunction::create(vm, this, 0, String(), objectPrivateFuncInstanceOf);
-    JSFunction* privateFuncThisTimeValue = JSFunction::create(vm, this, 0, String(), dateProtoFuncGetTime);
-#if ENABLE(INTL)
-    JSFunction* privateFuncDateTimeFormat = JSFunction::create(vm, this, 0, String(), globalFuncDateTimeFormat);
-#endif
-    JSFunction* privateFuncIsArraySlow = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArraySlow);
-    JSFunction* privateFuncConcatMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncConcatMemcpy);
-    JSFunction* privateFuncAppendMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncAppendMemcpy);
-    JSFunction* privateFuncMapBucketHead = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketHead, JSMapBucketHeadIntrinsic);
-    JSFunction* privateFuncMapBucketNext = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketNext, JSMapBucketNextIntrinsic);
-    JSFunction* privateFuncMapBucketKey = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketKey, JSMapBucketKeyIntrinsic);
-    JSFunction* privateFuncMapBucketValue = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketValue, JSMapBucketValueIntrinsic);
-    JSFunction* privateFuncSetBucketHead = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketHead, JSSetBucketHeadIntrinsic);
-    JSFunction* privateFuncSetBucketNext = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketNext, JSSetBucketNextIntrinsic);
-    JSFunction* privateFuncSetBucketKey = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketKey, JSSetBucketKeyIntrinsic);
-
     GetterSetter* regExpProtoFlagsGetter = getGetterById(this, m_regExpPrototype.get(), vm.propertyNames->flags);
     catchScope.assertNoException();
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpProtoFlagsGetter)].set(vm, this, regExpProtoFlagsGetter);
     GetterSetter* regExpProtoGlobalGetter = getGetterById(this, m_regExpPrototype.get(), vm.propertyNames->global);
     catchScope.assertNoException();
-    m_regExpProtoGlobalGetter.set(vm, this, regExpProtoGlobalGetter);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpProtoGlobalGetter)].set(vm, this, regExpProtoGlobalGetter);
     GetterSetter* regExpProtoIgnoreCaseGetter = getGetterById(this, m_regExpPrototype.get(), vm.propertyNames->ignoreCase);
     catchScope.assertNoException();
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpProtoIgnoreCaseGetter)].set(vm, this, regExpProtoIgnoreCaseGetter);
     GetterSetter* regExpProtoMultilineGetter = getGetterById(this, m_regExpPrototype.get(), vm.propertyNames->multiline);
     catchScope.assertNoException();
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpProtoMultilineGetter)].set(vm, this, regExpProtoMultilineGetter);
     GetterSetter* regExpProtoSourceGetter = getGetterById(this, m_regExpPrototype.get(), vm.propertyNames->source);
     catchScope.assertNoException();
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpProtoSourceGetter)].set(vm, this, regExpProtoSourceGetter);
     GetterSetter* regExpProtoStickyGetter = getGetterById(this, m_regExpPrototype.get(), vm.propertyNames->sticky);
     catchScope.assertNoException();
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpProtoStickyGetter)].set(vm, this, regExpProtoStickyGetter);
     GetterSetter* regExpProtoUnicodeGetter = getGetterById(this, m_regExpPrototype.get(), vm.propertyNames->unicode);
     catchScope.assertNoException();
-    m_regExpProtoUnicodeGetter.set(vm, this, regExpProtoUnicodeGetter);
-    JSObject* builtinRegExpExec = asObject(m_regExpPrototype->getDirect(vm, vm.propertyNames->exec).asCell());
-    m_regExpProtoExec.set(vm, this, builtinRegExpExec);
-    JSObject* regExpSymbolReplace = asObject(m_regExpPrototype->getDirect(vm, vm.propertyNames->replaceSymbol).asCell());
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpProtoUnicodeGetter)].set(vm, this, regExpProtoUnicodeGetter);
+    JSFunction* regExpSymbolReplace = jsCast<JSFunction*>(m_regExpPrototype->getDirect(vm, vm.propertyNames->replaceSymbol));
     m_regExpProtoSymbolReplace.set(vm, this, regExpSymbolReplace);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpBuiltinExec)].set(vm, this, jsCast<JSFunction*>(m_regExpPrototype->getDirect(vm, vm.propertyNames->exec)));
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpPrototypeSymbolReplace)].set(vm, this, m_regExpPrototype->getDirect(vm, vm.propertyNames->replaceSymbol).asCell());
+
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::Set)].set(vm, this, setConstructor);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::isArray)].set(vm, this, arrayConstructor->getDirect(vm, vm.propertyNames->isArray).asCell());
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::callFunction)].set(vm, this, callFunction);
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::applyFunction)].set(vm, this, applyFunction);
+
+#define INIT_PRIVATE_GLOBAL(funcName, code) \
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::funcName)].initLater([] (const Initializer<JSCell>& init) { \
+            JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner); \
+            init.set(JSFunction::create(init.vm, code ## CodeGenerator(init.vm), globalObject)); \
+        });
+    JSC_FOREACH_BUILTIN_FUNCTION_PRIVATE_GLOBAL_NAME(INIT_PRIVATE_GLOBAL)
+#undef INIT_PRIVATE_GLOBAL
 
-#define CREATE_PRIVATE_GLOBAL_FUNCTION(varName, funcName, code) JSFunction* varName ## PrivateFunction = JSFunction::create(vm, code ## CodeGenerator(vm), this);
-    JSC_FOREACH_BUILTIN_FUNCTION_PRIVATE_GLOBAL_NAME(CREATE_PRIVATE_GLOBAL_FUNCTION)
-#undef CREATE_PRIVATE_GLOBAL_FUNCTION
-
+    // FIXME: Initializing them lazily.
+    // https://bugs.webkit.org/show_bug.cgi?id=203795
     JSObject* arrayIteratorPrototype = ArrayIteratorPrototype::create(vm, this, ArrayIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
-    arrayIteratorConstructorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, arrayIteratorPrototype);
+    jsCast<JSObject*>(linkTimeConstant(LinkTimeConstant::ArrayIterator))->putDirect(vm, vm.propertyNames->prototype, arrayIteratorPrototype);
 
     JSObject* asyncFromSyncIteratorPrototype = AsyncFromSyncIteratorPrototype::create(vm, this, AsyncFromSyncIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
-    asyncFromSyncIteratorConstructorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, asyncFromSyncIteratorPrototype);
+    jsCast<JSObject*>(linkTimeConstant(LinkTimeConstant::AsyncFromSyncIterator))->putDirect(vm, vm.propertyNames->prototype, asyncFromSyncIteratorPrototype);
 
     JSObject* mapIteratorPrototype = MapIteratorPrototype::create(vm, this, MapIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
-    mapIteratorConstructorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, mapIteratorPrototype);
+    jsCast<JSObject*>(linkTimeConstant(LinkTimeConstant::MapIterator))->putDirect(vm, vm.propertyNames->prototype, mapIteratorPrototype);
 
     JSObject* regExpStringIteratorPrototype = RegExpStringIteratorPrototype::create(vm, this, RegExpStringIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
-    regExpStringIteratorConstructorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, regExpStringIteratorPrototype);
+    jsCast<JSObject*>(linkTimeConstant(LinkTimeConstant::RegExpStringIterator))->putDirect(vm, vm.propertyNames->prototype, regExpStringIteratorPrototype);
 
     JSObject* setIteratorPrototype = SetIteratorPrototype::create(vm, this, SetIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
-    setIteratorConstructorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, setIteratorPrototype);
+    jsCast<JSObject*>(linkTimeConstant(LinkTimeConstant::SetIterator))->putDirect(vm, vm.propertyNames->prototype, setIteratorPrototype);
 
-    m_newPromiseCapabilityFunction.set(vm, this, newPromiseCapabilityPrivateFunction);
-    m_resolvePromiseFunction.set(vm, this, resolvePromisePrivateFunction);
-    m_rejectPromiseFunction.set(vm, this, rejectPromisePrivateFunction);
+    // Map and Set helpers.
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::mapBucketHead)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), mapPrivateFuncMapBucketHead, JSMapBucketHeadIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::mapBucketNext)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), mapPrivateFuncMapBucketNext, JSMapBucketNextIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::mapBucketKey)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), mapPrivateFuncMapBucketKey, JSMapBucketKeyIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::mapBucketValue)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), mapPrivateFuncMapBucketValue, JSMapBucketValueIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::setBucketHead)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), setPrivateFuncSetBucketHead, JSSetBucketHeadIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::setBucketNext)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), setPrivateFuncSetBucketNext, JSSetBucketNextIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::setBucketKey)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), setPrivateFuncSetBucketKey, JSSetBucketKeyIntrinsic));
+        });
+
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::importModule)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), globalFuncImportModule));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::propertyIsEnumerable)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), globalFuncPropertyIsEnumerable));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::ownKeys)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), globalFuncOwnKeys));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::enqueueJob)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, "enqueueJob"_s, enqueueJob));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::makeTypeError)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), globalFuncMakeTypeError));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::typedArrayLength)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), typedArrayViewPrivateFuncLength));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::typedArrayGetOriginalConstructor)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), typedArrayViewPrivateFuncGetOriginalConstructor));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::typedArraySort)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), typedArrayViewPrivateFuncSort));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::isTypedArrayView)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), typedArrayViewPrivateFuncIsTypedArrayView, IsTypedArrayViewIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::typedArraySubarrayCreate)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), typedArrayViewPrivateFuncSubarrayCreate));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::isBoundFunction)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), isBoundFunction));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::hasInstanceBoundFunction)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), hasInstanceBoundFunction));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::instanceOf)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), objectPrivateFuncInstanceOf));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::BuiltinLog)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), globalFuncBuiltinLog));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::BuiltinDescribe)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), globalFuncBuiltinDescribe));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::trunc)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), mathProtoFuncTrunc, TruncIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::repeatCharacter)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), stringProtoFuncRepeatCharacter));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::arraySpeciesCreate)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), arrayProtoFuncSpeciesCreate));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::isArraySlow)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), arrayConstructorPrivateFuncIsArraySlow));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::concatMemcpy)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), arrayProtoPrivateFuncConcatMemcpy));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::appendMemcpy)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), arrayProtoPrivateFuncAppendMemcpy));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::hostPromiseRejectionTracker)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), globalFuncHostPromiseRejectionTracker));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::InspectorInstrumentation)].initLater([] (const Initializer<JSCell>& init) {
+            JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner);
+            init.set(InspectorInstrumentationObject::create(init.vm, globalObject, InspectorInstrumentationObject::createStructure(init.vm, globalObject, globalObject->m_objectPrototype.get())));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::thisTimeValue)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), dateProtoFuncGetTime, DatePrototypeGetTimeIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::isConstructor)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), esSpecIsConstructor, NoIntrinsic));
+        });
+
+    // RegExp.prototype helpers.
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpCreate)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), esSpecRegExpCreate, NoIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::isRegExp)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), esSpecIsRegExp, NoIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpMatchFast)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), regExpProtoFuncMatchFast, RegExpMatchFastIntrinsic));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpSearchFast)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), regExpProtoFuncSearchFast));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpSplitFast)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), regExpProtoFuncSplitFast));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpTestFast)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), regExpProtoFuncTestFast, RegExpTestFastIntrinsic));
+        });
+
+    // String.prototype helpers.
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::stringIncludesInternal)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), builtinStringIncludesInternal));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::stringSplitFast)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), stringProtoFuncSplitFast));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::stringSubstrInternal)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), builtinStringSubstrInternal));
+        });
+
+    // Function prototype helpers.
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::makeBoundFunction)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 5, String(), makeBoundFunction));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::hasOwnLengthProperty)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), hasOwnLengthProperty));
+        });
 
-    GlobalPropertyInfo staticGlobals[] = {
-#define INIT_PRIVATE_GLOBAL(varName, funcName, code) GlobalPropertyInfo(vm.propertyNames->builtinNames().funcName ## PrivateName(), varName ## PrivateFunction, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        JSC_FOREACH_BUILTIN_FUNCTION_PRIVATE_GLOBAL_NAME(INIT_PRIVATE_GLOBAL)
-#undef INIT_PRIVATE_GLOBAL
-        GlobalPropertyInfo(vm.propertyNames->NaN, jsNaN(), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->Infinity, jsNumber(std::numeric_limits<double>::infinity()), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->undefinedKeyword, jsUndefined(), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().propertyIsEnumerablePrivateName(), privateFuncPropertyIsEnumerable, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().ownKeysPrivateName(), privateFuncOwnKeys, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().importModulePrivateName(), privateFuncImportModule, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().enqueueJobPrivateName(), JSFunction::create(vm, this, 0, "enqueueJob"_s, enqueueJob), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().makeTypeErrorPrivateName(), privateFuncMakeTypeError, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArrayLengthPrivateName(), privateFuncTypedArrayLength, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArrayGetOriginalConstructorPrivateName(), privateFuncTypedArrayGetOriginalConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArraySortPrivateName(), privateFuncTypedArraySort, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().isTypedArrayViewPrivateName(), privateFuncIsTypedArrayView, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArraySubarrayCreatePrivateName(), privateFuncTypedArraySubarrayCreate, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().isBoundFunctionPrivateName(), privateFuncIsBoundFunction, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().hasInstanceBoundFunctionPrivateName(), privateFuncHasInstanceBoundFunction, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().instanceOfPrivateName(), privateFuncInstanceOf, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().BuiltinLogPrivateName(), builtinLog, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().BuiltinDescribePrivateName(), builtinDescribe, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().RegExpPrivateName(), regExpConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().truncPrivateName(), privateFuncTrunc, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().PromisePrivateName(), promiseConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().InternalPromisePrivateName(), internalPromiseConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().defaultPromiseThenPrivateName(), promiseProtoThenFunction(), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().repeatCharacterPrivateName(), JSFunction::create(vm, this, 2, String(), stringProtoFuncRepeatCharacter), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().arraySpeciesCreatePrivateName(), JSFunction::create(vm, this, 2, String(), arrayProtoFuncSpeciesCreate), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().isArrayPrivateName(), arrayConstructor->getDirect(vm, vm.propertyNames->isArray), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().isArraySlowPrivateName(), privateFuncIsArraySlow, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().concatMemcpyPrivateName(), privateFuncConcatMemcpy, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().appendMemcpyPrivateName(), privateFuncAppendMemcpy, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().hostPromiseRejectionTrackerPrivateName(), JSFunction::create(vm, this, 2, String(), globalFuncHostPromiseRejectionTracker), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().InspectorInstrumentationPrivateName(), InspectorInstrumentationObject::create(vm, this, InspectorInstrumentationObject::createStructure(vm, this, m_objectPrototype.get())), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().SetPrivateName(), setConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().thisTimeValuePrivateName(), privateFuncThisTimeValue, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
 #if ENABLE(INTL)
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().dateTimeFormatPrivateName(), privateFuncDateTimeFormat, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::dateTimeFormat)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), globalFuncDateTimeFormat));
+        });
 #endif // ENABLE(INTL)
-
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().isConstructorPrivateName(), JSFunction::create(vm, this, 1, String(), esSpecIsConstructor, NoIntrinsic), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpProtoFlagsGetterPrivateName(), regExpProtoFlagsGetter, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpProtoGlobalGetterPrivateName(), regExpProtoGlobalGetter, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpProtoIgnoreCaseGetterPrivateName(), regExpProtoIgnoreCaseGetter, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpProtoMultilineGetterPrivateName(), regExpProtoMultilineGetter, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpProtoSourceGetterPrivateName(), regExpProtoSourceGetter, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpProtoStickyGetterPrivateName(), regExpProtoStickyGetter, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpProtoUnicodeGetterPrivateName(), regExpProtoUnicodeGetter, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-
-        // RegExp.prototype helpers.
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpBuiltinExecPrivateName(), builtinRegExpExec, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpCreatePrivateName(), JSFunction::create(vm, this, 2, String(), esSpecRegExpCreate, NoIntrinsic), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().isRegExpPrivateName(), JSFunction::create(vm, this, 1, String(), esSpecIsRegExp, NoIntrinsic), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpMatchFastPrivateName(), JSFunction::create(vm, this, 1, String(), regExpProtoFuncMatchFast, RegExpMatchFastIntrinsic), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpSearchFastPrivateName(), JSFunction::create(vm, this, 1, String(), regExpProtoFuncSearchFast), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpSplitFastPrivateName(), JSFunction::create(vm, this, 2, String(), regExpProtoFuncSplitFast), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpPrototypeSymbolReplacePrivateName(), m_regExpPrototype->getDirect(vm, vm.propertyNames->replaceSymbol), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpTestFastPrivateName(), JSFunction::create(vm, this, 1, String(), regExpProtoFuncTestFast, RegExpTestFastIntrinsic), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-
-        // String.prototype helpers.
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().stringIncludesInternalPrivateName(), JSFunction::create(vm, this, 1, String(), builtinStringIncludesInternal), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().stringSplitFastPrivateName(), JSFunction::create(vm, this, 2, String(), stringProtoFuncSplitFast), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().stringSubstrInternalPrivateName(), JSFunction::create(vm, this, 2, String(), builtinStringSubstrInternal), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-
-        // Function prototype helpers.
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().makeBoundFunctionPrivateName(), JSFunction::create(vm, this, 5, String(), makeBoundFunction), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().hasOwnLengthPropertyPrivateName(), JSFunction::create(vm, this, 1, String(), hasOwnLengthProperty), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-
-        // Map and Set helpers.
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketHeadPrivateName(), privateFuncMapBucketHead, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketNextPrivateName(), privateFuncMapBucketNext, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketKeyPrivateName(), privateFuncMapBucketKey, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketValuePrivateName(), privateFuncMapBucketValue, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketHeadPrivateName(), privateFuncSetBucketHead, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketNextPrivateName(), privateFuncSetBucketNext, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketKeyPrivateName(), privateFuncSetBucketKey, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
 #if ENABLE(WEBASSEMBLY) && ENABLE(WEBASSEMBLY_STREAMING_API)
-        // WebAssembly Streaming API
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().webAssemblyCompileStreamingInternalPrivateName(), JSFunction::create(vm, this, 1, String(), webAssemblyCompileStreamingInternal), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->builtinNames().webAssemblyInstantiateStreamingInternalPrivateName(), JSFunction::create(vm, this, 1, String(), webAssemblyInstantiateStreamingInternal), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
+    // WebAssembly Streaming API
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::webAssemblyCompileStreamingInternal)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), webAssemblyCompileStreamingInternal));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::webAssemblyInstantiateStreamingInternal)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 1, String(), webAssemblyInstantiateStreamingInternal));
+        });
 #endif
+
+    GlobalPropertyInfo staticGlobals[] = {
+        GlobalPropertyInfo(vm.propertyNames->NaN, jsNaN(), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->Infinity, jsNumber(std::numeric_limits<double>::infinity()), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->undefinedKeyword, jsUndefined(), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
 #if !ASSERT_DISABLED
         GlobalPropertyInfo(vm.propertyNames->builtinNames().assertPrivateName(), JSFunction::create(vm, this, 1, String(), assertCall), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
 #endif
     };
     addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
     
-    m_specialPointers[Special::CallFunction] = m_callFunction.get();
-    m_specialPointers[Special::ApplyFunction] = m_applyFunction.get();
-    m_specialPointers[Special::ObjectConstructor] = objectConstructor;
-    m_specialPointers[Special::ArrayConstructor] = arrayConstructor;
-
-    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::ThrowTypeErrorFunction)] = m_throwTypeErrorFunction.get();
-
     if (UNLIKELY(Options::useDollarVM()))
         exposeDollarVM(vm);
 
@@ -1711,22 +1760,16 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 
     thisObject->m_parseIntFunction.visit(visitor);
     thisObject->m_parseFloatFunction.visit(visitor);
-    visitor.append(thisObject->m_callFunction);
-    visitor.append(thisObject->m_applyFunction);
-    visitor.append(thisObject->m_throwTypeErrorFunction);
     thisObject->m_arrayProtoToStringFunction.visit(visitor);
     thisObject->m_arrayProtoValuesFunction.visit(visitor);
     thisObject->m_evalFunction.visit(visitor);
     thisObject->m_iteratorProtocolFunction.visit(visitor);
     thisObject->m_promiseResolveFunction.visit(visitor);
-    visitor.append(thisObject->m_newPromiseCapabilityFunction);
-    visitor.append(thisObject->m_resolvePromiseFunction);
-    visitor.append(thisObject->m_rejectPromiseFunction);
-    visitor.append(thisObject->m_promiseProtoThenFunction);
     visitor.append(thisObject->m_objectProtoValueOfFunction);
     visitor.append(thisObject->m_numberProtoToStringFunction);
     visitor.append(thisObject->m_functionProtoHasInstanceSymbolFunction);
     thisObject->m_throwTypeErrorGetterSetter.visit(visitor);
+    visitor.append(thisObject->m_regExpProtoSymbolReplace);
     visitor.append(thisObject->m_throwTypeErrorArgumentsCalleeAndCallerGetterSetter);
     thisObject->m_moduleLoader.visit(visitor);
 
@@ -1794,6 +1837,9 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     thisObject->m_proxyObjectStructure.visit(visitor);
     thisObject->m_callableProxyObjectStructure.visit(visitor);
     thisObject->m_proxyRevokeStructure.visit(visitor);
+
+    for (auto& property : thisObject->m_linkTimeConstants)
+        property.visit(visitor);
     
 #if ENABLE(SHARED_ARRAY_BUFFER)
     visitor.append(thisObject->m_sharedArrayBufferPrototype);
index 8926aaa..ff1e1b2 100644 (file)
@@ -42,7 +42,6 @@
 #include "ParserModes.h"
 #include "RegExpGlobalData.h"
 #include "RuntimeFlags.h"
-#include "SpecialPointer.h"
 #include "StringPrototype.h"
 #include "SymbolPrototype.h"
 #include "VM.h"
@@ -119,6 +118,7 @@ class UnlinkedModuleProgramCodeBlock;
 class VariableEnvironment;
 struct ActivationStackNode;
 struct HashTable;
+enum class LinkTimeConstant : int32_t;
 
 #ifdef JSC_GLIB_API_ENABLED
 class WrapperMap;
@@ -297,26 +297,16 @@ public:
     LazyProperty<JSGlobalObject, JSFunction> m_parseIntFunction;
     LazyProperty<JSGlobalObject, JSFunction> m_parseFloatFunction;
 
-    WriteBarrier<JSFunction> m_callFunction;
-    WriteBarrier<JSFunction> m_applyFunction;
-    WriteBarrier<JSFunction> m_throwTypeErrorFunction;
     LazyProperty<JSGlobalObject, JSFunction> m_arrayProtoToStringFunction;
     LazyProperty<JSGlobalObject, JSFunction> m_arrayProtoValuesFunction;
     LazyProperty<JSGlobalObject, JSFunction> m_evalFunction;
     LazyProperty<JSGlobalObject, JSFunction> m_iteratorProtocolFunction;
     LazyProperty<JSGlobalObject, JSFunction> m_promiseResolveFunction;
-    WriteBarrier<JSFunction> m_newPromiseCapabilityFunction;
-    WriteBarrier<JSFunction> m_resolvePromiseFunction;
-    WriteBarrier<JSFunction> m_rejectPromiseFunction;
-    WriteBarrier<JSFunction> m_promiseProtoThenFunction;
     WriteBarrier<JSFunction> m_objectProtoValueOfFunction;
     WriteBarrier<JSFunction> m_numberProtoToStringFunction;
     WriteBarrier<JSFunction> m_functionProtoHasInstanceSymbolFunction;
     LazyProperty<JSGlobalObject, GetterSetter> m_throwTypeErrorGetterSetter;
-    WriteBarrier<JSObject> m_regExpProtoExec;
     WriteBarrier<JSObject> m_regExpProtoSymbolReplace;
-    WriteBarrier<GetterSetter> m_regExpProtoGlobalGetter;
-    WriteBarrier<GetterSetter> m_regExpProtoUnicodeGetter;
     WriteBarrier<GetterSetter> m_throwTypeErrorArgumentsCalleeAndCallerGetterSetter;
 
     LazyProperty<JSGlobalObject, JSModuleLoader> m_moduleLoader;
@@ -430,8 +420,7 @@ public:
     FOR_EACH_TYPED_ARRAY_TYPE(DECLARE_TYPED_ARRAY_TYPE_STRUCTURE)
 #undef DECLARE_TYPED_ARRAY_TYPE_STRUCTURE
 
-    JSCell* m_specialPointers[Special::TableSize]; // Special pointers used by the LLInt and JIT.
-    JSCell* m_linkTimeConstants[LinkTimeConstantCount];
+    Vector<LazyProperty<JSGlobalObject, JSCell>> m_linkTimeConstants;
 
     String m_name;
 
@@ -616,24 +605,22 @@ public:
     JSFunction* parseFloatFunction() const { return m_parseFloatFunction.get(this); }
 
     JSFunction* evalFunction() const { return m_evalFunction.get(this); }
-    JSFunction* callFunction() const { return m_callFunction.get(); }
-    JSFunction* applyFunction() const { return m_applyFunction.get(); }
-    JSFunction* throwTypeErrorFunction() const { return m_throwTypeErrorFunction.get(); }
+    JSFunction* throwTypeErrorFunction() const;
     JSFunction* arrayProtoToStringFunction() const { return m_arrayProtoToStringFunction.get(this); }
     JSFunction* arrayProtoValuesFunction() const { return m_arrayProtoValuesFunction.get(this); }
     JSFunction* iteratorProtocolFunction() const { return m_iteratorProtocolFunction.get(this); }
-    JSFunction* newPromiseCapabilityFunction() const { return m_newPromiseCapabilityFunction.get(); }
+    JSFunction* newPromiseCapabilityFunction() const;
     JSFunction* promiseResolveFunction() const { return m_promiseResolveFunction.get(this); }
-    JSFunction* resolvePromiseFunction() const { return m_resolvePromiseFunction.get(); }
-    JSFunction* rejectPromiseFunction() const { return m_rejectPromiseFunction.get(); }
-    JSFunction* promiseProtoThenFunction() const { return m_promiseProtoThenFunction.get(); }
+    JSFunction* resolvePromiseFunction() const;
+    JSFunction* rejectPromiseFunction() const;
+    JSFunction* promiseProtoThenFunction() const;
     JSFunction* objectProtoValueOfFunction() const { return m_objectProtoValueOfFunction.get(); }
     JSFunction* numberProtoToStringFunction() const { return m_numberProtoToStringFunction.get(); }
     JSFunction* functionProtoHasInstanceSymbolFunction() const { return m_functionProtoHasInstanceSymbolFunction.get(); }
-    JSObject* regExpProtoExecFunction() const { return m_regExpProtoExec.get(); }
+    JSFunction* regExpProtoExecFunction() const;
     JSObject* regExpProtoSymbolReplaceFunction() const { return m_regExpProtoSymbolReplace.get(); }
-    GetterSetter* regExpProtoGlobalGetter() const { return m_regExpProtoGlobalGetter.get(); }
-    GetterSetter* regExpProtoUnicodeGetter() const { return m_regExpProtoUnicodeGetter.get(); }
+    GetterSetter* regExpProtoGlobalGetter() const;
+    GetterSetter* regExpProtoUnicodeGetter() const;
     GetterSetter* throwTypeErrorArgumentsCalleeAndCallerGetterSetter()
     {
         return m_throwTypeErrorArgumentsCalleeAndCallerGetterSetter.get();
@@ -911,16 +898,11 @@ public:
         return lazyTypedArrayStructure(type).constructor(this);
     }
 
-    JSCell* actualPointerFor(Special::Pointer pointer)
+    JSCell* linkTimeConstant(LinkTimeConstant value) const
     {
-        ASSERT(pointer < Special::TableSize);
-        return m_specialPointers[pointer];
-    }
-    JSCell* jsCellForLinkTimeConstant(LinkTimeConstant type)
-    {
-        unsigned index = static_cast<unsigned>(type);
-        ASSERT(index < LinkTimeConstantCount);
-        return m_linkTimeConstants[index];
+        JSCell* result = m_linkTimeConstants[static_cast<unsigned>(value)].getInitializedOnMainThread(this);
+        ASSERT(result);
+        return result;
     }
 
     WatchpointSet* masqueradesAsUndefinedWatchpoint() { return m_masqueradesAsUndefinedWatchpoint.get(); }
index e0369be..aaaddf7 100644 (file)
@@ -29,6 +29,8 @@
 
 #include "ArrayConstructor.h"
 #include "ArrayPrototype.h"
+#include "JSFunction.h"
+#include "LinkTimeConstant.h"
 #include "ObjectPrototype.h"
 
 namespace JSC {
@@ -102,6 +104,15 @@ ALWAYS_INLINE Structure* JSGlobalObject::arrayStructureForIndexingTypeDuringAllo
     return InternalFunction::createSubclassStructure(globalObject, globalObject->arrayConstructor(), newTarget, arrayStructureForIndexingTypeDuringAllocation(indexingType));
 }
 
+inline JSFunction* JSGlobalObject::throwTypeErrorFunction() const { return jsCast<JSFunction*>(linkTimeConstant(LinkTimeConstant::throwTypeErrorFunction)); }
+inline JSFunction* JSGlobalObject::newPromiseCapabilityFunction() const { return jsCast<JSFunction*>(linkTimeConstant(LinkTimeConstant::newPromiseCapability)); }
+inline JSFunction* JSGlobalObject::resolvePromiseFunction() const { return jsCast<JSFunction*>(linkTimeConstant(LinkTimeConstant::resolvePromise)); }
+inline JSFunction* JSGlobalObject::rejectPromiseFunction() const { return jsCast<JSFunction*>(linkTimeConstant(LinkTimeConstant::rejectPromise)); }
+inline JSFunction* JSGlobalObject::promiseProtoThenFunction() const { return jsCast<JSFunction*>(linkTimeConstant(LinkTimeConstant::defaultPromiseThen)); }
+inline JSFunction* JSGlobalObject::regExpProtoExecFunction() const { return jsCast<JSFunction*>(linkTimeConstant(LinkTimeConstant::regExpBuiltinExec)); }
+inline GetterSetter* JSGlobalObject::regExpProtoGlobalGetter() const { return bitwise_cast<GetterSetter*>(linkTimeConstant(LinkTimeConstant::regExpProtoGlobalGetter)); }
+inline GetterSetter* JSGlobalObject::regExpProtoUnicodeGetter() const { return bitwise_cast<GetterSetter*>(linkTimeConstant(LinkTimeConstant::regExpProtoUnicodeGetter)); }
+
 ALWAYS_INLINE VM& getVM(JSGlobalObject* globalObject)
 {
     return globalObject->vm();