WebKit Bugzilla
Attachment 346673 Details for
Bug 187373
: New bytecode format for JSC
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-187373-20180806222352.patch (text/plain), 273.85 KB, created by
Tadeu Zagallo
on 2018-08-06 18:24:38 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Tadeu Zagallo
Created:
2018-08-06 18:24:38 PDT
Size:
273.85 KB
patch
obsolete
>Subversion Revision: 234092 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index ef79ffda4221f29db15ccadf6d983a72b0d87a86..ec2e4fef865dc31a635711d09568bbe54b4caddd 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,25 @@ >+2018-07-05 Tadeu Zagallo <tzagallo@apple.com> >+ >+ New bytecode format for JSC >+ https://bugs.webkit.org/show_bug.cgi?id=187373 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Work in progress for the new bytecode format. For now, there's just a >+ handful of docs that I've experimenting with as to how should we >+ declare the opcodes, how should we generate the code and what the >+ generated code should look like. >+ >+ * wip_bytecode/README.md: Briefly documents the goals of for the new >+ bytecode and how it's going work. Still missing a lot of info though. >+ * wip_bytecode/bytecode_generator.rb: Some hacky ruby that I'm >+ considering using for the generating the C++ code for the opcodes >+ * wip_bytecode/bytecode_structs.cpp: Some hacky C++ experiments of >+ what could/should the API for the generated opcodes look like. >+ * wip_bytecode/opcodes.yaml: A list of all the opcodes, with names and >+ types for its arguments and metadata. No idea why it ended up being a >+ yaml file, but if all is well I'll migrate it to the ruby syntax above. >+ > 2018-07-22 Yusuke Suzuki <utatane.tea@gmail.com> > > [JSC] GetByIdVariant and InByIdVariant do not need slot base if they are not "hit" variants >diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt >index 3691cf274ed190e3a2f7763bd807162f736c7bda..a39528c5a20ea6f255a18d71bc3a03533102ad82 100644 >--- a/Source/JavaScriptCore/CMakeLists.txt >+++ b/Source/JavaScriptCore/CMakeLists.txt >@@ -200,11 +200,29 @@ set(OFFLINE_ASM > offlineasm/x86.rb > ) > >+set(GENERATOR >+ generator/Argument.rb >+ generator/Assertion.rb >+ generator/DSL.rb >+ generator/Fits.rb >+ generator/GeneratedFile.rb >+ generator/Implementation.rb >+ generator/Interface.rb >+ generator/Metadata.rb >+ generator/Opcode.rb >+ generator/OpcodeGroup.rb >+ generator/Options.rb >+ generator/Section.rb >+ generator/Template.rb >+ generator/Type.rb >+ generator/main.rb >+) >+ > add_custom_command( > OUTPUT ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/Bytecodes.h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InitBytecodes.asm ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/BytecodeStructs.h >- MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/generate-bytecode-files >- DEPENDS ${JAVASCRIPTCORE_DIR}/generate-bytecode-files bytecode/BytecodeList.json >- COMMAND ${PYTHON_EXECUTABLE} ${JAVASCRIPTCORE_DIR}/generate-bytecode-files --bytecodes_h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/Bytecodes.h --init_bytecodes_asm ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InitBytecodes.asm --bytecode_structs_h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/BytecodeStructs.h ${JAVASCRIPTCORE_DIR}/bytecode/BytecodeList.json >+ MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/generator/main.rb >+ DEPENDS ${GENERATOR} bytecode/BytecodeList.rb >+ COMMAND ${RUBY_EXECUTABLE} ${JAVASCRIPTCORE_DIR}/generator/main.rb --bytecodes_h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/Bytecodes.h --init_bytecodes_asm ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InitBytecodes.asm --bytecode_structs_h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/BytecodeStructs.h ${JAVASCRIPTCORE_DIR}/bytecode/BytecodeList.rb > VERBATIM) > > list(APPEND JavaScriptCore_HEADERS >diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make >index d95cac50b5d6f567a8aeb87d5e390c8d88ff910f..1b161fe56f3ba78767772a9731aea8025e3b2055 100644 >--- a/Source/JavaScriptCore/DerivedSources.make >+++ b/Source/JavaScriptCore/DerivedSources.make >@@ -215,14 +215,8 @@ udis86_itab.h: $(JavaScriptCore)/disassembler/udis86/ud_itab.py $(JavaScriptCore > > # Bytecode files > >-Bytecodes.h: $(JavaScriptCore)/generate-bytecode-files $(JavaScriptCore)/bytecode/BytecodeList.json >- $(PYTHON) $(JavaScriptCore)/generate-bytecode-files --bytecodes_h Bytecodes.h $(JavaScriptCore)/bytecode/BytecodeList.json >- >-BytecodeStructs.h: $(JavaScriptCore)/generate-bytecode-files $(JavaScriptCore)/bytecode/BytecodeList.json >- $(PYTHON) $(JavaScriptCore)/generate-bytecode-files --bytecode_structs_h BytecodeStructs.h $(JavaScriptCore)/bytecode/BytecodeList.json >- >-InitBytecodes.asm: $(JavaScriptCore)/generate-bytecode-files $(JavaScriptCore)/bytecode/BytecodeList.json >- $(PYTHON) $(JavaScriptCore)/generate-bytecode-files --init_bytecodes_asm InitBytecodes.asm $(JavaScriptCore)/bytecode/BytecodeList.json >+Bytecodes.h BytecodeStructs.h InitBytecodes.asm: $(wildcard $(JavaScriptCore)/generator/*.rb) $(JavaScriptCore)/bytecode/BytecodeList.rb >+ $(RUBY) $(JavaScriptCore)/generator/main.rb $(JavaScriptCore)/bytecode/BytecodeList.rb --bytecode_structs_h BytecodeStructs.h --init_bytecodes_asm InitBytecodes.asm --bytecodes_h Bytecodes.h > > # Inspector interfaces > >diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >index 325df6e9eba0c8e84d216e81058c9810d5b310ca..91b351af49e2f2dbc58145d47a62303146f73d00 100644 >--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >@@ -1235,7 +1235,6 @@ > 969A072B0ED1CE6900F1F681 /* RegisterID.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07280ED1CE6900F1F681 /* RegisterID.h */; }; > 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07910ED1D3AE00F1F681 /* CodeBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 969A07980ED1D3AE00F1F681 /* DirectEvalCodeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07920ED1D3AE00F1F681 /* DirectEvalCodeCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07930ED1D3AE00F1F681 /* Instruction.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07950ED1D3AE00F1F681 /* Opcode.h */; }; > 978801411471AD920041B016 /* JSDateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 9788FC231471AD0C0068CE2D /* JSDateMath.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 981ED82328234D91BAECCADE /* MachineContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 28806E21155E478A93FA7B02 /* MachineContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -3163,6 +3162,10 @@ > 14AD912B1DCAAAB00014F9FE /* UnlinkedFunctionCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedFunctionCodeBlock.cpp; sourceTree = "<group>"; }; > 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MachineStackMarker.cpp; sourceTree = "<group>"; }; > 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachineStackMarker.h; sourceTree = "<group>"; }; >+ 14BA774E211085EF008D0B05 /* OpcodeSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpcodeSize.h; sourceTree = "<group>"; }; >+ 14BA774F211085F0008D0B05 /* Fits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Fits.h; sourceTree = "<group>"; }; >+ 14BA7750211085F0008D0B05 /* Instruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Instruction.h; sourceTree = "<group>"; }; >+ 14BA7751211086A0008D0B05 /* BytecodeList.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = BytecodeList.rb; sourceTree = "<group>"; }; > 14BA78F013AAB88F005B7C2C /* SlotVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotVisitor.h; sourceTree = "<group>"; }; > 14BA7A9513AADFF8005B7C2C /* Heap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Heap.cpp; sourceTree = "<group>"; }; > 14BA7A9613AADFF8005B7C2C /* Heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Heap.h; sourceTree = "<group>"; }; >@@ -3542,8 +3545,6 @@ > 6511230514046A4C002B101D /* testRegExp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testRegExp; sourceTree = BUILT_PRODUCTS_DIR; }; > 6514F21718B3E1670098FF8B /* Bytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bytecodes.h; sourceTree = "<group>"; }; > 6514F21818B3E1670098FF8B /* InitBytecodes.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; path = InitBytecodes.asm; sourceTree = "<group>"; }; >- 6529FB3018B2D63900C61102 /* generate-bytecode-files */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = "generate-bytecode-files"; sourceTree = "<group>"; }; >- 6529FB3118B2D99900C61102 /* BytecodeList.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BytecodeList.json; sourceTree = "<group>"; }; > 652A3A201651C66100A80AFE /* ARM64Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ARM64Disassembler.cpp; path = disassembler/ARM64Disassembler.cpp; sourceTree = "<group>"; }; > 652A3A221651C69700A80AFE /* A64DOpcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = A64DOpcode.cpp; path = disassembler/ARM64/A64DOpcode.cpp; sourceTree = "<group>"; }; > 652A3A231651C69700A80AFE /* A64DOpcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = A64DOpcode.h; path = disassembler/ARM64/A64DOpcode.h; sourceTree = "<group>"; }; >@@ -3891,7 +3892,6 @@ > 969A07900ED1D3AE00F1F681 /* CodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlock.cpp; sourceTree = "<group>"; }; > 969A07910ED1D3AE00F1F681 /* CodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlock.h; sourceTree = "<group>"; }; > 969A07920ED1D3AE00F1F681 /* DirectEvalCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectEvalCodeCache.h; sourceTree = "<group>"; }; >- 969A07930ED1D3AE00F1F681 /* Instruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Instruction.h; sourceTree = "<group>"; }; > 969A07940ED1D3AE00F1F681 /* Opcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Opcode.cpp; sourceTree = "<group>"; }; > 969A07950ED1D3AE00F1F681 /* Opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Opcode.h; sourceTree = "<group>"; }; > 969A09220ED1E09C00F1F681 /* Completion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Completion.cpp; sourceTree = "<group>"; }; >@@ -4931,7 +4931,6 @@ > F692A8540255597D01FF60F7 /* create_hash_table */, > 937B63CC09E766D200A671DD /* DerivedSources.make */, > 0F93275A1C20BCDF00CF6564 /* dynbench.cpp */, >- 6529FB3018B2D63900C61102 /* generate-bytecode-files */, > F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */, > 45E12D8806A49B0F00E9DF84 /* jsc.cpp */, > A7C225CC139981F100FF1662 /* KeywordLookupGenerator.py */, >@@ -4950,6 +4949,7 @@ > E3FF752D1D9CE9EA00C7E16D /* domjit */, > 0867D69AFE84028FC02AAC07 /* Frameworks */, > 0FEA09FC1705137F00BB722C /* ftl */, >+ 14BA774C211085A0008D0B05 /* generator */, > 142E312A134FF0A600AFADB5 /* heap */, > A5BA15DF1823409200A82E69 /* inspector */, > 1429D77A0ED20D7300B89619 /* interpreter */, >@@ -5951,6 +5951,24 @@ > path = debugger; > sourceTree = "<group>"; > }; >+ 14BA774C211085A0008D0B05 /* generator */ = { >+ isa = PBXGroup; >+ children = ( >+ 14BA774D211085DE008D0B05 /* runtime */, >+ ); >+ path = generator; >+ sourceTree = "<group>"; >+ }; >+ 14BA774D211085DE008D0B05 /* runtime */ = { >+ isa = PBXGroup; >+ children = ( >+ 14BA774F211085F0008D0B05 /* Fits.h */, >+ 14BA7750211085F0008D0B05 /* Instruction.h */, >+ 14BA774E211085EF008D0B05 /* OpcodeSize.h */, >+ ); >+ path = runtime; >+ sourceTree = "<group>"; >+ }; > 1C90513E0BA9E8830081E9D0 /* Configurations */ = { > isa = PBXGroup; > children = ( >@@ -7580,7 +7598,7 @@ > 7094C4DC1AE439530041A2EE /* BytecodeIntrinsicRegistry.cpp */, > 7094C4DD1AE439530041A2EE /* BytecodeIntrinsicRegistry.h */, > 0F2DD80A1AB3D85800BBB8E8 /* BytecodeKills.h */, >- 6529FB3118B2D99900C61102 /* BytecodeList.json */, >+ 14BA7751211086A0008D0B05 /* BytecodeList.rb */, > C2FCAE0E17A9C24E0034C735 /* BytecodeLivenessAnalysis.cpp */, > C2FCAE0F17A9C24E0034C735 /* BytecodeLivenessAnalysis.h */, > 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */, >@@ -7667,7 +7685,6 @@ > 0FB399BB20AF6B2A0017E213 /* InstanceOfStatus.h */, > 0FB399BC20AF6B2A0017E213 /* InstanceOfVariant.cpp */, > 0FB399B920AF6B2A0017E213 /* InstanceOfVariant.h */, >- 969A07930ED1D3AE00F1F681 /* Instruction.h */, > 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */, > BCFD8C900EEB2EE700283848 /* JumpTable.cpp */, > BCFD8C910EEB2EE700283848 /* JumpTable.h */, >@@ -8387,7 +8404,6 @@ > 53D444DC1DAF08AB00B92784 /* B3WasmAddressValue.h in Headers */, > 5341FC721DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h in Headers */, > 0F2C63B21E60AE4700C13839 /* B3Width.h in Headers */, >- 0F44A7B220BF68CE0022B171 /* ICStatusMap.h in Headers */, > 52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */, > 147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */, > 86976E5F1FA3E8BC00E7C4E1 /* BigIntConstructor.h in Headers */, >@@ -8608,7 +8624,6 @@ > 86EC9DC61328DF82002B2AD7 /* DFGGenerationInfo.h in Headers */, > 86EC9DC81328DF82002B2AD7 /* DFGGraph.h in Headers */, > 0F2FCCFA18A60070001A27F8 /* DFGGraphSafepoint.h in Headers */, >- 0F44A7B120BF68C90022B171 /* ExitingInlineKind.h in Headers */, > 0FB17661196B8F9E0091052A /* DFGHeapLocation.h in Headers */, > 0FC841691BA8C3210061837D /* DFGInferredTypeCheck.h in Headers */, > 0FB14E211812570B009B6B4D /* DFGInlineCacheWrapper.h in Headers */, >@@ -8752,6 +8767,8 @@ > 14142E531B796EDD00F4BF4B /* ExecutableInfo.h in Headers */, > 0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */, > 0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */, >+ 0F44A7B020BF68620022B171 /* ExitFlag.h in Headers */, >+ 0F44A7B120BF68C90022B171 /* ExitingInlineKind.h in Headers */, > 0F3AC754188E5EC80032029F /* ExitingJITType.h in Headers */, > 0FB105861675481200F8AB6E /* ExitKind.h in Headers */, > 0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */, >@@ -8759,7 +8776,6 @@ > A7A8AF3817ADB5F3005AB174 /* Float32Array.h in Headers */, > A7A8AF3917ADB5F3005AB174 /* Float64Array.h in Headers */, > 0F24E54317EA9F5900ABB217 /* FPRInfo.h in Headers */, >- 0F44A7B320BF68D10022B171 /* RecordedStatuses.h in Headers */, > E34EDBF71DB5FFC900DC87A5 /* FrameTracers.h in Headers */, > 0F5513A61D5A682C00C32BD8 /* FreeList.h in Headers */, > 0F6585E11EE0805A0095176D /* FreeListInlines.h in Headers */, >@@ -8899,6 +8915,7 @@ > FE1BD0251E72053800134BC9 /* HeapVerifier.h in Headers */, > 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */, > DC2143071CA32E55000A8869 /* ICStats.h in Headers */, >+ 0F44A7B220BF68CE0022B171 /* ICStatusMap.h in Headers */, > 0FB399BE20AF6B3D0017E213 /* ICStatusUtils.h in Headers */, > BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */, > 8606DDEA18DA44AB00A383D0 /* IdentifierInlines.h in Headers */, >@@ -8949,7 +8966,6 @@ > 0F49E9AA20AB4D00001CA0AA /* InstanceOfAccessCase.h in Headers */, > 0FB399BF20AF6B3F0017E213 /* InstanceOfStatus.h in Headers */, > 0FB399C020AF6B430017E213 /* InstanceOfVariant.h in Headers */, >- 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */, > A7A8AF3B17ADB5F3005AB174 /* Int16Array.h in Headers */, > A7A8AF3C17ADB5F3005AB174 /* Int32Array.h in Headers */, > A7A8AF3A17ADB5F3005AB174 /* Int8Array.h in Headers */, >@@ -9109,7 +9125,6 @@ > 7013CA8C1B491A9400CAE613 /* JSJob.h in Headers */, > BC18C4160E16F5CD00B34460 /* JSLexicalEnvironment.h in Headers */, > BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */, >- 0F44A7B020BF68620022B171 /* ExitFlag.h in Headers */, > C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */, > 2A4BB7F318A41179008A0FCD /* JSManagedValueInternal.h in Headers */, > A700874217CBE8EB00C3E643 /* JSMap.h in Headers */, >@@ -9366,6 +9381,7 @@ > 0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */, > 0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */, > 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */, >+ 0F44A7B320BF68D10022B171 /* RecordedStatuses.h in Headers */, > 0FF60AC216740F8300029779 /* ReduceWhitespace.h in Headers */, > E33637A61B63220200EE0840 /* ReflectObject.h in Headers */, > 996B73231BDA08EF00331B84 /* ReflectObject.lut.h in Headers */, >@@ -9425,7 +9441,6 @@ > A7299DA217D12848005F5FF9 /* SetPrototype.h in Headers */, > 0FEE98411A8865B700754E93 /* SetupVarargsFrame.h in Headers */, > DC17E8181C9C91D9008A6AB3 /* ShadowChicken.h in Headers */, >- 0F44A7B420BF68D90022B171 /* TerminatedCodeOrigin.h in Headers */, > DC17E8191C9C91DB008A6AB3 /* ShadowChickenInlines.h in Headers */, > FE3022D31E3D73A500BAC493 /* SigillCrashAnalyzer.h in Headers */, > 0F4D8C781FCA3CFA001D32AC /* SimpleMarkingConstraint.h in Headers */, >@@ -9480,6 +9495,7 @@ > 0F766D3915AE4A1F008F363E /* StructureStubClearingWatchpoint.h in Headers */, > BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */, > BC9041480EB9250900FE26FA /* StructureTransitionTable.h in Headers */, >+ 0F44767020C5E2B4008B2C36 /* StubInfoSummary.h in Headers */, > 0F7DF1371E2970E10095951B /* Subspace.h in Headers */, > 0F7DF1381E2970E40095951B /* SubspaceInlines.h in Headers */, > 0F4A38FA1C8E13DF00190318 /* SuperSampler.h in Headers */, >@@ -9498,6 +9514,7 @@ > DC7997831CDE9FA0004D4A09 /* TagRegistersMode.h in Headers */, > 70ECA6091AFDBEA200449739 /* TemplateObjectDescriptor.h in Headers */, > 0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */, >+ 0F44A7B420BF68D90022B171 /* TerminatedCodeOrigin.h in Headers */, > 0FA2C17C17D7CF84009D015F /* TestRunnerUtils.h in Headers */, > FE3422121D6B81C30032BE88 /* ThrowScope.h in Headers */, > 0F572D4F16879FDD00E57FBD /* ThunkGenerator.h in Headers */, >@@ -9581,7 +9598,6 @@ > AD5B416F1EBAFB77008EFA43 /* WasmName.h in Headers */, > AD7B4B2E1FA3E29800C9DF79 /* WasmNameSection.h in Headers */, > ADD8FA461EB3079700DF542F /* WasmNameSectionParser.h in Headers */, >- 0F44767020C5E2B4008B2C36 /* StubInfoSummary.h in Headers */, > 5311BD4B1EA581E500525281 /* WasmOMGPlan.h in Headers */, > 53C6FEEF1E8ADFA900B18425 /* WasmOpcodeOrigin.h in Headers */, > 53B4BD121F68B32500D2BEA3 /* WasmOps.h in Headers */, >@@ -9982,7 +9998,7 @@ > ); > runOnlyForDeploymentPostprocessing = 0; > shellPath = /bin/sh; >- shellScript = "exec ${SRCROOT}/postprocess-headers.sh"; >+ shellScript = "exec ${SRCROOT}/postprocess-headers.sh\n"; > }; > 374F95C9205F9975002BF68F /* Make libWTF.a Symbolic Link */ = { > isa = PBXShellScriptBuildPhase; >@@ -10103,7 +10119,7 @@ > ); > runOnlyForDeploymentPostprocessing = 0; > shellPath = /bin/sh; >- shellScript = "if [[ \"${ACTION}\" == \"installhdrs\" ]]; then\n exit 0\nfi\n\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\n/usr/bin/env ruby JavaScriptCore/offlineasm/asm.rb \"-I${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\" JavaScriptCore/llint/LowLevelInterpreter.asm \"${BUILT_PRODUCTS_DIR}/JSCLLIntOffsetsExtractor\" LLIntAssembly.h || exit 1"; >+ shellScript = "if [[ \"${ACTION}\" == \"installhdrs\" ]]; then\n exit 0\nfi\n\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\n/usr/bin/env ruby JavaScriptCore/offlineasm/asm.rb \"-I${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\" JavaScriptCore/llint/LowLevelInterpreter.asm \"${BUILT_PRODUCTS_DIR}/JSCLLIntOffsetsExtractor\" LLIntAssembly.h || exit 1\n"; > }; > 65FB3F6509D11E9100F49DEB /* Generate Derived Sources */ = { > isa = PBXShellScriptBuildPhase; >diff --git a/Source/JavaScriptCore/bytecode/BytecodeList.json b/Source/JavaScriptCore/bytecode/BytecodeList.json >deleted file mode 100644 >index f5bdc49a7a671b8de9cb348b7ebba936748b2f42..0000000000000000000000000000000000000000 >--- a/Source/JavaScriptCore/bytecode/BytecodeList.json >+++ /dev/null >@@ -1,236 +0,0 @@ >-[ >- { >- "section" : "Bytecodes", "emitInHFile" : true, "emitInStructsFile" : true, "emitInASMFile" : true, >- "emitOpcodeIDStringValuesInHFile" : true, "macroNameComponent" : "BYTECODE", "asmPrefix" : "llint_", >- "bytecodes" : [ >- { "name" : "op_enter", "length" : 1 }, >- { "name" : "op_get_scope", "length" : 2 }, >- { "name" : "op_create_direct_arguments", "length" : 2 }, >- { "name" : "op_create_scoped_arguments", "length" : 3 }, >- { "name" : "op_create_cloned_arguments", "length" : 2 }, >- { "name" : "op_create_this", "offsets" : >- [{"dst" : "int"}, >- {"callee" : "int"}, >- {"inlineCapacity" : "int"}, >- {"cachedCallee" : "WriteBarrier<JSCell>"}]}, >- { "name" : "op_get_argument", "length" : 4 }, >- { "name" : "op_argument_count", "length" : 2 }, >- { "name" : "op_to_this", "length" : 5 }, >- { "name" : "op_check_tdz", "length" : 2 }, >- { "name" : "op_new_object", "length" : 4 }, >- { "name" : "op_new_array", "length" : 5 }, >- { "name" : "op_new_array_with_size", "length" : 4 }, >- { "name" : "op_new_array_buffer", "offsets" : >- [{"dst" : "int"}, >- {"immutableButterfly" : "int"}, >- {"profile" : "ArrayAllocationProfile*"}]}, >- { "name" : "op_new_array_with_spread", "length" : 5 }, >- { "name" : "op_spread", "length" : 3 }, >- { "name" : "op_new_regexp", "length" : 3 }, >- { "name" : "op_mov", "length" : 3 }, >- { "name" : "op_not", "length" : 3 }, >- { "name" : "op_eq", "length" : 4 }, >- { "name" : "op_eq_null", "length" : 3 }, >- { "name" : "op_neq", "length" : 4 }, >- { "name" : "op_neq_null", "length" : 3 }, >- { "name" : "op_stricteq", "length" : 4 }, >- { "name" : "op_nstricteq", "length" : 4 }, >- { "name" : "op_less", "length" : 4 }, >- { "name" : "op_lesseq", "length" : 4 }, >- { "name" : "op_greater", "length" : 4 }, >- { "name" : "op_greatereq", "length" : 4 }, >- { "name" : "op_below", "length" : 4 }, >- { "name" : "op_beloweq", "length" : 4 }, >- { "name" : "op_inc", "length" : 2 }, >- { "name" : "op_dec", "length" : 2 }, >- { "name" : "op_to_number", "length" : 4 }, >- { "name" : "op_to_string", "length" : 3 }, >- { "name" : "op_to_object", "length" : 5 }, >- { "name" : "op_negate", "length" : 4 }, >- { "name" : "op_add", "length" : 5 }, >- { "name" : "op_mul", "length" : 5 }, >- { "name" : "op_div", "length" : 5 }, >- { "name" : "op_mod", "length" : 4 }, >- { "name" : "op_sub", "length" : 5 }, >- { "name" : "op_pow", "length" : 4 }, >- { "name" : "op_lshift", "length" : 4 }, >- { "name" : "op_rshift", "length" : 4 }, >- { "name" : "op_urshift", "length" : 4 }, >- { "name" : "op_unsigned", "length" : 3 }, >- { "name" : "op_bitand", "length" : 5 }, >- { "name" : "op_bitxor", "length" : 5 }, >- { "name" : "op_bitor", "length" : 5 }, >- { "name" : "op_identity_with_profile", "length" : 4 }, >- { "name" : "op_overrides_has_instance", "offsets" : >- [{"dst" : "int"}, >- {"constructor" : "int"}, >- {"hasInstanceValue" : "int"}] }, >- { "name" : "op_instanceof", "offsets" : >- [{"dst" : "int"}, >- {"value" : "int"}, >- {"prototype" : "int"}] }, >- { "name" : "op_instanceof_custom", "offsets" : >- [{"dst" : "int"}, >- {"value" : "int"}, >- {"constructor" : "int"}, >- {"hasInstanceValue" : "int"}] }, >- { "name" : "op_typeof", "length" : 3 }, >- { "name" : "op_is_empty", "length" : 3 }, >- { "name" : "op_is_undefined", "length" : 3 }, >- { "name" : "op_is_boolean", "length" : 3 }, >- { "name" : "op_is_number", "length" : 3 }, >- { "name" : "op_is_object", "length" : 3 }, >- { "name" : "op_is_object_or_null", "length" : 3 }, >- { "name" : "op_is_function", "length" : 3 }, >- { "name" : "op_is_cell_with_type", "length" : 4 }, >- { "name" : "op_in_by_val", "length" : 5 }, >- { "name" : "op_in_by_id", "length" : 4 }, >- { "name" : "op_get_array_length", "length" : 9 }, >- { "name" : "op_get_by_id", "length" : 9 }, >- { "name" : "op_get_by_id_proto_load", "length" : 9 }, >- { "name" : "op_get_by_id_unset", "length" : 9 }, >- { "name" : "op_get_by_id_with_this", "length" : 6 }, >- { "name" : "op_get_by_val_with_this", "length" : 6 }, >- { "name" : "op_get_by_id_direct", "length" : 7 }, >- { "name" : "op_try_get_by_id", "length" : 5 }, >- { "name" : "op_put_by_id", "length" : 9 }, >- { "name" : "op_put_by_id_with_this", "length" : 5 }, >- { "name" : "op_del_by_id", "length" : 4 }, >- { "name" : "op_get_by_val", "length" : 6 }, >- { "name" : "op_put_by_val", "length" : 5 }, >- { "name" : "op_put_by_val_with_this", "length" : 5 }, >- { "name" : "op_put_by_val_direct", "length" : 5 }, >- { "name" : "op_del_by_val", "length" : 4 }, >- { "name" : "op_put_getter_by_id", "length" : 5 }, >- { "name" : "op_put_setter_by_id", "length" : 5 }, >- { "name" : "op_put_getter_setter_by_id", "length" : 6 }, >- { "name" : "op_put_getter_by_val", "length" : 5 }, >- { "name" : "op_put_setter_by_val", "length" : 5 }, >- { "name" : "op_define_data_property", "length" : 5 }, >- { "name" : "op_define_accessor_property", "length" : 6 }, >- { "name" : "op_jmp", "length" : 2 }, >- { "name" : "op_jtrue", "length" : 3 }, >- { "name" : "op_jfalse", "length" : 3 }, >- { "name" : "op_jeq_null", "length" : 3 }, >- { "name" : "op_jneq_null", "length" : 3 }, >- { "name" : "op_jneq_ptr", "length" : 5 }, >- { "name" : "op_jeq", "length" : 4 }, >- { "name" : "op_jstricteq", "length" : 4 }, >- { "name" : "op_jneq", "length" : 4 }, >- { "name" : "op_jnstricteq", "length" : 4 }, >- { "name" : "op_jless", "length" : 4 }, >- { "name" : "op_jlesseq", "length" : 4 }, >- { "name" : "op_jgreater", "length" : 4 }, >- { "name" : "op_jgreatereq", "length" : 4 }, >- { "name" : "op_jnless", "length" : 4 }, >- { "name" : "op_jnlesseq", "length" : 4 }, >- { "name" : "op_jngreater", "length" : 4 }, >- { "name" : "op_jngreatereq", "length" : 4 }, >- { "name" : "op_jbelow", "length" : 4 }, >- { "name" : "op_jbeloweq", "length" : 4 }, >- { "name" : "op_loop_hint", "length" : 1 }, >- { "name" : "op_switch_imm", "length" : 4 }, >- { "name" : "op_switch_char", "length" : 4 }, >- { "name" : "op_switch_string", "length" : 4 }, >- { "name" : "op_new_func", "length" : 4 }, >- { "name" : "op_new_func_exp", "length" : 4 }, >- { "name" : "op_new_generator_func", "length" : 4 }, >- { "name" : "op_new_generator_func_exp", "length" : 4 }, >- { "name" : "op_new_async_func", "length" : 4 }, >- { "name" : "op_new_async_func_exp", "length" : 4 }, >- { "name" : "op_new_async_generator_func", "length" : 4 }, >- { "name" : "op_new_async_generator_func_exp", "length" : 4 }, >- { "name" : "op_set_function_name", "length" : 3 }, >- { "name" : "op_call", "length" : 9 }, >- { "name" : "op_tail_call", "length" : 9 }, >- { "name" : "op_call_eval", "length" : 9 }, >- { "name" : "op_call_varargs", "length" : 9 }, >- { "name" : "op_tail_call_varargs", "length" : 9 }, >- { "name" : "op_tail_call_forward_arguments", "length" : 9 }, >- { "name" : "op_ret", "length" : 2 }, >- { "name" : "op_construct", "length" : 9 }, >- { "name" : "op_construct_varargs", "length" : 9 }, >- { "name" : "op_strcat", "length" : 4 }, >- { "name" : "op_to_primitive", "length" : 3 }, >- { "name" : "op_resolve_scope", "length" : 7 }, >- { "name" : "op_get_from_scope", "length" : 8 }, >- { "name" : "op_put_to_scope", "length" : 7 }, >- { "name" : "op_get_from_arguments", "length" : 5 }, >- { "name" : "op_put_to_arguments", "length" : 4 }, >- { "name" : "op_push_with_scope", "length" : 4 }, >- { "name" : "op_create_lexical_environment", "length" : 5 }, >- { "name" : "op_get_parent_scope", "length" : 3 }, >- { "name" : "op_catch", "length" : 4 }, >- { "name" : "op_throw", "length" : 2 }, >- { "name" : "op_throw_static_error", "length" : 3 }, >- { "name" : "op_debug", "length" : 3 }, >- { "name" : "op_end", "length" : 2 }, >- { "name" : "op_profile_type", "length" : 6 }, >- { "name" : "op_profile_control_flow", "length" : 2 }, >- { "name" : "op_get_enumerable_length", "length" : 3 }, >- { "name" : "op_has_indexed_property", "length" : 5 }, >- { "name" : "op_has_structure_property", "length" : 5 }, >- { "name" : "op_has_generic_property", "length" : 4 }, >- { "name" : "op_get_direct_pname", "length" : 7 }, >- { "name" : "op_get_property_enumerator", "length" : 3 }, >- { "name" : "op_enumerator_structure_pname", "length" : 4 }, >- { "name" : "op_enumerator_generic_pname", "length" : 4 }, >- { "name" : "op_to_index_string", "length" : 3 }, >- { "name" : "op_unreachable", "length" : 1 }, >- { "name" : "op_create_rest", "length": 4 }, >- { "name" : "op_get_rest_length", "length": 3 }, >- { "name" : "op_yield", "length" : 4 }, >- { "name" : "op_check_traps", "length" : 1 }, >- { "name" : "op_log_shadow_chicken_prologue", "length" : 2}, >- { "name" : "op_log_shadow_chicken_tail", "length" : 3}, >- { "name" : "op_resolve_scope_for_hoisting_func_decl_in_eval", "length" : 4 }, >- { "name" : "op_nop", "length" : 1 }, >- { "name" : "op_super_sampler_begin", "length" : 1 }, >- { "name" : "op_super_sampler_end", "length" : 1 } >- ] >- }, >- { >- "section" : "CLoopHelpers", "emitInHFile" : true, "emitInStructsFile" : false, "emitInASMFile" : false, >- "emitOpcodeIDStringValuesInHFile" : false, "defaultLength" : 1, "macroNameComponent" : "CLOOP_BYTECODE_HELPER", >- "bytecodes" : [ >- { "name" : "llint_entry" }, >- { "name" : "getHostCallReturnValue" }, >- { "name" : "llint_return_to_host" }, >- { "name" : "llint_vm_entry_to_javascript" }, >- { "name" : "llint_vm_entry_to_native" }, >- { "name" : "llint_cloop_did_return_from_js_1" }, >- { "name" : "llint_cloop_did_return_from_js_2" }, >- { "name" : "llint_cloop_did_return_from_js_3" }, >- { "name" : "llint_cloop_did_return_from_js_4" }, >- { "name" : "llint_cloop_did_return_from_js_5" }, >- { "name" : "llint_cloop_did_return_from_js_6" }, >- { "name" : "llint_cloop_did_return_from_js_7" }, >- { "name" : "llint_cloop_did_return_from_js_8" }, >- { "name" : "llint_cloop_did_return_from_js_9" }, >- { "name" : "llint_cloop_did_return_from_js_10" }, >- { "name" : "llint_cloop_did_return_from_js_11" }, >- { "name" : "llint_cloop_did_return_from_js_12" } >- ] >- }, >- { >- "section" : "NativeHelpers", "emitInHFile" : true, "emitInStructsFile" : false, "emitInASMFile" : true, >- "emitOpcodeIDStringValuesInHFile" : false, "defaultLength" : 1, "macroNameComponent" : "BYTECODE_HELPER", >- "bytecodes" : [ >- { "name" : "llint_program_prologue" }, >- { "name" : "llint_eval_prologue" }, >- { "name" : "llint_module_program_prologue" }, >- { "name" : "llint_function_for_call_prologue" }, >- { "name" : "llint_function_for_construct_prologue" }, >- { "name" : "llint_function_for_call_arity_check" }, >- { "name" : "llint_function_for_construct_arity_check" }, >- { "name" : "llint_generic_return_point" }, >- { "name" : "llint_throw_from_slow_path_trampoline" }, >- { "name" : "llint_throw_during_call_trampoline" }, >- { "name" : "llint_native_call_trampoline" }, >- { "name" : "llint_native_construct_trampoline" }, >- { "name" : "llint_internal_function_call_trampoline" }, >- { "name" : "llint_internal_function_construct_trampoline" }, >- { "name" : "handleUncaughtException" } >- ] >- } >-] >diff --git a/Source/JavaScriptCore/bytecode/BytecodeList.rb b/Source/JavaScriptCore/bytecode/BytecodeList.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..3bbcefca95e1c7ac4ef0a0eb8cc50be61b10780a >--- /dev/null >+++ b/Source/JavaScriptCore/bytecode/BytecodeList.rb >@@ -0,0 +1,1079 @@ >+types [ >+ :VirtualRegister, >+ :Constant, >+ >+ :BasicBlockLocation, >+ :DebugHookType, >+ :ErrorType, >+ :GetPutInfo, >+ :JSCell, >+ :JSGlobalLexicalEnvironment, >+ :JSGlobalObject, >+ :JSObject, >+ :JSType, >+ :LLIntCallLinkInfo, >+ :ProfileTypeBytecodeFlag, >+ :PutByIdFlags, >+ :ResolveType, >+ :ScopeOffset, >+ :Structure, >+ :StructureID, >+ :StructureChain, >+ :ToThisStatus, >+ :TypeLocation, >+ >+ :ValueProfile, >+ :ValueProfileAndOperandBuffer, >+ :ArithProfile, >+ :ArrayProfile, >+ :ArrayAllocationProfile, >+ :ObjectAllocationProfile, >+] >+ >+namespace :Special do >+ types [ :Pointer ] >+end >+ >+templates [ >+ :WriteBarrierBase, >+] >+ >+begin_section :Bytecodes, >+ emit_in_h_file: true, >+ emit_in_stucts_file: true, >+ emit_in_asm_file: true, >+ emit_opcode_id_string_values_in_h_file: true, >+ macro_name_component: :BYTECODE, >+ asm_prefix: "llint_", >+ op_prefix: "op_" >+ >+op :wide >+ >+op :enter >+ >+op :get_scope, >+ args: { >+ dst: VirtualRegister >+ } >+ >+op :create_direct_arguments, >+ args: { >+ dst: VirtualRegister, >+ } >+ >+op :create_scoped_arguments, >+ args: { >+ dst: VirtualRegister, >+ scope: VirtualRegister, >+ } >+ >+op :create_cloned_arguments, >+ args: { >+ dst: VirtualRegister, >+ } >+ >+op :create_this, >+ args: { >+ dst: VirtualRegister, >+ callee: VirtualRegister, >+ inlineCapacity: unsigned, >+ }, >+ metadata: { >+ cachedCallee: WriteBarrierBase[JSCell] >+ } >+ >+op :get_argument, >+ args: { >+ dst: VirtualRegister, >+ index: unsigned, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :argument_count, >+ args: { >+ dst: VirtualRegister, >+ } >+ >+op :to_this, >+ args: { >+ src: VirtualRegister, >+ }, >+ metadata: { >+ cachedStructure: WriteBarrierBase[Structure], >+ toThisStatus: ToThisStatus, >+ profile: ValueProfile, >+ } >+ >+op :check_tdz, >+ args: { >+ target: VirtualRegister, >+ } >+ >+op :new_object, >+ args: { >+ dst: VirtualRegister, >+ inlineCapacity: unsigned, >+ }, >+ metadata: { >+ allocationProfile: ObjectAllocationProfile, >+ } >+ >+op :new_array, >+ args: { >+ dst: VirtualRegister, >+ argv?: VirtualRegister, >+ argc: unsigned, >+ }, >+ metadata: { >+ allocationProfile: ArrayAllocationProfile, >+ } >+ >+op :new_array_with_size, >+ args: { >+ dst: VirtualRegister, >+ length: unsigned, >+ }, >+ metadata: { >+ allocationProfile: ArrayAllocationProfile, >+ } >+ >+op :new_array_buffer, >+ args: { >+ dst: VirtualRegister, >+ immutableButterfly: Constant, >+ }, >+ metadata: { >+ allocationProfile: ArrayAllocationProfile, >+ } >+ >+op :new_array_with_spread, >+ args: { >+ dst: VirtualRegister, >+ argv?: VirtualRegister, >+ argc: unsigned, >+ bitVector: unsigned, # this could have type BitVector& if the instruction has a reference to the codeblock >+ } >+ >+op :spread, >+ args: { >+ dst: VirtualRegister, >+ argument: VirtualRegister, >+ } >+ >+op :new_regexp, >+ args: { >+ dst: VirtualRegister, >+ regexp: unsigned, # this could have type RegExp the instruction has a reference to the codeblock >+ } >+ >+op :mov, # damnit this is in reverse order to llint >+ args: { >+ dst: VirtualRegister, >+ src: VirtualRegister, >+ } >+ >+op :not, >+ args: { >+ dst: VirtualRegister, >+ operand: VirtualRegister, >+ } >+ >+op_group :BinaryOp, >+ [ >+ :eq, >+ :neq, >+ :stricteq, >+ :nstricteq, >+ :less, >+ :lesseq, >+ :greater, >+ :greatereq, >+ :below, >+ :beloweq, >+ :mod, >+ :pow, >+ :lshift, >+ :rshift, >+ :urshift, >+ ], >+ args: { >+ dst: VirtualRegister, >+ lhs: VirtualRegister, >+ rhs: VirtualRegister, >+ } >+ >+op_group :ProfiledBinaryOp, >+ [ >+ :add, >+ :mul, >+ :div, >+ :sub, >+ :bitand, >+ :bitxor, >+ :bitor, >+ ], >+ args: { >+ dst: VirtualRegister, >+ lhs: VirtualRegister, >+ rhs: VirtualRegister, >+ }, >+ metadata: { >+ arithProfile: :ArithProfile >+ } >+ >+op_group :UnaryOp, >+ [ >+ :eq_null, >+ :neq_null, >+ :to_string, >+ :unsigned, >+ :is_empty, >+ :is_undefined, >+ :is_boolean, >+ :is_number, >+ :is_object, >+ :is_object_or_null, >+ :is_function, >+ ], >+ args: { >+ dst: VirtualRegister, >+ operand: VirtualRegister, >+ } >+ >+op :to_number, >+ args: { >+ dst: VirtualRegister, >+ operand: VirtualRegister, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :inc, >+ args: { >+ srcDst: VirtualRegister, >+ } >+ >+op :dec, >+ args: { >+ srcDst: VirtualRegister, >+ } >+ >+op :to_object, >+ args: { >+ dst: VirtualRegister, >+ operand: VirtualRegister, >+ message: Constant, # Constants could possibly also have their final type >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :negate, >+ args: { >+ dst: VirtualRegister, >+ operand: VirtualRegister, >+ }, >+ metadata: { >+ arithProfile: ArithProfile, >+ } >+ >+op :identity_with_profile, >+ args: { >+ src: VirtualRegister, >+ topProfile: unsigned, >+ bottomProfile: unsigned, >+ } >+ >+op :overrides_has_instance, >+ args: { >+ dst: VirtualRegister, >+ constructor: VirtualRegister, >+ hasInstanceValue: VirtualRegister, >+ } >+ >+op :instanceof, >+ args: { >+ dst: VirtualRegister, >+ value: VirtualRegister, >+ prototype: VirtualRegister, >+ } >+ >+op :instanceof_custom, >+ args: { >+ dst: VirtualRegister, >+ value: VirtualRegister, >+ constructor: VirtualRegister, >+ hasInstanceValue: VirtualRegister, >+ } >+ >+op :typeof, >+ args: { >+ dst: VirtualRegister, >+ value: VirtualRegister, >+} >+ >+op :is_cell_with_type, >+ args: { >+ dst: VirtualRegister, >+ value: VirtualRegister, >+ type: JSType, >+ } >+ >+op :in_by_val, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: VirtualRegister, >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ } >+ >+op :in_by_id, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: VirtualRegister, >+ } >+ >+# NOTE: get_by_id variants >+# they all used to have to share the same size, in order to store all the metadata >+# for all the variants - this should no longer be necessary, since the metadata is >+# stored out-of-line, but has to be confirmed later on >+# we should also consider whether we want to keep modifying the bytecode stream >+# throughout execution, because otherwise we'll need an alternative way of specializing >+# get_by_id >+op :get_array_length, # special - never emitted >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, # must be a JSArray >+ property: Constant, # always "length" >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ } >+ >+op :get_by_id, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: Constant, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ hitCountForLLIntCaching: unsigned, >+ } >+ >+op :get_by_id_proto_load, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: Constant, >+ structure: StructureID, >+ slot: JSObject, >+ } >+ >+op :get_by_id_unset, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: Constant, >+ structure: StructureID, >+ } >+ >+op :get_by_id_with_this, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ thisValue: VirtualRegister, >+ property: Constant, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :get_by_val_with_this, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ thisValue: VirtualRegister, >+ property: Constant, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :get_by_id_direct, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: Constant, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ structure: StructureID, >+ offset: unsigned, >+ } >+ >+op :try_get_by_id, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: Constant, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :put_by_id, >+ args: { >+ base: VirtualRegister, >+ property: Constant, >+ value: VirtualRegister, >+ }, >+ metadata: { >+ oldStructure: StructureID, >+ offset: unsigned, >+ newStructure: StructureID, >+ structureChain: WriteBarrierBase[StructureChain], >+ flags: PutByIdFlags, >+ } >+ >+op :put_by_id_with_this, >+ args: { >+ base: VirtualRegister, >+ thisValue: VirtualRegister, >+ property: Constant, >+ value: VirtualRegister, >+ } >+ >+op :del_by_id, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: Constant, >+ } >+ >+op :get_by_val, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: Constant, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ arrayProfile: ArrayProfile, >+ } >+ >+op :put_by_val, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: VirtualRegister, >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ } >+ >+op :put_by_val_with_this, >+ args: { >+ base: VirtualRegister, >+ thisValue: VirtualRegister, >+ property: VirtualRegister, >+ value: VirtualRegister, >+ } >+ >+op :put_by_val_direct, >+ args: { >+ base: VirtualRegister, >+ property: VirtualRegister, >+ value: VirtualRegister, >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ } >+ >+op :del_by_val, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: VirtualRegister, >+ } >+ >+op :put_getter_by_id, >+ args: { >+ base: VirtualRegister, >+ property: Constant, >+ attributes: unsigned, >+ getter: VirtualRegister, >+ } >+ >+op :put_setter_by_id, >+ args: { >+ base: VirtualRegister, >+ property: Constant, >+ attributes: unsigned, >+ setter: VirtualRegister, >+ } >+ >+op :put_getter_setter_by_id, >+ args: { >+ base: VirtualRegister, >+ property: Constant, >+ attributes: unsigned, >+ getter: VirtualRegister, >+ setter: VirtualRegister, >+ } >+ >+op :put_getter_by_val, >+ args: { >+ base: VirtualRegister, >+ property: VirtualRegister, >+ attributes: unsigned, >+ getter: VirtualRegister, >+ } >+ >+op :put_setter_by_val, >+ args: { >+ base: VirtualRegister, >+ property: VirtualRegister, >+ attributes: unsigned, >+ setter: VirtualRegister, >+ } >+ >+op :define_data_property, >+ args: { >+ base: VirtualRegister, >+ property: VirtualRegister, >+ value: VirtualRegister, >+ attributes: VirtualRegister, >+ } >+ >+op :define_accessor_property, >+ args: { >+ base: VirtualRegister, >+ property: VirtualRegister, >+ getter: VirtualRegister, >+ setter: VirtualRegister, >+ attributes: VirtualRegister, >+ } >+ >+op :jmp, >+ args: { >+ target: int, >+ } >+ >+op :jtrue, >+ args: { >+ condition: VirtualRegister, >+ target: int, >+ } >+ >+op :jfalse, >+ args: { >+ condition: VirtualRegister, >+ target: int, >+ } >+ >+op :jeq_null, >+ args: { >+ condition: VirtualRegister, >+ target: int, >+ } >+ >+op :jneq_null, >+ args: { >+ condition: VirtualRegister, >+ target: int, >+ } >+ >+op :jneq_ptr, >+ args: { >+ condition: VirtualRegister, >+ specialPointer: Special::Pointer, >+ target: int, >+ }, >+ metadata: { >+ hasJumped: bool, >+ } >+ >+op_group :BinaryJmp, >+ [ >+ :jeq, >+ :jstricteq, >+ :jneq, >+ :jnstricteq, >+ :jless, >+ :jlesseq, >+ :jgreater, >+ :jgreatereq, >+ :jnless, >+ :jnlesseq, >+ :jngreater, >+ :jngreatereq, >+ :jbelow, >+ :jbeloweq, >+ ], >+ args: { >+ lhs: VirtualRegister, >+ rhs: VirtualRegister, >+ target: int, >+ } >+ >+op :loop_hint >+ >+op_group :SwitchValue, >+ [ >+ :switch_imm, >+ :switch_char, >+ :switch_string, >+ ], >+ args: { >+ tableIndex: int, >+ defaultOffset: int, >+ scrutinee: VirtualRegister, >+ } >+ >+op_group :NewFunction, >+ [ >+ :new_func, >+ :new_func_exp, >+ :new_generator_func, >+ :new_generator_func_exp, >+ :new_async_func, >+ :new_async_func_exp, >+ :new_async_generator_func, >+ :new_async_generator_func_exp, >+ ], >+ args: { >+ dst: VirtualRegister, >+ scope: VirtualRegister, >+ functionDecl: int, >+ } >+ >+op :set_function_name, >+ args: { >+ function: VirtualRegister, >+ name: VirtualRegister, >+ } >+ >+# op_call variations >+op :call, >+ args: { >+ dst: VirtualRegister, >+ callee: VirtualRegister, >+ argc: unsigned, >+ argv: unsigned, >+ }, >+ metadata: { >+ callLinkInfo: LLIntCallLinkInfo, >+ # ? there was an extra slot here >+ arrayProfile: ArrayProfile, >+ profile: ValueProfile, >+ } >+ >+op :tail_call, >+ args: { >+ dst: VirtualRegister, >+ callee: VirtualRegister, >+ argc: unsigned, >+ argv: unsigned, >+ }, >+ metadata: { >+ callLinkInfo: LLIntCallLinkInfo, >+ # ? there was an extra slot here >+ arrayProfile: ArrayProfile, >+ profile: ValueProfile, >+ } >+ >+op :call_eval, >+ args: { >+ dst: VirtualRegister, >+ callee: VirtualRegister, >+ argc: unsigned, >+ argv: unsigned, >+ }, >+ metadata: { >+ callLinkInfo: LLIntCallLinkInfo, >+ # ? there was an extra slot here >+ arrayProfile: ArrayProfile, >+ profile: ValueProfile, >+ } >+ >+op :call_varargs, >+ args: { >+ dst: VirtualRegister, >+ callee: VirtualRegister, >+ this?: VirtualRegister, >+ arguments?: VirtualRegister, >+ firstFree: VirtualRegister, >+ firstVarArg: int, >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ profile: ValueProfile, >+ } >+ >+op :tail_call_varargs, >+ args: { >+ dst: VirtualRegister, >+ callee: VirtualRegister, >+ this?: VirtualRegister, >+ arguments?: VirtualRegister, >+ firstFree: VirtualRegister, >+ firstVarArg: int, >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ profile: ValueProfile, >+ } >+ >+op :tail_call_forward_arguments, >+ args: { >+ dst: VirtualRegister, >+ callee: VirtualRegister, >+ this?: VirtualRegister, >+ arguments?: VirtualRegister, >+ firstFree: VirtualRegister, >+ firstVarArg: int, >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ profile: ValueProfile, >+ } >+ >+op :construct, >+ args: { >+ dst: VirtualRegister, >+ function: VirtualRegister, >+ argc: unsigned, >+ argv: unsigned, >+ }, >+ metadata: { >+ callLinkInfo: LLIntCallLinkInfo, >+ # ? there was an extra slot here >+ # ? empty slot here >+ profile: ValueProfile, >+ } >+ >+op :construct_varargs, >+ args: { >+ dst: VirtualRegister, >+ callee: VirtualRegister, >+ this?: VirtualRegister, >+ arguments?: VirtualRegister, >+ firstFree: VirtualRegister, >+ firstVarArg: int, >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ profile: ValueProfile, >+ } >+ >+op :ret, >+ args: { >+ value: VirtualRegister, >+ } >+ >+op :strcat, >+ args: { >+ dst: VirtualRegister, >+ src: VirtualRegister, >+ count: int, >+ } >+ >+op :to_primitive, >+ args: { >+ dst: VirtualRegister, >+ src: VirtualRegister, >+ } >+ >+op :resolve_scope, >+ args: { >+ dst: VirtualRegister, >+ scope: VirtualRegister, >+ var: Constant, >+ type: ResolveType, >+ localScopeDepth: int, >+ }, >+ metadata: { >+ globalObject: JSGlobalObject.*, >+ globalLexicalEnvironment: JSGlobalLexicalEnvironment.*, >+ } >+ >+op :get_from_scope, >+ args: { >+ dst: VirtualRegister, >+ scope: VirtualRegister, >+ var: Constant, >+ getPutInfo: GetPutInfo, >+ localScopeDepth: int, >+ variableOffset?: unsigned, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :put_to_scope, >+ args: { >+ scope: VirtualRegister, >+ var: Constant, >+ value: VirtualRegister, >+ getPutInfo: GetPutInfo, >+ depthOrSymbolTableIndex: unsigned, >+ scopeOffset?: ScopeOffset, >+ } >+ >+op :get_from_arguments, >+ args: { >+ dst: VirtualRegister, >+ scope: VirtualRegister, >+ offset: unsigned, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :put_to_arguments, >+ args: { >+ scope: VirtualRegister, >+ offset: unsigned, >+ value: VirtualRegister, >+ } >+ >+op :push_with_scope, >+ args: { >+ dst: VirtualRegister, >+ currentScope: VirtualRegister, >+ newScope: VirtualRegister, >+ } >+ >+op :create_lexical_environment, >+ args: { >+ dst: VirtualRegister, >+ scope: VirtualRegister, >+ symbolTable: VirtualRegister, >+ initialValue: VirtualRegister, >+ } >+ >+op :get_parent_scope, >+ args: { >+ dst: VirtualRegister, >+ scope: VirtualRegister, >+ } >+ >+op :catch, >+ args: { >+ exception: VirtualRegister, >+ thrownValue: VirtualRegister, >+ }, >+ metadata: { >+ buffer: ValueProfileAndOperandBuffer, >+ } >+ >+op :throw, >+ args: { >+ value: VirtualRegister, >+ } >+ >+op :throw_static_error, >+ args: { >+ message: VirtualRegister, >+ errorType: ErrorType, >+ } >+ >+op :debug, >+ args: { >+ debugHookType: DebugHookType, >+ hasBreakpoint: bool, >+ } >+ >+op :end, >+ args: { >+ value: VirtualRegister, >+ } >+ >+op :profile_type, >+ args: { >+ target: VirtualRegister, >+ flag: ProfileTypeBytecodeFlag, >+ identifier?: Constant, >+ resolveType: ResolveType, >+ }, >+ metadata: { >+ typeLocation: TypeLocation.*, >+ } >+ >+op :profile_control_flow, >+ args: { >+ textOffset: BasicBlockLocation.*, >+ } >+ >+op :get_enumerable_length, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ } >+ >+op :has_indexed_property, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: VirtualRegister, >+ }, >+ metadata: { >+ arrayProfile: ArrayProfile, >+ } >+ >+op :has_structure_property, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: VirtualRegister, >+ enumerator: VirtualRegister, >+ } >+ >+op :has_generic_property, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: VirtualRegister, >+ } >+ >+op :get_direct_pname, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ property: VirtualRegister, >+ index: VirtualRegister, >+ enumerator: VirtualRegister, >+ }, >+ metadata: { >+ profile: ValueProfile, >+ } >+ >+op :get_property_enumerator, >+ args: { >+ dst: VirtualRegister, >+ base: VirtualRegister, >+ } >+ >+op :enumerator_structure_pname, >+ args: { >+ dst: VirtualRegister, >+ enumerator: VirtualRegister, >+ index: VirtualRegister, >+ } >+ >+op :enumerator_generic_pname, >+ args: { >+ dst: VirtualRegister, >+ enumerator: VirtualRegister, >+ index: VirtualRegister, >+ } >+ >+op :to_index_string, >+ args: { >+ dst: VirtualRegister, >+ index: VirtualRegister, >+ } >+ >+op :unreachable >+ >+op :create_rest, >+ args: { >+ dst: VirtualRegister, >+ arraySize: unsigned, >+ numParametersToSkip: unsigned, >+ } >+ >+op :get_rest_length, >+ args: { >+ dst: VirtualRegister, >+ numParametersToSkip: unsigned, >+ } >+ >+op :yield, >+ args: { >+ generator: VirtualRegister, >+ yieldPoint: unsigned, >+ argument: VirtualRegister, >+ } >+ >+op :check_traps >+ >+op :log_shadow_chicken_prologue, >+ args: { >+ scope: VirtualRegister, >+ } >+ >+op :log_shadow_chicken_tail, >+ args: { >+ thisValue: VirtualRegister, >+ scope: VirtualRegister, >+ } >+ >+op :resolve_scope_for_hoisting_func_decl_in_eval, >+ args: { >+ dst: VirtualRegister, >+ scope: VirtualRegister, >+ property: Constant, >+ } >+ >+op :nop >+ >+op :super_sampler_begin >+ >+op :super_sampler_end >+ >+end_section :Bytecodes >+ >+begin_section :CLoopHelpers, >+ emit_in_h_file: true, >+ macro_name_component: :CLOOP_BYTECODE_HELPER >+ >+op :llint_entry >+op :getHostCallReturnValue >+op :llint_return_to_host >+op :llint_vm_entry_to_javascript >+op :llint_vm_entry_to_native >+op :llint_cloop_did_return_from_js_1 >+op :llint_cloop_did_return_from_js_2 >+op :llint_cloop_did_return_from_js_3 >+op :llint_cloop_did_return_from_js_4 >+op :llint_cloop_did_return_from_js_5 >+op :llint_cloop_did_return_from_js_6 >+op :llint_cloop_did_return_from_js_7 >+op :llint_cloop_did_return_from_js_8 >+op :llint_cloop_did_return_from_js_9 >+op :llint_cloop_did_return_from_js_10 >+op :llint_cloop_did_return_from_js_11 >+op :llint_cloop_did_return_from_js_12 >+ >+end_section :CLoopHelpers >+ >+begin_section :NativeHelpers, >+ emit_in_h_file: true, >+ emit_in_asm_file: true, >+ macro_name_component: :BYTECODE_HELPER >+ >+op :llint_program_prologue >+op :llint_eval_prologue >+op :llint_module_program_prologue >+op :llint_function_for_call_prologue >+op :llint_function_for_construct_prologue >+op :llint_function_for_call_arity_check >+op :llint_function_for_construct_arity_check >+op :llint_generic_return_point >+op :llint_throw_from_slow_path_trampoline >+op :llint_throw_during_call_trampoline >+op :llint_native_call_trampoline >+op :llint_native_construct_trampoline >+op :llint_internal_function_call_trampoline >+op :llint_internal_function_construct_trampoline >+op :handleUncaughtException >+ >+end_section :NativeHelpers >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >index d051ab37da10f70fde0fff97f37d201033ab7310..510c6323ce2e86a6904fb0ebd1db715851aaf130 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >@@ -542,7 +542,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink > > unsigned opLength = opcodeLength(pc[0].u.opcode); > >- instructions[i] = Interpreter::getOpcode(pc[0].u.opcode); >+ instructions[i] = pc[0].u.opcode; > for (size_t j = 1; j < opLength; ++j) { > if (sizeof(int32_t) != sizeof(intptr_t)) > instructions[i + j].u.pointer = 0; >@@ -1132,7 +1132,7 @@ void CodeBlock::propagateTransitions(const ConcurrentJSLocker&, SlotVisitor& vis > const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions(); > for (size_t i = 0; i < propertyAccessInstructions.size(); ++i) { > Instruction* instruction = &instructions()[propertyAccessInstructions[i]]; >- switch (Interpreter::getOpcodeID(instruction[0])) { >+ switch (instruction[0].u.opcode) { > case op_put_by_id: { > StructureID oldStructureID = instruction[4].u.structureID; > StructureID newStructureID = instruction[6].u.structureID; >@@ -1245,7 +1245,7 @@ void CodeBlock::determineLiveness(const ConcurrentJSLocker&, SlotVisitor& visito > > void CodeBlock::clearLLIntGetByIdCache(Instruction* instruction) > { >- instruction[0].u.opcode = LLInt::getOpcode(op_get_by_id); >+ instruction[0].u.opcode = op_get_by_id; > instruction[4].u.pointer = nullptr; > instruction[5].u.pointer = nullptr; > instruction[6].u.pointer = nullptr; >@@ -1257,7 +1257,7 @@ void CodeBlock::finalizeLLIntInlineCaches() > const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions(); > for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) { > Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]]; >- switch (Interpreter::getOpcodeID(curInstruction[0])) { >+ switch (curInstruction[0].u.opcode) { > case op_get_by_id: { > StructureID oldStructureID = curInstruction[4].u.structureID; > if (!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID))) >@@ -1349,7 +1349,7 @@ void CodeBlock::finalizeLLIntInlineCaches() > break; > } > default: >- OpcodeID opcodeID = Interpreter::getOpcodeID(curInstruction[0]); >+ OpcodeID opcodeID = curInstruction[0].u.opcode; > ASSERT_WITH_MESSAGE_UNUSED(opcodeID, false, "Unhandled opcode in CodeBlock::finalizeUnconditionally, %s(%d) at bc %u", opcodeNames[opcodeID], opcodeID, propertyAccessInstructions[i]); > } > } >@@ -1359,7 +1359,7 @@ void CodeBlock::finalizeLLIntInlineCaches() > m_llintGetByIdWatchpointMap.removeIf([&] (const StructureWatchpointMap::KeyValuePairType& pair) -> bool { > auto clear = [&] () { > Instruction* instruction = std::get<1>(pair.key); >- OpcodeID opcode = Interpreter::getOpcodeID(*instruction); >+ OpcodeID opcode = instruction->u.opcode; > if (opcode == op_get_by_id_proto_load || opcode == op_get_by_id_unset) { > if (Options::verboseOSR()) > dataLogF("Clearing LLInt property access.\n"); >@@ -1695,7 +1695,7 @@ CallSiteIndex CodeBlock::newExceptionHandlingCallSiteIndex(CallSiteIndex origina > > void CodeBlock::ensureCatchLivenessIsComputedForBytecodeOffsetSlow(unsigned bytecodeOffset) > { >- ASSERT(Interpreter::getOpcodeID(m_instructions[bytecodeOffset]) == op_catch); >+ ASSERT(m_instructions[bytecodeOffset].u.opcode == op_catch); > BytecodeLivenessAnalysis& bytecodeLiveness = livenessAnalysis(); > > // We get the live-out set of variables at op_catch, not the live-in. This >diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h >deleted file mode 100644 >index c133578b3263d3029845e48379a35960704a6efd..0000000000000000000000000000000000000000 >--- a/Source/JavaScriptCore/bytecode/Instruction.h >+++ /dev/null >@@ -1,160 +0,0 @@ >-/* >- * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * 3. Neither the name of Apple Inc. ("Apple") nor the names of >- * its contributors may be used to endorse or promote products derived >- * from this software without specific prior written permission. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 "BasicBlockLocation.h" >-#include "PutByIdFlags.h" >-#include "SymbolTable.h" >-#include "TypeLocation.h" >-#include "PropertySlot.h" >-#include "SpecialPointer.h" >-#include "Structure.h" >-#include "StructureChain.h" >-#include "ToThisStatus.h" >-#include <wtf/VectorTraits.h> >- >-namespace JSC { >- >-class ArrayAllocationProfile; >-class ArrayProfile; >-class ObjectAllocationProfile; >-class WatchpointSet; >-struct LLIntCallLinkInfo; >-struct ValueProfile; >- >-#if ENABLE(COMPUTED_GOTO_OPCODES) >-typedef void* Opcode; >-#else >-typedef OpcodeID Opcode; >-#endif >- >-struct Instruction { >- constexpr Instruction() >- : u({ nullptr }) >- { >- } >- >- Instruction(Opcode opcode) >- { >-#if !ENABLE(COMPUTED_GOTO_OPCODES) >- // We have to initialize one of the pointer members to ensure that >- // the entire struct is initialized, when opcode is not a pointer. >- u.jsCell.clear(); >-#endif >- u.opcode = opcode; >- } >- >- Instruction(int operand) >- { >- // We have to initialize one of the pointer members to ensure that >- // the entire struct is initialized in 64-bit. >- u.jsCell.clear(); >- u.operand = operand; >- } >- Instruction(unsigned unsignedValue) >- { >- // We have to initialize one of the pointer members to ensure that >- // the entire struct is initialized in 64-bit. >- u.jsCell.clear(); >- u.unsignedValue = unsignedValue; >- } >- >- Instruction(PutByIdFlags flags) >- { >- u.putByIdFlags = flags; >- } >- >- Instruction(VM& vm, JSCell* owner, Structure* structure) >- { >- u.structure.clear(); >- u.structure.set(vm, owner, structure); >- } >- Instruction(VM& vm, JSCell* owner, StructureChain* structureChain) >- { >- u.structureChain.clear(); >- u.structureChain.set(vm, owner, structureChain); >- } >- Instruction(VM& vm, JSCell* owner, JSCell* jsCell) >- { >- u.jsCell.clear(); >- u.jsCell.set(vm, owner, jsCell); >- } >- >- Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; } >- >- Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; } >- Instruction(ValueProfile* profile) { u.profile = profile; } >- Instruction(ArrayProfile* profile) { u.arrayProfile = profile; } >- Instruction(ArrayAllocationProfile* profile) { u.arrayAllocationProfile = profile; } >- Instruction(ObjectAllocationProfile* profile) { u.objectAllocationProfile = profile; } >- Instruction(WriteBarrier<Unknown>* variablePointer) { u.variablePointer = variablePointer; } >- Instruction(Special::Pointer pointer) { u.specialPointer = pointer; } >- Instruction(UniquedStringImpl* uid) { u.uid = uid; } >- Instruction(bool* predicatePointer) { u.predicatePointer = predicatePointer; } >- >- union { >- void* pointer; >- Opcode opcode; >- int operand; >- unsigned unsignedValue; >- WriteBarrierBase<Structure> structure; >- StructureID structureID; >- WriteBarrierBase<SymbolTable> symbolTable; >- WriteBarrierBase<StructureChain> structureChain; >- WriteBarrierBase<JSCell> jsCell; >- WriteBarrier<Unknown>* variablePointer; >- Special::Pointer specialPointer; >- PropertySlot::GetValueFunc getterFunc; >- LLIntCallLinkInfo* callLinkInfo; >- UniquedStringImpl* uid; >- ValueProfile* profile; >- ArrayProfile* arrayProfile; >- ArrayAllocationProfile* arrayAllocationProfile; >- ObjectAllocationProfile* objectAllocationProfile; >- WatchpointSet* watchpointSet; >- bool* predicatePointer; >- ToThisStatus toThisStatus; >- TypeLocation* location; >- BasicBlockLocation* basicBlockLocation; >- PutByIdFlags putByIdFlags; >- } u; >- >-private: >- Instruction(StructureChain*); >- Instruction(Structure*); >-}; >-static_assert(sizeof(Instruction) == sizeof(void*), ""); >- >-} // namespace JSC >- >-namespace WTF { >- >-template<> struct VectorTraits<JSC::Instruction> : VectorTraitsBase<true, JSC::Instruction> { }; >- >-} // namespace WTF >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 00afc9f96c2a95c17735f1634cbe70576cac3d17..5fb02e5c7e42a102b48ea19bbb932bf593f46b33 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -159,10 +159,7 @@ ParserError BytecodeGenerator::generate() > > for (auto& tuple : m_catchesToEmit) { > Ref<Label> realCatchTarget = newEmittedLabel(); >- emitOpcode(op_catch); >- instructions().append(std::get<1>(tuple)); >- instructions().append(std::get<2>(tuple)); >- instructions().append(0); >+ OpCatch::emit(this, std::get<1>(tuple), std::get<2>(tuple)); > > TryData* tryData = std::get<0>(tuple); > emitJump(tryData->target.get()); >@@ -448,20 +445,12 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke > entry.disableWatching(*m_vm); > functionSymbolTable->set(NoLockingNecessary, name, entry); > } >- emitOpcode(op_put_to_scope); >- instructions().append(m_lexicalEnvironmentRegister->index()); >- instructions().append(UINT_MAX); >- instructions().append(virtualRegisterForArgument(1 + i).offset()); >- instructions().append(GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand()); >- instructions().append(symbolTableConstantIndex); >- instructions().append(offset.offset()); >+ OpPutToScope::emit(this, m_lexicalEnvironmentRegister->index(), UINT_MAX, virtualRegisterForArgument(1 + i), GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand(), symbolTableConstantIndex, offset); > } > > // This creates a scoped arguments object and copies the overflow arguments into the > // scope. It's the equivalent of calling ScopedArguments::createByCopying(). >- emitOpcode(op_create_scoped_arguments); >- instructions().append(m_argumentsRegister->index()); >- instructions().append(m_lexicalEnvironmentRegister->index()); >+ OpCreateScopedArguments::emit(this, m_argumentsRegister, m_lexicalEnvironmentRegister); > } else { > // We're going to put all parameters into the DirectArguments object. First ensure > // that the symbol table knows that this is happening. >@@ -470,8 +459,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke > functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i)))); > } > >- emitOpcode(op_create_direct_arguments); >- instructions().append(m_argumentsRegister->index()); >+ OpCreateDirectArgument::emit(this, m_argumentsRegister); > } > } else if (isSimpleParameterList) { > // Create the formal parameters the normal way. Any of them could be captured, or not. If >@@ -495,20 +483,13 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke > static_cast<const BindingNode*>(parameters.at(i).first)->boundProperty(); > functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(offset))); > >- emitOpcode(op_put_to_scope); >- instructions().append(m_lexicalEnvironmentRegister->index()); >- instructions().append(addConstant(ident)); >- instructions().append(virtualRegisterForArgument(1 + i).offset()); >- instructions().append(GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand()); >- instructions().append(symbolTableConstantIndex); >- instructions().append(offset.offset()); >+ OpPutToScope::emit(this, m_lexicalEnvironmentRegister, addConstant(ident), virtualRegisterForArgument(1 + i), GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization), symbolTableConstantIndex, offset); > } > } > > if (needsArguments && (codeBlock->isStrictMode() || !isSimpleParameterList)) { > // Allocate a cloned arguments object. >- emitOpcode(op_create_cloned_arguments); >- instructions().append(m_argumentsRegister->index()); >+ OpCreateClonedArguments::emit(this, m_argumentsRegister); > } > > // There are some variables that need to be preinitialized to something other than Undefined: >@@ -1165,15 +1146,9 @@ void BytecodeGenerator::initializeVarLexicalEnvironment(int symbolTableConstantI > { > if (hasCapturedVariables) { > RELEASE_ASSERT(m_lexicalEnvironmentRegister); >- emitOpcode(op_create_lexical_environment); >- instructions().append(m_lexicalEnvironmentRegister->index()); >- instructions().append(scopeRegister()->index()); >- instructions().append(symbolTableConstantIndex); >- instructions().append(addConstantValue(jsUndefined())->index()); >+ OpCreateLexicalEnvironment::emit(this, m_lexicalEnvironmentRegister->index(), scopeRegister(), symbolTableConstantIndex, addConstantValue(jsUndefined())); > >- emitOpcode(op_mov); >- instructions().append(scopeRegister()->index()); >- instructions().append(m_lexicalEnvironmentRegister->index()); >+ OpMov::emit(this, scopeRegister(), m_lexicalEnvironmentRegister); > > pushLocalControlFlowScope(); > } >@@ -1267,14 +1242,14 @@ void BytecodeGenerator::emitLabel(Label& l0) > m_lastOpcodeID = op_end; > } > >-void BytecodeGenerator::emitOpcode(OpcodeID opcodeID) >+void BytecodeGenerator::recordOpcode(OpcodeID opcodeID) > { > #ifndef NDEBUG > size_t opcodePosition = instructions().size(); > ASSERT(opcodePosition - m_lastOpcodePosition == opcodeLength(m_lastOpcodeID) || m_lastOpcodeID == op_end); > m_lastOpcodePosition = opcodePosition; > #endif >- instructions().append(opcodeID); >+ m_lastOffset = instructions.size(); > m_lastOpcodeID = opcodeID; > } > >@@ -1293,18 +1268,9 @@ UnlinkedObjectAllocationProfile BytecodeGenerator::newObjectAllocationProfile() > return m_codeBlock->addObjectAllocationProfile(); > } > >-UnlinkedValueProfile BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID) >-{ >- emitOpcode(opcodeID); >- if (!m_vm->canUseJIT()) >- return static_cast<UnlinkedValueProfile>(-1); >- UnlinkedValueProfile result = m_codeBlock->addValueProfile(); >- return result; >-} >- > void BytecodeGenerator::emitEnter() > { >- emitOpcode(op_enter); >+ OpEnter::emit(this); > > if (LIKELY(Options::optimizeRecursiveTailCalls())) { > // We must add the end of op_enter as a potential jump target, because the bytecode parser may decide to split its basic block >@@ -1317,22 +1283,24 @@ void BytecodeGenerator::emitEnter() > > void BytecodeGenerator::emitLoopHint() > { >- emitOpcode(op_loop_hint); >+ OpLoopHint::emit(this); > emitCheckTraps(); > } > > void BytecodeGenerator::emitCheckTraps() > { >- emitOpcode(op_check_traps); >+ OpCheckTraps::emit(this); > } > > void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index) > { > ASSERT(instructions().size() >= 4); > size_t size = instructions().size(); >- dstIndex = instructions().at(size - 3).u.operand; >- src1Index = instructions().at(size - 2).u.operand; >- src2Index = instructions().at(size - 1).u.operand; >+ >+ auto instr = reinterpret_cast<Instruction*>(instructions().data() + m_lastOffset)->as<BinaryOp>(); >+ dst = instr->dst(); >+ src1Index = instr->lhs(); >+ src2Index = instr->rhs(); > } > > void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex) >@@ -1359,9 +1327,7 @@ void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp() > > void BytecodeGenerator::emitJump(Label& target) > { >- size_t begin = instructions().size(); >- emitOpcode(op_jmp); >- instructions().append(target.bind(begin, instructions().size())); >+ OpJmp::emit(this, target.bind(this, 1)); > } > > void BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label& target) >@@ -1376,11 +1342,7 @@ void BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label& target) > if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { > rewindBinaryOp(); > >- size_t begin = instructions().size(); >- emitOpcode(jumpID); >- instructions().append(src1Index); >- instructions().append(src2Index); >- instructions().append(target.bind(begin, instructions().size())); >+ BinaryJmp::emit(this, src1Index, src2Index, target.bind(this, 3)); > return true; > } > return false; >@@ -1424,11 +1386,7 @@ void BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label& target) > > if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { > rewindUnaryOp(); >- >- size_t begin = instructions().size(); >- emitOpcode(op_jeq_null); >- instructions().append(srcIndex); >- instructions().append(target.bind(begin, instructions().size())); >+ OpJeqNull::emit(this, srcIndex, target.bind(this, 2)); > return; > } > } else if (m_lastOpcodeID == op_neq_null && target.isForward()) { >@@ -1440,19 +1398,14 @@ void BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label& target) > if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { > rewindUnaryOp(); > >- size_t begin = instructions().size(); >- emitOpcode(op_jneq_null); >- instructions().append(srcIndex); >- instructions().append(target.bind(begin, instructions().size())); >+ OpJeqNull::emit(this, srcIndex, target.bind(this, 2)); > return; > } > } > > size_t begin = instructions().size(); > >- emitOpcode(op_jtrue); >- instructions().append(cond->index()); >- instructions().append(target.bind(begin, instructions().size())); >+ OpJtrue::emit(this, cond, target.bind(this, 2)); > } > > void BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label& target) >@@ -1467,14 +1420,10 @@ void BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label& target) > if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { > rewindBinaryOp(); > >- size_t begin = instructions().size(); >- emitOpcode(jumpID); > // Since op_below and op_beloweq only accepts Int32, replacing operands is not observable to users. > if (replaceOperands) > std::swap(src1Index, src2Index); >- instructions().append(src1Index); >- instructions().append(src2Index); >- instructions().append(target.bind(begin, instructions().size())); >+ BinaryJmp::emit(this, jumpID, src1Index, src2Index, target.bind(this, 3)); > return true; > } > return false; >@@ -1518,11 +1467,7 @@ void BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label& target) > > if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { > rewindUnaryOp(); >- >- size_t begin = instructions().size(); >- emitOpcode(op_jtrue); >- instructions().append(srcIndex); >- instructions().append(target.bind(begin, instructions().size())); >+ OpJtrue::emit(this, srcIndex, target.bind(this, 2)); > return; > } > } else if (m_lastOpcodeID == op_eq_null && target.isForward()) { >@@ -1533,11 +1478,7 @@ void BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label& target) > > if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { > rewindUnaryOp(); >- >- size_t begin = instructions().size(); >- emitOpcode(op_jneq_null); >- instructions().append(srcIndex); >- instructions().append(target.bind(begin, instructions().size())); >+ OpJneqNull::emit(this, srcIndex, target.bind(this, 2)); > return; > } > } else if (m_lastOpcodeID == op_neq_null && target.isForward()) { >@@ -1548,41 +1489,22 @@ void BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label& target) > > if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { > rewindUnaryOp(); >- >- size_t begin = instructions().size(); >- emitOpcode(op_jeq_null); >- instructions().append(srcIndex); >- instructions().append(target.bind(begin, instructions().size())); >+ OpJeqNull::emit(this, srcIndex, target.bind(this, 2)); > return; > } > } > >- size_t begin = instructions().size(); >- emitOpcode(op_jfalse); >- instructions().append(cond->index()); >- instructions().append(target.bind(begin, instructions().size())); >+ OpJfalse::emit(this, cond, target.bind(this, 2)); > } > > void BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label& target) > { >- size_t begin = instructions().size(); >- >- emitOpcode(op_jneq_ptr); >- instructions().append(cond->index()); >- instructions().append(Special::CallFunction); >- instructions().append(target.bind(begin, instructions().size())); >- instructions().append(0); >+ OpJneqPtr::emit(this, cond->index(), Special::CallFunction, target.bind(this, 3)); > } > > void BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label& target) > { >- size_t begin = instructions().size(); >- >- emitOpcode(op_jneq_ptr); >- instructions().append(cond->index()); >- instructions().append(Special::ApplyFunction); >- instructions().append(target.bind(begin, instructions().size())); >- instructions().append(0); >+ OpJneqPtr::emit(this, cond->index(), Special::ApplyFunction, target.bind(this, 3)); > } > > bool BytecodeGenerator::hasConstant(const Identifier& ident) const >@@ -1644,9 +1566,7 @@ RegisterID* BytecodeGenerator::moveLinkTimeConstant(RegisterID* dst, LinkTimeCon > if (!dst) > return m_linkTimeConstantRegisters[constantIndex]; > >- emitOpcode(op_mov); >- instructions().append(dst->index()); >- instructions().append(m_linkTimeConstantRegisters[constantIndex]->index()); >+ OpMov::emit(this, dst->index(), m_linkTimeConstantRegisters[constantIndex]->index()); > > return dst; > } >@@ -1655,9 +1575,8 @@ RegisterID* BytecodeGenerator::moveEmptyValue(RegisterID* dst) > { > RefPtr<RegisterID> emptyValue = addConstantEmptyValue(); > >- emitOpcode(op_mov); >- instructions().append(dst->index()); >- instructions().append(emptyValue->index()); >+ OpMov::emit(this, dst->index(), emptyValue->index()); >+ > return dst; > } > >@@ -1666,9 +1585,7 @@ RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src) > ASSERT(src != m_emptyValueRegister); > > m_staticPropertyAnalyzer.mov(dst->index(), src->index()); >- emitOpcode(op_mov); >- instructions().append(dst->index()); >- instructions().append(src->index()); >+ OpMov::emit(this, dst, src); > > return dst; > } >@@ -1677,22 +1594,13 @@ RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, R > { > ASSERT_WITH_MESSAGE(op_to_number != opcodeID, "op_to_number has a Value Profile."); > ASSERT_WITH_MESSAGE(op_negate != opcodeID, "op_negate has an Arith Profile."); >- emitOpcode(opcodeID); >- instructions().append(dst->index()); >- instructions().append(src->index()); >- >+ UnaryOp::emit(this, opcodeID, dst, src); > return dst; > } > > RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src, OperandTypes types) > { >- ASSERT_WITH_MESSAGE(op_to_number != opcodeID, "op_to_number has a Value Profile."); >- emitOpcode(opcodeID); >- instructions().append(dst->index()); >- instructions().append(src->index()); >- >- if (opcodeID == op_negate) >- instructions().append(ArithProfile(types.first()).bits()); >+ ArithUnaryOp::emit(this, opcodeID, dst, src); > return dst; > } > >@@ -1707,39 +1615,39 @@ RegisterID* BytecodeGenerator::emitUnaryOpProfiled(OpcodeID opcodeID, RegisterID > > RegisterID* BytecodeGenerator::emitToObject(RegisterID* dst, RegisterID* src, const Identifier& message) > { >- UnlinkedValueProfile profile = emitProfiledOpcode(op_to_object); >- instructions().append(dst->index()); >- instructions().append(src->index()); >- instructions().append(addConstant(message)); >- instructions().append(profile); >+ OpToObject::emit(this, dst, src, addConstant(message)); >+ return dst; >+} >+ >+RegisterID* BytecodeGenerator::emitToNumber(RegisterID* dst, RegisterID* src, const Identifier& message) >+{ >+ OpToNumber::emit(this, dst, src); > return dst; > } > > RegisterID* BytecodeGenerator::emitInc(RegisterID* srcDst) > { >- emitOpcode(op_inc); >- instructions().append(srcDst->index()); >+ OpInc::emit(this, srcDst); > return srcDst; > } > > RegisterID* BytecodeGenerator::emitDec(RegisterID* srcDst) > { >- emitOpcode(op_dec); >- instructions().append(srcDst->index()); >+ OpDec::emit(this, srcDst); > return srcDst; > } > > RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types) > { >- emitOpcode(opcodeID); >- instructions().append(dst->index()); >- instructions().append(src1->index()); >- instructions().append(src2->index()); >+ BinaryOp::emit(this, opcodeID, dst, src1, src2); >+ return dst; >+} > >- if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor || >- opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div) >- instructions().append(ArithProfile(types.first(), types.second()).bits()); >+RegisterID* BytecodeGenerator::emitProfiledBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types) >+{ >+ ProfiledBinaryOp::emit(dst, opcodeID, src1, src2); > >+ instructions().append(ArithProfile(types.first(), types.second()).bits()); > return dst; > } > >@@ -1758,70 +1666,48 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst > const String& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue(); > if (value == "undefined") { > rewindUnaryOp(); >- emitOpcode(op_is_undefined); >- instructions().append(dst->index()); >- instructions().append(srcIndex); >+ OpIsUndefined::emit(this, dst, srcIndex); > return dst; > } > if (value == "boolean") { > rewindUnaryOp(); >- emitOpcode(op_is_boolean); >- instructions().append(dst->index()); >- instructions().append(srcIndex); >+ OpIsBoolean::emit(this, dst, srcIndex); > return dst; > } > if (value == "number") { > rewindUnaryOp(); >- emitOpcode(op_is_number); >- instructions().append(dst->index()); >- instructions().append(srcIndex); >+ OpIsNumber::emit(this, dst, srcIndex); > return dst; > } > if (value == "string") { > rewindUnaryOp(); >- emitOpcode(op_is_cell_with_type); >- instructions().append(dst->index()); >- instructions().append(srcIndex); >- instructions().append(StringType); >+ OpIsCellWithType::emit(this, dst, srcIndex, StringType); > return dst; > } > if (value == "symbol") { > rewindUnaryOp(); >- emitOpcode(op_is_cell_with_type); >- instructions().append(dst->index()); >- instructions().append(srcIndex); >- instructions().append(SymbolType); >+ OpIsCellWithType::emit(this, dst, srcIndex, SymbolType); > return dst; > } > if (Options::useBigInt() && value == "bigint") { > rewindUnaryOp(); >- emitOpcode(op_is_cell_with_type); >- instructions().append(dst->index()); >- instructions().append(srcIndex); >- instructions().append(BigIntType); >+ OpIsCellWithType::emit(this, dst, srcIndex, BigIntType); > return dst; > } > if (value == "object") { > rewindUnaryOp(); >- emitOpcode(op_is_object_or_null); >- instructions().append(dst->index()); >- instructions().append(srcIndex); >+ OpIsObjectOrNull::emit(this, dst, srcIndex); > return dst; > } > if (value == "function") { > rewindUnaryOp(); >- emitOpcode(op_is_function); >- instructions().append(dst->index()); >- instructions().append(srcIndex); >+ OpIsFunction::emit(this, dst, srcIndex); > return dst; > } > } > } > >- emitOpcode(opcodeID); >- instructions().append(dst->index()); >- instructions().append(src1->index()); >- instructions().append(src2->index()); >+ BinaryOp::emit(this, dst, src1, src2); > return dst; > } > >@@ -1843,12 +1729,7 @@ void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTy > if (!registerToProfile) > return; > >- emitOpcode(op_profile_type); >- instructions().append(registerToProfile->index()); >- instructions().append(0); >- instructions().append(flag); >- instructions().append(0); >- instructions().append(resolveType()); >+ OpProfileType::emit(this, registerToProfile, flag, nullopt, resolveType()); > > // Don't emit expression info for this version of profile type. This generally means > // we're profiling information for something that isn't in the actual text of a JavaScript >@@ -1869,13 +1750,7 @@ void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTy > return; > > // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType? >- emitOpcode(op_profile_type); >- instructions().append(registerToProfile->index()); >- instructions().append(0); >- instructions().append(flag); >- instructions().append(0); >- instructions().append(resolveType()); >- >+ OpProfileType::emit(this, registerToProfile, flag, nullopt, resolveType()); > emitTypeProfilerExpressionInfo(startDivot, endDivot); > } > >@@ -1899,12 +1774,7 @@ void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const Var > } > > // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType? >- emitOpcode(op_profile_type); >- instructions().append(registerToProfile->index()); >- instructions().append(symbolTableOrScopeDepth); >- instructions().append(flag); >- instructions().append(addConstant(var.ident())); >- instructions().append(resolveType()); >+ OpProfileType::emit(this, registerToProfile, symbolTableOrScopeDepth, flag, addConstant(var.ident()), resolveType()); > > emitTypeProfilerExpressionInfo(startDivot, endDivot); > } >@@ -1916,8 +1786,7 @@ void BytecodeGenerator::emitProfileControlFlow(int textOffset) > size_t bytecodeOffset = instructions().size(); > m_codeBlock->addOpProfileControlFlowBytecodeOffset(bytecodeOffset); > >- emitOpcode(op_profile_control_flow); >- instructions().append(textOffset); >+ OpProfileControlFlow::emit(this, textOffset); > } > } > >@@ -2116,11 +1985,7 @@ void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environmen > if (constantSymbolTableResult) > *constantSymbolTableResult = constantSymbolTable; > >- emitOpcode(op_create_lexical_environment); >- instructions().append(newScope->index()); >- instructions().append(scopeRegister()->index()); >- instructions().append(constantSymbolTable->index()); >- instructions().append(addConstantValue(tdzRequirement == TDZRequirement::UnderTDZ ? jsTDZValue() : jsUndefined())->index()); >+ OpCreateLexicalEnvironment::emit(this, newScope, scopeRegister(), constantSymbolTable, addConstantValue(tdzRequirement == TDZRequirement::UnderTDZ ? jsTDZValue() : jsUndefined())->index()); > > move(scopeRegister(), newScope); > >@@ -2251,10 +2116,7 @@ RegisterID* BytecodeGenerator::emitResolveScopeForHoistingFuncDeclInEval(Registe > ASSERT(m_codeType == EvalCode); > > dst = finalDestination(dst); >- emitOpcode(op_resolve_scope_for_hoisting_func_decl_in_eval); >- instructions().append(kill(dst)); >- instructions().append(m_topMostScope->index()); >- instructions().append(addConstant(property)); >+ OpResolveScopeForHoistingFuncDeclInEval::emit(this, kill(dst), m_topMostScope, addConstant(property)); > return dst; > } > >@@ -2352,11 +2214,7 @@ void BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration(VariableEnvir > RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), loopScope); > move(scopeRegister(), parentScope.get()); > >- emitOpcode(op_create_lexical_environment); >- instructions().append(loopScope->index()); >- instructions().append(scopeRegister()->index()); >- instructions().append(loopSymbolTable->index()); >- instructions().append(addConstantValue(jsTDZValue())->index()); >+ OpCreateLexicalEnvironment::emit(this, loopScope, scopeRegister(), loopSymbolTable, addConstantValue(jsTDZValue())); > > move(scopeRegister(), loopScope); > >@@ -2481,10 +2339,7 @@ void BytecodeGenerator::createVariable( > > RegisterID* BytecodeGenerator::emitOverridesHasInstance(RegisterID* dst, RegisterID* constructor, RegisterID* hasInstanceValue) > { >- emitOpcode(op_overrides_has_instance); >- instructions().append(dst->index()); >- instructions().append(constructor->index()); >- instructions().append(hasInstanceValue->index()); >+ OpOverridesHasInstance::emit(this, dst, constructor, hasInstanceValue); > return dst; > } > >@@ -2549,13 +2404,7 @@ RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Variable& > > // resolve_scope dst, id, ResolveType, depth > dst = tempDestination(dst); >- emitOpcode(op_resolve_scope); >- instructions().append(kill(dst)); >- instructions().append(scopeRegister()->index()); >- instructions().append(addConstant(variable.ident())); >- instructions().append(resolveType()); >- instructions().append(localScopeDepth()); >- instructions().append(0); >+ OpResolveScope::emit(this, kill(dst), scopeRegister(), addConstant(variable.ident()), resolveType(), localScopeDepth()); > return dst; > } > >@@ -2605,10 +2454,7 @@ RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Variable& > return value; > > case VarKind::DirectArgument: >- emitOpcode(op_put_to_arguments); >- instructions().append(scope->index()); >- instructions().append(variable.offset().capturedArgumentsOffset().offset()); >- instructions().append(value->index()); >+ OpPutToArguments::emit(this, scope, variable.offset().capturedArgumentsOffset().offset(), value); > return value; > > case VarKind::Scope: >@@ -2616,10 +2462,7 @@ RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Variable& > m_codeBlock->addPropertyAccessInstruction(instructions().size()); > > // put_to_scope scope, id, value, GetPutInfo, Structure, Operand >- emitOpcode(op_put_to_scope); >- instructions().append(scope->index()); >- instructions().append(addConstant(variable.ident())); >- instructions().append(value->index()); >+ OpPutToScope::emit(this, scope, addConstant(variable.ident()), value); > ScopeOffset offset; > if (variable.offset().isScope()) { > offset = variable.offset().scopeOffset(); >@@ -2646,40 +2489,25 @@ RegisterID* BytecodeGenerator::initializeVariable(const Variable& variable, Regi > > RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype) > { >- emitOpcode(op_instanceof); >- instructions().append(dst->index()); >- instructions().append(value->index()); >- instructions().append(basePrototype->index()); >+ OpInstanceof::emit(this, dst, value, basePrototype); > return dst; > } > > RegisterID* BytecodeGenerator::emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue) > { >- emitOpcode(op_instanceof_custom); >- instructions().append(dst->index()); >- instructions().append(value->index()); >- instructions().append(constructor->index()); >- instructions().append(hasInstanceValue->index()); >+ OpInstanceofCustom::emit(this, dst, value, constructor, hasInstanceValue); > return dst; > } > > RegisterID* BytecodeGenerator::emitInByVal(RegisterID* dst, RegisterID* property, RegisterID* base) > { >- UnlinkedArrayProfile arrayProfile = newArrayProfile(); >- emitOpcode(op_in_by_val); >- instructions().append(dst->index()); >- instructions().append(base->index()); >- instructions().append(property->index()); >- instructions().append(arrayProfile); >+ OpInByVal::emit(this, dst, base, property); > return dst; > } > > RegisterID* BytecodeGenerator::emitInById(RegisterID* dst, RegisterID* base, const Identifier& property) > { >- emitOpcode(op_in_by_id); >- instructions().append(dst->index()); >- instructions().append(base->index()); >- instructions().append(addConstant(property)); >+ OpInById::emit(this, dst, base, addConstant(property)); > return dst; > } > >@@ -2687,11 +2515,7 @@ RegisterID* BytecodeGenerator::emitTryGetById(RegisterID* dst, RegisterID* base, > { > ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties are not supported with tryGetById."); > >- UnlinkedValueProfile profile = emitProfiledOpcode(op_try_get_by_id); >- instructions().append(kill(dst)); >- instructions().append(base->index()); >- instructions().append(addConstant(property)); >- instructions().append(profile); >+ OpTryGetById::emit(this, kill(dst), base, addConstant(property)); > return dst; > } > >@@ -2701,15 +2525,8 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co > > m_codeBlock->addPropertyAccessInstruction(instructions().size()); > >- UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_id); >- instructions().append(kill(dst)); >- instructions().append(base->index()); >- instructions().append(addConstant(property)); >- instructions().append(0); >- instructions().append(0); >- instructions().append(0); >- instructions().append(Options::prototypeHitCountForLLIntCaching()); >- instructions().append(profile); >+ OpGetById::emit(this, kill(dst), base, addConstant(property)); >+ // TODO: instructions().append(Options::prototypeHitCountForLLIntCaching()); > return dst; > } > >@@ -2717,12 +2534,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, Re > { > ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val."); > >- UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_id_with_this); >- instructions().append(kill(dst)); >- instructions().append(base->index()); >- instructions().append(thisVal->index()); >- instructions().append(addConstant(property)); >- instructions().append(profile); >+ OpGetByIdWithThis::emit(this, kill(dst), base, thisVal, addConstant(property)); > return dst; > } > >@@ -2732,13 +2544,7 @@ RegisterID* BytecodeGenerator::emitDirectGetById(RegisterID* dst, RegisterID* ba > > m_codeBlock->addPropertyAccessInstruction(instructions().size()); > >- UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_id_direct); >- instructions().append(kill(dst)); >- instructions().append(base->index()); >- instructions().append(addConstant(property)); >- instructions().append(0); >- instructions().append(0); >- instructions().append(profile); >+ OpGetByIdDirect::emit(this, kill(dst), base, addConstant(property)); > return dst; > } > >@@ -2752,15 +2558,8 @@ RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& p > > m_codeBlock->addPropertyAccessInstruction(instructions().size()); > >- emitOpcode(op_put_by_id); >- instructions().append(base->index()); >- instructions().append(propertyIndex); >- instructions().append(value->index()); >- instructions().append(0); // old structure >- instructions().append(0); // offset >- instructions().append(0); // new structure >- instructions().append(0); // structure chain >- instructions().append(static_cast<int>(PutByIdNone)); // is not direct >+ OpPutById::emit(this, base, propertyIndex, value); >+ // TODO: instructions().append(static_cast<int>(PutByIdNone)); // is not direct > > return value; > } >@@ -2771,11 +2570,7 @@ RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, RegisterID* thisVal > > unsigned propertyIndex = addConstant(property); > >- emitOpcode(op_put_by_id_with_this); >- instructions().append(base->index()); >- instructions().append(thisValue->index()); >- instructions().append(propertyIndex); >- instructions().append(value->index()); >+ OpPutByIdWithThis::emit(this, base, thisValue, propertyIndex, value); > > return value; > } >@@ -2790,15 +2585,8 @@ RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identif > > m_codeBlock->addPropertyAccessInstruction(instructions().size()); > >- emitOpcode(op_put_by_id); >- instructions().append(base->index()); >- instructions().append(propertyIndex); >- instructions().append(value->index()); >- instructions().append(0); // old structure >- instructions().append(0); // offset >- instructions().append(0); // new structure >- instructions().append(0); // structure chain (unused if direct) >- instructions().append(static_cast<int>((putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone)); >+ OpPutById::emit(this, base, propertyIndex, value); >+ // TODO: instructions().append(static_cast<int>((putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone)); > return value; > } > >@@ -2807,11 +2595,7 @@ void BytecodeGenerator::emitPutGetterById(RegisterID* base, const Identifier& pr > unsigned propertyIndex = addConstant(property); > m_staticPropertyAnalyzer.putById(base->index(), propertyIndex); > >- emitOpcode(op_put_getter_by_id); >- instructions().append(base->index()); >- instructions().append(propertyIndex); >- instructions().append(attributes); >- instructions().append(getter->index()); >+ OpPutGetterById::emit(this, base, propertyIndex, attributes, getter); > } > > void BytecodeGenerator::emitPutSetterById(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* setter) >@@ -2819,11 +2603,7 @@ void BytecodeGenerator::emitPutSetterById(RegisterID* base, const Identifier& pr > unsigned propertyIndex = addConstant(property); > m_staticPropertyAnalyzer.putById(base->index(), propertyIndex); > >- emitOpcode(op_put_setter_by_id); >- instructions().append(base->index()); >- instructions().append(propertyIndex); >- instructions().append(attributes); >- instructions().append(setter->index()); >+ OpPutSetterById::emit(this, base, propertyIndex, attributes, setter); > } > > void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* getter, RegisterID* setter) >@@ -2832,30 +2612,17 @@ void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& > > m_staticPropertyAnalyzer.putById(base->index(), propertyIndex); > >- emitOpcode(op_put_getter_setter_by_id); >- instructions().append(base->index()); >- instructions().append(propertyIndex); >- instructions().append(attributes); >- instructions().append(getter->index()); >- instructions().append(setter->index()); >+ OpPutGetterSetterById::emit(this, base, propertyIndex, attributes, getter, setter); > } > > void BytecodeGenerator::emitPutGetterByVal(RegisterID* base, RegisterID* property, unsigned attributes, RegisterID* getter) > { >- emitOpcode(op_put_getter_by_val); >- instructions().append(base->index()); >- instructions().append(property->index()); >- instructions().append(attributes); >- instructions().append(getter->index()); >+ OpPutGetterByVal::emit(this, base, property, attributes, getter); > } > > void BytecodeGenerator::emitPutSetterByVal(RegisterID* base, RegisterID* property, unsigned attributes, RegisterID* setter) > { >- emitOpcode(op_put_setter_by_val); >- instructions().append(base->index()); >- instructions().append(property->index()); >- instructions().append(attributes); >- instructions().append(setter->index()); >+ OpPutSetterByVal::emit(this, base, property, attributes, setter); > } > > void BytecodeGenerator::emitPutGeneratorFields(RegisterID* nextFunction) >@@ -2896,10 +2663,7 @@ void BytecodeGenerator::emitPutAsyncGeneratorFields(RegisterID* nextFunction) > > RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property) > { >- emitOpcode(op_del_by_id); >- instructions().append(dst->index()); >- instructions().append(base->index()); >- instructions().append(addConstant(property)); >+ OpDelById::emit(this, dst, base, addConstant(property)); > return dst; > } > >@@ -2920,112 +2684,70 @@ RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, R > > ASSERT(context.type() == ForInContext::StructureForInContextType); > StructureForInContext& structureContext = static_cast<StructureForInContext&>(context); >- UnlinkedValueProfile profile = emitProfiledOpcode(op_get_direct_pname); >- instructions().append(kill(dst)); >- instructions().append(base->index()); >- instructions().append(property->index()); >- instructions().append(structureContext.index()->index()); >- instructions().append(structureContext.enumerator()->index()); >- instructions().append(profile); >+ OpGetDirectPname::emit(this, kill(dst), base, property, structureContext.index()->index(), structureContext.enumerator()->index()); > > structureContext.addGetInst(instIndex, property->index(), profile); > return dst; > } > >- UnlinkedArrayProfile arrayProfile = newArrayProfile(); >- UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val); >- instructions().append(kill(dst)); >- instructions().append(base->index()); >- instructions().append(property->index()); >- instructions().append(arrayProfile); >- instructions().append(profile); >+ OpGetByVal::emit(this, kill(dst), base, property); > return dst; > } > > RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* thisValue, RegisterID* property) > { >- UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val_with_this); >- instructions().append(kill(dst)); >- instructions().append(base->index()); >- instructions().append(thisValue->index()); >- instructions().append(property->index()); >- instructions().append(profile); >+ OpGetByValWithThis::emit(this, kill(dst), base, thisValue, property); > return dst; > } > > RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value) > { >- UnlinkedArrayProfile arrayProfile = newArrayProfile(); >- emitOpcode(op_put_by_val); >- instructions().append(base->index()); >- instructions().append(property->index()); >- instructions().append(value->index()); >- instructions().append(arrayProfile); >- >+ OpPutByVal::emit(this, base, property, value); > return value; > } > > RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value) > { >- emitOpcode(op_put_by_val_with_this); >- instructions().append(base->index()); >- instructions().append(thisValue->index()); >- instructions().append(property->index()); >- instructions().append(value->index()); >- >+ OpPutByValWithThis::emit(this, base, thisValue, property, value); > return value; > } > > RegisterID* BytecodeGenerator::emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value) > { >- UnlinkedArrayProfile arrayProfile = newArrayProfile(); >- emitOpcode(op_put_by_val_direct); >- instructions().append(base->index()); >- instructions().append(property->index()); >- instructions().append(value->index()); >- instructions().append(arrayProfile); >+ OpPutByValDirect::emit(this, base, property, value); > return value; > } > > RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property) > { >- emitOpcode(op_del_by_val); >- instructions().append(dst->index()); >- instructions().append(base->index()); >- instructions().append(property->index()); >+ OpDelByVal::emit(this, dst, base, property); > return dst; > } > > void BytecodeGenerator::emitSuperSamplerBegin() > { >- emitOpcode(op_super_sampler_begin); >+ OpSuperSamplerBegin::emit(this); > } > > void BytecodeGenerator::emitSuperSamplerEnd() > { >- emitOpcode(op_super_sampler_end); >+ OpSuperSamplerEnd::emit(this); > } > > RegisterID* BytecodeGenerator::emitIdWithProfile(RegisterID* src, SpeculatedType profile) > { >- emitOpcode(op_identity_with_profile); >- instructions().append(src->index()); >- instructions().append(static_cast<uint32_t>(profile >> 32)); >- instructions().append(static_cast<uint32_t>(profile)); >+ OpIdentityWithProfile::emit(this, src, static_cast<uint32_t>(profile >> 32), static_cast<uint32_t>(profile)); > return src; > } > > void BytecodeGenerator::emitUnreachable() > { >- emitOpcode(op_unreachable); >+ OpUnreachable::emit(this); > } > > RegisterID* BytecodeGenerator::emitGetArgument(RegisterID* dst, int32_t index) > { >- UnlinkedValueProfile profile = emitProfiledOpcode(op_get_argument); >- instructions().append(dst->index()); >- instructions().append(index + 1); // Including |this|. >- instructions().append(profile); >+ OpGetArgument::emit(this, dst, index + 1 /* Including |this| */); > return dst; > } > >@@ -3035,18 +2757,13 @@ RegisterID* BytecodeGenerator::emitCreateThis(RegisterID* dst) > m_staticPropertyAnalyzer.createThis(dst->index(), begin + 3); > > m_codeBlock->addPropertyAccessInstruction(instructions().size()); >- emitOpcode(op_create_this); >- instructions().append(dst->index()); >- instructions().append(dst->index()); >- instructions().append(0); >- instructions().append(0); >+ OpCreateThis::emit(this, dst, dst, 0); > return dst; > } > > void BytecodeGenerator::emitTDZCheck(RegisterID* target) > { >- emitOpcode(op_check_tdz); >- instructions().append(target->index()); >+ OpCheckTdz::emit(this, target); > } > > bool BytecodeGenerator::needsTDZCheck(const Variable& variable) >@@ -3149,10 +2866,7 @@ RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst) > size_t begin = instructions().size(); > m_staticPropertyAnalyzer.newObject(dst->index(), begin + 2); > >- emitOpcode(op_new_object); >- instructions().append(dst->index()); >- instructions().append(0); >- instructions().append(newObjectAllocationProfile()); >+ OpNewObject::emit(this, dst, 0); > return dst; > } > >@@ -3195,10 +2909,7 @@ RegisterID* BytecodeGenerator::addTemplateObjectConstant(Ref<TemplateObjectDescr > > RegisterID* BytecodeGenerator::emitNewArrayBuffer(RegisterID* dst, JSImmutableButterfly* array, IndexingType recommendedIndexingType) > { >- emitOpcode(op_new_array_buffer); >- instructions().append(dst->index()); >- instructions().append(addConstantValue(array)->index()); >- instructions().append(newArrayAllocationProfile(recommendedIndexingType)); >+ OpNewArrayBuffer::emit(this, dst, addConstantValue(array)); > return dst; > } > >@@ -3216,11 +2927,7 @@ RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elemen > emitNode(argv.last().get(), n->value()); > } > ASSERT(!length); >- emitOpcode(op_new_array); >- instructions().append(dst->index()); >- instructions().append(argv.size() ? argv[0]->index() : 0); // argv >- instructions().append(argv.size()); // argc >- instructions().append(newArrayAllocationProfile(recommendedIndexingType)); >+ OpNewArray::emit(this, dst, argv.size() ? argv[0]->index() : nullopt, argv.size()); > return dst; > } > >@@ -3246,9 +2953,7 @@ RegisterID* BytecodeGenerator::emitNewArrayWithSpread(RegisterID* dst, ElementNo > RefPtr<RegisterID> tmp = newTemporary(); > emitNode(tmp.get(), expression); > >- emitOpcode(op_spread); >- instructions().append(argv[i].get()->index()); >- instructions().append(tmp.get()->index()); >+ OpSpread::emit(this, argv[i].get(), tmp.get()); > } else { > ExpressionNode* expression = node->value(); > emitNode(argv[i].get(), expression); >@@ -3258,30 +2963,19 @@ RegisterID* BytecodeGenerator::emitNewArrayWithSpread(RegisterID* dst, ElementNo > } > > unsigned bitVectorIndex = m_codeBlock->addBitVector(WTFMove(bitVector)); >- emitOpcode(op_new_array_with_spread); >- instructions().append(dst->index()); >- instructions().append(argv[0]->index()); // argv >- instructions().append(argv.size()); // argc >- instructions().append(bitVectorIndex); >- >+ OpNewArrayWithSpread::emit(this, dst, argv[0], argv.size(), bitVectorIndex); > return dst; > } > > RegisterID* BytecodeGenerator::emitNewArrayWithSize(RegisterID* dst, RegisterID* length) > { >- emitOpcode(op_new_array_with_size); >- instructions().append(dst->index()); >- instructions().append(length->index()); >- instructions().append(newArrayAllocationProfile(ArrayWithUndecided)); >- >+ OpNewArrayWithSize::emit(This, dst, length); > return dst; > } > > RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp) > { >- emitOpcode(op_new_regexp); >- instructions().append(dst->index()); >- instructions().append(addConstantValue(regExp)->index()); >+ OpNewRegexp::emit(This, dst, addConstantValue(regExpr)); > return dst; > } > >@@ -3309,10 +3003,7 @@ void BytecodeGenerator::emitNewFunctionExpressionCommon(RegisterID* dst, Functio > break; > } > >- emitOpcode(opcodeID); >- instructions().append(dst->index()); >- instructions().append(scopeRegister()->index()); >- instructions().append(index); >+ NewFunction::emit(this, opcodeID, dst, scopeRegister(), index); > } > > RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func) >@@ -3345,28 +3036,24 @@ RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, Constr > > unsigned index = m_codeBlock->addFunctionExpr(executable); > >- emitOpcode(op_new_func_exp); >- instructions().append(dst->index()); >- instructions().append(scopeRegister()->index()); >- instructions().append(index); >+ OpNewFuncExp::emit(this, dst, scopeRegister(), index); > return dst; > } > > RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionMetadataNode* function) > { > unsigned index = m_codeBlock->addFunctionDecl(makeFunction(function)); >+ OpcodeID opcodeID; > if (isGeneratorWrapperParseMode(function->parseMode())) >- emitOpcode(op_new_generator_func); >+ opcodeID = op_new_generator_func; > else if (function->parseMode() == SourceParseMode::AsyncFunctionMode) >- emitOpcode(op_new_async_func); >+ opcodeID = op_new_async_func; > else if (isAsyncGeneratorWrapperParseMode(function->parseMode())) { > ASSERT(Options::useAsyncIterator()); >- emitOpcode(op_new_async_generator_func); >+ opcodeID = op_new_async_generator_func; > } else >- emitOpcode(op_new_func); >- instructions().append(dst->index()); >- instructions().append(scopeRegister()->index()); >- instructions().append(index); >+ opcodeID = op_new_func; >+ NewFunction::emit(this, opcodeID, dst, scopeRegister(), index); > return dst; > } > >@@ -3387,9 +3074,7 @@ void BytecodeGenerator::emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, R > > // FIXME: We should use an op_call to an internal function here instead. > // https://bugs.webkit.org/show_bug.cgi?id=155547 >- emitOpcode(op_set_function_name); >- instructions().append(value->index()); >- instructions().append(name->index()); >+ OpSetFunctionName::emit(this, value, name); > } > > RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall) >@@ -3430,11 +3115,7 @@ ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, > return NoExpectedFunction; > > size_t begin = instructions().size(); >- emitOpcode(op_jneq_ptr); >- instructions().append(func->index()); >- instructions().append(Special::ObjectConstructor); >- instructions().append(realCall->bind(begin, instructions().size())); >- instructions().append(0); >+ OpJneqPtr::emit(this, func, Special::ObjectConstructor, realCall->bind(begin, instructions().size()); > > if (dst != ignoredResult()) > emitNewObject(dst); >@@ -3451,22 +3132,15 @@ ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, > return NoExpectedFunction; > > size_t begin = instructions().size(); >- emitOpcode(op_jneq_ptr); >- instructions().append(func->index()); >- instructions().append(Special::ArrayConstructor); >- instructions().append(realCall->bind(begin, instructions().size())); >- instructions().append(0); >+ OpJneqPtr::emit(This, func, Special::ArrayConstructor, realCall->bind(begin, instructions().size()); > > if (dst != ignoredResult()) { > if (callArguments.argumentCountIncludingThis() == 2) > emitNewArrayWithSize(dst, callArguments.argumentRegister(0)); > else { > ASSERT(callArguments.argumentCountIncludingThis() == 1); >- emitOpcode(op_new_array); >- instructions().append(dst->index()); >- instructions().append(0); >- instructions().append(0); >- instructions().append(newArrayAllocationProfile(ArrayWithUndecided)); >+ OpNewArray::emit(This, dst, nullopt, 0); >+ // instructions().append(newArrayAllocationProfile(ArrayWithUndecided)); > } > } > break; >@@ -3478,8 +3152,7 @@ ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, > } > > size_t begin = instructions().size(); >- emitOpcode(op_jmp); >- instructions().append(done.bind(begin, instructions().size())); >+ OpJmp::emit(this, done.bind(begin, instructions().size())); > emitLabel(realCall.get()); > > return expectedFunction; >@@ -3502,9 +3175,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi > if (elements && !elements->next() && elements->value()->isSpreadExpression()) { > ExpressionNode* expression = static_cast<SpreadExpressionNode*>(elements->value())->expression(); > RefPtr<RegisterID> argumentRegister = emitNode(callArguments.argumentRegister(0), expression); >- emitOpcode(op_spread); >- instructions().append(argumentRegister.get()->index()); >- instructions().append(argumentRegister.get()->index()); >+ OpSpread::emit(this, argumentRegister, argumentRegister); > > RefPtr<RegisterID> thisRegister = move(newTemporary(), callArguments.thisRegister()); > return emitCallVarargs(opcodeID == op_tail_call ? op_tail_call_varargs : op_call_varargs, dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, debuggableCall); >@@ -3605,17 +3276,14 @@ void BytecodeGenerator::emitLogShadowChickenPrologueIfNecessary() > { > if (!m_shouldEmitDebugHooks && !Options::alwaysUseShadowChicken()) > return; >- emitOpcode(op_log_shadow_chicken_prologue); >- instructions().append(scopeRegister()->index()); >+ OpLogShadowChickenPrologue::emit(this, scopeRegister()); > } > > void BytecodeGenerator::emitLogShadowChickenTailIfNecessary() > { > if (!m_shouldEmitDebugHooks && !Options::alwaysUseShadowChicken()) > return; >- emitOpcode(op_log_shadow_chicken_tail); >- instructions().append(thisRegister()->index()); >- instructions().append(scopeRegister()->index()); >+ OpLogShadowChickenTail::emit(this, thisRegister(), scopeRegister()); > } > > void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister, >@@ -3661,18 +3329,9 @@ void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* p > else > setter = throwTypeErrorFunction; > >- emitOpcode(op_define_accessor_property); >- instructions().append(newObj->index()); >- instructions().append(propertyNameRegister->index()); >- instructions().append(getter->index()); >- instructions().append(setter->index()); >- instructions().append(emitLoad(nullptr, jsNumber(attributes.rawRepresentation()))->index()); >+ OpDefineAccessorProperty::emit(this, newObj, propertyNameRegister, getter, setter, emitLoad(nullptr, jsNumber(attributes.rawRepresentation()))); > } else { >- emitOpcode(op_define_data_property); >- instructions().append(newObj->index()); >- instructions().append(propertyNameRegister->index()); >- instructions().append(valueRegister->index()); >- instructions().append(emitLoad(nullptr, jsNumber(attributes.rawRepresentation()))->index()); >+ OpDefineDataProperty::emit(this, newObj, propertyNameRegister, valueRegister, emitLoad(nullptr, jsNumber(attributes.rawRepresentation()))); > } > } > >@@ -3696,18 +3355,12 @@ RegisterID* BytecodeGenerator::emitReturn(RegisterID* src, ReturnFrom from) > emitLabel(isUndefinedLabel.get()); > emitTDZCheck(&m_thisRegister); > } >- emitUnaryNoDstOp(op_ret, &m_thisRegister); >+ OpRet::emit(this, &m_thisRegister); > emitLabel(isObjectLabel.get()); > } > } > >- return emitUnaryNoDstOp(op_ret, src); >-} >- >-RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src) >-{ >- emitOpcode(opcodeID); >- instructions().append(src->index()); >+ OpRet::emit(this, src); > return src; > } > >@@ -3728,9 +3381,7 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, > if (elements && !elements->next() && elements->value()->isSpreadExpression()) { > ExpressionNode* expression = static_cast<SpreadExpressionNode*>(elements->value())->expression(); > RefPtr<RegisterID> argumentRegister = emitNode(callArguments.argumentRegister(0), expression); >- emitOpcode(op_spread); >- instructions().append(argumentRegister.get()->index()); >- instructions().append(argumentRegister.get()->index()); >+ OpSpread::emit(this, argumentRegister.get(), argumentRegister.get()); > > move(callArguments.thisRegister(), lazyThis); > RefPtr<RegisterID> thisRegister = move(newTemporary(), callArguments.thisRegister()); >@@ -3778,25 +3429,18 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, > > RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count) > { >- emitOpcode(op_strcat); >- instructions().append(dst->index()); >- instructions().append(src->index()); >- instructions().append(count); >- >+ OpStrcat::emit(this, dst, src, count); > return dst; > } > > void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src) > { >- emitOpcode(op_to_primitive); >- instructions().append(dst->index()); >- instructions().append(src->index()); >+ OpToPrimitive::emit(this, dst, src); > } > > void BytecodeGenerator::emitGetScope() > { >- emitOpcode(op_get_scope); >- instructions().append(scopeRegister()->index()); >+ OpGetScope::emit(this, scopeRegister()); > } > > RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* objectScope) >@@ -3805,10 +3449,7 @@ RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* objectScope) > RegisterID* newScope = newBlockScopeVariable(); > newScope->ref(); > >- emitOpcode(op_push_with_scope); >- instructions().append(newScope->index()); >- instructions().append(scopeRegister()->index()); >- instructions().append(objectScope->index()); >+ OpPushWithScope::emit(this, newScope, scopeRegister(), objectScope); > > move(scopeRegister(), newScope); > m_lexicalScopeStack.append({ nullptr, newScope, true, 0 }); >@@ -3818,9 +3459,7 @@ RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* objectScope) > > RegisterID* BytecodeGenerator::emitGetParentScope(RegisterID* dst, RegisterID* scope) > { >- emitOpcode(op_get_parent_scope); >- instructions().append(dst->index()); >- instructions().append(scope->index()); >+ OpGetParentScope::emit(this, dst, scope); > return dst; > } > >@@ -3845,9 +3484,7 @@ void BytecodeGenerator::emitDebugHook(DebugHookType debugHookType, const JSTextP > return; > > emitExpressionInfo(divot, divot, divot); >- emitOpcode(op_debug); >- instructions().append(debugHookType); >- instructions().append(false); >+ OpDebug::emit(this, debugHookType, false); > } > > void BytecodeGenerator::emitDebugHook(DebugHookType debugHookType, unsigned line, unsigned charOffset, unsigned lineStart) >@@ -4062,16 +3699,12 @@ void BytecodeGenerator::emitThrowStaticError(ErrorType errorType, RegisterID* ra > { > RefPtr<RegisterID> message = newTemporary(); > emitToString(message.get(), raw); >- emitOpcode(op_throw_static_error); >- instructions().append(message->index()); >- instructions().append(static_cast<unsigned>(errorType)); >+ OpThrowStaticError::emit(this, message, errorType); > } > > void BytecodeGenerator::emitThrowStaticError(ErrorType errorType, const Identifier& message) > { >- emitOpcode(op_throw_static_error); >- instructions().append(addConstantValue(addStringConstant(message))->index()); >- instructions().append(static_cast<unsigned>(errorType)); >+ OpThrowStaticError::emit(this, addConstantValue(addStringConstant(message)), errorType); > } > > void BytecodeGenerator::emitThrowReferenceError(const String& message) >@@ -4151,23 +3784,22 @@ void BytecodeGenerator::emitPopCatchScope(VariableEnvironment& environment) > void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type) > { > SwitchInfo info = { static_cast<uint32_t>(instructions().size()), type }; >+ OpcodeID opcode; > switch (type) { > case SwitchInfo::SwitchImmediate: >- emitOpcode(op_switch_imm); >+ opcode = op_switch_imm; > break; > case SwitchInfo::SwitchCharacter: >- emitOpcode(op_switch_char); >+ opcode = op_switch_char; > break; > case SwitchInfo::SwitchString: >- emitOpcode(op_switch_string); >+ opcode = op_switch_string; > break; > default: > RELEASE_ASSERT_NOT_REACHED(); > } > >- instructions().append(0); // place holder for table index >- instructions().append(0); // place holder for default target >- instructions().append(scrutineeRegister->index()); >+ SwitchValue::emit(this, opcode, 0, 0, scrutineeRegister); > m_switchContextStack.append(info); > } > >@@ -4459,114 +4091,79 @@ RegisterID* BytecodeGenerator::emitGetGlobalPrivate(RegisterID* dst, const Ident > > RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base) > { >- emitOpcode(op_get_enumerable_length); >- instructions().append(dst->index()); >- instructions().append(base->index()); >+ OpGetEnumerableLength::emit(this, dst, base); > return dst; > } > > RegisterID* BytecodeGenerator::emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName) > { >- emitOpcode(op_has_generic_property); >- instructions().append(dst->index()); >- instructions().append(base->index()); >- instructions().append(propertyName->index()); >+ OpHasGenericProperty::emit(this, dst, base, property); > return dst; > } > > RegisterID* BytecodeGenerator::emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName) > { >- UnlinkedArrayProfile arrayProfile = newArrayProfile(); >- emitOpcode(op_has_indexed_property); >- instructions().append(dst->index()); >- instructions().append(base->index()); >- instructions().append(propertyName->index()); >- instructions().append(arrayProfile); >+ OpHasIndexedProperty::emit(this, dst, base, propertyName); > return dst; > } > > RegisterID* BytecodeGenerator::emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator) > { >- emitOpcode(op_has_structure_property); >- instructions().append(dst->index()); >- instructions().append(base->index()); >- instructions().append(propertyName->index()); >- instructions().append(enumerator->index()); >+ OpHasStructureProperty::emit(this, dst, base, propertyName, enumerator); > return dst; > } > > RegisterID* BytecodeGenerator::emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base) > { >- emitOpcode(op_get_property_enumerator); >- instructions().append(dst->index()); >- instructions().append(base->index()); >+ OpGetPropertyEnumerator::emit(this, dst, base); > return dst; > } > > RegisterID* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index) > { >- emitOpcode(op_enumerator_structure_pname); >- instructions().append(dst->index()); >- instructions().append(enumerator->index()); >- instructions().append(index->index()); >+ OpEnumeratorStructurePname::emit(this, dst, enumerator, index); > return dst; > } > > RegisterID* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index) > { >- emitOpcode(op_enumerator_generic_pname); >- instructions().append(dst->index()); >- instructions().append(enumerator->index()); >- instructions().append(index->index()); >+ OpEnumeratorGenericPname::emit(this, dst, enumerator, index); > return dst; > } > > RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index) > { >- emitOpcode(op_to_index_string); >- instructions().append(dst->index()); >- instructions().append(index->index()); >+ OpToIndexString::emit(this, dst, index); > return dst; > } > > RegisterID* BytecodeGenerator::emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType type) > { >- emitOpcode(op_is_cell_with_type); >- instructions().append(dst->index()); >- instructions().append(src->index()); >- instructions().append(type); >+ OpIsCellWithType::emit(this, dst, src, type); > return dst; > } > > RegisterID* BytecodeGenerator::emitIsObject(RegisterID* dst, RegisterID* src) > { >- emitOpcode(op_is_object); >- instructions().append(dst->index()); >- instructions().append(src->index()); >+ OpIsObject::emit(this, dst, src); > return dst; > } > > RegisterID* BytecodeGenerator::emitIsNumber(RegisterID* dst, RegisterID* src) > { >- emitOpcode(op_is_number); >- instructions().append(dst->index()); >- instructions().append(src->index()); >+ OpIsNumber::emit(this, dst, src); > return dst; > } > > RegisterID* BytecodeGenerator::emitIsUndefined(RegisterID* dst, RegisterID* src) > { >- emitOpcode(op_is_undefined); >- instructions().append(dst->index()); >- instructions().append(src->index()); >+ OpIsUndefined::emit(this, dst, src); > return dst; > } > > RegisterID* BytecodeGenerator::emitIsEmpty(RegisterID* dst, RegisterID* src) > { >- emitOpcode(op_is_empty); >- instructions().append(dst->index()); >- instructions().append(src->index()); >+ OpIsEmpty::emit(this, dst, src); > return dst; > } > >@@ -4771,14 +4368,9 @@ void BytecodeGenerator::invalidateForInContextForLocal(RegisterID* localRegister > RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip) > { > RefPtr<RegisterID> restArrayLength = newTemporary(); >- emitOpcode(op_get_rest_length); >- instructions().append(restArrayLength->index()); >- instructions().append(numParametersToSkip); >+ OpGetRestLength::emit(this, restArrayLength, numParametersToSkip); > >- emitOpcode(op_create_rest); >- instructions().append(result->index()); >- instructions().append(restArrayLength->index()); >- instructions().append(numParametersToSkip); >+ OpCreateRest::emit(this, result, restArrayLength, numParametersToSkip); > > return result; > } >@@ -4789,9 +4381,7 @@ void BytecodeGenerator::emitRequireObjectCoercible(RegisterID* value, const Stri > // thus incorrectly throws a TypeError for interfaces like HTMLAllCollection. > Ref<Label> target = newLabel(); > size_t begin = instructions().size(); >- emitOpcode(op_jneq_null); >- instructions().append(value->index()); >- instructions().append(target->bind(begin, instructions().size())); >+ OpJneqNull::emit(this, value, target->bind(begin, instruction().size())); > emitThrowTypeError(error); > emitLabel(target.get()); > } >@@ -4822,10 +4412,7 @@ void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGeneratorFun > Vector<TryContext> savedTryContextStack; > m_tryContextStack.swap(savedTryContextStack); > >- emitOpcode(op_yield); >- instructions().append(generatorFrameRegister()->index()); >- instructions().append(yieldPointIndex); >- instructions().append(argument->index()); >+ OpYield::emit(this, generatorFrameRegister(), yieldPointIndex, argument); > > // Restore the try contexts, which start offset is updated to the merge point. > m_tryContextStack.swap(savedTryContextStack); >@@ -5241,11 +4828,8 @@ void IndexedForInContext::finalize(BytecodeGenerator& generator) > void BytecodeGenerator::emitToThis() > { > m_codeBlock->addPropertyAccessInstruction(instructions().size()); >- UnlinkedValueProfile profile = emitProfiledOpcode(op_to_this); >- instructions().append(kill(&m_thisRegister)); >- instructions().append(0); >- instructions().append(0); >- instructions().append(profile); >+ >+ OpToThis::emit(this, kill(&m_thisRegister)); > } > > } // namespace JSC >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >index 8ac6bc1e88ef9ec86d88461d1617515fd0e3ed59..c34ef90d20711ecf930eca9859325bf8393d3d53 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >@@ -495,6 +495,12 @@ namespace JSC { > n->emitBytecode(*this, dst); > } > >+ void recordOpcode(unsigned opcode) >+ { >+ m_lastOpcodeID = opcode; >+ m_lastOffset = m_instructions.size(); >+ }; >+ > void emitNode(StatementNode* n) > { > emitNode(nullptr, n); >@@ -685,7 +691,7 @@ namespace JSC { > RegisterID* moveLinkTimeConstant(RegisterID* dst, LinkTimeConstant); > RegisterID* moveEmptyValue(RegisterID* dst); > >- RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOpProfiled(op_to_number, dst, src); } >+ RegisterID* emitToNumber(RegisterID* dst, RegisterID* src); > RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); } > RegisterID* emitToObject(RegisterID* dst, RegisterID* src, const Identifier& message); > RegisterID* emitInc(RegisterID* srcDst); >@@ -1125,7 +1131,26 @@ namespace JSC { > JSValue addBigIntConstant(const Identifier&, uint8_t radix, bool sign); > RegisterID* addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&&); > >- Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; } >+ Vector<uint8_t, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; } >+ void write(uint8_t byte) { m_instructions.append(byte); } >+ void write(uint32_t i) >+ { >+ union { >+ uint32_t i; >+ uint8_t bytes[4]; >+ } u { i }; >+#if CPU(BIG_ENDIAN) >+ write(u.bytes[0]); >+ write(u.bytes[1]); >+ write(u.bytes[2]); >+ write(u.bytes[3]); >+#else // !CPU(BIG_ENDIAN) >+ write(u.bytes[3]); >+ write(u.bytes[2]); >+ write(u.bytes[1]); >+ write(u.bytes[0]); >+#endif // !CPU(BIG_ENDIAN) >+ } > > RegisterID* emitThrowExpressionTooDeepException(); > >@@ -1139,7 +1164,7 @@ namespace JSC { > void restoreTDZStack(const PreservedTDZStack&); > > private: >- Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions; >+ Vector<uint8_t, 0, UnsafeVectorOverflow> m_instructions; > > bool m_shouldEmitDebugHooks; > >diff --git a/Source/JavaScriptCore/bytecompiler/Label.h b/Source/JavaScriptCore/bytecompiler/Label.h >index 3e2d297f23d105c15984011a0f55a33574df053a..5a677c823f3c8550f253a9e2faf075ef6836ce8a 100644 >--- a/Source/JavaScriptCore/bytecompiler/Label.h >+++ b/Source/JavaScriptCore/bytecompiler/Label.h >@@ -28,6 +28,7 @@ > > #pragma once > >+#include "BytecodeGenerator.h" > #include "Instruction.h" > #include <wtf/Assertions.h> > #include <wtf/Vector.h> >@@ -35,23 +36,46 @@ > > namespace JSC { > >- class BytecodeGenerator; >+ static unsigned padding(size_t width) >+ { >+ return width == 1 ? 0 : 1; >+ } > > class Label { > WTF_MAKE_NONCOPYABLE(Label); > public: > Label() = default; > >+ Label(unsigned location) >+ : m_location(location) >+ { } >+ > void setLocation(BytecodeGenerator&, unsigned); > >- int bind(int opcode, int offset) const >+ Label& bind(BytecodeGenerator* generator, int offset) >+ { >+ m_opcode = generator->instructions().size(); >+ m_offset = offset; >+ return *this; >+ } >+ >+ int compute() const >+ { >+ return m_location - m_opcode; >+ } >+ >+ int compute(size_t width) > { >+ ASSERT(!m_bound); >+ ASSERT(m_opcode); >+ ASSERT(m_offset); > m_bound = true; > if (m_location == invalidLocation) { >- m_unresolvedJumps.append(std::make_pair(opcode, offset)); >+ m_unresolvedJumps.append(std::make_pair(m_opcode, m_opcode + m_offset * width + padding(width))); > return 0; > } >- return m_location - opcode; >+ return m_location - m_opcode; >+ > } > > void ref() { ++m_refCount; } >@@ -65,11 +89,11 @@ namespace JSC { > > bool isForward() const { return m_location == invalidLocation; } > >- int bind() >- { >- ASSERT(!isForward()); >- return bind(0, 0); >- } >+ //int bind() >+ //{ >+ //ASSERT(!isForward()); >+ //return bind(0, 0); >+ //} > > bool isBound() const { return m_bound; } > >@@ -79,6 +103,8 @@ namespace JSC { > static const unsigned invalidLocation = UINT_MAX; > > int m_refCount { 0 }; >+ int m_offset; >+ unsigned m_opcode; > unsigned m_location { invalidLocation }; > mutable bool m_bound { false }; > mutable JumpVector m_unresolvedJumps; >diff --git a/Source/JavaScriptCore/bytecompiler/StaticPropertyAnalyzer.h b/Source/JavaScriptCore/bytecompiler/StaticPropertyAnalyzer.h >index cc3b1e4a983391501d3fdf3a67a9c4a34bd9a268..182317145d5deeece507fbaf425bd4b11fedf086 100644 >--- a/Source/JavaScriptCore/bytecompiler/StaticPropertyAnalyzer.h >+++ b/Source/JavaScriptCore/bytecompiler/StaticPropertyAnalyzer.h >@@ -35,7 +35,7 @@ namespace JSC { > // is understood to be lossy, and it's OK if it turns out to be wrong sometimes. > class StaticPropertyAnalyzer { > public: >- StaticPropertyAnalyzer(Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>*); >+ StaticPropertyAnalyzer(Vector<uint8_t, 0, UnsafeVectorOverflow>*); > > void createThis(int dst, unsigned offsetOfInlineCapacityOperand); > void newObject(int dst, unsigned offsetOfInlineCapacityOperand); >@@ -48,12 +48,12 @@ public: > private: > void kill(StaticPropertyAnalysis*); > >- Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>* m_instructions; >+ Vector<uint8_t, 0, UnsafeVectorOverflow>* m_instructions; > typedef HashMap<int, RefPtr<StaticPropertyAnalysis>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> AnalysisMap; > AnalysisMap m_analyses; > }; > >-inline StaticPropertyAnalyzer::StaticPropertyAnalyzer(Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>* instructions) >+inline StaticPropertyAnalyzer::StaticPropertyAnalyzer(Vector<uint8_t, 0, UnsafeVectorOverflow>* instructions) > : m_instructions(instructions) > { > } >diff --git a/Source/JavaScriptCore/generate-bytecode-files b/Source/JavaScriptCore/generate-bytecode-files >deleted file mode 100644 >index fa25fd2ef31be4c1eb3c3a585be529d67cfed6d8..0000000000000000000000000000000000000000 >--- a/Source/JavaScriptCore/generate-bytecode-files >+++ /dev/null >@@ -1,302 +0,0 @@ >-#! /usr/bin/env python >- >-# Copyright (C) 2014-2017 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 AND ITS CONTRIBUTORS "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 OR ITS 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. >- >-# This tool processes the bytecode list to create Bytecodes.h and InitBytecodes.asm >- >-import hashlib >-import json >-import optparse >-import os >-import re >-import sys >- >-cCopyrightMsg = """/* >-* Copyright (C) 2014 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 AND ITS CONTRIBUTORS "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 OR ITS 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. >- >-* Autogenerated from %s, do not modify. >-*/ >- >-""" >- >-asmCopyrightMsg = """# Copyright (C) 2014 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 AND ITS CONTRIBUTORS "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 OR ITS 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. >- >-# Autogenerated from %s, do not modify. >- >-""" >-def openOrExit(path, mode): >- try: >- return open(path, mode) >- except IOError as e: >- print("I/O error opening {0}, ({1}): {2}".format(path, e.errno, e.strerror)) >- exit(1) >- >-def hashFile(file): >- sha1 = hashlib.sha1() >- file.seek(0) >- for line in file: >- sha1.update(line) >- >- file.seek(0) >- >- return sha1.hexdigest() >- >- >-def toCpp(name): >- camelCase = re.sub(r'([^a-z0-9].)', lambda c: c.group(0)[1].upper(), name) >- CamelCase = camelCase[:1].upper() + camelCase[1:] >- return CamelCase >- >- >-def writeInstructionAccessor(bytecodeHFile, typeName, name): >- bytecodeHFile.write(" {0}& {1}() {{ return *bitwise_cast<{0}*>(&m_{1}); }}\n".format(typeName, name)) >- bytecodeHFile.write(" const {0}& {1}() const {{ return *bitwise_cast<const {0}*>(&m_{1}); }}\n".format(typeName, name)) >- >- >-def writeInstructionMember(bytecodeHFile, typeName, name): >- bytecodeHFile.write(" std::aligned_storage<sizeof({0}), sizeof(Instruction)>::type m_{1};\n".format(typeName, name)) >- bytecodeHFile.write(" static_assert(sizeof({0}) <= sizeof(Instruction), \"Size of {0} shouldn't be bigger than an Instruction.\");\n".format(typeName, name)) >- >-def writeStruct(bytecodeHFile, bytecode): >- bytecodeHFile.write("struct {0} {{\n".format(toCpp(bytecode["name"]))) >- bytecodeHFile.write("public:\n") >- >- writeInstructionAccessor(bytecodeHFile, "Opcode", "opcode") >- for offset in bytecode["offsets"]: >- for name, typeName in offset.iteritems(): >- writeInstructionAccessor(bytecodeHFile, typeName, name) >- >- bytecodeHFile.write("\nprivate:\n") >- bytecodeHFile.write(" friend class LLIntOffsetsExtractor;\n\n") >- >- writeInstructionMember(bytecodeHFile, "Opcode", "opcode") >- for offset in bytecode["offsets"]: >- for name, typeName in offset.iteritems(): >- writeInstructionMember(bytecodeHFile, typeName, name) >- bytecodeHFile.write("};\n\n") >- >- >-if __name__ == "__main__": >- parser = optparse.OptionParser(usage = "usage: %prog [--bytecodes_h <FILE>] [--init_bytecodes_asm <FILE>] <bytecode-json-file>") >- parser.add_option("-b", "--bytecodes_h", dest = "bytecodesHFileName", help = "generate bytecodes macro .h FILE", metavar = "FILE") >- parser.add_option("-s", "--bytecode_structs_h", dest = "bytecodeStructsHFileName", help = "generate bytecodes macro .h FILE", metavar = "FILE") >- parser.add_option("-a", "--init_bytecodes_asm", dest = "initASMFileName", help="generate ASM bytecodes init FILE", metavar = "FILE") >- (options, args) = parser.parse_args() >- >- if len(args) != 1: >- parser.error("missing <bytecode-json-file>") >- >- bytecodeJSONFile = args[0] >- bytecodeFile = openOrExit(bytecodeJSONFile, "rb") >- sha1Hash = hashFile(bytecodeFile) >- >- hFileHashString = "// SHA1Hash: {0}\n".format(sha1Hash) >- asmFileHashString = "# SHA1Hash: {0}\n".format(sha1Hash) >- >- bytecodeHFilename = options.bytecodesHFileName >- bytecodeStructsHFilename = options.bytecodeStructsHFileName >- initASMFileName = options.initASMFileName >- >- if not bytecodeHFilename and not initASMFileName and not bytecodeStructsHFilename: >- parser.print_help() >- exit(0) >- >- needToGenerate = False >- >- if bytecodeHFilename: >- try: >- bytecodeHReadFile = open(bytecodeHFilename, "rb") >- >- hashLine = bytecodeHReadFile.readline() >- if hashLine != hFileHashString: >- needToGenerate = True >- except: >- needToGenerate = True >- else: >- bytecodeHReadFile.close() >- >- if bytecodeStructsHFilename: >- try: >- bytecodeStructsHReadFile = open(bytecodeStructsHFilename, "rb") >- >- hashLine = bytecodeStructsHReadFile.readline() >- if hashLine != hFileHashString: >- needToGenerate = True >- except: >- needToGenerate = True >- else: >- bytecodeStructsHReadFile.close() >- >- if initASMFileName: >- try: >- initBytecodesReadFile = open(initASMFileName, "rb") >- >- hashLine = initBytecodesReadFile.readline() >- if hashLine != asmFileHashString: >- needToGenerate = True >- except: >- needToGenerate = True >- else: >- initBytecodesReadFile.close() >- >- if not needToGenerate: >- exit(0) >- >- if bytecodeHFilename: >- bytecodeHFile = openOrExit(bytecodeHFilename, "wb") >- >- if bytecodeStructsHFilename: >- bytecodeStructsHFile = openOrExit(bytecodeStructsHFilename, "wb") >- >- if initASMFileName: >- initBytecodesFile = openOrExit(initASMFileName, "wb") >- >- try: >- bytecodeSections = json.load(bytecodeFile, encoding = "utf-8") >- except: >- print("Unexpected error parsing {0}: {1}".format(bytecodeJSONFile, sys.exc_info())) >- >- if bytecodeHFilename: >- bytecodeHFile.write(hFileHashString) >- bytecodeHFile.write(cCopyrightMsg % bytecodeJSONFile) >- bytecodeHFile.write("#pragma once\n\n") >- >- if bytecodeStructsHFilename: >- bytecodeStructsHFile.write(hFileHashString) >- bytecodeStructsHFile.write(cCopyrightMsg % bytecodeJSONFile) >- bytecodeStructsHFile.write("#pragma once\n\n") >- bytecodeStructsHFile.write("#include \"Instruction.h\"\n") >- bytecodeStructsHFile.write("\n") >- >- if initASMFileName: >- initBytecodesFile.write(asmFileHashString) >- initBytecodesFile.write(asmCopyrightMsg % bytecodeJSONFile) >- initASMBytecodeNum = 0 >- >- for section in bytecodeSections: >- if bytecodeHFilename and section['emitInHFile']: >- bytecodeHFile.write("#define FOR_EACH_{0}_ID(macro) \\\n".format(section["macroNameComponent"])) >- firstMacro = True >- defaultLength = 1 >- if "defaultLength" in section: >- defaultLength = section["defaultLength"] >- >- bytecodeNum = 0 >- for bytecode in section["bytecodes"]: >- if not firstMacro: >- bytecodeHFile.write(" \\\n") >- >- length = defaultLength >- if "length" in bytecode: >- length = bytecode["length"] >- elif "offsets" in bytecode: >- # Add one for the opcode >- length = len(bytecode["offsets"]) + 1 >- >- bytecodeHFile.write(" macro({0}, {1})".format(bytecode["name"], length)) >- firstMacro = False >- bytecodeNum = bytecodeNum + 1 >- >- bytecodeHFile.write("\n\n") >- bytecodeHFile.write("#define NUMBER_OF_{0}_IDS {1}\n\n".format(section["macroNameComponent"], bytecodeNum)) >- >- >- if bytecodeStructsHFilename and section['emitInStructsFile']: >- bytecodeStructsHFile.write("namespace JSC {\n\n") >- >- for bytecode in section["bytecodes"]: >- if not "offsets" in bytecode: >- continue >- writeStruct(bytecodeStructsHFile, bytecode) >- >- bytecodeStructsHFile.write("} // namespace JSC \n") >- >- if bytecodeHFilename and section['emitOpcodeIDStringValuesInHFile']: >- bytecodeNum = 0 >- for bytecode in section["bytecodes"]: >- bytecodeHFile.write("#define {0}_value_string \"{1}\"\n".format(bytecode["name"], bytecodeNum)) >- firstMacro = False >- bytecodeNum = bytecodeNum + 1 >- >- bytecodeHFile.write("\n") >- >- if initASMFileName and section['emitInASMFile']: >- prefix = "" >- if "asmPrefix" in section: >- prefix = section["asmPrefix"] >- for bytecode in section["bytecodes"]: >- initBytecodesFile.write("setEntryAddress({0}, _{1}{2})\n".format(initASMBytecodeNum, prefix, bytecode["name"])) >- initASMBytecodeNum = initASMBytecodeNum + 1 >- >- if bytecodeHFilename: >- bytecodeHFile.close() >- >- if initASMFileName: >- initBytecodesFile.close() >- >- bytecodeFile.close() >- >- exit(0) >diff --git a/Source/JavaScriptCore/generator/Argument.rb b/Source/JavaScriptCore/generator/Argument.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..c9e16842a7ea43daf2bc3b8d0d593e755856cab7 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Argument.rb >@@ -0,0 +1,33 @@ >+require_relative 'Fits' >+ >+class Argument >+ def initialize(name, type) >+ @optional = name[-1] == "?" >+ @name = name[-1] == "?" ? name[0...-1] : name >+ @type = type >+ end >+ >+ def field(_) >+ "#{@type.to_s} #{@name};" >+ end >+ >+ def create_param >+ "#{@type.to_s} #{@name}" >+ end >+ >+ def fits_check(size) >+ Fits::check size, @name, @type >+ end >+ >+ def fits_write(size) >+ Fits::write size, @name, @type >+ end >+ >+ def assert_fits(size) >+ "ASSERT((#{fits_check size}));" >+ end >+ >+ def load_from_stream(index, size) >+ "#{@name} = #{Fits::cast(size, "stream[#{index+1}]", @type)};" >+ end >+end >diff --git a/Source/JavaScriptCore/generator/Assertion.rb b/Source/JavaScriptCore/generator/Assertion.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..a93dd4d9feff9750471fb66d94fd73b2da5faee0 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Assertion.rb >@@ -0,0 +1,9 @@ >+class AssertionError < RuntimeError >+ def initialize(msg) >+ super >+ end >+end >+ >+def assert(msg, &block) >+ raise AssertionError, msg unless yield >+end >diff --git a/Source/JavaScriptCore/generator/DSL.rb b/Source/JavaScriptCore/generator/DSL.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..faf08f8e45794560e382622186a70f86d22f5f13 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/DSL.rb >@@ -0,0 +1,110 @@ >+require_relative 'Assertion' >+require_relative 'Section' >+require_relative 'Template' >+require_relative 'Type' >+require_relative 'GeneratedFile' >+ >+module DSL >+ @sections = [] >+ @current_section = nil >+ @context = binding() >+ >+ def self.begin_section(name, config={}) >+ assert("must call `end_section` before beginning a new section") { @current_section.nil? } >+ @current_section = Section.new name, config >+ end >+ >+ def self.end_section(name) >+ assert("current section's name is `#{@current_section.name}`, but end_section was called with `#{name}`") { @current_section.name == name } >+ @sections << @current_section >+ @current_section = nil >+ end >+ >+ def self.op(name, config = {}) >+ assert("`op` can only be called in between `begin_section` and `end_section`") { not @current_section.nil? } >+ @current_section.add_opcode(name, config) >+ end >+ >+ def self.op_group(desc, ops, config) >+ assert("`op_group` can only be called in between `begin_section` and `end_section`") { not @current_section.nil? } >+ @current_section.add_opcode_group(desc, ops, config) >+ end >+ >+ def self.types(types) >+ types.map do |type| >+ @context.eval("#{type} = Type.new :#{type}") >+ end >+ end >+ >+ def self.templates(types) >+ types.map do |type| >+ @context.eval("#{type} = Template.new :#{type}") >+ end >+ end >+ >+ def self.namespace(name) >+ ctx = @context >+ @context = @context.eval(" >+ module #{name} >+ def self.get_binding >+ binding() >+ end >+ end >+ #{name}.get_binding >+ ") >+ yield >+ @context = ctx >+ end >+ >+ def self.run(options) >+ bytecodeListPath = options[:bytecodeList] >+ bytecodeList = File.open(bytecodeListPath) >+ @context.eval(bytecodeList.read, bytecodeListPath) >+ assert("must end last section") { @current_section.nil? } >+ >+ write_bytecodes(bytecodeList, options[:bytecodesFilename]) >+ write_bytecode_structs(bytecodeList, options[:bytecodeStructsFilename]) >+ write_init_asm(bytecodeList, options[:initAsmFilename]) >+ end >+ >+ def self.write_bytecodes(bytecode_list, bytecodes_filename) >+ GeneratedFile::create(bytecodes_filename, bytecode_list) do |template| >+ template.prefix = "#pragma once" >+ template.body = @sections.map(&:header_helpers).join("\n") >+ end >+ end >+ >+ def self.write_bytecode_structs(bytecode_list, bytecode_structs_filename) >+ GeneratedFile::create(bytecode_structs_filename, bytecode_list) do |template| >+ template.prefix = <<-EOF >+ #pragma once >+ >+ #include "BytecodeGenerator.h" >+ #include "Fits.h" >+ #include "Instruction.h" >+ #include "OpcodeSize.h" >+ >+ namespace JSC { >+ >+ using Constant = VirtualRegister; >+ EOF >+ template.suffix = "} // namespace JSC" >+ template.body = opcodes_for(:emit_in_structs_file).map(&:cpp_class).join("\n") >+ end >+ end >+ >+ def self.write_init_asm(bytecode_list, init_asm_filename) >+ opcodes = opcodes_for(:emit_in_asm_file) >+ >+ GeneratedFile::create(init_asm_filename, bytecode_list) do |template| >+ template.multiline_comment = nil >+ template.line_comment = "#" >+ template.body = (opcodes.map(&:set_entry_address) + opcodes.map(&:set_entry_address_wide)) .join("\n") >+ end >+ end >+ >+ def self.opcodes_for(file) >+ sections = @sections.select { |s| s.config[:emit_in_h_file] } >+ sections.map(&:opcodes).flatten >+ end >+end >diff --git a/Source/JavaScriptCore/generator/Fits.rb b/Source/JavaScriptCore/generator/Fits.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..7587aa8f983e5ca9a0ad3162a4dd20aebbfa9c09 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Fits.rb >@@ -0,0 +1,18 @@ >+module Fits >+ def self.cast(size, name, type) >+ "Fits<#{type.to_s}, #{size}>::convert(#{name})" >+ end >+ >+ def self.check(size, name, type) >+ "Fits<#{type.to_s}, #{size}>::check(#{name})" >+ end >+ >+ def self.write(size, name, type) >+ "generator->write(#{cast(size, name, type)});" >+ end >+ >+ def self.choose_width(name, *args) >+ args = args.map(&:to_s).join ", " >+ "(isWide() ? wide()->#{name}(#{args}) : narrow()->#{name}(#{args}))" >+ end >+end >diff --git a/Source/JavaScriptCore/generator/GeneratedFile.rb b/Source/JavaScriptCore/generator/GeneratedFile.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..69e6657d8f60983c02e759573e2ab4192e03009a >--- /dev/null >+++ b/Source/JavaScriptCore/generator/GeneratedFile.rb >@@ -0,0 +1,79 @@ >+require 'date' >+require 'digest' >+ >+$LICENSE = <<-EOF >+Copyright (C) #{Date.today.year} 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 AND ITS CONTRIBUTORS "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 OR ITS 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. >+EOF >+ >+module GeneratedFile >+ class Template < Struct.new(:multiline_comment, :line_comment, :prefix, :suffix, :body) >+ def initialize >+ super(["/*", " *", "*/"], "// ", nil, nil, nil) >+ end >+ end >+ >+ def self.create(filename, dependency) >+ template = Template.new >+ yield template >+ >+ file = File.open(filename, "w") >+ self.sha1(file, template, dependency) >+ self.license(file, template, dependency) >+ >+ unless template.prefix.nil? >+ write(file, template.prefix.to_s, "\n") >+ end >+ unless template.body.nil? >+ write(file, template.body.to_s, "\n") >+ end >+ unless template.suffix.nil? >+ write(file, template.suffix.to_s, "\n") >+ end >+ end >+ >+ def self.sha1(file, template, dependency) >+ write(file, template.line_comment, " SHA1Hash: ", Digest::SHA1.hexdigest(dependency.read), "\n") >+ end >+ >+ def self.license(file, template, dependency) >+ unless template.multiline_comment.nil? >+ write(file, template.multiline_comment[0], "\n") >+ end >+ >+ comment = if template.multiline_comment.nil? then template.line_comment else template.multiline_comment[1] end >+ write(file, $LICENSE.strip.split("\n").map { |line| "#{comment} #{line}" }.join("\n"), "\n\n") >+ write(file, comment, " Autogenerated from ", dependency.path, ", do not modify.\n") >+ >+ unless template.multiline_comment.nil? >+ write(file, template.multiline_comment[2], "\n") >+ end >+ >+ write(file, "\n") >+ end >+ >+ def self.write(file, *strings) >+ file.write(strings.map(&:to_s).join) >+ end >+end >+ >diff --git a/Source/JavaScriptCore/generator/Metadata.rb b/Source/JavaScriptCore/generator/Metadata.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..a3e686276b84c7debfad4a60a0f65d21e779b084 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Metadata.rb >@@ -0,0 +1,49 @@ >+require_relative 'Fits' >+ >+class Metadata >+ def initialize(fields) >+ @fields = fields >+ end >+ >+ def empty? >+ @fields.nil? >+ end >+ >+ def cpp_class >+ return if @fields.nil? >+ >+ fields = @fields.map { |field, type| "#{type.to_s} #{field.to_s};" }.join "\n" >+ <<-EOF >+ struct Metadata { >+ #{fields} >+ }; >+ EOF >+ end >+ >+ def accessor >+ return if @fields.nil? >+ >+ <<-EOF >+ Metadata& metadata(ExecState& exec) >+ { >+ auto meta = exec.codeBlock()->metadata<Metadata>(opcodeID()); >+ const auto& it = meta.find(metadataID); >+ if (it != meta.end()) >+ return it->second; >+ return meta.emplace(std::make_pair(metadataID, Metadata { })).first->second; >+ } >+ EOF >+ end >+ >+ def field >+ return if @fields.nil? >+ >+ "unsigned metadataID;" >+ end >+ >+ def load_from_stream(index, size) >+ return if @fields.nil? >+ >+ "metadataID = #{Fits::cast(size, "stream[#{index}]", :unsigned)};" >+ end >+end >diff --git a/Source/JavaScriptCore/generator/Opcode.rb b/Source/JavaScriptCore/generator/Opcode.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..e7dad4dbf08cf4f21cb05e0773264b301d9ee701 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Opcode.rb >@@ -0,0 +1,147 @@ >+require_relative 'Argument' >+require_relative 'Fits' >+require_relative 'Metadata' >+ >+class Opcode >+ attr_reader :id >+ attr_reader :metadata >+ >+ module Size >+ Narrow = "OpcodeSize::Narrow" >+ Wide = "OpcodeSize::Wide" >+ end >+ >+ @@id = 0 >+ >+ def self.id >+ tid = @@id >+ @@id = @@id + 1 >+ tid >+ end >+ >+ def initialize(section, name, args, metadata) >+ @id = self.class.id >+ @section = section >+ @name = name >+ @metadata = Metadata.new metadata >+ @args = args.map { |arg_name, type| Argument.new arg_name, type } unless args.nil? >+ end >+ >+ def print_args(&block) >+ return if @args.nil? >+ >+ @args.map.with_index(&block).join "\n" >+ end >+ >+ def capitalized_name >+ name.split('_').map(&:capitalize).join >+ end >+ >+ def typed_args >+ return if @args.nil? >+ >+ @args.map(&:create_param).unshift("").join(", ") >+ end >+ >+ def map_fields_with_size(size, &block) >+ opcodeID = Argument.new("opcodeID()", :unsigned) >+ args = if @args.nil? then [opcodeID] else [opcodeID] + @args end >+ args.map { |arg| block.call(arg, size) } >+ end >+ >+ def cpp_class >+ <<-EOF >+ struct #{capitalized_name} { >+ #{opcodeID} >+ >+ #{emitter} >+ >+ #{constructor} >+ >+ #{metadata} >+ >+ #{members} >+ }; >+ EOF >+ end >+ >+ def opcodeID >+ "static constexpr unsigned opcodeID() { return #{@id}; }" >+ end >+ >+ def emitter >+ op_wide = Argument.new("op_wide", :unsigned) >+ <<-EOF >+ static void emit(BytecodeGenerator* generator#{typed_args}) >+ { >+ generator->recordOpcode(opcodeID()); >+ if (#{map_fields_with_size(Size::Narrow, &:fits_check).join " && "}) { >+ #{map_fields_with_size(Size::Narrow, &:fits_write).join "\n"} >+ } else { >+ #{op_wide.assert_fits Size::Narrow} >+ #{map_fields_with_size(Size::Wide, &:assert_fits).join "\n"} >+ >+ #{op_wide.fits_write Size::Narrow} >+ #{map_fields_with_size(Size::Narrow, &:fits_write).join "\n"} >+ } >+ } >+ EOF >+ end >+ >+ def constructor >+ <<-EOF >+ #{capitalized_name}(uint8_t* stream) >+ { >+ if (*stream != op_wide) { >+ load<OpcodeSize::Narrow>(stream); >+ } else { >+ auto wideStream = reinterpret_cast<uint32_t*>(stream + 1); >+ load<OpcodeSize::Wide>(wideStream); >+ } >+ } >+ >+ template<OpcodeSize size> >+ void load(typename TypeBySize<size>::type* stream) >+ { >+ assert(stream[0] == opcodeID()); >+ #{print_args { |arg, i| arg.load_from_stream(i, "size")}} >+ #{@metadata.load_from_stream(length, "size")} >+ } >+ EOF >+ end >+ >+ def metadata >+ <<-EOF >+ #{@metadata.cpp_class} >+ >+ #{@metadata.accessor} >+ EOF >+ end >+ >+ def members >+ <<-EOF >+ #{print_args(&:field)} >+ #{@metadata.field} >+ EOF >+ end >+ >+ def set_entry_address >+ "setEntryAddress(#{@id}, _#{full_name})" >+ end >+ >+ def set_entry_address_wide >+ "setEntryAddressWide(#{@id}, _#{full_name}_wide)" >+ end >+ >+ def full_name >+ "#{@section.config[:asm_prefix]}#{@section.config[:op_prefix]}#{@name}" >+ end >+ >+ def name >+ "#{@section.config[:op_prefix]}#{@name}" >+ end >+ >+ def length >+ 1 + (@args.nil? ? 0 : @args.length) + (@metadata.empty? ? 0 : 1) >+ end >+end >diff --git a/Source/JavaScriptCore/generator/OpcodeGroup.rb b/Source/JavaScriptCore/generator/OpcodeGroup.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..0b7971f9a67ba7c66f9906d77cf98dc6d641035e >--- /dev/null >+++ b/Source/JavaScriptCore/generator/OpcodeGroup.rb >@@ -0,0 +1,14 @@ >+require_relative 'Opcode' >+ >+class OpcodeGroup >+ attr_reader :name >+ attr_reader :opcodes >+ attr_reader :config >+ >+ def initialize(section, desc, opcodes, config) >+ @section = section >+ @name = name >+ @opcodes = opcodes >+ @config = config >+ end >+end >diff --git a/Source/JavaScriptCore/generator/Options.rb b/Source/JavaScriptCore/generator/Options.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..2ca194a17dd25a03dbda9cce58d077eb3270f6da >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Options.rb >@@ -0,0 +1,59 @@ >+require 'optparse' >+ >+$config = { >+ bytecodesFilename: { >+ short: "-b", >+ long: "--bytecodes_h FILE", >+ desc: "generate bytecodes macro .h FILE", >+ }, >+ bytecodeStructsFilename: { >+ short: "-s", >+ long: "--bytecode_structs_h FILE", >+ desc: "generate bytecode structs .h FILE", >+ }, >+ initAsmFilename: { >+ short: "-a", >+ long: "--init_bytecodes_asm FILE", >+ desc: "generate ASM bytecodes init FILE", >+ }, >+}; >+ >+module Options >+ def self.optparser(options) >+ OptionParser.new do |opts| >+ opts.banner = "usage: #{opts.program_name} [options] <bytecode-list-file>" >+ $config.map do |key, option| >+ opts.on(option[:short], option[:long], option[:desc]) do |v| >+ options[key] = v >+ end >+ end >+ end >+ end >+ >+ def self.check(argv, options) >+ missing = $config.keys.select{ |param| options[param].nil? } >+ unless missing.empty? >+ raise OptionParser::MissingArgument.new(missing.join(', ')) >+ end >+ unless argv.length == 1 >+ raise OptionParser::MissingArgument.new("<bytecode-list-file>") >+ end >+ end >+ >+ def self.parse(argv) >+ options = {} >+ parser = optparser(options) >+ >+ begin >+ parser.parse!(argv) >+ check(argv, options) >+ rescue OptionParser::MissingArgument, OptionParser::InvalidOption >+ puts $!.to_s >+ puts parser >+ exit 1 >+ end >+ >+ options[:bytecodeList] = argv[0] >+ options >+ end >+end >diff --git a/Source/JavaScriptCore/generator/Section.rb b/Source/JavaScriptCore/generator/Section.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..b2e8a790c4f5e2d4dd589e5f8adf947805f438af >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Section.rb >@@ -0,0 +1,47 @@ >+require_relative 'Opcode' >+require_relative 'OpcodeGroup' >+ >+class Section >+ attr_reader :name >+ attr_reader :config >+ attr_reader :opcodes >+ >+ def initialize(name, config) >+ @name = name >+ @config = config >+ @opcodes = [] >+ @opcode_groups = [] >+ end >+ >+ def add_opcode(name, config) >+ @opcodes << create_opcode(name, config) >+ end >+ >+ def create_opcode(name, config) >+ Opcode.new(self, name, config[:args], config[:metadata]) >+ end >+ >+ def add_opcode_group(name, opcodes, config) >+ opcodes = opcodes.map { |opcode| create_opcode(opcode, config) } >+ @opcode_groups << OpcodeGroup.new(self, name, opcodes, config) >+ @opcodes += opcodes >+ end >+ >+ def header_helpers >+ out = StringIO.new >+ if config[:emit_in_h_file] >+ out.write("#define FOR_EACH_#{config[:macro_name_component]}_ID(macro) \\\n") >+ opcodes.each { |opcode| out.write("macro(#{opcode.name}, #{opcode.length}) \\\n") } >+ out << "\n" >+ out.write("#define NUMBER_OF_#{config[:macro_name_component]}_IDS #{opcodes.length}\n") >+ end >+ >+ if config[:emit_opcode_id_string_values_in_h_file] >+ out << "\n" >+ opcodes.each { |opcode| >+ out.write("#define #{opcode.name}_value_string \"#{opcode.id}\"\n") >+ } >+ end >+ out.string >+ end >+end >diff --git a/Source/JavaScriptCore/generator/Template.rb b/Source/JavaScriptCore/generator/Template.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..a4e429ecbc1fc2956df4142c70fadf8c21fb89a7 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Template.rb >@@ -0,0 +1,7 @@ >+require_relative 'Type' >+ >+class Template < Type >+ def [](*types) >+ Type.new "#{@name}<#{types.map(&:to_s).join ","}>" >+ end >+end >diff --git a/Source/JavaScriptCore/generator/Type.rb b/Source/JavaScriptCore/generator/Type.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..3b148bdcbd8ee70859f05f29bf41edbf1fbec41c >--- /dev/null >+++ b/Source/JavaScriptCore/generator/Type.rb >@@ -0,0 +1,13 @@ >+class Type >+ def initialize(name) >+ @name = name >+ end >+ >+ def * >+ Type.new "#{@name}*" >+ end >+ >+ def to_s >+ @name.to_s >+ end >+end >diff --git a/Source/JavaScriptCore/generator/main.rb b/Source/JavaScriptCore/generator/main.rb >new file mode 100644 >index 0000000000000000000000000000000000000000..adfc3cf57fe62a03433c0cb9665e3cd50e8cb48e >--- /dev/null >+++ b/Source/JavaScriptCore/generator/main.rb >@@ -0,0 +1,15 @@ >+require_relative 'DSL' >+require_relative 'Options' >+ >+# for some reason, lower case variables are not accessible until the next invocation of eval >+# so we bind them here, before eval'ing the file >+DSL::types [ >+ :bool, >+ :int, >+ :unsigned, >+] >+ >+ >+ >+options = Options::parse(ARGV) >+DSL::run(options) >diff --git a/Source/JavaScriptCore/generator/runtime/Fits.h b/Source/JavaScriptCore/generator/runtime/Fits.h >new file mode 100644 >index 0000000000000000000000000000000000000000..e068eaaaeaf4595833bb3af6e193a8b6550b34c4 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/runtime/Fits.h >@@ -0,0 +1,118 @@ >+#pragma once >+ >+#include "Label.h" >+#include "OpcodeSize.h" >+#include "VirtualRegister.h" >+#include <type_traits> >+ >+namespace JSC { >+ >+enum OpcodeSize { >+ Narrow = 1, >+ Wide = 4, >+}; >+ >+template<OpcodeSize> >+struct TypeBySize; >+ >+template<> >+struct TypeBySize<OpcodeSize::Narrow> { >+ using type = uint8_t; >+}; >+ >+template<> >+struct TypeBySize<OpcodeSize::Wide> { >+ using type = uint32_t; >+}; >+ >+// Fits template >+template<typename, OpcodeSize, typename = std::true_type> >+struct Fits; >+ >+// validate overloaded signature >+template<typename T, OpcodeSize size> >+static typename TypeBySize<size>::type _convert(T t) { return Fits<T, size>::convert(t); } >+ >+template<typename T, OpcodeSize size> >+static T _convert(typename TypeBySize<size>::type t) { return Fits<T, size>::convert(t); } >+ >+template<typename T, OpcodeSize size> >+static bool _check(T t) { return Fits<T, size>::check(t); >+} >+ >+// Implicit conversion for types of the same size >+template<typename T, OpcodeSize size> >+struct Fits<T, size, std::enable_if_t<sizeof(T) == size, std::true_type>> { >+ static bool check(T) { return true; } >+ static typename TypeBySize<size>::type convert(T t) { return static_cast<typename TypeBySize<size>::type>(t); } >+ >+ template<class T1 = T, OpcodeSize size1, typename = std::enable_if_t<!std::is_same<T1, typename TypeBySize<size1>::type>::value, std::true_type>> >+ static T1 convert(typename TypeBySize<size1>::type t) { return static_cast<T1>(t); } >+}; >+ >+template<> >+struct Fits<uint32_t, OpcodeSize::Narrow> { >+ static bool check(unsigned u) { return u <= UINT8_MAX; } >+ static uint8_t convert(unsigned u) >+ { >+ assert(check(u)); >+ return static_cast<uint8_t>(u); >+ } >+ static unsigned convert(uint8_t u) >+ { >+ return u; >+ } >+}; >+ >+template<> >+struct Fits<int, OpcodeSize::Narrow> { >+ static bool check(int i) >+ { >+ return i >= INT8_MIN && i <= INT8_MAX; >+ } >+ >+ static uint8_t convert(int i) >+ { >+ return static_cast<uint8_t>(i); >+ } >+ >+ static int convert(uint8_t i) >+ { >+ return static_cast<int8_t>(i); >+ } >+}; >+ >+template<OpcodeSize size> >+struct Fits<Label&, size> : Fits<int, size> { >+ using Base = Fits<int, size>; >+ static bool check(const Label& target) { return Base::check(target.compute()); } >+ static typename TypeBySize<size>::type convert(const Label& target) >+ { >+ return Base::convert(target.compute(OpcodeSize::Narrow)); >+ } >+ >+ static Label convert(typename TypeBySize<size>::type target) >+ { >+ return Label(target); >+ } >+}; >+ >+template<> >+struct Fits<VirtualRegister, OpcodeSize::Narrow> : public Fits<int, OpcodeSize::Narrow> { >+ using Base = Fits<int, OpcodeSize::Narrow>; >+ static bool check(const VirtualRegister& r) { return Base::check(r.offset()); } >+ static uint8_t convert(const VirtualRegister& r) >+ { >+ return Base::convert(r.offset()); >+ } >+}; >+ >+//template <typename T, OpcodeSize Width> >+//struct Fits<T, Width> : public Fits<unsigned, Width, std::enable_if_t<sizeof(T) != Width, std::true_type>> { >+ //using Base = Fits<unsigned, Width>; >+ >+ //static bool check(T t) { return Base::check(t->toUnsigned()); } >+ //static T convert(T t) { return Fits::convert(t->toUnsigned()); } >+//}; >+ >+} // namespace JSC >diff --git a/Source/JavaScriptCore/generator/runtime/Instruction.h b/Source/JavaScriptCore/generator/runtime/Instruction.h >new file mode 100644 >index 0000000000000000000000000000000000000000..2fb0ebda452eb4a5e4dd9c2ab6cbe11163b97f77 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/runtime/Instruction.h >@@ -0,0 +1,77 @@ >+#pragma once >+ >+#include "Fits.h" >+ >+namespace JSC { >+ >+struct Instruction { >+private: >+ template<OpcodeSize Width> >+ class Impl { >+ public: >+ unsigned opcodeID() { return *reinterpret_cast<unsigned*>(m_opcode); } >+ >+ private: >+ typename uint8_t m_opcode[Width]; >+ }; >+ >+public: >+ unsigned opcodeID() >+ { >+ if (isWide()) >+ return wide()->opcodeID(); >+ return narrow()->opcodeID(); >+ } >+ >+ bool isWide() >+ { >+ return narrow()->opcodeID() == op_wide; >+ }; >+ >+ size_t length() >+ { >+ return opcode_length[opcodeID()]; >+ } >+ >+ size_t size() >+ { >+ auto isWide = this->isWide(); >+ return length() * (isWide ? OpcodeSize::Wide : OpcodeSize::Narrow) + isWide; >+ } >+ >+ >+ template<class T> >+ bool is() >+ { >+ return opcodeID() == T::opcodeID(); >+ } >+ >+ template<class T> >+ T as() >+ { >+ assert(is<T>()); >+ return T(reinterpret_cast<uint8_t*>(this)); >+ } >+ >+ Impl<OpcodeSize::Narrow>* narrow() >+ { >+ return (Impl<OpcodeSize::Narrow>*)this; >+ } >+ >+ Impl<OpcodeSize::Wide>* wide() >+ { >+ >+ assert(isWide()); >+ return (Impl<OpcodeSize::Wide>*)((uintptr_t)this + 1); >+ } >+ >+ //static Instruction* read(BytecodeReader& reader) >+ //{ >+ >+ //auto* instr = reinterpret_cast<Instruction*>(&reader.get()); >+ //reader.advance(instr->size()); >+ //return instr; >+ //} >+}; >+ >+} // namespace JSC >diff --git a/Source/JavaScriptCore/generator/runtime/OpcodeSize.h b/Source/JavaScriptCore/generator/runtime/OpcodeSize.h >new file mode 100644 >index 0000000000000000000000000000000000000000..11672ba2c020eaa81cfc56b2d65523263924e689 >--- /dev/null >+++ b/Source/JavaScriptCore/generator/runtime/OpcodeSize.h >@@ -0,0 +1,6 @@ >+#pragma once >+ >+enum OpcodeSize : size_t { >+ Narrow = 1, >+ Wide = 4, >+}; >diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h >index 49227ebe515663ffde03c9e0a3fcb64967a0f568..d672b4a84725c22c0b733cc24aa1ff92bfe5de80 100644 >--- a/Source/JavaScriptCore/interpreter/Interpreter.h >+++ b/Source/JavaScriptCore/interpreter/Interpreter.h >@@ -104,6 +104,7 @@ namespace JSC { > static inline OpcodeID getOpcodeID(Opcode); > static inline OpcodeID getOpcodeID(const Instruction&); > static inline OpcodeID getOpcodeID(const UnlinkedInstruction&); >+ static inline OpcodeID getOpcodeID(OpcodeID); > > #if !ASSERT_DISABLED > static bool isOpcode(Opcode); >diff --git a/Source/JavaScriptCore/interpreter/InterpreterInlines.h b/Source/JavaScriptCore/interpreter/InterpreterInlines.h >index fc89a189d6057d8e4e0ab10a8791f856b49f9071..5e58ffffa40543d8c9fbbddf74bfd03e11d124c2 100644 >--- a/Source/JavaScriptCore/interpreter/InterpreterInlines.h >+++ b/Source/JavaScriptCore/interpreter/InterpreterInlines.h >@@ -65,7 +65,7 @@ inline OpcodeID Interpreter::getOpcodeID(Opcode opcode) > > inline OpcodeID Interpreter::getOpcodeID(const Instruction& instruction) > { >- return getOpcodeID(instruction.u.opcode); >+ return static_cast<OpcodeID>(instruction.u.unsignedValue); > } > > inline OpcodeID Interpreter::getOpcodeID(const UnlinkedInstruction& instruction) >@@ -73,6 +73,11 @@ inline OpcodeID Interpreter::getOpcodeID(const UnlinkedInstruction& instruction) > return instruction.u.opcode; > } > >+inline OpcodeID Interpreter::getOpcodeID(OpcodeID opcode) >+{ >+ return opcode; >+} >+ > ALWAYS_INLINE JSValue Interpreter::execute(CallFrameClosure& closure) > { > VM& vm = *closure.vm; >diff --git a/Source/JavaScriptCore/llint/LLIntData.cpp b/Source/JavaScriptCore/llint/LLIntData.cpp >index c93d15c74c58ff5d96aa0aad943413f085a3d92e..b92259220b637307bb11475932080abeb457e3b3 100644 >--- a/Source/JavaScriptCore/llint/LLIntData.cpp >+++ b/Source/JavaScriptCore/llint/LLIntData.cpp >@@ -45,9 +45,10 @@ namespace JSC { namespace LLInt { > > Instruction Data::s_exceptionInstructions[maxOpcodeLength + 1] = { }; > Opcode Data::s_opcodeMap[numOpcodeIDs] = { }; >+Opcode Data::s_opcodeMapWide[numOpcodeIDs] = { }; > > #if ENABLE(JIT) >-extern "C" void llint_entry(void*); >+extern "C" void llint_entry(void*, void*); > #endif > > void initialize() >@@ -56,7 +57,7 @@ void initialize() > CLoop::initialize(); > > #else // ENABLE(JIT) >- llint_entry(&Data::s_opcodeMap); >+ llint_entry(&Data::s_opcodeMap, &Data::s_opcodeMapWide); > > for (int i = 0; i < numOpcodeIDs; ++i) > Data::s_opcodeMap[i] = tagCodePtr(Data::s_opcodeMap[i], BytecodePtrTag); >diff --git a/Source/JavaScriptCore/llint/LLIntData.h b/Source/JavaScriptCore/llint/LLIntData.h >index be58c00ae5c66ac30581ae3d4849428e5bb301d0..3937f33a15fc8fffbab69e8469ca2f5d05ad1b60 100644 >--- a/Source/JavaScriptCore/llint/LLIntData.h >+++ b/Source/JavaScriptCore/llint/LLIntData.h >@@ -83,9 +83,7 @@ inline Opcode getOpcode(OpcodeID id) > template<PtrTag tag> > ALWAYS_INLINE MacroAssemblerCodePtr<tag> getCodePtr(OpcodeID opcodeID) > { >- void* address = reinterpret_cast<void*>(getOpcode(opcodeID)); >- address = retagCodePtr<BytecodePtrTag, tag>(address); >- return MacroAssemblerCodePtr<tag>::createFromExecutableAddress(address); >+ return MacroAssemblerCodePtr<tag>::createFromExecutableAddress((void*)opcodeID); > } > > template<PtrTag tag> >@@ -109,7 +107,7 @@ ALWAYS_INLINE LLIntCode getCodeFunctionPtr(OpcodeID opcodeID) > #else > ALWAYS_INLINE void* getCodePtr(OpcodeID id) > { >- return reinterpret_cast<void*>(getOpcode(id)); >+ return reinterpret_cast<void*>(id); > } > #endif > >diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >index f2e411f8da89cfa10a3832e41cc1c5a650f456d1..653124ba25aabbedf0c4a133fecb295ad2d19182 100644 >--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >@@ -237,7 +237,7 @@ extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* > exec->codeBlock(), > exec, > static_cast<intptr_t>(exec->codeBlock()->bytecodeOffset(pc)), >- Interpreter::getOpcodeID(pc[0].u.opcode), >+ pc[0].u.opcode, > fromWhere, > operand, > pc[operand].u.operand); >@@ -264,7 +264,7 @@ extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc > exec->codeBlock(), > exec, > static_cast<intptr_t>(exec->codeBlock()->bytecodeOffset(pc)), >- Interpreter::getOpcodeID(pc[0].u.opcode), >+ pc[0].u.opcode, > fromWhere, > operand, > pc[operand].u.operand, >@@ -327,7 +327,7 @@ LLINT_SLOW_PATH_DECL(trace) > if (!Options::traceLLIntExecution()) > LLINT_END_IMPL(); > >- OpcodeID opcodeID = Interpreter::getOpcodeID(pc[0].u.opcode); >+ OpcodeID opcodeID = pc[0].u.opcode; > dataLogF("<%p> %p / %p: executing bc#%zu, %s, pc = %p\n", > &Thread::current(), > exec->codeBlock(), >@@ -726,13 +726,13 @@ static void setupGetByIdPrototypeCache(ExecState* exec, VM& vm, Instruction* pc, > ConcurrentJSLocker locker(codeBlock->m_lock); > > if (slot.isUnset()) { >- pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_unset); >+ pc[0].u.unsignedValue = op_get_by_id_unset; > pc[4].u.structureID = structure->id(); > return; > } > ASSERT(slot.isValue()); > >- pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_load); >+ pc[0].u.unsignedValue = op_get_by_id_proto_load; > pc[4].u.structureID = structure->id(); > pc[5].u.operand = offset; > // We know that this pointer will remain valid because it will be cleared by either a watchpoint fire or >@@ -760,7 +760,7 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) > { > StructureID oldStructureID = pc[4].u.structureID; > if (oldStructureID) { >- auto opcode = Interpreter::getOpcodeID(pc[0]); >+ auto opcode = pc[0].u.opcode; > if (opcode == op_get_by_id > || opcode == op_get_by_id_unset > || opcode == op_get_by_id_proto_load) { >@@ -779,7 +779,7 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) > Structure* structure = baseCell->structure(vm); > if (slot.isValue() && slot.slotBase() == baseValue) { > // Start out by clearing out the old cache. >- pc[0].u.opcode = LLInt::getOpcode(op_get_by_id); >+ pc[0].u.unsignedValue = op_get_by_id; > pc[4].u.pointer = nullptr; // old structure > pc[5].u.pointer = nullptr; // offset > >@@ -804,7 +804,7 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) > } else if (!LLINT_ALWAYS_ACCESS_SLOW > && isJSArray(baseValue) > && ident == vm.propertyNames->length) { >- pc[0].u.opcode = LLInt::getOpcode(op_get_array_length); >+ pc[0].u.unsignedValue = op_get_array_length; > ArrayProfile* arrayProfile = codeBlock->getOrAddArrayProfile(codeBlock->bytecodeOffset(pc)); > arrayProfile->observeStructure(baseValue.asCell()->structure(vm)); > pc[4].u.arrayProfile = arrayProfile; >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >index 88b80d37720c4251f8235d79cd15026dd5b9f1d5..d0118a9c388a8a9e05cee6dd83828a093e0955fc 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >@@ -352,6 +352,39 @@ else > end > end > >+macro dispatch(advance) >+ addi advance, PC >+ loadb [PB, PC, 1], t0 >+ loadp Data::s_opcodeMap[t0], t0 >+ jmp t0, BytecodePtrTag >+end >+ >+macro dispatchWide(advance) >+ leap 1[advance, PC, 4], PC >+ loadb [PB, PC, 1], t0 >+ loadp Data::s_opcodeMapWide[t0], t0 >+ jmp t0, BytecodePtrTag >+end >+ >+macro getOperandNarrow(offset, dst) >+ loadb [offset, PC, 1], dst >+end >+ >+macro getOperandWide(offset, dst) >+ loadis [offset, PC, 4], dst >+end >+ >+macro op(label, callback) >+label: >+ traceExecution() >+ callback(getOperandNarrow, macro dispatch(constexpr label##_length) end) >+ >+label##_wide: >+ traceExecution() >+ callback(getOperandWide, macro dispatch(constexpr label##_wide_length) end) >+end >+ >+ > if X86_64_WIN > const extraTempReg = t0 > else >@@ -1239,30 +1272,38 @@ end > # The PC base is in t1, as this is what _llint_entry leaves behind through > # initPCRelative(t1) > macro setEntryAddress(index, label) >+ setEntryAddressCommon(index, label, a0) >+end >+ >+macro setEntryAddressWide(index, label) >+ setEntryAddressCommon(index, label, a1) >+end >+ >+macro setEntryAddressCommon(index, label, map) > if X86_64 or X86_64_WIN > leap (label - _relativePCBase)[t1], t3 > move index, t4 >- storep t3, [a0, t4, 8] >+ storep t3, [map, t4, 8] > elsif X86 or X86_WIN > leap (label - _relativePCBase)[t1], t3 > move index, t4 >- storep t3, [a0, t4, 4] >+ storep t3, [map, t4, 4] > elsif ARM64 or ARM64E > pcrtoaddr label, t1 > move index, t4 >- storep t1, [a0, t4, 8] >+ storep t1, [map, t4, 8] > elsif ARM or ARMv7 or ARMv7_TRADITIONAL > mvlbl (label - _relativePCBase), t4 > addp t4, t1, t4 > move index, t3 >- storep t4, [a0, t3, 4] >+ storep t4, [map, t3, 4] > elsif MIPS > la label, t4 > la _relativePCBase, t3 > subp t3, t4 > addp t4, t1, t4 > move index, t3 >- storep t4, [a0, t3, 4] >+ storep t4, [map, t3, 4] > end > end > >@@ -1273,6 +1314,7 @@ _llint_entry: > pushCalleeSaves() > if X86 or X86_WIN > loadp 20[sp], a0 >+ loadp 24[sp], a1 > end > initPCRelative(t1) > >@@ -1284,47 +1326,54 @@ _llint_entry: > ret > end > >-_llint_program_prologue: >+op(_llint_program_prologue, macro (getOperand, dispatch) > prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) >- dispatch(0) >+ dispatch() >+end) > > >-_llint_module_program_prologue: >+op(_llint_module_program_prologue, macro (getOperand, dispatch) > prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) >- dispatch(0) >+ dispatch() >+end) > > >-_llint_eval_prologue: >+op(_llint_eval_prologue, macro (getOperand, dispatch) > prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) >- dispatch(0) >+ dispatch() >+end) > > >-_llint_function_for_call_prologue: >+op(_llint_function_for_call_prologue, macro (getOperand, dispatch) > prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call) > functionInitialization(0) >- dispatch(0) >+ dispatch() >+end) > > >-_llint_function_for_construct_prologue: >+op(_llint_function_for_construct_prologue, macro (getOperand, dispatch) > prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct) > functionInitialization(1) >- dispatch(0) >+ dispatch() >+end) > > >-_llint_function_for_call_arity_check: >+op(_llint_function_for_call_arity_check, macro (getOperand, dispatch) > prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call) > functionArityCheck(.functionForCallBegin, _slow_path_call_arityCheck) > .functionForCallBegin: > functionInitialization(0) >- dispatch(0) >+ dispatch() >+end) > > >-_llint_function_for_construct_arity_check: >+op(_llint_function_for_construct_arity_check, macro (getOperand, dispatch) > prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct) > functionArityCheck(.functionForConstructBegin, _slow_path_construct_arityCheck) > .functionForConstructBegin: > functionInitialization(1) >- dispatch(0) >+ dispatch() >+end) > > > # Value-representation-specific code. >@@ -1336,374 +1385,379 @@ end > > > # Value-representation-agnostic code. >-_llint_op_create_direct_arguments: >- traceExecution() >+op(_llint_op_create_direct_arguments, macro (getOperand, dispatch) > callSlowPath(_slow_path_create_direct_arguments) >- dispatch(constexpr op_create_direct_arguments_length) >+ dispatch() >+end) > > >-_llint_op_create_scoped_arguments: >- traceExecution() >+op(_llint_op_create_scoped_arguments, macro (getOperand, dispatch) > callSlowPath(_slow_path_create_scoped_arguments) >- dispatch(constexpr op_create_scoped_arguments_length) >+ dispatch() >+end) > > >-_llint_op_create_cloned_arguments: >- traceExecution() >+op(_llint_op_create_cloned_arguments, macro (getOperand, dispatch) > callSlowPath(_slow_path_create_cloned_arguments) >- dispatch(constexpr op_create_cloned_arguments_length) >+ dispatch() >+end) > > >-_llint_op_create_this: >- traceExecution() >+op(_llint_op_create_this, macro (getOperand, dispatch) > callSlowPath(_slow_path_create_this) >- dispatch(constexpr op_create_this_length) >+ dispatch() >+end) > > >-_llint_op_new_object: >- traceExecution() >+op(_llint_op_new_object, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_object) >- dispatch(constexpr op_new_object_length) >+ dispatch() >+end) > > >-_llint_op_new_func: >- traceExecution() >+op(_llint_op_new_func, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_func) >- dispatch(constexpr op_new_func_length) >+ dispatch() >+end) > > >-_llint_op_new_generator_func: >- traceExecution() >+op(_llint_op_new_generator_func, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_generator_func) >- dispatch(constexpr op_new_generator_func_length) >+ dispatch() >+end) > >-_llint_op_new_async_generator_func: >- traceExecution() >+ >+op(_llint_op_new_async_generator_func, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_async_generator_func) >- dispatch(constexpr op_new_async_generator_func_length) >+ dispatch() >+end) > >-_llint_op_new_async_generator_func_exp: >- traceExecution() >+ >+op(_llint_op_new_async_generator_func_exp, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_async_generator_func_exp) >- dispatch(constexpr op_new_async_generator_func_exp_length) >+ dispatch() >+end) > >-_llint_op_new_async_func: >- traceExecution() >+ >+op(_llint_op_new_async_func, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_async_func) >- dispatch(constexpr op_new_async_func_length) >+ dispatch() >+end) > > >-_llint_op_new_array: >- traceExecution() >+op(_llint_op_new_array, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_array) >- dispatch(constexpr op_new_array_length) >+ dispatch() >+end) > > >-_llint_op_new_array_with_spread: >- traceExecution() >+op(_llint_op_new_array_with_spread, macro (getOperand, dispatch) > callSlowPath(_slow_path_new_array_with_spread) >- dispatch(constexpr op_new_array_with_spread_length) >+ dispatch() >+end) > > >-_llint_op_spread: >- traceExecution() >+op(_llint_op_spread, macro (getOperand, dispatch) > callSlowPath(_slow_path_spread) >- dispatch(constexpr op_spread_length) >+ dispatch() >+end) > > >-_llint_op_new_array_with_size: >- traceExecution() >+op(_llint_op_new_array_with_size, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_array_with_size) >- dispatch(constexpr op_new_array_with_size_length) >+ dispatch() >+end) > > >-_llint_op_new_array_buffer: >- traceExecution() >+op(_llint_op_new_array_buffer, macro (getOperand, dispatch) > callSlowPath(_slow_path_new_array_buffer) >- dispatch(constexpr op_new_array_buffer_length) >+ dispatch() >+end) > > >-_llint_op_new_regexp: >- traceExecution() >+op(_llint_op_new_regexp, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_regexp) >- dispatch(constexpr op_new_regexp_length) >+ dispatch() >+end) > > >-_llint_op_less: >- traceExecution() >+op(_llint_op_less, macro (getOperand, dispatch) > callSlowPath(_slow_path_less) >- dispatch(constexpr op_less_length) >+ dispatch() >+end) > > >-_llint_op_lesseq: >- traceExecution() >+op(_llint_op_lesseq, macro (getOperand, dispatch) > callSlowPath(_slow_path_lesseq) >- dispatch(constexpr op_lesseq_length) >+ dispatch() >+end) > > >-_llint_op_greater: >- traceExecution() >+op(_llint_op_greater, macro (getOperand, dispatch) > callSlowPath(_slow_path_greater) >- dispatch(constexpr op_greater_length) >+ dispatch() >+end) > > >-_llint_op_greatereq: >- traceExecution() >+op(_llint_op_greatereq, macro (getOperand, dispatch) > callSlowPath(_slow_path_greatereq) >- dispatch(constexpr op_greatereq_length) >+ dispatch() >+end) > > >-_llint_op_eq: >- traceExecution() >+op(_llint_op_eq, macro (getOperand, dispatch) > equalityComparison( > macro (left, right, result) cieq left, right, result end, > _slow_path_eq) >+end) > > >-_llint_op_neq: >- traceExecution() >+op(_llint_op_neq, macro (getOperand, dispatch) > equalityComparison( > macro (left, right, result) cineq left, right, result end, > _slow_path_neq) >+end) > > >-_llint_op_below: >- traceExecution() >+op(_llint_op_below, macro (getOperand, dispatch) > compareUnsigned( > macro (left, right, result) cib left, right, result end) >+end) > > >-_llint_op_beloweq: >- traceExecution() >+op(_llint_op_beloweq, macro (getOperand, dispatch) > compareUnsigned( > macro (left, right, result) cibeq left, right, result end) >+end) > > >-_llint_op_mod: >- traceExecution() >+op(_llint_op_mod, macro (getOperand, dispatch) > callSlowPath(_slow_path_mod) >- dispatch(constexpr op_mod_length) >+ dispatch() >+end) > > >-_llint_op_pow: >- traceExecution() >+op(_llint_op_pow, macro (getOperand, dispatch) > callSlowPath(_slow_path_pow) >- dispatch(constexpr op_pow_length) >+ dispatch() >+end) > > >-_llint_op_typeof: >- traceExecution() >+op(_llint_op_typeof, macro (getOperand, dispatch) > callSlowPath(_slow_path_typeof) >- dispatch(constexpr op_typeof_length) >+ dispatch() >+end) > > >-_llint_op_is_object_or_null: >- traceExecution() >+op(_llint_op_is_object_or_null, macro (getOperand, dispatch) > callSlowPath(_slow_path_is_object_or_null) >- dispatch(constexpr op_is_object_or_null_length) >+ dispatch() >+end) > >-_llint_op_is_function: >- traceExecution() >+ >+op(_llint_op_is_function, macro (getOperand, dispatch) > callSlowPath(_slow_path_is_function) >- dispatch(constexpr op_is_function_length) >+ dispatch() >+end) > > >-_llint_op_in_by_id: >- traceExecution() >+op(_llint_op_in_by_id, macro (getOperand, dispatch) > callSlowPath(_slow_path_in_by_id) >- dispatch(constexpr op_in_by_id_length) >+ dispatch() >+end) > > >-_llint_op_in_by_val: >- traceExecution() >+op(_llint_op_in_by_val, macro (getOperand, dispatch) > callSlowPath(_slow_path_in_by_val) >- dispatch(constexpr op_in_by_val_length) >+ dispatch() >+end) > > >-_llint_op_try_get_by_id: >- traceExecution() >+op(_llint_op_try_get_by_id, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_try_get_by_id) >- dispatch(constexpr op_try_get_by_id_length) >+ dispatch() >+end) > > >-_llint_op_del_by_id: >- traceExecution() >+op(_llint_op_del_by_id, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_del_by_id) >- dispatch(constexpr op_del_by_id_length) >+ dispatch() >+end) > > >-_llint_op_del_by_val: >- traceExecution() >+op(_llint_op_del_by_val, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_del_by_val) >- dispatch(constexpr op_del_by_val_length) >+ dispatch() >+end) > > >-_llint_op_put_getter_by_id: >- traceExecution() >+op(_llint_op_put_getter_by_id, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_put_getter_by_id) >- dispatch(constexpr op_put_getter_by_id_length) >+ dispatch() >+end) > > >-_llint_op_put_setter_by_id: >- traceExecution() >+op(_llint_op_put_setter_by_id, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_put_setter_by_id) >- dispatch(constexpr op_put_setter_by_id_length) >+ dispatch() >+end) > > >-_llint_op_put_getter_setter_by_id: >- traceExecution() >+op(_llint_op_put_getter_setter_by_id, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_put_getter_setter_by_id) >- dispatch(constexpr op_put_getter_setter_by_id_length) >+ dispatch() >+end) > > >-_llint_op_put_getter_by_val: >+op(_llint_op_put_getter_by_val, macro (getOperand, dispatch) > traceExecution() > callSlowPath(_llint_slow_path_put_getter_by_val) >- dispatch(constexpr op_put_getter_by_val_length) >+ dispatch() >+end) > > >-_llint_op_put_setter_by_val: >- traceExecution() >+op(_llint_op_put_setter_by_val, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_put_setter_by_val) >- dispatch(constexpr op_put_setter_by_val_length) >+ dispatch() >+end) > > >-_llint_op_define_data_property: >- traceExecution() >+op(_llint_op_define_data_property, macro (getOperand, dispatch) > callSlowPath(_slow_path_define_data_property) >- dispatch(constexpr op_define_data_property_length) >+ dispatch() >+end) > > >-_llint_op_define_accessor_property: >- traceExecution() >+op(_llint_op_define_accessor_property, macro (getOperand, dispatch) > callSlowPath(_slow_path_define_accessor_property) >- dispatch(constexpr op_define_accessor_property_length) >+ dispatch() >+end) > > >-_llint_op_jtrue: >- traceExecution() >+op(_llint_op_jtrue, macro (getOperand, dispatch) > jumpTrueOrFalse( > macro (value, target) btinz value, 1, target end, > _llint_slow_path_jtrue) >+end) > > >-_llint_op_jfalse: >- traceExecution() >+op(_llint_op_jfalse, macro (getOperand, dispatch) > jumpTrueOrFalse( > macro (value, target) btiz value, 1, target end, > _llint_slow_path_jfalse) >+end) > > >-_llint_op_jless: >- traceExecution() >+op(_llint_op_jless, macro (getOperand, dispatch) > compareJump( > macro (left, right, target) bilt left, right, target end, > macro (left, right, target) bdlt left, right, target end, > _llint_slow_path_jless) >+end) > > >-_llint_op_jnless: >- traceExecution() >+op(_llint_op_jnless, macro (getOperand, dispatch) > compareJump( > macro (left, right, target) bigteq left, right, target end, > macro (left, right, target) bdgtequn left, right, target end, > _llint_slow_path_jnless) >+end) > > >-_llint_op_jgreater: >- traceExecution() >+op(_llint_op_jgreater, macro (getOperand, dispatch) > compareJump( > macro (left, right, target) bigt left, right, target end, > macro (left, right, target) bdgt left, right, target end, > _llint_slow_path_jgreater) >+end) > > >-_llint_op_jngreater: >- traceExecution() >+op(_llint_op_jngreater, macro (getOperand, dispatch) > compareJump( > macro (left, right, target) bilteq left, right, target end, > macro (left, right, target) bdltequn left, right, target end, > _llint_slow_path_jngreater) >+end) > > >-_llint_op_jlesseq: >- traceExecution() >+op(_llint_op_jlesseq, macro (getOperand, dispatch) > compareJump( > macro (left, right, target) bilteq left, right, target end, > macro (left, right, target) bdlteq left, right, target end, > _llint_slow_path_jlesseq) >+end) > > >-_llint_op_jnlesseq: >- traceExecution() >+op(_llint_op_jnlesseq, macro (getOperand, dispatch) > compareJump( > macro (left, right, target) bigt left, right, target end, > macro (left, right, target) bdgtun left, right, target end, > _llint_slow_path_jnlesseq) >+end) > > >-_llint_op_jgreatereq: >- traceExecution() >+op(_llint_op_jgreatereq, macro (getOperand, dispatch) > compareJump( > macro (left, right, target) bigteq left, right, target end, > macro (left, right, target) bdgteq left, right, target end, > _llint_slow_path_jgreatereq) >+end) > > >-_llint_op_jngreatereq: >- traceExecution() >+op(_llint_op_jngreatereq, macro (getOperand, dispatch) > compareJump( > macro (left, right, target) bilt left, right, target end, > macro (left, right, target) bdltun left, right, target end, > _llint_slow_path_jngreatereq) >+end) > > >-_llint_op_jeq: >- traceExecution() >+op(_llint_op_jeq, macro (getOperand, dispatch) > equalityJump( > macro (left, right, target) bieq left, right, target end, > _llint_slow_path_jeq) >+end) > > >-_llint_op_jneq: >- traceExecution() >+op(_llint_op_jneq, macro (getOperand, dispatch) > equalityJump( > macro (left, right, target) bineq left, right, target end, > _llint_slow_path_jneq) >+end) > > >-_llint_op_jbelow: >- traceExecution() >+op(_llint_op_jbelow, macro (getOperand, dispatch) > compareUnsignedJump( > macro (left, right, target) bib left, right, target end) >+end) > > >-_llint_op_jbeloweq: >- traceExecution() >+op(_llint_op_jbeloweq, macro (getOperand, dispatch) > compareUnsignedJump( > macro (left, right, target) bibeq left, right, target end) >+end) > > >-_llint_op_loop_hint: >- traceExecution() >+op(_llint_op_loop_hint, macro (getOperand, dispatch) > checkSwitchToJITForLoop() >- dispatch(constexpr op_loop_hint_length) >+ dispatch() >+end) > > >-_llint_op_check_traps: >- traceExecution() >+op(_llint_op_check_traps, macro (getOperand, dispatch) > loadp CodeBlock[cfr], t1 > loadp CodeBlock::m_poisonedVM[t1], t1 > unpoison(_g_CodeBlockPoison, t1, t2) > loadb VM::m_traps+VMTraps::m_needTrapHandling[t1], t0 > btpnz t0, .handleTraps > .afterHandlingTraps: >- dispatch(constexpr op_check_traps_length) >+ dispatch() > .handleTraps: > callTrapHandler(.throwHandler) > jmp .afterHandlingTraps > .throwHandler: > jmp _llint_throw_from_slow_path_trampoline >+end) > > > # Returns the packet pointer in t0. >@@ -1719,62 +1773,68 @@ macro acquireShadowChickenPacket(slow) > end > > >-_llint_op_nop: >- dispatch(constexpr op_nop_length) >+op(_llint_op_nop, macro (getOperand, dispatch) >+ dispatch() >+end) > > >-_llint_op_super_sampler_begin: >+op(_llint_op_super_sampler_begin, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_super_sampler_begin) >- dispatch(constexpr op_super_sampler_begin_length) >+ dispatch() >+end) > > >-_llint_op_super_sampler_end: >- traceExecution() >+op(_llint_op_super_sampler_end, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_super_sampler_end) >- dispatch(constexpr op_super_sampler_end_length) >+ dispatch() >+end) > > >-_llint_op_switch_string: >- traceExecution() >+op(_llint_op_switch_string, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_switch_string) >- dispatch(0) >+ dispatch() >+end) > > >-_llint_op_new_func_exp: >- traceExecution() >+op(_llint_op_new_func_exp, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_func_exp) >- dispatch(constexpr op_new_func_exp_length) >+ dispatch() >+end) > >-_llint_op_new_generator_func_exp: >- traceExecution() >+op(_llint_op_new_generator_func_exp, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_generator_func_exp) >- dispatch(constexpr op_new_generator_func_exp_length) >+ dispatch() >+end) > >-_llint_op_new_async_func_exp: >- traceExecution() >+op(_llint_op_new_async_func_exp, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_new_async_func_exp) >- dispatch(constexpr op_new_async_func_exp_length) >+ dispatch() >+end) > > >-_llint_op_set_function_name: >- traceExecution() >+op(_llint_op_set_function_name, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_set_function_name) >- dispatch(constexpr op_set_function_name_length) >+ dispatch() >+end) > >-_llint_op_call: >- traceExecution() >+ >+op(_llint_op_call, macro (getOperand, dispatch) > arrayProfileForCall() > doCall(_llint_slow_path_call, prepareForRegularCall) >+end) > >-_llint_op_tail_call: >- traceExecution() >+ >+op(_llint_op_tail_call, macro (getOperand, dispatch) > arrayProfileForCall() > checkSwitchToJITForEpilogue() > doCall(_llint_slow_path_call, prepareForTailCall) >+end) > >-_llint_op_construct: >- traceExecution() >+ >+op(_llint_op_construct, macro (getOperand, dispatch) > doCall(_llint_slow_path_construct, prepareForRegularCall) >+end) >+ > > macro doCallVarargs(frameSlowPath, slowPath, prepareCall) > callSlowPath(frameSlowPath) >@@ -1794,34 +1854,33 @@ macro doCallVarargs(frameSlowPath, slowPath, prepareCall) > slowPathForCall(slowPath, prepareCall) > end > >-_llint_op_call_varargs: >- traceExecution() >+ >+op(_llint_op_call_varargs, macro (getOperand, dispatch) > doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForRegularCall) >+end) > >-_llint_op_tail_call_varargs: >- traceExecution() >+op(_llint_op_tail_call_varargs, macro (getOperand, dispatch) > checkSwitchToJITForEpilogue() > # We lie and perform the tail call instead of preparing it since we can't > # prepare the frame for a call opcode > doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForTailCall) >+end) > > >-_llint_op_tail_call_forward_arguments: >- traceExecution() >+op(_llint_op_tail_call_forward_arguments, macro (getOperand, dispatch) > checkSwitchToJITForEpilogue() > # We lie and perform the tail call instead of preparing it since we can't > # prepare the frame for a call opcode > doCallVarargs(_llint_slow_path_size_frame_for_forward_arguments, _llint_slow_path_tail_call_forward_arguments, prepareForTailCall) >+end) > > >-_llint_op_construct_varargs: >- traceExecution() >+op(_llint_op_construct_varargs, macro (getOperand, dispatch) > doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_construct_varargs, prepareForRegularCall) >+end) > > >-_llint_op_call_eval: >- traceExecution() >- >+op(_llint_op_call_eval, macro (getOperand, dispatch) > # Eval is executed in one of two modes: > # > # 1) We find that we're really invoking eval() in which case the >@@ -1856,162 +1915,169 @@ _llint_op_call_eval: > # returns the JS value that the eval returned. > > slowPathForCall(_llint_slow_path_call_eval, prepareForRegularCall) >+end) > > >-_llint_generic_return_point: >+op(_llint_generic_return_point, macro (getOperand, dispatch) > dispatchAfterCall() >+end) > > >-_llint_op_strcat: >- traceExecution() >+op(_llint_op_strcat, macro (getOperand, dispatch) > callSlowPath(_slow_path_strcat) >- dispatch(constexpr op_strcat_length) >+ dispatch() >+end) > > >-_llint_op_push_with_scope: >- traceExecution() >+op(_llint_op_push_with_scope, macro (getOperand, dispatch) > callSlowPath(_slow_path_push_with_scope) >- dispatch(constexpr op_push_with_scope_length) >+ dispatch() >+end) > > >-_llint_op_identity_with_profile: >- traceExecution() >- dispatch(constexpr op_identity_with_profile_length) >+op(_llint_op_identity_with_profile, macro (getOperand, dispatch) >+ dispatch() >+end) > > >-_llint_op_unreachable: >- traceExecution() >+op(_llint_op_unreachable, macro (getOperand, dispatch) > callSlowPath(_slow_path_unreachable) >- dispatch(constexpr op_unreachable_length) >+ dispatch() >+end) > > >-_llint_op_yield: >+op(_llint_op_yield, macro (getOperand, dispatch) > notSupported() >+end) > > >-_llint_op_create_lexical_environment: >- traceExecution() >+op(_llint_op_create_lexical_environment, macro (getOperand, dispatch) > callSlowPath(_slow_path_create_lexical_environment) >- dispatch(constexpr op_create_lexical_environment_length) >+ dispatch() >+end) > > >-_llint_op_throw: >- traceExecution() >+op(_llint_op_throw, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_throw) >- dispatch(constexpr op_throw_length) >+ dispatch() >+end) > > >-_llint_op_throw_static_error: >- traceExecution() >+op(_llint_op_throw_static_error, macro (getOperand, dispatch) > callSlowPath(_slow_path_throw_static_error) >- dispatch(constexpr op_throw_static_error_length) >+ dispatch() >+end) > > >-_llint_op_debug: >- traceExecution() >+op(_llint_op_debug, macro (getOperand, dispatch) > loadp CodeBlock[cfr], t0 > loadi CodeBlock::m_debuggerRequests[t0], t0 > btiz t0, .opDebugDone > callSlowPath(_llint_slow_path_debug) > .opDebugDone: >- dispatch(constexpr op_debug_length) >+ dispatch() >+end) > > >-_llint_native_call_trampoline: >+macro(_llint_native_call_trampoline, macro (getOperand, dispatch) > nativeCallTrampoline(NativeExecutable::m_function) >+end) > > >-_llint_native_construct_trampoline: >+op(_llint_native_construct_trampoline, dispatch (getOperand, dispatch) > nativeCallTrampoline(NativeExecutable::m_constructor) >+end) > > >-_llint_internal_function_call_trampoline: >+op(_llint_internal_function_call_trampoline, macro (getOperand, dispatch) > internalFunctionCallTrampoline(InternalFunction::m_functionForCall) >+end) > > >-_llint_internal_function_construct_trampoline: >+op(_llint_internal_function_construct_trampoline, macro (getOperand, dispatch) > internalFunctionCallTrampoline(InternalFunction::m_functionForConstruct) >+end) > > >-_llint_op_get_enumerable_length: >- traceExecution() >+op(_llint_op_get_enumerable_length, macro (getOperand, dispatch) > callSlowPath(_slow_path_get_enumerable_length) >- dispatch(constexpr op_get_enumerable_length_length) >+ dispatch() >+end) > >-_llint_op_has_indexed_property: >- traceExecution() >+op(_llint_op_has_indexed_property, macro (getOperand, dispatch) > callSlowPath(_slow_path_has_indexed_property) >- dispatch(constexpr op_has_indexed_property_length) >+ dispatch() >+end) > >-_llint_op_has_structure_property: >- traceExecution() >+op(_llint_op_has_structure_property, macro (getOperand, dispatch) > callSlowPath(_slow_path_has_structure_property) >- dispatch(constexpr op_has_structure_property_length) >+ dispatch() >+end) > >-_llint_op_has_generic_property: >- traceExecution() >+op(_llint_op_has_generic_property, macro (getOperand, dispatch) > callSlowPath(_slow_path_has_generic_property) >- dispatch(constexpr op_has_generic_property_length) >+ dispatch() >+end) > >-_llint_op_get_direct_pname: >- traceExecution() >+op(_llint_op_get_direct_pname, macro (getOperand, dispatch) > callSlowPath(_slow_path_get_direct_pname) >- dispatch(constexpr op_get_direct_pname_length) >+ dispatch() >+end) > >-_llint_op_get_property_enumerator: >- traceExecution() >+op(_llint_op_get_property_enumerator, macro (getOperand, dispatch) > callSlowPath(_slow_path_get_property_enumerator) >- dispatch(constexpr op_get_property_enumerator_length) >+ dispatch() >+end) > >-_llint_op_enumerator_structure_pname: >- traceExecution() >+op(_llint_op_enumerator_structure_pname, macro (getOperand, dispatch) > callSlowPath(_slow_path_next_structure_enumerator_pname) >- dispatch(constexpr op_enumerator_structure_pname_length) >+ dispatch() >+end) > >-_llint_op_enumerator_generic_pname: >- traceExecution() >+op(_llint_op_enumerator_generic_pname, macro (getOperand, dispatch) > callSlowPath(_slow_path_next_generic_enumerator_pname) >- dispatch(constexpr op_enumerator_generic_pname_length) >+ dispatch() >+end) > >-_llint_op_to_index_string: >- traceExecution() >+op(_llint_op_to_index_string, macro (getOperand, dispatch) > callSlowPath(_slow_path_to_index_string) >- dispatch(constexpr op_to_index_string_length) >+ dispatch() >+end) > >-_llint_op_create_rest: >- traceExecution() >+op(_llint_op_create_rest, macro (getOperand, dispatch) > callSlowPath(_slow_path_create_rest) >- dispatch(constexpr op_create_rest_length) >+ dispatch() >+end) > >-_llint_op_instanceof: >- traceExecution() >+op(_llint_op_instanceof, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_instanceof) >- dispatch(constexpr op_instanceof_length) >+ dispatch() >+end) > >-_llint_op_get_by_id_with_this: >- traceExecution() >+op(_llint_op_get_by_id_with_this, macro (getOperand, dispatch) > callSlowPath(_slow_path_get_by_id_with_this) >- dispatch(constexpr op_get_by_id_with_this_length) >+ dispatch() >+end) > >-_llint_op_get_by_val_with_this: >- traceExecution() >+op(_llint_op_get_by_val_with_this, macro (getOperand, dispatch) > callSlowPath(_slow_path_get_by_val_with_this) >- dispatch(constexpr op_get_by_val_with_this_length) >+ dispatch() >+end) > >-_llint_op_put_by_id_with_this: >- traceExecution() >+op(_llint_op_put_by_id_with_this, macro (getOperand, dispatch) > callSlowPath(_slow_path_put_by_id_with_this) >- dispatch(constexpr op_put_by_id_with_this_length) >+ dispatch() >+end) > >-_llint_op_put_by_val_with_this: >- traceExecution() >+op(_llint_op_put_by_val_with_this, macro (getOperand, dispatch) > callSlowPath(_slow_path_put_by_val_with_this) >- dispatch(constexpr op_put_by_val_with_this_length) >+ dispatch() >+end) > >-_llint_op_resolve_scope_for_hoisting_func_decl_in_eval: >- traceExecution() >+op(_llint_op_resolve_scope_for_hoisting_func_decl_in_eval, macro (getOperand, dispatch) > callSlowPath(_slow_path_resolve_scope_for_hoisting_func_decl_in_eval) >- dispatch(constexpr op_resolve_scope_for_hoisting_func_decl_in_eval_length) >+ dispatch() >+end) > > # Lastly, make sure that we can link even though we don't support all opcodes. > # These opcodes should never arise when using LLInt or either JIT. We assert >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp b/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp >index 78bff0884c4802939a4de860f76b582eaa9a4265..828fc4f85ac7495a75f5cf9b4ae8fb6d68669ebd 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp >@@ -108,13 +108,20 @@ using namespace JSC::LLInt; > > #define OFFLINE_ASM_GLOBAL_LABEL(label) label: USE_LABEL(label); > >+#if ENABLE(LABEL_TRACING) >+#define TRACE_LABEL(prefix, label) dataLog(#prefix, ": ", #label, "\n") >+#else >+#define TRACE_LABEL(prefix, label) do { } while (false); >+#endif >+ >+ > #if ENABLE(COMPUTED_GOTO_OPCODES) >-#define OFFLINE_ASM_GLUE_LABEL(label) label: USE_LABEL(label); >+#define OFFLINE_ASM_GLUE_LABEL(label) label: TRACE_LABEL("OFFLINE_ASM_GLUE_LABEL", label); USE_LABEL(label); > #else > #define OFFLINE_ASM_GLUE_LABEL(label) case label: label: USE_LABEL(label); > #endif > >-#define OFFLINE_ASM_LOCAL_LABEL(label) label: USE_LABEL(label); >+#define OFFLINE_ASM_LOCAL_LABEL(label) label: TRACE_LABEL("OFFLINE_ASM_LOCAL_LABEL", #label); USE_LABEL(label); > > > //============================================================================ >@@ -238,7 +245,7 @@ struct CLoopRegister { > EncodedJSValue encodedJSValue; > double castToDouble; > #endif >- Opcode opcode; >+ OpcodeID opcode; > }; > > operator ExecState*() { return execState; } >@@ -288,8 +295,8 @@ JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, > // can depend on the opcodeMap. > Instruction* exceptionInstructions = LLInt::exceptionInstructions(); > for (int i = 0; i < maxOpcodeLength + 1; ++i) >- exceptionInstructions[i].u.pointer = >- LLInt::getCodePtr(llint_throw_from_slow_path_trampoline); >+ exceptionInstructions[i].u.unsignedValue = >+ llint_throw_from_slow_path_trampoline; > > return JSValue(); > } >@@ -353,7 +360,7 @@ JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, > CLoopStack& cloopStack = vm->interpreter->cloopStack(); > StackPointerScope stackPointerScope(cloopStack); > >- lr.opcode = getOpcode(llint_return_to_host); >+ lr.opcode = llint_return_to_host; > sp.vp = cloopStack.currentStackPointer(); > cfr.callFrame = vm->topCallFrame; > #ifndef NDEBUG >@@ -376,7 +383,7 @@ JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, > // Interpreter variables for value passing between opcodes and/or helpers: > NativeFunction nativeFunc = nullptr; > JSValue functionReturnValue; >- Opcode opcode = getOpcode(entryOpcodeID); >+ OpcodeID opcode = entryOpcodeID; > > #define PUSH(cloopReg) \ > do { \ >@@ -399,7 +406,7 @@ JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, > #if USE(JSVALUE32_64) > #define FETCH_OPCODE() pc.opcode > #else // USE(JSVALUE64) >-#define FETCH_OPCODE() *bitwise_cast<Opcode*>(pcBase.i8p + pc.i * 8) >+#define FETCH_OPCODE() *bitwise_cast<OpcodeID*>(pcBase.i8p + pc.i * 8) > #endif // USE(JSVALUE64) > > #define NEXT_INSTRUCTION() \ >@@ -413,7 +420,7 @@ JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, > //======================================================================== > // Loop dispatch mechanism using computed goto statements: > >- #define DISPATCH_OPCODE() goto *opcode >+ #define DISPATCH_OPCODE() goto *getOpcode(opcode); > > #define DEFINE_OPCODE(__opcode) \ > __opcode: \ >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >index f867597fc46e531a385561f271b871a98422bab0..f2595cd0c44abde89e6f2abce38c6e301acad3c5 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >@@ -23,23 +23,6 @@ > > > # Utilities. >-macro jumpToInstruction() >- jmp [PB, PC, 8], BytecodePtrTag >-end >- >-macro dispatch(advance) >- addp advance, PC >- jumpToInstruction() >-end >- >-macro dispatchInt(advance) >- addi advance, PC >- jumpToInstruction() >-end >- >-macro dispatchIntIndirect(offset) >- dispatchInt(offset * 8[PB, PC, 8]) >-end > > macro dispatchAfterCall() > loadi ArgumentCount + TagOffset[cfr], PC >@@ -277,7 +260,7 @@ macro makeHostFunctionCall(entry, temp) > end > end > >-_handleUncaughtException: >+op(_handleUncaughtException, macro (getOperand, dispatch) > loadp Callee[cfr], t3 > andp MarkedBlockMask, t3 > loadp MarkedBlockFooterOffset + MarkedBlock::Footer::m_vm[t3], t3 >@@ -299,6 +282,7 @@ _handleUncaughtException: > popCalleeSaves() > functionEpilogue() > ret >+end > > > macro prepareStateForCCall() >@@ -591,8 +575,15 @@ end > > > # Instruction implementations >-_llint_op_enter: >+_llint_op_wide: > traceExecution() >+ dispatchWide(constexpr op_wide_length) >+ >+_llint_op_wide_wide: >+ traceExecution() >+ crash() >+ >+op(_llint_op_enter, macro (getOperand, dispatch) > checkStackPointerAlignment(t2, 0xdead00e1) > loadp CodeBlock[cfr], t2 // t2<CodeBlock> = cfr.CodeBlock > loadi CodeBlock::m_numVars[t2], t2 // t2<size_t> = t2<CodeBlock>.m_numVars >@@ -609,11 +600,11 @@ _llint_op_enter: > btqnz t2, .opEnterLoop > .opEnterDone: > callSlowPath(_slow_path_enter) >- dispatch(constexpr op_enter_length) >+ dispatch() >+end) > > >-_llint_op_get_argument: >- traceExecution() >+op(_llint_op_get_argument, macro (getOperand, dispatch) > loadisFromInstruction(1, t1) > loadisFromInstruction(2, t2) > loadi PayloadOffset + ArgumentCount[cfr], t0 >@@ -621,35 +612,35 @@ _llint_op_get_argument: > loadq ThisArgumentOffset[cfr, t2, 8], t0 > storeq t0, [cfr, t1, 8] > valueProfile(t0, 3, t2) >- dispatch(constexpr op_get_argument_length) >+ dispatch() > > .opGetArgumentOutOfBounds: > storeq ValueUndefined, [cfr, t1, 8] > valueProfile(ValueUndefined, 3, t2) >- dispatch(constexpr op_get_argument_length) >+ dispatch() >+end) > > >-_llint_op_argument_count: >- traceExecution() >- loadisFromInstruction(1, t1) >+op(_llint_op_argument_count, macro (getOperand, dispatch) >+ getOperand(1, t1) > loadi PayloadOffset + ArgumentCount[cfr], t0 > subi 1, t0 > orq TagTypeNumber, t0 > storeq t0, [cfr, t1, 8] >- dispatch(constexpr op_argument_count_length) >+ dispatch() >+end) > > >-_llint_op_get_scope: >- traceExecution() >+op(_llint_op_get_scope, macro (getOperand, dispatch) > loadp Callee[cfr], t0 > loadp JSCallee::m_scope[t0], t0 > loadisFromInstruction(1, t1) > storeq t0, [cfr, t1, 8] >- dispatch(constexpr op_get_scope_length) >+ dispatch() >+end) > > >-_llint_op_to_this: >- traceExecution() >+op(_llint_op_to_this, macro (getOperand, dispatch) > loadisFromInstruction(1, t0) > loadq [cfr, t0, 8], t0 > btqnz t0, tagMask, .opToThisSlow >@@ -657,47 +648,48 @@ _llint_op_to_this: > loadStructureWithScratch(t0, t1, t2, t3) > loadpFromInstruction(2, t2) > bpneq t1, t2, .opToThisSlow >- dispatch(constexpr op_to_this_length) >+ dispatch() > > .opToThisSlow: > callSlowPath(_slow_path_to_this) >- dispatch(constexpr op_to_this_length) >+ dispatch() >+end) > > >-_llint_op_check_tdz: >- traceExecution() >- loadisFromInstruction(1, t0) >+op(_llint_op_check_tdz, macro (getOperand, dispatch) >+ getOperand(1, t0) > loadConstantOrVariable(t0, t1) > bqneq t1, ValueEmpty, .opNotTDZ > callSlowPath(_slow_path_throw_tdz_error) > > .opNotTDZ: >- dispatch(constexpr op_check_tdz_length) >+ dispatch() >+end) > > >-_llint_op_mov: >- traceExecution() >- loadisFromInstruction(2, t1) >- loadisFromInstruction(1, t0) >+op(_llint_op_mov, macro (getOperand, dispatch) >+ getOperand(2, t1) >+ getOperand(1, t0) > loadConstantOrVariable(t1, t2) > storeq t2, [cfr, t0, 8] >- dispatch(constexpr op_mov_length) >+ dispatch() >+end) > > >-_llint_op_not: >- traceExecution() >- loadisFromInstruction(2, t0) >- loadisFromInstruction(1, t1) >+op(_llint_op_not, macro (getOperand, dispatch) >+ getOperand(2, t0) >+ getOperand(1, t1) > loadConstantOrVariable(t0, t2) > xorq ValueFalse, t2 > btqnz t2, ~1, .opNotSlow > xorq ValueTrue, t2 > storeq t2, [cfr, t1, 8] >- dispatch(constexpr op_not_length) >+ dispatch() > > .opNotSlow: > callSlowPath(_slow_path_not) >- dispatch(constexpr op_not_length) >+ dispatch() >+end) > > > macro equalityComparison(integerComparison, slowPath) >@@ -753,22 +745,22 @@ macro equalNullComparison() > .done: > end > >-_llint_op_eq_null: >- traceExecution() >+op(_llint_op_eq_null, macro (getOperand, dispatch) > equalNullComparison() >- loadisFromInstruction(1, t1) >+ getOperand(1, t1) > orq ValueFalse, t0 > storeq t0, [cfr, t1, 8] >- dispatch(constexpr op_eq_null_length) >+ dispatch() >+end) > > >-_llint_op_neq_null: >- traceExecution() >+op(_llint_op_neq_null, macro (getOperand, dispatch) > equalNullComparison() > loadisFromInstruction(1, t1) > xorq ValueTrue, t0 > storeq t0, [cfr, t1, 8] >- dispatch(constexpr op_neq_null_length) >+ dispatch() >+end) > > > macro strictEq(equalityOperation, slowPath) >@@ -812,47 +804,46 @@ macro strictEqualityJump(equalityOperation, slowPath) > btqnz t1, tagTypeNumber, .slow > .rightOK: > equalityOperation(t0, t1, .jumpTarget) >- dispatch(constexpr op_jstricteq_length) >+ dispatch() > > .jumpTarget: > dispatchIntIndirect(3) > > .slow: > callSlowPath(slowPath) >- dispatch(0) >+ dispatch() > end > > >-_llint_op_stricteq: >- traceExecution() >+op(_llint_op_stricteq, macro (getOperand, dispatch) > strictEq( > macro (left, right, result) cqeq left, right, result end, > _slow_path_stricteq) >+end) > > >-_llint_op_nstricteq: >- traceExecution() >+op(_llint_op_nstricteq, macro (getOperand, dispatch) > strictEq( > macro (left, right, result) cqneq left, right, result end, > _slow_path_nstricteq) >+end) > > >-_llint_op_jstricteq: >- traceExecution() >+op(_llint_op_jstricteq, macro (getOperand, dispatch) > strictEqualityJump( > macro (left, right, target) bqeq left, right, target end, > _llint_slow_path_jstricteq) >+end) > > >-_llint_op_jnstricteq: >- traceExecution() >+op(_llint_op_jnstricteq, macro (getOperand, dispatch) > strictEqualityJump( > macro (left, right, target) bqneq left, right, target end, > _llint_slow_path_jnstricteq) >+end) > > > macro preOp(arithmeticOperation, slowPath) >- traceExecution() > loadisFromInstruction(1, t0) > loadq [cfr, t0, 8], t1 > bqb t1, tagTypeNumber, .slow >@@ -866,20 +857,21 @@ macro preOp(arithmeticOperation, slowPath) > dispatch(2) > end > >-_llint_op_inc: >+op(llint_op_inc, macro (getOperand, dispatch) > preOp( > macro (value, slow) baddio 1, value, slow end, > _slow_path_inc) >+end) > > >-_llint_op_dec: >+op(_llint_op_dec, macro (getOperand, dispatch) > preOp( > macro (value, slow) bsubio 1, value, slow end, > _slow_path_dec) >+end) > > >-_llint_op_to_number: >- traceExecution() >+op(_llint_op_to_number, macro (getOperand, dispatch) > loadisFromInstruction(2, t0) > loadisFromInstruction(1, t1) > loadConstantOrVariable(t0, t2) >@@ -888,15 +880,15 @@ _llint_op_to_number: > .opToNumberIsImmediate: > storeq t2, [cfr, t1, 8] > valueProfile(t2, 3, t0) >- dispatch(constexpr op_to_number_length) >+ dispatch() > > .opToNumberSlow: > callSlowPath(_slow_path_to_number) >- dispatch(constexpr op_to_number_length) >+ dispatch() >+end) > > >-_llint_op_to_string: >- traceExecution() >+op(_llint_op_to_string, macro (getOperand, dispatch) > loadisFromInstruction(2, t1) > loadisFromInstruction(1, t2) > loadConstantOrVariable(t1, t0) >@@ -909,10 +901,10 @@ _llint_op_to_string: > .opToStringSlow: > callSlowPath(_slow_path_to_string) > dispatch(constexpr op_to_string_length) >+end) > > >-_llint_op_to_object: >- traceExecution() >+op(_llint_op_to_object, macro (getOperand, dispatch) > loadisFromInstruction(2, t0) > loadisFromInstruction(1, t1) > loadConstantOrVariable(t0, t2) >@@ -920,15 +912,15 @@ _llint_op_to_object: > bbb JSCell::m_type[t2], ObjectType, .opToObjectSlow > storeq t2, [cfr, t1, 8] > valueProfile(t2, 4, t0) >- dispatch(constexpr op_to_object_length) >+ dispatch() > > .opToObjectSlow: > callSlowPath(_slow_path_to_object) >- dispatch(constexpr op_to_object_length) >+ dispatch() >+end) > > >-_llint_op_negate: >- traceExecution() >+op(_llint_op_negate, macro (getOperand, dispatch) > loadisFromInstruction(2, t0) > loadisFromInstruction(1, t1) > loadConstantOrVariable(t0, t3) >@@ -947,11 +939,12 @@ _llint_op_negate: > ori ArithProfileNumber, t2 > storeq t3, [cfr, t1, 8] > storeisToInstruction(t2, 3) >- dispatch(constexpr op_negate_length) >+ dispatch() > > .opNegateSlow: > callSlowPath(_slow_path_negate) >- dispatch(constexpr op_negate_length) >+ dispatch() >+end) > > > macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath) >@@ -1025,16 +1018,15 @@ macro binaryOp(integerOperation, doubleOperation, slowPath) > doubleOperation, slowPath) > end > >-_llint_op_add: >- traceExecution() >+op(_llint_op_add, macro (getOperand, dispatch) > binaryOp( > macro (left, right, slow) baddio left, right, slow end, > macro (left, right) addd left, right end, > _slow_path_add) >+end) > > >-_llint_op_mul: >- traceExecution() >+op(_llint_op_mul, macro (getOperand, dispatch) > binaryOpCustomStore( > macro (left, right, slow, index) > # Assume t3 is scratchable. >@@ -1049,18 +1041,18 @@ _llint_op_mul: > end, > macro (left, right) muld left, right end, > _slow_path_mul) >+end) > > >-_llint_op_sub: >- traceExecution() >+op(_llint_op_sub, macro (getOperand, dispatch) > binaryOp( > macro (left, right, slow) bsubio left, right, slow end, > macro (left, right) subd left, right end, > _slow_path_sub) >+end) > > >-_llint_op_div: >- traceExecution() >+op(_llint_op_div, macro (getOperand, dispatch) > if X86_64 or X86_64_WIN > binaryOpCustomStore( > macro (left, right, slow, index) >@@ -1086,6 +1078,7 @@ _llint_op_div: > callSlowPath(_slow_path_div) > dispatch(constexpr op_div_length) > end >+end) > > > macro bitOp(operation, slowPath, advance) >@@ -1106,32 +1099,31 @@ macro bitOp(operation, slowPath, advance) > dispatch(advance) > end > >-_llint_op_lshift: >- traceExecution() >+op(_llint_op_lshift, macro (getOperand, dispatch) > bitOp( > macro (left, right) lshifti left, right end, > _slow_path_lshift, > constexpr op_lshift_length) >+end) > > >-_llint_op_rshift: >- traceExecution() >+op(_llint_op_rshift, macro (getOperand, dispatch) > bitOp( > macro (left, right) rshifti left, right end, > _slow_path_rshift, > constexpr op_rshift_length) >+end) > > >-_llint_op_urshift: >- traceExecution() >+op(_llint_op_urshift, macro (getOperand, dispatch) > bitOp( > macro (left, right) urshifti left, right end, > _slow_path_urshift, > constexpr op_urshift_length) >+end) > > >-_llint_op_unsigned: >- traceExecution() >+op(_llint_op_unsigned, macro (getOperand, dispatch) > loadisFromInstruction(1, t0) > loadisFromInstruction(2, t1) > loadConstantOrVariable(t1, t2) >@@ -1141,34 +1133,35 @@ _llint_op_unsigned: > .opUnsignedSlow: > callSlowPath(_slow_path_unsigned) > dispatch(constexpr op_unsigned_length) >+end) > > >-_llint_op_bitand: >- traceExecution() >+op(_llint_op_bitand, macro (getOperand, dispatch) > bitOp( > macro (left, right) andi left, right end, > _slow_path_bitand, > constexpr op_bitand_length) >+end) > > >-_llint_op_bitxor: >- traceExecution() >+op(_llint_op_bitxor, macro (getOperand, dispatch) > bitOp( > macro (left, right) xori left, right end, > _slow_path_bitxor, > constexpr op_bitxor_length) >+end) > > >-_llint_op_bitor: >+op(_llint_op_bitor, macro (getOperand, dispatch) > traceExecution() > bitOp( > macro (left, right) ori left, right end, > _slow_path_bitor, > constexpr op_bitor_length) >+end) > > >-_llint_op_overrides_has_instance: >- traceExecution() >+op(_llint_op_overrides_has_instance, macro (getOperand, dispatch) > loadisFromStruct(OpOverridesHasInstance::m_dst, t3) > > loadisFromStruct(OpOverridesHasInstance::m_hasInstanceValue, t1) >@@ -1183,32 +1176,32 @@ _llint_op_overrides_has_instance: > tbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, t1 > orq ValueFalse, t1 > storeq t1, [cfr, t3, 8] >- dispatch(constexpr op_overrides_has_instance_length) >+ dispatch() > > .opOverridesHasInstanceNotDefaultSymbol: > storeq ValueTrue, [cfr, t3, 8] >- dispatch(constexpr op_overrides_has_instance_length) >+ dispatch() >+end) > > >-_llint_op_instanceof_custom: >- traceExecution() >+op(_llint_op_instanceof_custom, macro (getOperand, dispatch) > callSlowPath(_llint_slow_path_instanceof_custom) >- dispatch(constexpr op_instanceof_custom_length) >+ dispatch() >+end) > > >-_llint_op_is_empty: >- traceExecution() >+op(_llint_op_is_empty, macro (getOperand, dispatch) > loadisFromInstruction(2, t1) > loadisFromInstruction(1, t2) > loadConstantOrVariable(t1, t0) > cqeq t0, ValueEmpty, t3 > orq ValueFalse, t3 > storeq t3, [cfr, t2, 8] >- dispatch(constexpr op_is_empty_length) >+ dispatch() >+end) > > >-_llint_op_is_undefined: >- traceExecution() >+op(_llint_op_is_undefined, macro (getOperand, dispatch) > loadisFromInstruction(2, t1) > loadisFromInstruction(1, t2) > loadConstantOrVariable(t1, t0) >@@ -1216,12 +1209,12 @@ _llint_op_is_undefined: > cqeq t0, ValueUndefined, t3 > orq ValueFalse, t3 > storeq t3, [cfr, t2, 8] >- dispatch(constexpr op_is_undefined_length) >+ dispatch() > .opIsUndefinedCell: > btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined > move ValueFalse, t1 > storeq t1, [cfr, t2, 8] >- dispatch(constexpr op_is_undefined_length) >+ dispatch() > .masqueradesAsUndefined: > loadStructureWithScratch(t0, t3, t1, t5) > loadp CodeBlock[cfr], t1 >@@ -1229,11 +1222,11 @@ _llint_op_is_undefined: > cpeq Structure::m_globalObject[t3], t1, t0 > orq ValueFalse, t0 > storeq t0, [cfr, t2, 8] >- dispatch(constexpr op_is_undefined_length) >+ dispatch() >+end) > > >-_llint_op_is_boolean: >- traceExecution() >+op(_llint_op_is_boolean, macro (getOperand, dispatch) > loadisFromInstruction(2, t1) > loadisFromInstruction(1, t2) > loadConstantOrVariable(t1, t0) >@@ -1241,22 +1234,22 @@ _llint_op_is_boolean: > tqz t0, ~1, t0 > orq ValueFalse, t0 > storeq t0, [cfr, t2, 8] >- dispatch(constexpr op_is_boolean_length) >+ dispatch() >+end) > > >-_llint_op_is_number: >- traceExecution() >+op(_llint_op_is_number, macro (getOperand, dispatch) > loadisFromInstruction(2, t1) > loadisFromInstruction(1, t2) > loadConstantOrVariable(t1, t0) > tqnz t0, tagTypeNumber, t1 > orq ValueFalse, t1 > storeq t1, [cfr, t2, 8] >- dispatch(constexpr op_is_number_length) >+ dispatch() >+end) > > >-_llint_op_is_cell_with_type: >- traceExecution() >+op(_llint_op_is_cell_with_type, macro (getOperand, dispatch) > loadisFromInstruction(3, t0) > loadisFromInstruction(2, t1) > loadisFromInstruction(1, t2) >@@ -1265,14 +1258,14 @@ _llint_op_is_cell_with_type: > cbeq JSCell::m_type[t3], t0, t1 > orq ValueFalse, t1 > storeq t1, [cfr, t2, 8] >- dispatch(constexpr op_is_cell_with_type_length) >+ dispatch() > .notCellCase: > storeq ValueFalse, [cfr, t2, 8] >- dispatch(constexpr op_is_cell_with_type_length) >+ dispatch() >+end) > > >-_llint_op_is_object: >- traceExecution() >+op(_llint_op_is_object, macro (getOperand, dispatch) > loadisFromInstruction(2, t1) > loadisFromInstruction(1, t2) > loadConstantOrVariable(t1, t0) >@@ -1280,10 +1273,11 @@ _llint_op_is_object: > cbaeq JSCell::m_type[t0], ObjectType, t1 > orq ValueFalse, t1 > storeq t1, [cfr, t2, 8] >- dispatch(constexpr op_is_object_length) >+ dispatch() > .opIsObjectNotCell: > storeq ValueFalse, [cfr, t2, 8] >- dispatch(constexpr op_is_object_length) >+ dispatch() >+end) > > > macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value) >@@ -1312,8 +1306,7 @@ macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value > end > > >-_llint_op_get_by_id_direct: >- traceExecution() >+op(_llint_op_get_by_id_direct, macro (getOperand, dispatch) > loadisFromInstruction(2, t0) > loadConstantOrVariableCell(t0, t3, .opGetByIdDirectSlow) > loadi JSCell::m_structureID[t3], t1 >@@ -1324,15 +1317,15 @@ _llint_op_get_by_id_direct: > loadPropertyAtVariableOffset(t1, t3, t0) > storeq t0, [cfr, t2, 8] > valueProfile(t0, 6, t1) >- dispatch(constexpr op_get_by_id_direct_length) >+ dispatch() > > .opGetByIdDirectSlow: > callSlowPath(_llint_slow_path_get_by_id_direct) >- dispatch(constexpr op_get_by_id_direct_length) >+ dispatch() >+end) > > >-_llint_op_get_by_id: >- traceExecution() >+op(_llint_op_get_by_id, macro (getOperand, dispatch) > loadisFromInstruction(2, t0) > loadConstantOrVariableCell(t0, t3, .opGetByIdSlow) > loadi JSCell::m_structureID[t3], t1 >@@ -1343,15 +1336,15 @@ _llint_op_get_by_id: > loadPropertyAtVariableOffset(t1, t3, t0) > storeq t0, [cfr, t2, 8] > valueProfile(t0, 8, t1) >- dispatch(constexpr op_get_by_id_length) >+ dispatch() > > .opGetByIdSlow: > callSlowPath(_llint_slow_path_get_by_id) >- dispatch(constexpr op_get_by_id_length) >+ dispatch() >+end) > > >-_llint_op_get_by_id_proto_load: >- traceExecution() >+op(_llint_op_get_by_id_proto_load, macro (getOperand, dispatch) > loadisFromInstruction(2, t0) > loadConstantOrVariableCell(t0, t3, .opGetByIdProtoSlow) > loadi JSCell::m_structureID[t3], t1 >@@ -1363,15 +1356,15 @@ _llint_op_get_by_id_proto_load: > loadPropertyAtVariableOffset(t1, t3, t0) > storeq t0, [cfr, t2, 8] > valueProfile(t0, 8, t1) >- dispatch(constexpr op_get_by_id_proto_load_length) >+ dispatch() > > .opGetByIdProtoSlow: > callSlowPath(_llint_slow_path_get_by_id) >- dispatch(constexpr op_get_by_id_proto_load_length) >+ dispatch() >+end) > > >-_llint_op_get_by_id_unset: >- traceExecution() >+op(_llint_op_get_by_id_unset, macro (getOperand, dispatch) > loadisFromInstruction(2, t0) > loadConstantOrVariableCell(t0, t3, .opGetByIdUnsetSlow) > loadi JSCell::m_structureID[t3], t1 >@@ -1380,15 +1373,15 @@ _llint_op_get_by_id_unset: > loadisFromInstruction(1, t2) > storeq ValueUndefined, [cfr, t2, 8] > valueProfile(ValueUndefined, 8, t1) >- dispatch(constexpr op_get_by_id_unset_length) >+ dispatch() > > .opGetByIdUnsetSlow: > callSlowPath(_llint_slow_path_get_by_id) >- dispatch(constexpr op_get_by_id_unset_length) >+ dispatch() >+end) > > >-_llint_op_get_array_length: >- traceExecution() >+op(_llint_op_get_array_length, macro (getOperand, dispatch) > loadisFromInstruction(2, t0) > loadpFromInstruction(4, t1) > loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow) >@@ -1403,15 +1396,15 @@ _llint_op_get_array_length: > orq tagTypeNumber, t0 > valueProfile(t0, 8, t2) > storeq t0, [cfr, t1, 8] >- dispatch(constexpr op_get_array_length_length) >+ dispatch() > > .opGetArrayLengthSlow: > callSlowPath(_llint_slow_path_get_by_id) >- dispatch(constexpr op_get_array_length_length) >+ dispatch() >+end) > > >-_llint_op_put_by_id: >- traceExecution() >+op(_llint_op_put_by_id, macro (getOperand, dispatch) > loadisFromInstruction(1, t3) > loadConstantOrVariableCell(t3, t0, .opPutByIdSlow) > loadisFromInstruction(4, t2) >@@ -1546,11 +1539,12 @@ _llint_op_put_by_id: > loadisFromInstruction(5, t1) > storePropertyAtVariableOffset(t1, t0, t2) > writeBarrierOnOperands(1, 3) >- dispatch(constexpr op_put_by_id_length) >+ dispatch() > > .opPutByIdSlow: > callSlowPath(_llint_slow_path_put_by_id) >- dispatch(constexpr op_put_by_id_length) >+ dispatch() >+end) > > > macro finishGetByVal(result, scratch) >@@ -1571,8 +1565,7 @@ macro finishDoubleGetByVal(result, scratch1, scratch2) > finishGetByVal(scratch1, scratch2) > end > >-_llint_op_get_by_val: >- traceExecution() >+op(_llint_op_get_by_val, macro (getOperand, dispatch) > loadisFromInstruction(2, t2) > loadConstantOrVariableCell(t2, t0, .opGetByValSlow) > loadpFromInstruction(4, t3) >@@ -1614,7 +1607,7 @@ _llint_op_get_by_val: > .opGetByValDone: > storeq t2, [cfr, t0, 8] > valueProfile(t2, 5, t0) >- dispatch(constexpr op_get_by_val_length) >+ dispatch() > > .opGetByValNotIndexedStorage: > # First lets check if we even have a typed array. This lets us do some boilerplate up front. >@@ -1711,7 +1704,8 @@ _llint_op_get_by_val: > > .opGetByValSlow: > callSlowPath(_llint_slow_path_get_by_val) >- dispatch(constexpr op_get_by_val_length) >+ dispatch() >+end) > > > macro contiguousPutByVal(storeCallback) >@@ -1806,17 +1800,18 @@ macro putByVal(slowPath) > dispatch(5) > end > >-_llint_op_put_by_val: >+op(_llint_op_put_by_val, macro (getOperand, dispatch) > putByVal(_llint_slow_path_put_by_val) >+end) > >-_llint_op_put_by_val_direct: >+op(_llint_op_put_by_val_direct, macro (getOperand, dispatch) > putByVal(_llint_slow_path_put_by_val_direct) >+end) > > >-_llint_op_jmp: >- traceExecution() >+op(_llint_op_jmp, macro (getOperand, dispatch) > dispatchIntIndirect(1) >- >+end) > > macro jumpTrueOrFalse(conditionOp, slow) > loadisFromInstruction(1, t1) >@@ -1852,8 +1847,7 @@ macro equalNull(cellHandler, immediateHandler) > dispatch(3) > end > >-_llint_op_jeq_null: >- traceExecution() >+op(_llint_op_jeq_null, macro (getOperand, dispatch) > equalNull( > macro (structure, value, target) > btbz value, MasqueradesAsUndefined, .notMasqueradesAsUndefined >@@ -1863,10 +1857,10 @@ _llint_op_jeq_null: > .notMasqueradesAsUndefined: > end, > macro (value, target) bqeq value, ValueNull, target end) >+end) > > >-_llint_op_jneq_null: >- traceExecution() >+op(_llint_op_jneq_null, macro (getOperand, dispatch) > equalNull( > macro (structure, value, target) > btbz value, MasqueradesAsUndefined, target >@@ -1875,21 +1869,22 @@ _llint_op_jneq_null: > bpneq Structure::m_globalObject[structure], t0, target > end, > macro (value, target) bqneq value, ValueNull, target end) >+end) > > >-_llint_op_jneq_ptr: >- traceExecution() >+op(_llint_op_jneq_ptr, macro (getOperand, dispatch) > loadisFromInstruction(1, t0) > loadisFromInstruction(2, t1) > loadp CodeBlock[cfr], t2 > loadp CodeBlock::m_globalObject[t2], t2 > loadp JSGlobalObject::m_specialPointers[t2, t1, 8], t1 > bpneq t1, [cfr, t0, 8], .opJneqPtrTarget >- dispatch(5) >+ dispatch() > > .opJneqPtrTarget: > storei 1, 32[PB, PC, 8] > dispatchIntIndirect(3) >+end) > > > macro compareJump(integerCompare, doubleCompare, slowPath) >@@ -1960,8 +1955,7 @@ macro compareUnsigned(integerCompareAndSet) > end > > >-_llint_op_switch_imm: >- traceExecution() >+op(_llint_op_switch_imm, macro (getOperand, dispatch) > loadisFromInstruction(3, t2) > loadisFromInstruction(1, t3) > loadConstantOrVariable(t2, t1) >@@ -1986,10 +1980,10 @@ _llint_op_switch_imm: > .opSwitchImmSlow: > callSlowPath(_llint_slow_path_switch_imm) > dispatch(0) >+end) > > >-_llint_op_switch_char: >- traceExecution() >+op(_llint_op_switch_char, macro (getOperand, dispatch) > loadisFromInstruction(3, t2) > loadisFromInstruction(1, t3) > loadConstantOrVariable(t2, t1) >@@ -2023,6 +2017,7 @@ _llint_op_switch_char: > .opSwitchOnRope: > callSlowPath(_llint_slow_path_switch_char) > dispatch(0) >+end) > > > macro arrayProfileForCall() >@@ -2068,16 +2063,15 @@ macro doCall(slowPath, prepareCall) > slowPathForCall(slowPath, prepareCall) > end > >-_llint_op_ret: >- traceExecution() >+op(_llint_op_ret, macro (getOperand, dispatch) > checkSwitchToJITForEpilogue() > loadisFromInstruction(1, t2) > loadConstantOrVariable(t2, r0) > doReturn() >+end) > > >-_llint_op_to_primitive: >- traceExecution() >+op(_llint_op_to_primitive, macro (getOperand, dispatch) > loadisFromInstruction(2, t2) > loadisFromInstruction(1, t3) > loadConstantOrVariable(t2, t0) >@@ -2085,14 +2079,15 @@ _llint_op_to_primitive: > bbaeq JSCell::m_type[t0], ObjectType, .opToPrimitiveSlowCase > .opToPrimitiveIsImm: > storeq t0, [cfr, t3, 8] >- dispatch(constexpr op_to_primitive_length) >+ dispatch() > > .opToPrimitiveSlowCase: > callSlowPath(_slow_path_to_primitive) >- dispatch(constexpr op_to_primitive_length) >+ dispatch() >+end) > > >-_llint_op_catch: >+op(_llint_op_catch, macro (getOperand, dispatch) > # This is where we end up from the JIT's throw trampoline (because the > # machine code return address will be set to _llint_op_catch), and from > # the interpreter's throw trampoline (see _llint_throw_trampoline). >@@ -2135,19 +2130,20 @@ _llint_op_catch: > > callSlowPath(_llint_slow_path_profile_catch) > >- dispatch(constexpr op_catch_length) >+ dispatch() >+end) > > >-_llint_op_end: >- traceExecution() >+op(_llint_op_end, macro (getOperand, dispatch) > checkSwitchToJITForEpilogue() > loadisFromInstruction(1, t0) > assertNotConstant(t0) > loadq [cfr, t0, 8], r0 > doReturn() >+end) > > >-_llint_throw_from_slow_path_trampoline: >+op(_llint_throw_from_slow_path_trampoline, macro (getOperand, dispatch) > loadp Callee[cfr], t1 > andp MarkedBlockMask, t1 > loadp MarkedBlockFooterOffset + MarkedBlock::Footer::m_vm[t1], t1 >@@ -2162,11 +2158,13 @@ _llint_throw_from_slow_path_trampoline: > andp MarkedBlockMask, t1 > loadp MarkedBlockFooterOffset + MarkedBlock::Footer::m_vm[t1], t1 > jmp VM::targetMachinePCForThrow[t1], ExceptionHandlerPtrTag >+end) > > >-_llint_throw_during_call_trampoline: >+op(_llint_throw_during_call_trampoline, macro (getOperand, dispatch) > preserveReturnAddressAfterCall(t2) > jmp _llint_throw_from_slow_path_trampoline >+end) > > > macro nativeCallTrampoline(executableOffsetToFunction) >@@ -2288,62 +2286,62 @@ macro resolveScope() > end > > >-_llint_op_resolve_scope: >- traceExecution() >+op(_llint_op_resolve_scope, macro (getOperand, dispatch) > loadisFromInstruction(4, t0) > > #rGlobalProperty: > bineq t0, GlobalProperty, .rGlobalVar > getConstantScope(1) >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rGlobalVar: > bineq t0, GlobalVar, .rGlobalLexicalVar > getConstantScope(1) >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rGlobalLexicalVar: > bineq t0, GlobalLexicalVar, .rClosureVar > getConstantScope(1) >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rClosureVar: > bineq t0, ClosureVar, .rModuleVar > resolveScope() >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rModuleVar: > bineq t0, ModuleVar, .rGlobalPropertyWithVarInjectionChecks > getConstantScope(1) >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rGlobalPropertyWithVarInjectionChecks: > bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) > getConstantScope(1) >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rGlobalVarWithVarInjectionChecks: > bineq t0, GlobalVarWithVarInjectionChecks, .rGlobalLexicalVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) > getConstantScope(1) >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rGlobalLexicalVarWithVarInjectionChecks: > bineq t0, GlobalLexicalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) > getConstantScope(1) >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rClosureVarWithVarInjectionChecks: > bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic > varInjectionCheck(.rDynamic) > resolveScope() >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() > > .rDynamic: > callSlowPath(_slow_path_resolve_scope) >- dispatch(constexpr op_resolve_scope_length) >+ dispatch() >+end) > > > macro loadWithStructureCheck(operand, slowPath) >@@ -2379,8 +2377,7 @@ macro getClosureVar() > storeq t0, [cfr, t1, 8] > end > >-_llint_op_get_from_scope: >- traceExecution() >+op(_llint_op_get_from_scope, macro (getOperand, dispatch) > loadisFromInstruction(4, t0) > andi ResolveTypeMask, t0 > >@@ -2388,12 +2385,12 @@ _llint_op_get_from_scope: > bineq t0, GlobalProperty, .gGlobalVar > loadWithStructureCheck(2, .gDynamic) > getProperty() >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() > > .gGlobalVar: > bineq t0, GlobalVar, .gGlobalLexicalVar > getGlobalVar(macro(v) end) >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() > > .gGlobalLexicalVar: > bineq t0, GlobalLexicalVar, .gClosureVar >@@ -2401,25 +2398,25 @@ _llint_op_get_from_scope: > macro (value) > bqeq value, ValueEmpty, .gDynamic > end) >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() > > .gClosureVar: > bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks > loadVariable(2, t0) > getClosureVar() >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() > > .gGlobalPropertyWithVarInjectionChecks: > bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks > loadWithStructureCheck(2, .gDynamic) > getProperty() >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() > > .gGlobalVarWithVarInjectionChecks: > bineq t0, GlobalVarWithVarInjectionChecks, .gGlobalLexicalVarWithVarInjectionChecks > varInjectionCheck(.gDynamic) > getGlobalVar(macro(v) end) >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() > > .gGlobalLexicalVarWithVarInjectionChecks: > bineq t0, GlobalLexicalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks >@@ -2428,18 +2425,19 @@ _llint_op_get_from_scope: > macro (value) > bqeq value, ValueEmpty, .gDynamic > end) >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() > > .gClosureVarWithVarInjectionChecks: > bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic > varInjectionCheck(.gDynamic) > loadVariable(2, t0) > getClosureVar() >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() > > .gDynamic: > callSlowPath(_llint_slow_path_get_from_scope) >- dispatch(constexpr op_get_from_scope_length) >+ dispatch() >+end) > > > macro putProperty() >@@ -2488,58 +2486,58 @@ macro checkTDZInGlobalPutToScopeIfNecessary() > end > > >-_llint_op_put_to_scope: >- traceExecution() >+op(_llint_op_put_to_scope, macro (getOperand, dispatch) > loadisFromInstruction(4, t0) > andi ResolveTypeMask, t0 >+end) > > #pLocalClosureVar: > bineq t0, LocalClosureVar, .pGlobalProperty > loadVariable(1, t0) > putLocalClosureVar() > writeBarrierOnOperands(1, 3) >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pGlobalProperty: > bineq t0, GlobalProperty, .pGlobalVar > loadWithStructureCheck(1, .pDynamic) > putProperty() > writeBarrierOnOperands(1, 3) >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pGlobalVar: > bineq t0, GlobalVar, .pGlobalLexicalVar > writeBarrierOnGlobalObject(3) > putGlobalVariable() >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pGlobalLexicalVar: > bineq t0, GlobalLexicalVar, .pClosureVar > writeBarrierOnGlobalLexicalEnvironment(3) > checkTDZInGlobalPutToScopeIfNecessary() > putGlobalVariable() >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pClosureVar: > bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks > loadVariable(1, t0) > putClosureVar() > writeBarrierOnOperands(1, 3) >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pGlobalPropertyWithVarInjectionChecks: > bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks > loadWithStructureCheck(1, .pDynamic) > putProperty() > writeBarrierOnOperands(1, 3) >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pGlobalVarWithVarInjectionChecks: > bineq t0, GlobalVarWithVarInjectionChecks, .pGlobalLexicalVarWithVarInjectionChecks > writeBarrierOnGlobalObject(3) > varInjectionCheck(.pDynamic) > putGlobalVariable() >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pGlobalLexicalVarWithVarInjectionChecks: > bineq t0, GlobalLexicalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks >@@ -2547,7 +2545,7 @@ _llint_op_put_to_scope: > varInjectionCheck(.pDynamic) > checkTDZInGlobalPutToScopeIfNecessary() > putGlobalVariable() >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pClosureVarWithVarInjectionChecks: > bineq t0, ClosureVarWithVarInjectionChecks, .pModuleVar >@@ -2555,51 +2553,51 @@ _llint_op_put_to_scope: > loadVariable(1, t0) > putClosureVar() > writeBarrierOnOperands(1, 3) >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pModuleVar: > bineq t0, ModuleVar, .pDynamic > callSlowPath(_slow_path_throw_strict_mode_readonly_property_write_error) >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() > > .pDynamic: > callSlowPath(_llint_slow_path_put_to_scope) >- dispatch(constexpr op_put_to_scope_length) >+ dispatch() >+end) > > >-_llint_op_get_from_arguments: >- traceExecution() >+op(_llint_op_get_from_arguments, macro (getOperand, dispatch) > loadVariable(2, t0) > loadi 24[PB, PC, 8], t1 > loadq DirectArguments_storage[t0, t1, 8], t0 > valueProfile(t0, 4, t1) > loadisFromInstruction(1, t1) > storeq t0, [cfr, t1, 8] >- dispatch(constexpr op_get_from_arguments_length) >+ dispatch() >+end) > > >-_llint_op_put_to_arguments: >- traceExecution() >+op(_llint_op_put_to_arguments, macro (getOperand, dispatch) > loadVariable(1, t0) > loadi 16[PB, PC, 8], t1 > loadisFromInstruction(3, t3) > loadConstantOrVariable(t3, t2) > storeq t2, DirectArguments_storage[t0, t1, 8] > writeBarrierOnOperands(1, 3) >- dispatch(constexpr op_put_to_arguments_length) >+ dispatch() >+end) > > >-_llint_op_get_parent_scope: >- traceExecution() >+op(_llint_op_get_parent_scope, macro (getOperand, dispatch) > loadVariable(2, t0) > loadp JSScope::m_next[t0], t0 > loadisFromInstruction(1, t1) > storeq t0, [cfr, t1, 8] >- dispatch(constexpr op_get_parent_scope_length) >+ dispatch() >+end) > > >-_llint_op_profile_type: >- traceExecution() >+op(_llint_op_profile_type, macro (getOperand, dispatch) > loadp CodeBlock[cfr], t1 > loadp CodeBlock::m_poisonedVM[t1], t1 > unpoison(_g_CodeBlockPoison, t1, t3) >@@ -2637,17 +2635,18 @@ _llint_op_profile_type: > callSlowPath(_slow_path_profile_type_clear_log) > > .opProfileTypeDone: >- dispatch(constexpr op_profile_type_length) >+ dispatch() >+end) > >-_llint_op_profile_control_flow: >- traceExecution() >+ >+op(_llint_op_profile_control_flow, macro (getOperand, dispatch) > loadpFromInstruction(1, t0) > addq 1, BasicBlockLocation::m_executionCount[t0] >- dispatch(constexpr op_profile_control_flow_length) >+ dispatch() >+end) > > >-_llint_op_get_rest_length: >- traceExecution() >+op(_llint_op_get_rest_length, macro (getOperand, dispatch) > loadi PayloadOffset + ArgumentCount[cfr], t0 > subi 1, t0 > loadisFromInstruction(2, t1) >@@ -2660,11 +2659,11 @@ _llint_op_get_rest_length: > orq tagTypeNumber, t0 > loadisFromInstruction(1, t1) > storeq t0, [cfr, t1, 8] >- dispatch(constexpr op_get_rest_length_length) >+ dispatch() >+end) > > >-_llint_op_log_shadow_chicken_prologue: >- traceExecution() >+op(_llint_op_log_shadow_chicken_prologue, macro (getOperand, dispatch) > acquireShadowChickenPacket(.opLogShadowChickenPrologueSlow) > storep cfr, ShadowChicken::Packet::frame[t0] > loadp CallerFrame[cfr], t1 >@@ -2673,14 +2672,14 @@ _llint_op_log_shadow_chicken_prologue: > storep t1, ShadowChicken::Packet::callee[t0] > loadVariable(1, t1) > storep t1, ShadowChicken::Packet::scope[t0] >- dispatch(constexpr op_log_shadow_chicken_prologue_length) >+ dispatch() > .opLogShadowChickenPrologueSlow: > callSlowPath(_llint_slow_path_log_shadow_chicken_prologue) >- dispatch(constexpr op_log_shadow_chicken_prologue_length) >+ dispatch() >+end) > > >-_llint_op_log_shadow_chicken_tail: >- traceExecution() >+op(_llint_op_log_shadow_chicken_tail, macro (getOperand, dispatch) > acquireShadowChickenPacket(.opLogShadowChickenTailSlow) > storep cfr, ShadowChicken::Packet::frame[t0] > storep ShadowChickenTailMarker, ShadowChicken::Packet::callee[t0] >@@ -2691,7 +2690,8 @@ _llint_op_log_shadow_chicken_tail: > loadp CodeBlock[cfr], t1 > storep t1, ShadowChicken::Packet::codeBlock[t0] > storei PC, ShadowChicken::Packet::callSiteIndex[t0] >- dispatch(constexpr op_log_shadow_chicken_tail_length) >+ dispatch() > .opLogShadowChickenTailSlow: > callSlowPath(_llint_slow_path_log_shadow_chicken_tail) >- dispatch(constexpr op_log_shadow_chicken_tail_length) >+ dispatch() >+end) >diff --git a/Source/JavaScriptCore/offlineasm/asm.rb b/Source/JavaScriptCore/offlineasm/asm.rb >index 06041497423eb4c5767d52fa894f914f53953c2b..46c7b1f023736e1a832886fd061d39da3656d597 100644 >--- a/Source/JavaScriptCore/offlineasm/asm.rb >+++ b/Source/JavaScriptCore/offlineasm/asm.rb >@@ -390,6 +390,12 @@ File.open(outputFlnm, "w") { > lowLevelAST.validate > emitCodeInConfiguration(concreteSettings, lowLevelAST, backend) { > $asm.inAsm { >+ $wideOpcodes = false >+ lowLevelAST.lower(backend) >+ } >+ >+ $asm.inAsm { >+ $wideOpcodes = true > lowLevelAST.lower(backend) > } > } >diff --git a/Source/JavaScriptCore/offlineasm/ast.rb b/Source/JavaScriptCore/offlineasm/ast.rb >index 0ccf7b331bbb30ee11c976c08eb6b29660d8de15..f4b62a2f9a8b328958720b08690d899ce841816b 100644 >--- a/Source/JavaScriptCore/offlineasm/ast.rb >+++ b/Source/JavaScriptCore/offlineasm/ast.rb >@@ -1016,8 +1016,6 @@ $labelMapping = {} > $referencedExternLabels = Array.new > > class Label < NoChildren >- attr_reader :name >- > def initialize(codeOrigin, name) > super(codeOrigin) > @name = name >@@ -1076,6 +1074,10 @@ class Label < NoChildren > @global > end > >+ def name >+ $wideOpcodes ? "#{@name}_wide" : @name >+ end >+ > def dump > "#{name}:" > end >diff --git a/Source/JavaScriptCore/offlineasm/cloop.rb b/Source/JavaScriptCore/offlineasm/cloop.rb >index 870525922f02a4447e8732f99a0d8bfe5d186cc4..9dd818dc623d7e7f02e2384e5649a0fa04525324 100644 >--- a/Source/JavaScriptCore/offlineasm/cloop.rb >+++ b/Source/JavaScriptCore/offlineasm/cloop.rb >@@ -222,7 +222,7 @@ class Address > "*CAST<NativeFunction*>(#{pointerExpr})" > end > def opcodeMemRef >- "*CAST<Opcode*>(#{pointerExpr})" >+ "*CAST<OpcodeID*>(#{pointerExpr})" > end > def dblMemRef > "*CAST<double*>(#{pointerExpr})" >@@ -286,7 +286,7 @@ class BaseIndex > "*CAST<uintptr_t*>(#{pointerExpr})" > end > def opcodeMemRef >- "*CAST<Opcode*>(#{pointerExpr})" >+ "*CAST<OpcodeID*>(#{pointerExpr})" > end > def dblMemRef > "*CAST<double*>(#{pointerExpr})" >@@ -1077,7 +1077,7 @@ class Instruction > # as an opcode dispatch. > when "cloopCallJSFunction" > uid = $asm.newUID >- $asm.putc "lr.opcode = getOpcode(llint_cloop_did_return_from_js_#{uid});" >+ $asm.putc "lr.opcode = llint_cloop_did_return_from_js_#{uid};" > $asm.putc "opcode = #{operands[0].clValue(:opcode)};" > $asm.putc "DISPATCH_OPCODE();" > $asm.putsLabel("llint_cloop_did_return_from_js_#{uid}", false) >diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp >index 6e93ce810011618e8d4c8b80e670d83e8e18a129..f5054f8aa8fe08f49b8848ee5503900991620ae9 100644 >--- a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp >+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp >@@ -55,7 +55,7 @@ BytecodeSequence::BytecodeSequence(CodeBlock* codeBlock) > for (unsigned bytecodeIndex = 0; bytecodeIndex < codeBlock->instructions().size();) { > out.reset(); > codeBlock->dumpBytecode(out, bytecodeIndex, statusMap); >- OpcodeID opcodeID = Interpreter::getOpcodeID(codeBlock->instructions()[bytecodeIndex].u.opcode); >+ OpcodeID opcodeID = codeBlock->instructions()[bytecodeIndex].u.opcode; > m_sequence.append(Bytecode(bytecodeIndex, opcodeID, out.toCString())); > bytecodeIndex += opcodeLength(opcodeID); > } >diff --git a/Source/JavaScriptCore/wip_bytecode/README.md b/Source/JavaScriptCore/wip_bytecode/README.md >new file mode 100644 >index 0000000000000000000000000000000000000000..dfd11654f7b196b89392d674711c5a383a4b74ab >--- /dev/null >+++ b/Source/JavaScriptCore/wip_bytecode/README.md >@@ -0,0 +1,151 @@ >+# Bytecode format >+ >++--------------+ >+| header | >++==============+ >+| instruction0 | >++--------------+ >+| instruction1 | >++--------------+ >+| ... | >++--------------+ >+| instructionN | >++--------------+ >+ >+## Header >+ >++--------------+ >+|num_parameters| >++--------------+ >+| has_metadata | >++--------------+ >+| count_op1 | >++--------------+ >+| ... | >++--------------+ >+| count_opN | >++--------------+ >+| liveness | >++--------------+ >+| global_info | >++--------------+ >+| constants | >++--------------+ >+ >+* `has_metada` is a BitMap that indicates which opcodes need side table entries >+* `count_opI` is a varible length unsigned number that indicates how many entries are necessary for opcode I. >+ >+Given that we currently have < 256 opcodes, the BitMap should fit in 4 bytes. >+Of all opcodes, ~40 will currently ever need metadata, so that if the bytecode for any CodeBlock uses all of this opcodes, it would an extra 40~160b, depending on how many instances of each opcode appear in the bytecode. >+ >+## Instruction >+ >+Instructions have variable length, and have the form >+ >++-----------+------+-----+------+------------+ >+| opcode_id | arg0 | ... | argN | metadataID | >++-----------+------+-----+------+------------+ >+ >+where N <= 0 and metadataID is optional >+ >+### Narrow Instructions >+ >+By the default, we try to encode every instruction in a narrow setting, where every segment has 1-byte. However, we will fall back to a "Wide Instruction" whenever any of the arguments overflows, i.e.: >+ >+* opcode_id: we currently have 167 opcodes, so this won't be a problem for now but, hypothetically, any opcodes beyond id 256 will have to be encoded as a wide instruction. >+* arg: the type of the operand should never be ambiguous, therefore we support: >+ + up to 256 of each of the following: local registers, constants and arguments >+ + up to 8-byte types: we'll attempt to fit integers and unsigned integers in 8 bytes, otherwise fallback to a wide instruction. >+* up to 256 metadata entries per opcode, i.e. if an opcode has metadata, only 256 instances of the same opcode will fit into the same CodeBlock. >+ >+### Wide Instructions >+ >+Wide instructions have 4-byte segments, but otherwise indistinguishable from narrow instructions. >+ >+We reserve the first opcode to a trampoline that will evaluate the next instruction as a "Wide Instruction", where each segment of the instruction has 4 bytes. This opcode will also be responsible to guaranteeing 4-byte alignment on ARM. >+ >+## API >+ >+A class/struct will be generated for each opcode. The struct wil be responsible for: >+* Encoding, e.g. dumping the instruction into a binary format, and choosing between narrow or wide encoding >+* Providing access to each of the instruction's arguments and metadata >+* Potentially allow dumping the instruction, simplifying the work done by the BytecodeDumper >+ >+Here's what the API may look like for each of this operations, for e.g. the `op_get_argument` (this opcode should be a good example, since it has multiple argument types and metadata). Here is its current declaration (syntax may still change) >+ >+```ruby >+op :get_argument, >+ args: { >+ dst: :Register, >+ index: :unsigned, >+ }, >+ metadata: { >+ profile: :ValueProfile, >+ } >+``` >+ >+### Encoding >+ >+```cpp >+static void OpGetArgument::create(BytecodeGenerator& generator RegisterID* register, unsigned index); >+``` >+ >+ >+### Field Access >+ >+```cpp >+RegisterID OpGetArgument::dst(); >+unsigned OpGetArgument::index(); >+``` >+ >+### Metadata Acess >+```cpp >+ValueProfile* OpGetArgument::profile(ExecState&); >+``` >+ >+### BytecodeDumper >+ >+```cpp >+void OpGetArguments::dump(BytecodeDumper&); >+``` >+ >+### Decoding >+ >+Decoding should be done by the base instruction/reader class. >+ >+```cpp >+Instruction::Unknown* Instruction::read(UnlinkedInstructionStream::Reader&); >+``` >+ >+## "Linking" >+ >+Linking, in its current form, should no longer be necessary. Instead, it will consist of creating the side table for the bytecode metadata and ensuring that the jump table with the offset for each opcode has been initialized. >+ >+### Side table >+ >+A callee-saved register pointing to the current CodeBlock's can be kept at all times to speed up metadata accesses that are necessary specially for profiling. >+ >+### Jump table >+ >+A mapping from opcode IDs to opcode addresses is already generated in InitBytecodes.asm and loaded by LLIntData. >+ >+## Portability >+ >+Due to different alignment requirements, the bytecode should not portable across different platforms. >+Does enabling the JIT affect the bytecode? Possibly not, since it may only affect the metadata and not the bytecode itself, but TBC. >+ >+## Performance >+ >+Removing the linking step means that the interpreter will no longer be direct-threaded. Disabling COMPUTED_GOTO in CLoop (in order to disable direct threading) shows a 1% regression on PLT. >+ >+However, CLoop's fallback implementation is a switch statement, which affects branch prediction. >+ >+Alternatively, hacking JSC to skip replacing opcodes with their addresses during linking and modifying the dispatch macro in CLoop to fetch opcodes addresses shows a ~1% progression over CLoop with COMPUTED_GOTO enabled. >+ >+### get_by_id >+ >+`get_by_id` is the instruction that will require the most change, since we currently rewrite the bytecode stream to select from multiple implementations that share the same size. We can default to trying the most performance critical version of `get_by_id` first and fallback to loading the metadata field that specifies which version of the opcode should we execute. >+ >+# Current issues >+ >+Forward jumps will always generate wide opcodes: UINT_MAX is used as invalidLocation, which means that the address won't fit into a 1-byte operand. We might need to compact it later. >diff --git a/Source/JavaScriptCore/wip_bytecode/bytecode_structs.cpp b/Source/JavaScriptCore/wip_bytecode/bytecode_structs.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..ad372fd45f8acd2fcd4766b209cf5d3d74f173ae >--- /dev/null >+++ b/Source/JavaScriptCore/wip_bytecode/bytecode_structs.cpp >@@ -0,0 +1,393 @@ >+#include <cassert> >+#include <cstdint> >+#include <iostream> >+#include <type_traits> >+#include <unordered_map> >+#include <vector> >+ >+typedef unsigned Opcode; >+ >+enum OpcodeSize : size_t { >+ Narrow = 1, >+ Wide = 4, >+}; >+ >+size_t opcode_count = 2; >+size_t metadata_count[] = { >+ 0, >+ 3 >+}; >+size_t opcode_length[] = { >+ 0, >+ 4 >+}; >+ >+ >+class BytecodeGenerator { >+public: >+ BytecodeGenerator() >+ : m_metadata(opcode_count) >+ { } >+ >+ void write(uint8_t op) >+ { >+ m_opcodes.push_back(op); >+ } >+ >+ void write(unsigned op) >+ { >+ uint8_t* b = (uint8_t*)&op; >+ m_opcodes.push_back(b[0]); >+ m_opcodes.push_back(b[1]); >+ m_opcodes.push_back(b[2]); >+ m_opcodes.push_back(b[3]); >+ } >+ >+ unsigned metadataFor(Opcode opcode) >+ { >+ auto& it = m_metadata.at(opcode); >+ return it++; >+ } >+ >+ std::vector<uint8_t> m_opcodes; >+private: >+ std::vector<unsigned> m_metadata; >+}; >+ >+class RegisterID { >+public: >+ RegisterID(unsigned offset) >+ : m_offset(offset) >+ { } >+ >+ unsigned m_offset; >+}; >+ >+using Register = RegisterID; >+ >+template <typename T, size_t Width, typename = std::true_type> >+struct Fits { }; >+ >+template <typename T, size_t Width> >+struct Fits<T, Width, std::enable_if_t<sizeof(T) == Width, std::true_type>> { >+ using type = T; >+ static bool check(T) { return true; } >+ static T convert(T t) { return t; } >+}; >+ >+template<> >+struct Fits<unsigned, 1> { >+ using type = uint8_t; >+ >+ static bool check(unsigned u) >+ { >+ std::cout << "HERE: " << u << " <= " << UINT8_MAX << std::endl; >+ return u <= UINT8_MAX; >+ } >+ >+ static type convert(unsigned u) >+ { >+ assert(check(u)); >+ return static_cast<uint8_t>(u); >+ } >+}; >+ >+template<> >+struct Fits<RegisterID*, 1> { >+ using type = uint8_t; >+ >+ static bool check(RegisterID* r) >+ { >+ return Fits<unsigned, 1>::check(r->m_offset); >+ } >+ >+ static type convert(RegisterID* r) >+ { >+ return Fits<unsigned, 1>::convert(r->m_offset); >+ } >+}; >+ >+template<> >+struct Fits<RegisterID*, 4> { >+ using type = unsigned; >+ >+ static bool check(RegisterID* r) >+ { >+ return true; >+ } >+ >+ static type convert(RegisterID* r) >+ { >+ return r->m_offset; >+ } >+}; >+ >+class BytecodeReader { >+public: >+ BytecodeReader(std::vector<uint8_t>& stream) >+ : m_stream(stream) >+ { } >+ >+ uint8_t& get() >+ { >+ assert(m_index < m_stream.size()); >+ std::cout << "BytecodeReader::read [" << m_index << "]" << std::endl; >+ return m_stream[m_index]; >+ }; >+ >+ void advance(size_t offset) >+ { >+ m_index += offset; >+ assert(m_index <= m_stream.size()); >+ } >+ >+private: >+ unsigned m_index; >+ std::vector<uint8_t>& m_stream; >+}; >+ >+struct OpWide final { >+ static Opcode opcodeID() { return 0; } >+}; >+ >+class Instruction { >+private: >+ template<OpcodeSize Width> >+ class Impl { >+ public: >+ Opcode opcodeID() { return m_opcode; } >+ >+ private: >+ typename Fits<Opcode, Width>::type m_opcode; >+ }; >+ >+public: >+ unsigned opcodeID() >+ { >+ if (isWide()) >+ return wide()->opcodeID(); >+ return narrow()->opcodeID(); >+ } >+ >+ bool isWide() >+ { >+ return narrow()->opcodeID() == OpWide::opcodeID(); >+ }; >+ >+ size_t length() >+ { >+ return opcode_length[opcodeID()]; >+ } >+ >+ size_t size() >+ { >+ auto isWide = this->isWide(); >+ return length() * (isWide ? OpcodeSize::Wide : OpcodeSize::Narrow) + isWide; >+ } >+ >+ >+ template<class T> >+ bool is() >+ { >+ return opcodeID() == T::opcodeID(); >+ } >+ >+ template<class T> >+ T as() >+ { >+ assert(is<T>()); >+ return T(reinterpret_cast<uint8_t*>(this)); >+ } >+ >+ Impl<OpcodeSize::Narrow>* narrow() >+ { >+ return (Impl<OpcodeSize::Narrow>*)this; >+ } >+ >+ Impl<OpcodeSize::Wide>* wide() >+ { >+ >+ assert(isWide()); >+ return (Impl<OpcodeSize::Wide>*)((uintptr_t)this + 1); >+ } >+ >+ static Instruction* read(BytecodeReader& reader) >+ { >+ >+ auto* instr = reinterpret_cast<Instruction*>(&reader.get()); >+ reader.advance(instr->size()); >+ return instr; >+ } >+}; >+ >+class ValueProfile { >+public: >+ ValueProfile() >+ { >+ static unsigned id = 0; >+ m_id = id++; >+ } >+ >+ unsigned id() { return m_id; } >+ >+private: >+ unsigned m_id; >+}; >+ >+template <typename Key, typename Value> >+using HashMap = std::unordered_map<Key, Value>; >+ >+typedef struct _OpaqueMetadata* OpaqueMetadata; >+ >+class CodeBlock { >+public: >+ CodeBlock() >+ : m_metadata(opcode_count) >+ { >+ for (unsigned i = 0; i < opcode_count; i++) { >+ auto count = metadata_count[i]; >+ if (count) { >+ std::cout << "opcode: " << i << ", metadata_count: " << count << std::endl; >+ m_metadata[i] = HashMap<unsigned, OpaqueMetadata>(count); >+ } >+ >+ } >+ } >+ >+ template <typename Value> >+ HashMap <unsigned, Value>& metadata(Opcode opcode) >+ { >+ auto& meta = m_metadata.at(opcode); >+ return *reinterpret_cast<HashMap<unsigned, Value>*>(&meta); >+ } >+ >+private: >+ HashMap <Opcode, HashMap<unsigned, OpaqueMetadata>> m_metadata; >+}; >+ >+class ExecState { >+public: >+ ExecState(CodeBlock* codeBlock) >+ : m_codeBlock(codeBlock) >+ { } >+ >+ CodeBlock* codeBlock() { return m_codeBlock; } >+ >+private: >+ CodeBlock* m_codeBlock; >+}; >+ >+ >+struct OpGetArgument final { >+ OpGetArgument(uint8_t* stream) >+ { >+ auto load = [this](auto s) { >+ assert(s[0] == opcodeID()); >+ dst = s[1]; >+ index = s[2]; >+ metadataID = s[3]; >+ }; >+ >+ if (*stream == OpWide::opcodeID()) { >+ auto wideStream = reinterpret_cast<uint32_t*>(stream + 1); >+ load(wideStream); >+ } else { >+ load(stream); >+ } >+ } >+ >+ static constexpr unsigned opcodeID() { return 1; } >+ >+ static void emit(BytecodeGenerator& generator, RegisterID* dst, unsigned index) >+ { >+ if (Fits<Opcode, 1>::check(opcodeID()) && Fits<decltype(dst), 1>::check(dst) && Fits<decltype(index), 1>::check(index)) { >+ generator.write(Fits<Opcode, 1>::convert(opcodeID())); >+ generator.write(Fits<decltype(dst), 1>::convert(dst)); >+ generator.write(Fits<decltype(index), 1>::convert(index)); >+ generator.write(Fits<unsigned, 1>::convert(generator.metadataFor(opcodeID()))); >+ } else { >+ assert((Fits<decltype(opcodeID()), 4>::check(opcodeID()))); >+ assert((Fits<decltype(dst), 4>::check(dst))); >+ assert((Fits<decltype(index), 4>::check(index))); >+ >+ generator.write(Fits<Opcode, 1>::convert(OpWide::opcodeID())); >+ generator.write(OpGetArgument::opcodeID()); >+ generator.write(Fits<decltype(dst), 4>::convert(dst)); >+ generator.write(Fits<decltype(index), 4>::convert(index)); >+ generator.write(Fits<unsigned, 4>::convert(generator.metadataFor(opcodeID()))); >+ } >+ } >+ >+ struct Metadata { >+ ValueProfile profile; >+ }; >+ >+ Register dst; >+ unsigned index; >+ unsigned metadataID; >+ >+ Metadata& metadata(ExecState& exec) >+ { >+ auto meta = exec.codeBlock()->metadata<OpGetArgument::Metadata>(opcodeID()); >+ const auto& it = meta.find(metadataID); >+ if (it != meta.end()) >+ return it->second; >+ return meta.emplace(std::make_pair(metadataID, Metadata { })).first->second; >+ } >+}; >+ >+ >+int main() >+{ >+ BytecodeGenerator generator; >+ RegisterID dst(3); >+ CodeBlock codeBlock; >+ ExecState exec(&codeBlock); >+ >+ OpGetArgument::emit(generator, &dst, 1); >+ OpGetArgument::emit(generator, &dst, 1256); >+ OpGetArgument::emit(generator, &dst, 42); >+ >+ std::cout << "writing " << generator.m_opcodes.size() << " bytes" << std::endl; >+ for (auto op : generator.m_opcodes) >+ std::cout << std::to_string(op) << std::endl; >+ >+ BytecodeReader reader(generator.m_opcodes); >+ { >+ auto instr = Instruction::read(reader); >+ std::cout << "opcode: " << instr->opcodeID() << std::endl; >+ std::cout << "isWide: " << instr->isWide() << std::endl; >+ std::cout << "size: " << instr->size() << std::endl; >+ } >+ >+ { >+ auto instr = Instruction::read(reader); >+ std::cout << "opcode: " << instr->opcodeID() << std::endl; >+ std::cout << "isWide: " << instr->isWide() << std::endl; >+ std::cout << "size: " << instr->size() << std::endl; >+ >+ auto wide = instr->as<OpGetArgument>(); >+ std::cout << "as<OpGetArgument>->wide(): " << &wide << std::endl; >+ std::cout << "as<OpGetArgument>->wide()->dst(): " << wide.dst.m_offset << std::endl; >+ std::cout << "as<OpGetArgument>->wide()->metadata(): " << wide.metadataID << std::endl; >+ std::cout << "as<OpGetArgument>->wide()->metadata(exec).profile.id(): " << wide.metadata(exec).profile.id() << std::endl; >+ } >+ >+ { >+ auto instr = Instruction::read(reader); >+ std::cout << "opcode: " << instr->opcodeID() << std::endl; >+ std::cout << "isWide: " << instr->isWide() << std::endl; >+ std::cout << "size: " << instr->size() << std::endl; >+ >+ std::cout << "is<OpGetArgument>: " << instr->is<OpGetArgument>() << std::endl; >+ std::cout << "is<OpWide>: " << instr->is<OpWide>() << std::endl; >+ >+ std::cout << "as<OpGetArgument>->index: " << instr->as<OpGetArgument>().index << std::endl; >+ >+ auto narrow = instr->as<OpGetArgument>(); >+ std::cout << "as<OpGetArgument>->narrow(): " << &narrow << std::endl; >+ std::cout << "as<OpGetArgument>->narrow()->dst(): " << narrow.dst.m_offset << std::endl; >+ std::cout << "as<OpGetArgument>->narrow()->metadata(exec).profile.id(): " << narrow.metadata(exec).profile.id() << std::endl; >+ } >+ return 0; >+};
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 187373
:
344389
|
344531
|
344635
|
344935
|
345812
|
346138
|
346673
|
346756
|
346862
|
347641
|
347766
|
348149
|
348294
|
348572
|
348792
|
348847
|
348971
|
349051
|
349080
|
349211
|
349307
|
349396
|
349473
|
349594
|
349700
|
349991
|
350040
|
350625
|
350716
|
350743
|
350835
|
350888
|
350987
|
351708
|
351743
|
351841
|
351955
|
351964
|
351995
|
352037
|
352050
|
352126
|
352232
|
352267
|
352268
|
352284
|
352287
|
352288
|
352312
|
352319
|
352322
|
352565
|
352580
|
352600
|
352639
|
352651
|
352664
|
352677
|
352680
|
352689
|
352692
|
352707
|
352719
|
352750
|
352806
|
352809
|
352811
|
352823
|
352843
|
352852
|
352853
|
352861
|
352863
|
352865
|
352866
|
352868
|
352913
|
352926
|
352936
|
352948
|
352981
|
352988
|
352993
|
352999
|
353008
|
353009
|
353033
|
353166
|
353170
|
353199
|
353213
|
353227
|
353235